summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/angle/.gitignore15
-rw-r--r--src/3rdparty/angle/AUTHORS6
-rw-r--r--src/3rdparty/angle/CONTRIBUTORS21
-rw-r--r--src/3rdparty/angle/include/EGL/egl.h9
-rw-r--r--src/3rdparty/angle/include/EGL/eglext.h24
-rw-r--r--src/3rdparty/angle/include/EGL/eglplatform.h17
-rw-r--r--src/3rdparty/angle/include/GLSLANG/ShaderLang.h30
-rw-r--r--src/3rdparty/angle/include/GLSLANG/ShaderVars.h9
-rwxr-xr-x[-rw-r--r--]src/3rdparty/angle/include/KHR/khrplatform.h2
-rw-r--r--src/3rdparty/angle/include/angle_gl.h6
-rw-r--r--src/3rdparty/angle/include/export.h28
-rw-r--r--src/3rdparty/angle/include/platform/Platform.h112
-rw-r--r--src/3rdparty/angle/src/commit.h12
-rw-r--r--src/3rdparty/angle/src/common/MemoryBuffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp)42
-rw-r--r--src/3rdparty/angle/src/common/MemoryBuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h)12
-rw-r--r--src/3rdparty/angle/src/common/Optional.h61
-rw-r--r--src/3rdparty/angle/src/common/RefCountObject.h95
-rw-r--r--src/3rdparty/angle/src/common/angleutils.cpp3
-rw-r--r--src/3rdparty/angle/src/common/angleutils.h35
-rw-r--r--src/3rdparty/angle/src/common/debug.cpp263
-rw-r--r--src/3rdparty/angle/src/common/debug.h82
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.cpp38
-rw-r--r--src/3rdparty/angle/src/common/event_tracer.h34
-rw-r--r--src/3rdparty/angle/src/common/mathutil.h61
-rw-r--r--src/3rdparty/angle/src/common/platform.h109
-rw-r--r--src/3rdparty/angle/src/common/tls.h4
-rw-r--r--src/3rdparty/angle/src/common/utilities.cpp40
-rw-r--r--src/3rdparty/angle/src/common/utilities.h18
-rw-r--r--src/3rdparty/angle/src/common/version.h13
-rw-r--r--src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h39
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h7
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h7
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h6
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h7
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y4
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Input.h2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Lexer.h2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Macro.h1
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h6
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h7
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Token.h1
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h2
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l4
-rw-r--r--src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BaseTypes.h49
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp415
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h112
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp37
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp410
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/CodeGen.cpp22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Common.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.cpp107
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Compiler.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ConstantUnion.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Diagnostics.h9
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp528
-rw-r--r--src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h74
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/HashNames.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InfoSink.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.cpp703
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Initialize.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeDll.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/InitializeVariables.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.cpp311
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermNode.h287
-rw-r--r--src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp54
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Intermediate.cpp114
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Intermediate.h (renamed from src/3rdparty/angle/src/compiler/translator/intermediate.h)16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/LoopInfo.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/MMap.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/NodeSearch.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.cpp195
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Operator.h226
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp23
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputESSL.h11
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp52
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSL.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp216
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp991
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputHLSL.h113
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.cpp626
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ParseContext.h61
-rw-r--r--src/3rdparty/angle/src/compiler/translator/PoolAlloc.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Pragma.h13
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/translator/QualifierAlive.h5
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp157
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h43
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RemoveTree.h7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RenameFunction.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp1
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SearchSymbol.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp22
-rw-r--r--src/3rdparty/angle/src/compiler/translator/StructureHLSL.h14
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp218
-rw-r--r--src/3rdparty/angle/src/compiler/translator/SymbolTable.h70
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp69
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp114
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp16
-rw-r--r--src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h8
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.cpp18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/Types.h38
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h9
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp28
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h29
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp17
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UniformHLSL.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp7
-rw-r--r--src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp87
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h4
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h5
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp200
-rw-r--r--src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h52
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp36
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariableInfo.h8
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariablePacker.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VersionGLSL.h18
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.cpp123
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayout.h (renamed from src/3rdparty/angle/src/common/blocklayout.h)45
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp (renamed from src/3rdparty/angle/src/common/blocklayout.cpp)110
-rw-r--r--src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h62
-rw-r--r--src/3rdparty/angle/src/compiler/translator/compilerdebug.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h8
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h12
-rw-r--r--src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h25
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.h4
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.l19
-rw-r--r--src/3rdparty/angle/src/compiler/translator/glslang.y427
-rw-r--r--src/3rdparty/angle/src/compiler/translator/intermOut.cpp110
-rw-r--r--src/3rdparty/angle/src/compiler/translator/length_limits.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h33
-rw-r--r--src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h6
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.cpp2
-rw-r--r--src/3rdparty/angle/src/compiler/translator/util.h10
-rw-r--r--src/3rdparty/angle/src/id/commit.h3
-rw-r--r--src/3rdparty/angle/src/libANGLE/AttributeMap.cpp (renamed from src/3rdparty/angle/src/libEGL/AttributeMap.cpp)19
-rw-r--r--src/3rdparty/angle/src/libANGLE/AttributeMap.h (renamed from src/3rdparty/angle/src/libEGL/AttributeMap.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/BinaryStream.h (renamed from src/3rdparty/angle/src/libGLESv2/BinaryStream.h)28
-rw-r--r--src/3rdparty/angle/src/libANGLE/Buffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Buffer.cpp)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/Buffer.h (renamed from src/3rdparty/angle/src/libGLESv2/Buffer.h)16
-rw-r--r--src/3rdparty/angle/src/libANGLE/Caps.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Caps.cpp)120
-rw-r--r--src/3rdparty/angle/src/libANGLE/Caps.h (renamed from src/3rdparty/angle/src/libGLESv2/Caps.h)117
-rw-r--r--src/3rdparty/angle/src/libANGLE/Compiler.cpp38
-rw-r--r--src/3rdparty/angle/src/libANGLE/Compiler.h39
-rw-r--r--src/3rdparty/angle/src/libANGLE/Config.cpp275
-rw-r--r--src/3rdparty/angle/src/libANGLE/Config.h91
-rw-r--r--src/3rdparty/angle/src/libANGLE/Constants.h (renamed from src/3rdparty/angle/src/libGLESv2/constants.h)6
-rw-r--r--src/3rdparty/angle/src/libANGLE/Context.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Context.cpp)356
-rw-r--r--src/3rdparty/angle/src/libANGLE/Context.h (renamed from src/3rdparty/angle/src/libGLESv2/Context.h)84
-rw-r--r--src/3rdparty/angle/src/libANGLE/Data.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Data.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/Data.h (renamed from src/3rdparty/angle/src/libGLESv2/Data.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.cpp675
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.h124
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.cpp86
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.h83
-rw-r--r--src/3rdparty/angle/src/libANGLE/Error.inl163
-rw-r--r--src/3rdparty/angle/src/libANGLE/Fence.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Fence.cpp)9
-rw-r--r--src/3rdparty/angle/src/libANGLE/Fence.h (renamed from src/3rdparty/angle/src/libGLESv2/Fence.h)22
-rw-r--r--src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/Framebuffer.cpp658
-rw-r--r--src/3rdparty/angle/src/libANGLE/Framebuffer.h144
-rw-r--r--src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp (renamed from src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp)148
-rw-r--r--src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h (renamed from src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h)70
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp133
-rw-r--r--src/3rdparty/angle/src/libANGLE/HandleAllocator.h63
-rw-r--r--src/3rdparty/angle/src/libANGLE/ImageIndex.cpp (renamed from src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp)32
-rw-r--r--src/3rdparty/angle/src/libANGLE/ImageIndex.h (renamed from src/3rdparty/angle/src/libGLESv2/ImageIndex.h)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/Platform.cpp35
-rw-r--r--src/3rdparty/angle/src/libANGLE/Program.cpp (renamed from src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp)1764
-rw-r--r--src/3rdparty/angle/src/libANGLE/Program.h (renamed from src/3rdparty/angle/src/libGLESv2/ProgramBinary.h)225
-rw-r--r--src/3rdparty/angle/src/libANGLE/Query.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Query.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/Query.h (renamed from src/3rdparty/angle/src/libGLESv2/Query.h)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/RefCountObject.cpp (renamed from src/3rdparty/angle/src/common/RefCountObject.cpp)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/RefCountObject.h110
-rw-r--r--src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp)69
-rw-r--r--src/3rdparty/angle/src/libANGLE/Renderbuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/Renderbuffer.h)18
-rw-r--r--src/3rdparty/angle/src/libANGLE/ResourceManager.cpp (renamed from src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp)117
-rw-r--r--src/3rdparty/angle/src/libANGLE/ResourceManager.h (renamed from src/3rdparty/angle/src/libGLESv2/ResourceManager.h)45
-rw-r--r--src/3rdparty/angle/src/libANGLE/Sampler.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Sampler.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/Sampler.h (renamed from src/3rdparty/angle/src/libGLESv2/Sampler.h)8
-rw-r--r--src/3rdparty/angle/src/libANGLE/Shader.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Shader.cpp)38
-rw-r--r--src/3rdparty/angle/src/libANGLE/Shader.h (renamed from src/3rdparty/angle/src/libGLESv2/Shader.h)18
-rw-r--r--src/3rdparty/angle/src/libANGLE/State.cpp (renamed from src/3rdparty/angle/src/libGLESv2/State.cpp)236
-rw-r--r--src/3rdparty/angle/src/libANGLE/State.h (renamed from src/3rdparty/angle/src/libGLESv2/State.h)60
-rw-r--r--src/3rdparty/angle/src/libANGLE/Surface.cpp166
-rw-r--r--src/3rdparty/angle/src/libANGLE/Surface.h98
-rw-r--r--src/3rdparty/angle/src/libANGLE/Texture.cpp573
-rw-r--r--src/3rdparty/angle/src/libANGLE/Texture.h156
-rw-r--r--src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp (renamed from src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/TransformFeedback.h (renamed from src/3rdparty/angle/src/libGLESv2/TransformFeedback.h)11
-rw-r--r--src/3rdparty/angle/src/libANGLE/Uniform.cpp (renamed from src/3rdparty/angle/src/libGLESv2/Uniform.cpp)6
-rw-r--r--src/3rdparty/angle/src/libANGLE/Uniform.h (renamed from src/3rdparty/angle/src/libGLESv2/Uniform.h)22
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexArray.cpp (renamed from src/3rdparty/angle/src/libGLESv2/VertexArray.cpp)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexArray.h (renamed from src/3rdparty/angle/src/libGLESv2/VertexArray.h)18
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp (renamed from src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp)22
-rw-r--r--src/3rdparty/angle/src/libANGLE/VertexAttribute.h (renamed from src/3rdparty/angle/src/libGLESv2/VertexAttribute.h)11
-rw-r--r--src/3rdparty/angle/src/libANGLE/angletypes.cpp (renamed from src/3rdparty/angle/src/libGLESv2/angletypes.cpp)62
-rw-r--r--src/3rdparty/angle/src/libANGLE/angletypes.h (renamed from src/3rdparty/angle/src/libGLESv2/angletypes.h)160
-rw-r--r--src/3rdparty/angle/src/libANGLE/features.h (renamed from src/3rdparty/angle/src/common/features.h)5
-rw-r--r--src/3rdparty/angle/src/libANGLE/formatutils.cpp (renamed from src/3rdparty/angle/src/libGLESv2/formatutils.cpp)383
-rw-r--r--src/3rdparty/angle/src/libANGLE/formatutils.h81
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryconversions.cpp (renamed from src/3rdparty/angle/src/libGLESv2/queryconversions.cpp)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/queryconversions.h (renamed from src/3rdparty/angle/src/libGLESv2/queryconversions.h)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h)17
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h30
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp58
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h99
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h68
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Image.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/Image.h)26
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h68
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp)38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h)23
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h)96
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h33
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp72
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Renderer.h91
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h)20
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp22
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h48
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h72
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h74
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp)36
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp128
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h48
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp357
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h61
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp)287
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h)16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp463
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h111
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp)35
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp47
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h84
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h)39
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp)60
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h)25
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp)384
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h)105
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp36
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h42
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp)57
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h43
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp628
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h)182
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp)229
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h)47
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp61
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h54
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp396
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h92
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp)897
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h)183
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp)26
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp)104
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h)23
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp)208
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp)491
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h)38
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp)320
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h)53
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp119
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h39
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp)11
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp270
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h45
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp)198
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h)31
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp430
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h)22
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h (renamed from src/3rdparty/angle/src/common/NativeWindow.h)28
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp)52
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp)19
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp)27
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp)52
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h)34
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp)1729
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h)214
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp)16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h)18
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp)174
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h)25
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp)716
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h)82
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp95
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h43
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp)66
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h)16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h40
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl)123
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp)479
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp)310
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl)3
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl)0
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp (renamed from src/3rdparty/angle/src/common/win32/NativeWindow.cpp)16
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp (renamed from src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp)116
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h110
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp (renamed from src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h (renamed from src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h)30
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp (renamed from src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp)6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h (renamed from src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp)74
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h)24
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h)15
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp36
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp)7
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h)11
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp422
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h41
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp)106
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h)28
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp)43
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h)29
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp)1080
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h)167
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp)8
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp)23
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h)21
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp)26
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h)26
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp)18
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp)96
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h)20
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp)91
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h)14
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps)6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs (renamed from src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs)4
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h)6
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp147
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h50
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h)10
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp)13
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h (renamed from src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h)12
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl (renamed from src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl)2
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp (renamed from src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp)39
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationEGL.cpp503
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationEGL.h49
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES.cpp (renamed from src/3rdparty/angle/src/libGLESv2/validationES.cpp)406
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES.h (renamed from src/3rdparty/angle/src/libGLESv2/validationES.h)22
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.cpp (renamed from src/3rdparty/angle/src/libGLESv2/validationES2.cpp)286
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES2.h (renamed from src/3rdparty/angle/src/libGLESv2/validationES2.h)8
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES3.cpp (renamed from src/3rdparty/angle/src/libGLESv2/validationES3.cpp)266
-rw-r--r--src/3rdparty/angle/src/libANGLE/validationES3.h (renamed from src/3rdparty/angle/src/libGLESv2/validationES3.h)11
-rw-r--r--src/3rdparty/angle/src/libEGL/Config.cpp353
-rw-r--r--src/3rdparty/angle/src/libEGL/Config.h114
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.cpp648
-rw-r--r--src/3rdparty/angle/src/libEGL/Display.h104
-rw-r--r--src/3rdparty/angle/src/libEGL/Error.cpp48
-rw-r--r--src/3rdparty/angle/src/libEGL/Error.h39
-rw-r--r--src/3rdparty/angle/src/libEGL/Surface.cpp505
-rw-r--r--src/3rdparty/angle/src/libEGL/Surface.h120
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.cpp1235
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.def12
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL.rc103
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGL_mingw32.def12
-rw-r--r--src/3rdparty/angle/src/libEGL/libEGLd.def12
-rw-r--r--src/3rdparty/angle/src/libEGL/main.cpp203
-rw-r--r--src/3rdparty/angle/src/libEGL/main.h45
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Error.cpp48
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Error.h39
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py78
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp672
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Framebuffer.h126
-rw-r--r--src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp63
-rw-r--r--src/3rdparty/angle/src/libGLESv2/HandleAllocator.h44
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Program.cpp668
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Program.h151
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Texture.cpp1012
-rw-r--r--src/3rdparty/angle/src/libGLESv2/Texture.h241
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp1127
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl.h74
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp271
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h30
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp4318
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h163
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp1058
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h78
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp3394
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h125
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp14
-rw-r--r--src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h23
-rw-r--r--src/3rdparty/angle/src/libGLESv2/formatutils.h106
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.cpp235
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.h49
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp8423
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.def12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2.rc103
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d.def12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def12
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.cpp186
-rw-r--r--src/3rdparty/angle/src/libGLESv2/main.h61
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h52
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp46
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp36
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h53
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h41
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp172
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h193
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h78
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h64
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h39
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h35
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp26
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h50
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h51
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp801
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp255
-rw-r--r--src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h6
-rw-r--r--src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp2
-rw-r--r--src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h2
-rw-r--r--src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h6
-rw-r--r--src/3rdparty/angle/src/third_party/trace_event/trace_event.h795
-rw-r--r--src/3rdparty/libpng.pri1
-rw-r--r--src/3rdparty/libpng/ANNOUNCE86
-rw-r--r--src/3rdparty/libpng/CHANGES1452
-rw-r--r--src/3rdparty/libpng/INSTALL316
-rw-r--r--src/3rdparty/libpng/LICENSE6
-rw-r--r--src/3rdparty/libpng/README63
-rw-r--r--src/3rdparty/libpng/libpng-manual.txt1399
-rw-r--r--src/3rdparty/libpng/png.c2716
-rw-r--r--src/3rdparty/libpng/png.h1902
-rw-r--r--src/3rdparty/libpng/pngconf.h468
-rw-r--r--src/3rdparty/libpng/pngdebug.h22
-rw-r--r--src/3rdparty/libpng/pngerror.c434
-rw-r--r--src/3rdparty/libpng/pngget.c563
-rw-r--r--src/3rdparty/libpng/pnginfo.h76
-rw-r--r--src/3rdparty/libpng/pnglibconf.h183
-rw-r--r--src/3rdparty/libpng/pngmem.c672
-rw-r--r--src/3rdparty/libpng/pngpread.c426
-rw-r--r--src/3rdparty/libpng/pngpriv.h1649
-rw-r--r--src/3rdparty/libpng/pngread.c3689
-rw-r--r--src/3rdparty/libpng/pngrio.c74
-rw-r--r--src/3rdparty/libpng/pngrtran.c1501
-rw-r--r--src/3rdparty/libpng/pngrutil.c3233
-rw-r--r--src/3rdparty/libpng/pngset.c1115
-rw-r--r--src/3rdparty/libpng/pngstruct.h213
-rw-r--r--src/3rdparty/libpng/pngtrans.c180
-rw-r--r--src/3rdparty/libpng/pngwio.c114
-rw-r--r--src/3rdparty/libpng/pngwrite.c1742
-rw-r--r--src/3rdparty/libpng/pngwtran.c255
-rw-r--r--src/3rdparty/libpng/pngwutil.c1858
-rw-r--r--src/3rdparty/libpng/qtpatches.diff77
-rw-r--r--src/3rdparty/pcre/pcre_compile.c142
-rw-r--r--src/3rdparty/pcre/pcre_dfa_exec.c5
-rw-r--r--src/3rdparty/pcre/pcre_exec.c20
-rw-r--r--src/3rdparty/pcre/pcre_jit_compile.c8
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.c6
-rw-r--r--src/3rdparty/pcre/sljit/sljitLir.h12
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java9
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtNative.java4
-rw-r--r--src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch477
-rw-r--r--src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch439
-rw-r--r--src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch927
-rw-r--r--src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch363
-rw-r--r--src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch (renamed from src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch)33
-rw-r--r--src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch109
-rw-r--r--src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch84
-rw-r--r--src/angle/patches/0009-ANGLE-Support-WinRT.patch837
-rw-r--r--src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch637
-rw-r--r--src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch48
-rw-r--r--src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch100
-rw-r--r--src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch69
-rw-r--r--src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch536
-rw-r--r--src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch169
-rw-r--r--src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch62
-rw-r--r--src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch106
-rw-r--r--src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch37
-rw-r--r--src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch30
-rw-r--r--src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch43
-rw-r--r--src/angle/src/common/common.pri18
-rw-r--r--src/angle/src/compiler/preprocessor/preprocessor.pro2
-rw-r--r--src/angle/src/compiler/translator.pro39
-rw-r--r--src/angle/src/config.pri5
-rw-r--r--src/angle/src/libEGL/libEGL.pro35
-rw-r--r--src/angle/src/libGLESv2/libGLESv2.pro760
-rw-r--r--src/corelib/codecs/qiconvcodec.cpp2
-rw-r--r--src/corelib/doc/src/resource-system.qdoc2
-rw-r--r--src/corelib/global/qcompilerdetection.h4
-rw-r--r--src/corelib/global/qnamespace.h1
-rw-r--r--src/corelib/global/qnamespace.qdoc53
-rw-r--r--src/corelib/io/qabstractfileengine.cpp2
-rw-r--r--src/corelib/io/qdir.cpp6
-rw-r--r--src/corelib/io/qfile.cpp4
-rw-r--r--src/corelib/io/qfileinfo.cpp8
-rw-r--r--src/corelib/io/qfilesystemengine.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_unix.cpp2
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp10
-rw-r--r--src/corelib/io/qfilesystemwatcher.cpp2
-rw-r--r--src/corelib/io/qfilesystemwatcher.h12
-rw-r--r--src/corelib/io/qfsfileengine.cpp4
-rw-r--r--src/corelib/io/qiodevice.cpp6
-rw-r--r--src/corelib/io/qlockfile_unix.cpp2
-rw-r--r--src/corelib/io/qloggingcategory.cpp2
-rw-r--r--src/corelib/io/qprocess.cpp34
-rw-r--r--src/corelib/io/qprocess.h25
-rw-r--r--src/corelib/io/qprocess_p.h4
-rw-r--r--src/corelib/io/qprocess_unix.cpp4
-rw-r--r--src/corelib/io/qprocess_win.cpp19
-rw-r--r--src/corelib/io/qprocess_wince.cpp4
-rw-r--r--src/corelib/io/qsettings.cpp42
-rw-r--r--src/corelib/io/qstorageinfo_unix.cpp6
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.h84
-rw-r--r--src/corelib/itemmodels/qabstractproxymodel.h6
-rw-r--r--src/corelib/kernel/qcoreapplication.cpp4
-rw-r--r--src/corelib/kernel/qcoreapplication.h6
-rw-r--r--src/corelib/kernel/qcoreapplication_win.cpp46
-rw-r--r--src/corelib/kernel/qcoreevent.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_blackberry.cpp2
-rw-r--r--src/corelib/kernel/qeventdispatcher_winrt.cpp327
-rw-r--r--src/corelib/kernel/qmetatype.cpp63
-rw-r--r--src/corelib/kernel/qmetatype.h1
-rw-r--r--src/corelib/kernel/qobject.cpp4
-rw-r--r--src/corelib/kernel/qobject.h34
-rw-r--r--src/corelib/kernel/qppsattribute.cpp4
-rw-r--r--src/corelib/kernel/qppsattribute_p.h5
-rw-r--r--src/corelib/kernel/qppsobject.cpp4
-rw-r--r--src/corelib/kernel/qsocketnotifier.h6
-rw-r--r--src/corelib/kernel/qtimer.h6
-rw-r--r--src/corelib/kernel/qwineventnotifier.h6
-rw-r--r--src/corelib/mimetypes/qmimedatabase.cpp2
-rw-r--r--src/corelib/plugin/qlibrary.cpp8
-rw-r--r--src/corelib/plugin/qpluginloader.cpp2
-rw-r--r--src/corelib/statemachine/qabstractstate.h12
-rw-r--r--src/corelib/statemachine/qabstracttransition.h18
-rw-r--r--src/corelib/statemachine/qhistorystate.h12
-rw-r--r--src/corelib/statemachine/qsignaltransition.h12
-rw-r--r--src/corelib/statemachine/qstate.h30
-rw-r--r--src/corelib/statemachine/qstatemachine.cpp566
-rw-r--r--src/corelib/statemachine/qstatemachine.h12
-rw-r--r--src/corelib/statemachine/qstatemachine_p.h26
-rw-r--r--src/corelib/thread/qreadwritelock.cpp57
-rw-r--r--src/corelib/thread/qreadwritelock_p.h1
-rw-r--r--src/corelib/thread/qthread.h12
-rw-r--r--src/corelib/thread/qthread_unix.cpp2
-rw-r--r--src/corelib/tools/qbytearraylist.h4
-rw-r--r--src/corelib/tools/qelapsedtimer.cpp6
-rw-r--r--src/corelib/tools/qlist.h7
-rw-r--r--src/corelib/tools/qscopedvaluerollback.h10
-rw-r--r--src/corelib/tools/qstring.cpp12
-rw-r--r--src/corelib/tools/qstringlist.h4
-rw-r--r--src/corelib/tools/qtimeline.h24
-rw-r--r--src/corelib/tools/qtimezone.cpp2
-rw-r--r--src/dbus/qdbusintegrator.cpp11
-rw-r--r--src/dbus/qdbusserver.cpp1
-rw-r--r--src/gui/image/qimage.cpp10
-rw-r--r--src/gui/image/qimage_conversions.cpp6
-rw-r--r--src/gui/image/qimage_sse4.cpp3
-rw-r--r--src/gui/kernel/qclipboard.cpp4
-rw-r--r--src/gui/kernel/qguiapplication.cpp7
-rw-r--r--src/gui/kernel/qpaintdevicewindow.cpp22
-rw-r--r--src/gui/kernel/qplatformintegration.cpp16
-rw-r--r--src/gui/kernel/qplatformintegration.h8
-rw-r--r--src/gui/kernel/qplatformtheme.cpp2
-rw-r--r--src/gui/kernel/qstylehints.cpp12
-rw-r--r--src/gui/kernel/qstylehints.h2
-rw-r--r--src/gui/kernel/qwindow.cpp4
-rw-r--r--src/gui/opengl/qopengl.cpp42
-rw-r--r--src/gui/opengl/qopengl_p.h24
-rw-r--r--src/gui/opengl/qopengltexture.cpp10
-rw-r--r--src/gui/opengl/qopengltexturehelper.cpp2
-rw-r--r--src/gui/painting/painting.pri3
-rw-r--r--src/gui/painting/qblendfunctions.cpp2136
-rw-r--r--src/gui/painting/qdrawhelper.cpp92
-rw-r--r--src/gui/painting/qdrawhelper_p.h36
-rw-r--r--src/gui/painting/qdrawhelper_sse4.cpp7
-rw-r--r--src/gui/painting/qdrawingprimitive_sse2_p.h21
-rw-r--r--src/gui/painting/qimagescale.cpp1155
-rw-r--r--src/gui/painting/qimagescale_p.h9
-rw-r--r--src/gui/painting/qimagescale_sse4.cpp247
-rw-r--r--src/gui/painting/qpdf.cpp490
-rw-r--r--src/gui/painting/qpdf_p.h13
-rw-r--r--src/gui/painting/qrgb.h37
-rw-r--r--src/gui/text/qfontdatabase.cpp2
-rw-r--r--src/gui/text/qtextcursor.cpp8
-rw-r--r--src/gui/text/qtextdocument.cpp3
-rw-r--r--src/gui/text/qtextengine.cpp15
-rw-r--r--src/gui/text/qtextengine_p.h1
-rw-r--r--src/gui/text/qtextformat.cpp4
-rw-r--r--src/gui/text/qtextlayout.cpp8
-rw-r--r--src/gui/text/qtextobject.cpp2
-rw-r--r--src/gui/util/qvalidator.cpp3
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp3
-rw-r--r--src/network/access/qnetworkreplynsurlconnectionimpl.mm13
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp4
-rw-r--r--src/network/ssl/qsslsocket.cpp2
-rw-r--r--src/network/ssl/qsslsocket_openssl.cpp2
-rw-r--r--src/platformheaders/xcbfunctions/qxcbwindowfunctions.h11
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformintegration.cpp4
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm2
-rw-r--r--src/platformsupport/input/evdevtouch/evdevtouch.pri6
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp (renamed from src/platformsupport/input/evdevtouch/qevdevtouch.cpp)75
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h (renamed from src/platformsupport/input/evdevtouch/qevdevtouch_p.h)9
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp122
-rw-r--r--src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h76
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp8
-rw-r--r--src/plugins/generic/evdevtouch/main.cpp4
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp6
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp32
-rw-r--r--src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h1
-rw-r--r--src/plugins/platforms/android/androidjniinput.cpp12
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm13
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm3
-rw-r--r--src/plugins/platforms/cocoa/qcocoawindow.mm3
-rw-r--r--src/plugins/platforms/cocoa/qnsview.h1
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm72
-rw-r--r--src/plugins/platforms/ios/qiostextresponder.mm4
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp4
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.cpp4
-rw-r--r--src/plugins/platforms/qnx/qqnxfilepicker.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxsystemsettings.h4
-rw-r--r--src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h2
-rw-r--r--src/plugins/platforms/windows/accessible/iaccessible2.cpp2
-rw-r--r--src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp4
-rw-r--r--src/plugins/platforms/windows/openglblacklists/default.json6
-rw-r--r--src/plugins/platforms/windows/qwindowseglcontext.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsglcontext.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowsopengltester.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp10
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.cpp64
-rw-r--r--src/plugins/platforms/winrt/qwinrtinputcontext.h8
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp29
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp74
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h15
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.cpp9
-rw-r--r--src/plugins/platforms/xcb/qxcbcursor.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp11
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp95
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.h41
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp226
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.h12
-rw-r--r--src/plugins/platforms/xcb/qxcbwmsupport.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbxsettings.h4
-rw-r--r--src/printsupport/dialogs/qpagesetupdialog_win.cpp2
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm13
-rw-r--r--src/printsupport/kernel/qprintengine_win.cpp39
-rw-r--r--src/src.pro4
-rw-r--r--src/testlib/qtestblacklist.cpp9
-rw-r--r--src/testlib/qtestmouse.h2
-rw-r--r--src/testlib/testlib.pro8
-rw-r--r--src/tools/moc/generator.cpp3
-rw-r--r--src/tools/qdoc/cppcodeparser.cpp5
-rw-r--r--src/tools/qdoc/generator.cpp21
-rw-r--r--src/tools/qdoc/generator.h1
-rw-r--r--src/tools/qdoc/htmlgenerator.cpp19
-rw-r--r--src/tools/qdoc/node.cpp2
-rw-r--r--src/tools/qdoc/node.h5
-rw-r--r--src/tools/qdoc/tokenizer.cpp3
-rw-r--r--src/tools/qdoc/tokenizer.h4
-rw-r--r--src/widgets/dialogs/qfiledialog.cpp149
-rw-r--r--src/widgets/dialogs/qfiledialog_p.h6
-rw-r--r--src/widgets/graphicsview/qgraphicsanchorlayout_p.h4
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp2
-rw-r--r--src/widgets/kernel/qapplication.cpp1
-rw-r--r--src/widgets/kernel/qwidget.cpp2
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp1
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp4
736 files changed, 61566 insertions, 44430 deletions
diff --git a/src/3rdparty/angle/.gitignore b/src/3rdparty/angle/.gitignore
index cbb7e6a5af..17958a0fb5 100644
--- a/src/3rdparty/angle/.gitignore
+++ b/src/3rdparty/angle/.gitignore
@@ -6,19 +6,28 @@ build
extensions
samples
tests
-third_party
src/ipch
+util
.svn
# Files from ANGLE we don't want/need
DEPS
+*.chromium
+*.isolate
+*.md
+*.gn
*.gyp
*.gypi
*.sh
*.bat
*.patch
*.py
+*.rc
+*_unittest.cpp
codereview.settings
+src/commit.h
+src/libANGLE/renderer/gl
+src/third_party/khronos/GL
# Generated by flex/bison
src/compiler/preprocessor/Tokenizer.cpp
@@ -28,5 +37,5 @@ src/compiler/translator/glslang_tab.cpp
src/compiler/translator/glslang_tab.h
# Generated by FXC
-src/libGLESv2/renderer/d3d/d3d9/shaders/compiled/*.h
-src/libGLESv2/renderer/d3d/d3d11/shaders/compiled/*.h
+src/libANGLE/renderer/d3d/d3d9/shaders/compiled/*.h
+src/libANGLE/renderer/d3d/d3d11/shaders/compiled/*.h
diff --git a/src/3rdparty/angle/AUTHORS b/src/3rdparty/angle/AUTHORS
index be114bcf68..836bed8e8a 100644
--- a/src/3rdparty/angle/AUTHORS
+++ b/src/3rdparty/angle/AUTHORS
@@ -16,17 +16,22 @@ Autodesk, Inc.
BlackBerry Limited
Cable Television Laboratories, Inc.
Cloud Party, Inc.
+Imagination Technologies Ltd.
Intel Corporation
Mozilla Corporation
Turbulenz
Klarälvdalens Datakonsult AB
+Microsoft Corporation
Microsoft Open Technologies, Inc.
NVIDIA Corporation
+Opera Software ASA
+The Qt Company Ltd.
Jacek Caban
Mark Callow
Ginn Chen
Tibor den Ouden
+Régis Fénéon
James Hauxwell
Sam Hocevar
Pierre Leveille
@@ -35,3 +40,4 @@ Boying Lu
Aitor Moreno
Yuri O'Donnell
Josh Soref
+Maks Naumov
diff --git a/src/3rdparty/angle/CONTRIBUTORS b/src/3rdparty/angle/CONTRIBUTORS
index 6b27416e38..5252141973 100644
--- a/src/3rdparty/angle/CONTRIBUTORS
+++ b/src/3rdparty/angle/CONTRIBUTORS
@@ -1,4 +1,4 @@
-# This is the official list of people who can contribute
+# This is the official list of people who can contribute
# (and who have contributed) code to the ANGLE project
# repository.
# The AUTHORS file lists the copyright holders; this file
@@ -40,6 +40,7 @@ Google Inc.
thestig@chromium.org
Justin Schuh
Scott Graham
+ Corentin Wallez
Adobe Systems Inc.
Alexandru Chiculita
@@ -55,6 +56,9 @@ Cloud Party, Inc.
The Qt Company Ltd.
Andrew Knight
+Imagination Technologies Ltd.
+ Gregoire Payen de La Garanderie
+
Intel Corporation
Jin Yang
Andy Chen
@@ -80,10 +84,21 @@ Mark Banner (standard8mbp)
David Kilzer
Jacek Caban
Tibor den Ouden
+Régis Fénéon
+
+Microsoft Corporation
+ Cooper Partin
+ Austin Kinross
+ Minmin Gong
Microsoft Open Technologies, Inc.
-Cooper Partin
-Austin Kinross
+ Cooper Partin
+ Austin Kinross
NVIDIA Corporation
Olli Etuaho
+ Arun Patole
+ Qingqing Deng
+
+Opera Software ASA
+ Daniel Bratell
diff --git a/src/3rdparty/angle/include/EGL/egl.h b/src/3rdparty/angle/include/EGL/egl.h
index 12590a0e20..5a27291213 100644
--- a/src/3rdparty/angle/include/EGL/egl.h
+++ b/src/3rdparty/angle/include/EGL/egl.h
@@ -33,12 +33,12 @@ extern "C" {
** used to make the header, and the header can be found at
** http://www.opengl.org/registry/
**
-** Khronos $Revision: 27018 $ on $Date: 2014-06-10 08:06:12 -0700 (Tue, 10 Jun 2014) $
+** Khronos $Revision: 29318 $ on $Date: 2015-01-02 03:16:10 -0800 (Fri, 02 Jan 2015) $
*/
#include <EGL/eglplatform.h>
-/* Generated on date 20140610 */
+/* Generated on date 20150102 */
/* Generated C header for:
* API: egl
@@ -240,6 +240,7 @@ EGLAPI EGLContext EGLAPIENTRY eglGetCurrentContext (void);
typedef void *EGLSync;
typedef intptr_t EGLAttrib;
typedef khronos_utime_nanoseconds_t EGLTime;
+typedef void *EGLImage;
#define EGL_CONTEXT_MAJOR_VERSION 0x3098
#define EGL_CONTEXT_MINOR_VERSION 0x30FB
#define EGL_CONTEXT_OPENGL_PROFILE_MASK 0x30FD
@@ -281,10 +282,14 @@ typedef khronos_utime_nanoseconds_t EGLTime;
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y 0x30B6
#define EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z 0x30B7
#define EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z 0x30B8
+#define EGL_IMAGE_PRESERVED 0x30D2
+#define EGL_NO_IMAGE ((EGLImage)0)
EGLAPI EGLSync EGLAPIENTRY eglCreateSync (EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
EGLAPI EGLBoolean EGLAPIENTRY eglDestroySync (EGLDisplay dpy, EGLSync sync);
EGLAPI EGLint EGLAPIENTRY eglClientWaitSync (EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
EGLAPI EGLBoolean EGLAPIENTRY eglGetSyncAttrib (EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+EGLAPI EGLImage EGLAPIENTRY eglCreateImage (EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+EGLAPI EGLBoolean EGLAPIENTRY eglDestroyImage (EGLDisplay dpy, EGLImage image);
EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplay (EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface (EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
EGLAPI EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface (EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
diff --git a/src/3rdparty/angle/include/EGL/eglext.h b/src/3rdparty/angle/include/EGL/eglext.h
index 0cc5eec293..a44afecb3f 100644
--- a/src/3rdparty/angle/include/EGL/eglext.h
+++ b/src/3rdparty/angle/include/EGL/eglext.h
@@ -440,24 +440,28 @@ EGLAPI EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE (EGLDisplay dpy, EGLSu
#ifndef EGL_ANGLE_platform_angle
#define EGL_ANGLE_platform_angle 1
-#define EGL_PLATFORM_ANGLE_ANGLE 0x3201
-#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3202
-#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3203
-#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3204
-#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_ANGLE 0x3202
+#define EGL_PLATFORM_ANGLE_TYPE_ANGLE 0x3203
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE 0x3204
+#define EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE 0x3205
+#define EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE 0x3206
#endif /* EGL_ANGLE_platform_angle */
#ifndef EGL_ANGLE_platform_angle_d3d
#define EGL_ANGLE_platform_angle_d3d 1
-#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3206
-#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3207
-#define EGL_PLATFORM_ANGLE_USE_WARP_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE 0x3207
+#define EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE 0x3208
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE 0x3209
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE 0x320B
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE 0x320C
+#define EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE 0x320F
#endif /* EGL_ANGLE_platform_angle_d3d */
#ifndef EGL_ANGLE_platform_angle_opengl
#define EGL_ANGLE_platform_angle_opengl 1
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x3209
-#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320A
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE 0x320D
+#define EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE 0x320E
#endif /* EGL_ANGLE_platform_angle_opengl */
#ifndef EGL_ARM_pixmap_multisample_discard
diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
index 2eb3674a0b..519df3e750 100644
--- a/src/3rdparty/angle/include/EGL/eglplatform.h
+++ b/src/3rdparty/angle/include/EGL/eglplatform.h
@@ -73,15 +73,14 @@
#endif
#include <windows.h>
+typedef HDC EGLNativeDisplayType;
typedef HBITMAP EGLNativePixmapType;
-#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
+#if !defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) /* Windows Desktop */
+typedef HWND EGLNativeWindowType;
+#else /* Windows Store */
#include <inspectable.h>
-typedef IInspectable* EGLNativeDisplayType;
typedef IInspectable* EGLNativeWindowType;
-#else
-typedef HDC EGLNativeDisplayType;
-typedef HWND EGLNativeWindowType;
#endif
#elif defined(__WINSCW__) || defined(__SYMBIAN32__) /* Symbian */
@@ -110,6 +109,14 @@ typedef Display *EGLNativeDisplayType;
typedef Pixmap EGLNativePixmapType;
typedef Window EGLNativeWindowType;
+#elif defined(__GNUC__) && ( defined(__APPLE_CPP__) || defined(__APPLE_CC__) || defined(__MACOS_CLASSIC__) )
+
+// TODO(jmadill): native implementation for OSX
+
+typedef void *EGLNativeDisplayType;
+typedef void *EGLNativePixmapType;
+typedef void *EGLNativeWindowType;
+
#else
#error "Platform not recognized"
#endif
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
index 647fed6a02..126205af2c 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderLang.h
@@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-#ifndef _COMPILER_INTERFACE_INCLUDED_
-#define _COMPILER_INTERFACE_INCLUDED_
+#ifndef GLSLANG_SHADERLANG_H_
+#define GLSLANG_SHADERLANG_H_
#if defined(COMPONENT_BUILD) && !defined(ANGLE_TRANSLATOR_STATIC)
#if defined(_WIN32) || defined(_WIN64)
@@ -48,7 +48,7 @@ typedef unsigned int GLenum;
// Version number for shader translation API.
// It is incremented every time the API changes.
-#define ANGLE_SH_VERSION 132
+#define ANGLE_SH_VERSION 134
typedef enum {
SH_GLES2_SPEC = 0x8B40,
@@ -81,11 +81,16 @@ typedef enum {
} ShShaderSpec;
typedef enum {
- SH_ESSL_OUTPUT = 0x8B45,
- SH_GLSL_OUTPUT = 0x8B46,
- SH_HLSL_OUTPUT = 0x8B47,
- SH_HLSL9_OUTPUT = 0x8B47,
- SH_HLSL11_OUTPUT = 0x8B48
+ SH_ESSL_OUTPUT = 0x8B45,
+ // SH_GLSL_OUTPUT is deprecated. This is to not break the build.
+ SH_GLSL_OUTPUT = 0x8B46,
+ SH_GLSL_COMPATIBILITY_OUTPUT = 0x8B46,
+ SH_GLSL_CORE_OUTPUT = 0x8B47,
+
+ // HLSL output only supported in some configurations.
+ SH_HLSL_OUTPUT = 0x8B48,
+ SH_HLSL9_OUTPUT = 0x8B48,
+ SH_HLSL11_OUTPUT = 0x8B49
} ShShaderOutput;
// Compile options.
@@ -223,6 +228,10 @@ typedef struct
int EXT_draw_buffers;
int EXT_frag_depth;
int EXT_shader_texture_lod;
+ int WEBGL_debug_shader_precision;
+ int EXT_shader_framebuffer_fetch;
+ int NV_shader_framebuffer_fetch;
+ int ARM_shader_framebuffer_fetch;
// Set to 1 to enable replacing GL_EXT_draw_buffers #extension directives
// with GL_NV_draw_buffers in ESSL output. This flag can be used to emulate
@@ -290,7 +299,8 @@ COMPILER_EXPORT const std::string &ShGetBuiltInResourcesString(const ShHandle ha
// spec: Specifies the language spec the compiler must conform to -
// SH_GLES2_SPEC or SH_WEBGL_SPEC.
// output: Specifies the output code type - SH_ESSL_OUTPUT, SH_GLSL_OUTPUT,
-// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT.
+// SH_HLSL9_OUTPUT or SH_HLSL11_OUTPUT. Note: HLSL output is only
+// supported in some configurations.
// resources: Specifies the built-in resources.
COMPILER_EXPORT ShHandle ShConstructCompiler(
sh::GLenum type,
@@ -408,4 +418,4 @@ COMPILER_EXPORT bool ShGetUniformRegister(const ShHandle handle,
const std::string &uniformName,
unsigned int *indexOut);
-#endif // _COMPILER_INTERFACE_INCLUDED_
+#endif // GLSLANG_SHADERLANG_H_
diff --git a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
index da21c3e76e..4128c343f8 100644
--- a/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
+++ b/src/3rdparty/angle/include/GLSLANG/ShaderVars.h
@@ -7,8 +7,8 @@
// Types to represent GL variables (varyings, uniforms, etc)
//
-#ifndef _COMPILER_INTERFACE_VARIABLES_
-#define _COMPILER_INTERFACE_VARIABLES_
+#ifndef GLSLANG_SHADERVARS_H_
+#define GLSLANG_SHADERVARS_H_
#include <string>
#include <vector>
@@ -28,6 +28,9 @@ enum InterpolationType
INTERPOLATION_FLAT
};
+// Validate link & SSO consistency of interpolation qualifiers
+COMPILER_EXPORT bool InterpolationTypesMatch(InterpolationType a, InterpolationType b);
+
// Uniform block layout qualifier, see section 4.3.8.3 of the ESSL 3.00.4 spec
enum BlockLayoutType
{
@@ -182,4 +185,4 @@ struct COMPILER_EXPORT InterfaceBlock
}
-#endif // _COMPILER_INTERFACE_VARIABLES_
+#endif // GLSLANG_SHADERVARS_H_
diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h
index 1ac2d3f324..c9e6f17d34 100644..100755
--- a/src/3rdparty/angle/include/KHR/khrplatform.h
+++ b/src/3rdparty/angle/include/KHR/khrplatform.h
@@ -97,7 +97,7 @@
*-------------------------------------------------------------------------
* This precedes the return type of the function in the function prototype.
*/
-#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
+#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
# define KHRONOS_APICALL __declspec(dllimport)
#elif defined (__SYMBIAN32__)
# define KHRONOS_APICALL IMPORT_C
diff --git a/src/3rdparty/angle/include/angle_gl.h b/src/3rdparty/angle/include/angle_gl.h
index d093f75ee2..e7ecdbd2f0 100644
--- a/src/3rdparty/angle/include/angle_gl.h
+++ b/src/3rdparty/angle/include/angle_gl.h
@@ -7,8 +7,8 @@
// Includes all necessary GL headers and definitions for ANGLE.
//
-#ifndef ANGLE_GL_H_
-#define ANGLE_GL_H_
+#ifndef ANGLEGL_H_
+#define ANGLEGL_H_
#include "GLES2/gl2.h"
#include "GLES2/gl2ext.h"
@@ -20,4 +20,4 @@
#define GL_SAMPLER_2D_RECT_ARB 0x8B63
#endif
-#endif // ANGLE_GL_H_
+#endif // ANGLEGL_H_
diff --git a/src/3rdparty/angle/include/export.h b/src/3rdparty/angle/include/export.h
new file mode 100644
index 0000000000..cdf6245d6d
--- /dev/null
+++ b/src/3rdparty/angle/include/export.h
@@ -0,0 +1,28 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// export.h : Defines ANGLE_EXPORT, a macro for exporting functions from the DLL
+
+#ifndef LIBGLESV2_EXPORT_H_
+#define LIBGLESV2_EXPORT_H_
+
+#if defined(_WIN32)
+# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
+# define ANGLE_EXPORT __declspec(dllexport)
+# else
+# define ANGLE_EXPORT __declspec(dllimport)
+# endif
+#elif defined(__GNUC__)
+# if defined(LIBGLESV2_IMPLEMENTATION) || defined(LIBANGLE_IMPLEMENTATION)
+# define ANGLE_EXPORT __attribute__((visibility ("default")))
+# else
+# define ANGLE_EXPORT
+# endif
+#else
+# define ANGLE_EXPORT
+#endif
+
+#endif // LIBGLESV2_EXPORT_H_
diff --git a/src/3rdparty/angle/include/platform/Platform.h b/src/3rdparty/angle/include/platform/Platform.h
new file mode 100644
index 0000000000..d915d5c0fd
--- /dev/null
+++ b/src/3rdparty/angle/include/platform/Platform.h
@@ -0,0 +1,112 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Platform.h: The public interface ANGLE exposes to the API layer, for
+// doing platform-specific tasks like gathering data, or for tracing.
+
+#ifndef ANGLE_PLATFORM_H
+#define ANGLE_PLATFORM_H
+
+#include <stdint.h>
+
+#include "../export.h"
+
+namespace angle
+{
+
+class Platform
+{
+ public:
+
+ // Tracing --------
+
+ typedef uint64_t TraceEventHandle;
+
+ // Add a trace event to the platform tracing system. Depending on the actual
+ // enabled state, this event may be recorded or dropped.
+ // - phase specifies the type of event:
+ // - BEGIN ('B'): Marks the beginning of a scoped event.
+ // - END ('E'): Marks the end of a scoped event.
+ // - COMPLETE ('X'): Marks the beginning of a scoped event, but doesn't
+ // need a matching END event. Instead, at the end of the scope,
+ // updateTraceEventDuration() must be called with the TraceEventHandle
+ // returned from addTraceEvent().
+ // - INSTANT ('I'): Standalone, instantaneous event.
+ // - START ('S'): Marks the beginning of an asynchronous event (the end
+ // event can occur in a different scope or thread). The id parameter is
+ // used to match START/FINISH pairs.
+ // - FINISH ('F'): Marks the end of an asynchronous event.
+ // - COUNTER ('C'): Used to trace integer quantities that change over
+ // time. The argument values are expected to be of type int.
+ // - METADATA ('M'): Reserved for internal use.
+ // - categoryEnabled is the pointer returned by getTraceCategoryEnabledFlag.
+ // - name is the name of the event. Also used to match BEGIN/END and
+ // START/FINISH pairs.
+ // - id optionally allows events of the same name to be distinguished from
+ // each other. For example, to trace the consutruction and destruction of
+ // objects, specify the pointer as the id parameter.
+ // - numArgs specifies the number of elements in argNames, argTypes, and
+ // argValues.
+ // - argNames is the array of argument names. Use long-lived literal strings
+ // or specify the COPY flag.
+ // - argTypes is the array of argument types:
+ // - BOOL (1): bool
+ // - UINT (2): unsigned long long
+ // - INT (3): long long
+ // - DOUBLE (4): double
+ // - POINTER (5): void*
+ // - STRING (6): char* (long-lived null-terminated char* string)
+ // - COPY_STRING (7): char* (temporary null-terminated char* string)
+ // - CONVERTABLE (8): WebConvertableToTraceFormat
+ // - argValues is the array of argument values. Each value is the unsigned
+ // long long member of a union of all supported types.
+ // - flags can be 0 or one or more of the following, ORed together:
+ // - COPY (0x1): treat all strings (name, argNames and argValues of type
+ // string) as temporary so that they will be copied by addTraceEvent.
+ // - HAS_ID (0x2): use the id argument to uniquely identify the event for
+ // matching with other events of the same name.
+ // - MANGLE_ID (0x4): specify this flag if the id parameter is the value
+ // of a pointer.
+ virtual TraceEventHandle addTraceEvent(char phase,
+ const unsigned char *categoryEnabledFlag,
+ const char *name,
+ unsigned long long id,
+ double timestamp,
+ int numArgs,
+ const char **argNames,
+ const unsigned char *argTypes,
+ const unsigned long long *argValues,
+ unsigned char flags)
+ {
+ return 0;
+ }
+
+ // Set the duration field of a COMPLETE trace event.
+ virtual void updateTraceEventDuration(const unsigned char* categoryEnabledFlag, const char* name, TraceEventHandle) { }
+
+ // Callbacks for reporting histogram data.
+ // CustomCounts histogram has exponential bucket sizes, so that min=1, max=1000000, bucketCount=50 would do.
+ virtual void histogramCustomCounts(const char* name, int sample, int min, int max, int bucketCount) { }
+ // Enumeration histogram buckets are linear, boundaryValue should be larger than any possible sample value.
+ virtual void histogramEnumeration(const char* name, int sample, int boundaryValue) { }
+ // Unlike enumeration histograms, sparse histograms only allocate memory for non-empty buckets.
+ virtual void histogramSparse(const char* name, int sample) { }
+
+ protected:
+ virtual ~Platform() { }
+};
+
+}
+
+typedef void(*ANGLEPlatformInitializeFunc)(angle::Platform*);
+ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform*);
+
+typedef void (*ANGLEPlatformShutdownFunc)();
+ANGLE_EXPORT void ANGLEPlatformShutdown();
+
+typedef angle::Platform *(*ANGLEPlatformCurrentFunc)();
+ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent();
+
+#endif // ANGLE_PLATFORM_H
diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h
deleted file mode 100644
index 08fc893c25..0000000000
--- a/src/3rdparty/angle/src/commit.h
+++ /dev/null
@@ -1,12 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-// commit.h:
-// This is a default commit hash header, when git is not available.
-//
-
-#define ANGLE_COMMIT_HASH "30d6c255d238"
-#define ANGLE_COMMIT_HASH_SIZE 12
-#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp b/src/3rdparty/angle/src/common/MemoryBuffer.cpp
index 2b5b09a324..e7a3fb4a2b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp
+++ b/src/3rdparty/angle/src/common/MemoryBuffer.cpp
@@ -4,12 +4,13 @@
// found in the LICENSE file.
//
-#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
-#include "common/debug.h"
+#include "common/MemoryBuffer.h"
#include <algorithm>
#include <cstdlib>
+#include "common/debug.h"
+
namespace rx
{
@@ -32,26 +33,31 @@ bool MemoryBuffer::resize(size_t size)
free(mData);
mData = NULL;
mSize = 0;
+ return true;
+ }
+
+ if (size == mSize)
+ {
+ return true;
}
- else
+
+ // Only reallocate if the size has changed.
+ uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
+ if (newMemory == NULL)
+ {
+ return false;
+ }
+
+ if (mData)
{
- uint8_t *newMemory = reinterpret_cast<uint8_t*>(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;
+ // 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;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h b/src/3rdparty/angle/src/common/MemoryBuffer.h
index c65f79fe10..ec621cbca7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/MemoryBuffer.h
+++ b/src/3rdparty/angle/src/common/MemoryBuffer.h
@@ -4,16 +4,18 @@
// found in the LICENSE file.
//
-#ifndef LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
-#define LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H_
+#ifndef COMMON_MEMORYBUFFER_H_
+#define COMMON_MEMORYBUFFER_H_
+
+#include "common/angleutils.h"
#include <cstddef>
-#include <cstdint>
+#include <stdint.h>
namespace rx
{
-class MemoryBuffer
+class MemoryBuffer : angle::NonCopyable
{
public:
MemoryBuffer();
@@ -33,4 +35,4 @@ class MemoryBuffer
}
-#endif // LIBGLESV2_RENDERER_D3D_MEMORYBUFFER_H
+#endif // COMMON_MEMORYBUFFER_H_
diff --git a/src/3rdparty/angle/src/common/Optional.h b/src/3rdparty/angle/src/common/Optional.h
new file mode 100644
index 0000000000..9665b7ddf6
--- /dev/null
+++ b/src/3rdparty/angle/src/common/Optional.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// Optional.h:
+// Represents a type that may be invalid, similar to std::optional.
+//
+
+#ifndef COMMON_OPTIONAL_H_
+#define COMMON_OPTIONAL_H_
+
+template <class T>
+struct Optional
+{
+ Optional()
+ : mValid(false),
+ mValue(T())
+ {}
+
+ explicit Optional(const T &valueIn)
+ : mValid(true),
+ mValue(valueIn)
+ {}
+
+ Optional(const Optional &other)
+ : mValid(other.mValid),
+ mValue(other.mValue)
+ {}
+
+ Optional &operator=(const Optional &other)
+ {
+ this->mValid = other.mValid;
+ this->mValue = other.mValue;
+ return *this;
+ }
+
+ static Optional None()
+ {
+ return Optional();
+ }
+
+ bool valid() const { return mValid; }
+ const T &value() const { return mValue; }
+
+ bool operator==(const Optional &other) const
+ {
+ return ((mValid == other.mValid) && (!mValid || (mValue == other.mValue)));
+ }
+
+ bool operator!=(const Optional &other) const
+ {
+ return !(*this == other);
+ }
+
+ private:
+ bool mValid;
+ T mValue;
+};
+
+#endif // COMMON_OPTIONAL_H_
diff --git a/src/3rdparty/angle/src/common/RefCountObject.h b/src/3rdparty/angle/src/common/RefCountObject.h
deleted file mode 100644
index 6eeaee1928..0000000000
--- a/src/3rdparty/angle/src/common/RefCountObject.h
+++ /dev/null
@@ -1,95 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RefCountObject.h: Defines the gl::RefCountObject base class that provides
-// lifecycle support for GL objects using the traditional BindObject scheme, but
-// that need to be reference counted for correct cross-context deletion.
-// (Concretely, textures, buffers and renderbuffers.)
-
-#ifndef COMMON_REFCOUNTOBJECT_H_
-#define COMMON_REFCOUNTOBJECT_H_
-
-#include "common/debug.h"
-
-#include "angle_gl.h"
-
-#include <cstddef>
-
-class RefCountObject
-{
- public:
- explicit RefCountObject(GLuint id);
- virtual ~RefCountObject();
-
- virtual void addRef() const;
- virtual void release() const;
-
- GLuint id() const { return mId; }
-
- private:
- GLuint mId;
-
- mutable std::size_t mRefCount;
-};
-
-class RefCountObjectBindingPointer
-{
- protected:
- RefCountObjectBindingPointer() : mObject(NULL) { }
- ~RefCountObjectBindingPointer() { ASSERT(mObject == NULL); } // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
-
- void set(RefCountObject *newObject);
- RefCountObject *get() const { return mObject; }
-
- public:
- GLuint id() const { return (mObject != NULL) ? mObject->id() : 0; }
- bool operator!() const { return (get() == NULL); }
-
- private:
- RefCountObject *mObject;
-};
-
-template <class ObjectType>
-class BindingPointer : public RefCountObjectBindingPointer
-{
- public:
- void set(ObjectType *newObject) { RefCountObjectBindingPointer::set(newObject); }
- ObjectType *get() const { return static_cast<ObjectType*>(RefCountObjectBindingPointer::get()); }
- ObjectType *operator->() const { return get(); }
-};
-
-template <class ObjectType>
-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<ObjectType*>(RefCountObjectBindingPointer::get()); }
- ObjectType *operator->() const { return get(); }
-
- private:
- GLintptr mOffset;
- GLsizeiptr mSize;
-};
-
-#endif // COMMON_REFCOUNTOBJECT_H_
diff --git a/src/3rdparty/angle/src/common/angleutils.cpp b/src/3rdparty/angle/src/common/angleutils.cpp
index c1367c460a..af5eb6c447 100644
--- a/src/3rdparty/angle/src/common/angleutils.cpp
+++ b/src/3rdparty/angle/src/common/angleutils.cpp
@@ -5,7 +5,8 @@
//
#include "common/angleutils.h"
-#include "debug.h"
+#include "common/debug.h"
+
#include <stdio.h>
#include <vector>
diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
index b343ece5bc..4cf84a3182 100644
--- a/src/3rdparty/angle/src/common/angleutils.h
+++ b/src/3rdparty/angle/src/common/angleutils.h
@@ -11,19 +11,31 @@
#include "common/platform.h"
-#include <stddef.h>
-#include <limits.h>
+#include <climits>
+#include <cstdarg>
+#include <cstddef>
#include <string>
#include <set>
#include <sstream>
-#include <cstdarg>
#include <vector>
-// A macro to disallow the copy constructor and operator= functions
-// This must be used in the private: declarations for a class
-#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
- TypeName(const TypeName&); \
- void operator=(const TypeName&)
+// A helper class to disallow copy and assignment operators
+namespace angle
+{
+
+class NonCopyable
+{
+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+ public:
+ NonCopyable() = default;
+ ~NonCopyable() = default;
+ protected:
+ NonCopyable(const NonCopyable&) = delete;
+ void operator=(const NonCopyable&) = delete;
+#endif
+};
+
+}
template <typename T, size_t N>
inline size_t ArraySize(T(&)[N])
@@ -150,13 +162,12 @@ std::string FormatString(const char *fmt, ...);
#define snprintf _snprintf
#endif
-#define VENDOR_ID_AMD 0x1002
-#define VENDOR_ID_INTEL 0x8086
-#define VENDOR_ID_NVIDIA 0x10DE
-
#define GL_BGRA4_ANGLEX 0x6ABC
#define GL_BGR5_A1_ANGLEX 0x6ABD
#define GL_INT_64_ANGLEX 0x6ABE
#define GL_STRUCT_ANGLEX 0x6ABF
+// Hidden enum for the NULL D3D device type.
+#define EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE 0x6AC0
+
#endif // COMMON_ANGLEUTILS_H_
diff --git a/src/3rdparty/angle/src/common/debug.cpp b/src/3rdparty/angle/src/common/debug.cpp
index 5f55ff1e39..2fc0a2984a 100644
--- a/src/3rdparty/angle/src/common/debug.cpp
+++ b/src/3rdparty/angle/src/common/debug.cpp
@@ -17,172 +17,9 @@
namespace gl
{
-#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
-// Wraps the D3D9/D3D11 debug annotation functions.
-class DebugAnnotationWrapper
-{
- public:
- DebugAnnotationWrapper() { };
- virtual ~DebugAnnotationWrapper() { };
- virtual void beginEvent(const std::wstring &eventName) = 0;
- virtual void endEvent() = 0;
- virtual void setMarker(const std::wstring &markerName) = 0;
- virtual bool getStatus() = 0;
-};
-#if defined(ANGLE_ENABLE_D3D9)
-class D3D9DebugAnnotationWrapper : public DebugAnnotationWrapper
+namespace
{
- public:
- void beginEvent(const std::wstring &eventName)
- {
- D3DPERF_BeginEvent(0, eventName.c_str());
- }
-
- void endEvent()
- {
- D3DPERF_EndEvent();
- }
-
- void setMarker(const std::wstring &markerName)
- {
- D3DPERF_SetMarker(0, markerName.c_str());
- }
-
- bool getStatus()
- {
- return !!D3DPERF_GetStatus();
- }
-};
-#endif // ANGLE_ENABLE_D3D9
-
-#if defined(ANGLE_ENABLE_D3D11)
-class D3D11DebugAnnotationWrapper : public DebugAnnotationWrapper
-{
- public:
-
- D3D11DebugAnnotationWrapper()
- : mInitialized(false),
- mD3d11Module(NULL),
- mUserDefinedAnnotation(NULL)
- {
- // D3D11 devices can't be created during DllMain.
- // We defer device creation until the object is actually used.
- }
-
- ~D3D11DebugAnnotationWrapper()
- {
- if (mInitialized)
- {
- SafeRelease(mUserDefinedAnnotation);
- FreeLibrary(mD3d11Module);
- }
- }
-
- virtual void beginEvent(const std::wstring &eventName)
- {
- initializeDevice();
-
- mUserDefinedAnnotation->BeginEvent(eventName.c_str());
- }
-
- virtual void endEvent()
- {
- initializeDevice();
-
- mUserDefinedAnnotation->EndEvent();
- }
-
- virtual void setMarker(const std::wstring &markerName)
- {
- initializeDevice();
-
- mUserDefinedAnnotation->SetMarker(markerName.c_str());
- }
-
- virtual bool getStatus()
- {
- // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
-
-#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
- // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
- // This should only be called in DEBUG mode.
- // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
- IDXGraphicsAnalysis* graphicsAnalysis;
- DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
- bool underCapture = (graphicsAnalysis != NULL);
- SafeRelease(graphicsAnalysis);
- return underCapture;
-#endif
-
- // Otherwise, we have to return true here.
- return true;
- }
-
- protected:
-
- void initializeDevice()
- {
- if (!mInitialized)
- {
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
- ASSERT(mD3d11Module);
-
- PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
- ASSERT(D3D11CreateDevice != NULL);
-#endif // !ANGLE_ENABLE_WINDOWS_STORE
-
- ID3D11Device* device = NULL;
- ID3D11DeviceContext* context = NULL;
-
- HRESULT hr = E_FAIL;
-
- // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
- hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, NULL, 0, NULL, 0, D3D11_SDK_VERSION, &device, NULL, &context);
- ASSERT(SUCCEEDED(hr));
-
- hr = context->QueryInterface(__uuidof(mUserDefinedAnnotation), reinterpret_cast<void**>(&mUserDefinedAnnotation));
- ASSERT(SUCCEEDED(hr) && mUserDefinedAnnotation != NULL);
-
- SafeRelease(device);
- SafeRelease(context);
-
- mInitialized = true;
- }
- }
-
- bool mInitialized;
- HMODULE mD3d11Module;
- ID3DUserDefinedAnnotation* mUserDefinedAnnotation;
-};
-#endif // ANGLE_ENABLE_D3D11
-
-static DebugAnnotationWrapper* g_DebugAnnotationWrapper = NULL;
-
-void InitializeDebugAnnotations()
-{
-#if defined(ANGLE_ENABLE_D3D9)
- g_DebugAnnotationWrapper = new D3D9DebugAnnotationWrapper();
-#elif defined(ANGLE_ENABLE_D3D11)
- // If the project uses D3D9 then we can use the D3D9 debug annotations, even with the D3D11 renderer.
- // However, if D3D9 is unavailable (e.g. in Windows Store), then we use D3D11 debug annotations.
- // The D3D11 debug annotations are methods on ID3DUserDefinedAnnotation, which is implemented by the DeviceContext.
- // This doesn't have to be the same DeviceContext that the renderer uses, though.
- g_DebugAnnotationWrapper = new D3D11DebugAnnotationWrapper();
-#endif
-}
-
-void UninitializeDebugAnnotations()
-{
- if (g_DebugAnnotationWrapper != NULL)
- {
- SafeDelete(g_DebugAnnotationWrapper);
- }
-}
-
-#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
-
enum DebugTraceOutputType
{
DebugTraceOutputTypeNone,
@@ -190,29 +27,44 @@ enum DebugTraceOutputType
DebugTraceOutputTypeBeginEvent
};
-static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const char *format, va_list vararg)
-{
-#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
- static std::vector<char> buffer(512);
+DebugAnnotator *g_debugAnnotator = nullptr;
- if (perfActive())
+void output(bool traceInDebugOnly, MessageType messageType, DebugTraceOutputType outputType,
+ const char *format, va_list vararg)
+{
+ if (DebugAnnotationsActive())
{
+ static std::vector<char> buffer(512);
size_t len = FormatStringIntoVector(format, vararg, buffer);
std::wstring formattedWideMessage(buffer.begin(), buffer.begin() + len);
+ ASSERT(g_debugAnnotator != nullptr);
switch (outputType)
{
- case DebugTraceOutputTypeNone:
- break;
- case DebugTraceOutputTypeBeginEvent:
- g_DebugAnnotationWrapper->beginEvent(formattedWideMessage);
- break;
- case DebugTraceOutputTypeSetMarker:
- g_DebugAnnotationWrapper->setMarker(formattedWideMessage);
- break;
+ case DebugTraceOutputTypeNone:
+ break;
+ case DebugTraceOutputTypeBeginEvent:
+ g_debugAnnotator->beginEvent(formattedWideMessage);
+ break;
+ case DebugTraceOutputTypeSetMarker:
+ g_debugAnnotator->setMarker(formattedWideMessage);
+ break;
}
}
-#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
+
+ std::string formattedMessage;
+ UNUSED_TRACE_VARIABLE(formattedMessage);
+
+#if !defined(NDEBUG) && defined(_MSC_VER)
+ if (messageType == MESSAGE_ERR)
+ {
+ if (formattedMessage.empty())
+ {
+ formattedMessage = FormatString(format, vararg);
+ }
+ OutputDebugStringA(formattedMessage.c_str());
+ }
+#endif
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
#if defined(NDEBUG)
@@ -221,7 +73,10 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
return;
}
#endif // NDEBUG
- std::string formattedMessage = FormatString(format, vararg);
+ if (formattedMessage.empty())
+ {
+ formattedMessage = FormatString(format, vararg);
+ }
static std::ofstream file(TRACE_OUTPUT_FILE, std::ofstream::app);
if (file)
@@ -237,53 +92,57 @@ static void output(bool traceInDebugOnly, DebugTraceOutputType outputType, const
#endif // ANGLE_ENABLE_DEBUG_TRACE
}
-void trace(bool traceInDebugOnly, const char *format, ...)
+} // namespace
+
+bool DebugAnnotationsActive()
{
- va_list vararg;
- va_start(vararg, format);
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
- output(traceInDebugOnly, DebugTraceOutputTypeSetMarker, format, vararg);
+ return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
#else
- output(traceInDebugOnly, DebugTraceOutputTypeNone, format, vararg);
+ return false;
#endif
- va_end(vararg);
}
-bool perfActive()
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator)
{
-#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
- static bool active = g_DebugAnnotationWrapper->getStatus();
- return active;
-#else
- return false;
-#endif
+ UninitializeDebugAnnotations();
+ g_debugAnnotator = debugAnnotator;
+}
+
+void UninitializeDebugAnnotations()
+{
+ // Pointer is not managed.
+ g_debugAnnotator = nullptr;
+}
+
+void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...)
+{
+ va_list vararg;
+ va_start(vararg, format);
+ output(traceInDebugOnly, messageType, DebugTraceOutputTypeSetMarker, format, vararg);
+ va_end(vararg);
}
ScopedPerfEventHelper::ScopedPerfEventHelper(const char* format, ...)
{
#if !defined(ANGLE_ENABLE_DEBUG_TRACE)
- if (!perfActive())
+ if (!DebugAnnotationsActive())
{
return;
}
#endif // !ANGLE_ENABLE_DEBUG_TRACE
va_list vararg;
va_start(vararg, format);
-#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
- output(true, DebugTraceOutputTypeBeginEvent, format, vararg);
-#else
- output(true, DebugTraceOutputTypeNone, format, vararg);
-#endif // ANGLE_ENABLE_DEBUG_ANNOTATIONS
+ output(true, MESSAGE_EVENT, DebugTraceOutputTypeBeginEvent, format, vararg);
va_end(vararg);
}
ScopedPerfEventHelper::~ScopedPerfEventHelper()
{
-#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
- if (perfActive())
+ if (DebugAnnotationsActive())
{
- g_DebugAnnotationWrapper->endEvent();
+ g_debugAnnotator->endEvent();
}
-#endif
}
+
}
diff --git a/src/3rdparty/angle/src/common/debug.h b/src/3rdparty/angle/src/common/debug.h
index c177f51314..c4f118ebae 100644
--- a/src/3rdparty/angle/src/common/debug.h
+++ b/src/3rdparty/angle/src/common/debug.h
@@ -9,8 +9,9 @@
#ifndef COMMON_DEBUG_H_
#define COMMON_DEBUG_H_
-#include <stdio.h>
#include <assert.h>
+#include <stdio.h>
+#include <string>
#include "common/angleutils.h"
@@ -20,50 +21,71 @@
namespace gl
{
- // Outputs text to the debugging log, or the debugging window
- void trace(bool traceInDebugOnly, const char *format, ...);
- // Returns whether D3DPERF is active.
- bool perfActive();
+enum MessageType
+{
+ MESSAGE_TRACE,
+ MESSAGE_FIXME,
+ MESSAGE_ERR,
+ MESSAGE_EVENT,
+};
- // Pairs a D3D begin event with an end event.
- class ScopedPerfEventHelper
- {
- public:
- ScopedPerfEventHelper(const char* format, ...);
- ~ScopedPerfEventHelper();
+// Outputs text to the debugging log, or the debugging window
+void trace(bool traceInDebugOnly, MessageType messageType, const char *format, ...);
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedPerfEventHelper);
- };
+// Pairs a D3D begin event with an end event.
+class ScopedPerfEventHelper : angle::NonCopyable
+{
+ public:
+ ScopedPerfEventHelper(const char* format, ...);
+ ~ScopedPerfEventHelper();
+};
+
+// Wraps the D3D9/D3D11 debug annotation functions.
+class DebugAnnotator : angle::NonCopyable
+{
+ public:
+ DebugAnnotator() { };
+ virtual ~DebugAnnotator() { };
+ virtual void beginEvent(const std::wstring &eventName) = 0;
+ virtual void endEvent() = 0;
+ virtual void setMarker(const std::wstring &markerName) = 0;
+ virtual bool getStatus() = 0;
+};
+
+void InitializeDebugAnnotations(DebugAnnotator *debugAnnotator);
+void UninitializeDebugAnnotations();
+bool DebugAnnotationsActive();
- void InitializeDebugAnnotations();
- void UninitializeDebugAnnotations();
}
-// A macro to output a trace of a function call and its arguments to the debugging log
#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
-#define TRACE(message, ...) gl::trace(true, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#define ANGLE_TRACE_ENABLED
+#endif
+
+// A macro to output a trace of a function call and its arguments to the debugging log
+#if defined(ANGLE_TRACE_ENABLED)
+#define TRACE(message, ...) gl::trace(true, gl::MESSAGE_TRACE, "trace: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define TRACE(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, to denote an item in need of fixing.
-#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
-#define FIXME(message, ...) gl::trace(false, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#if defined(ANGLE_TRACE_ENABLED)
+#define FIXME(message, ...) gl::trace(false, gl::MESSAGE_FIXME, "fixme: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define FIXME(message, ...) (void(0))
#endif
// A macro to output a function call and its arguments to the debugging log, in case of error.
-#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
-#define ERR(message, ...) gl::trace(false, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
+#if defined(ANGLE_TRACE_ENABLED)
+#define ERR(message, ...) gl::trace(false, gl::MESSAGE_ERR, "err: %s(%d): " message "\n", __FUNCTION__, __LINE__, ##__VA_ARGS__)
#else
#define ERR(message, ...) (void(0))
#endif
// A macro to log a performance event around a scope.
-#if defined(ANGLE_ENABLE_DEBUG_TRACE) || defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
+#if defined(ANGLE_TRACE_ENABLED)
#if defined(_MSC_VER)
#define EVENT(message, ...) gl::ScopedPerfEventHelper scopedPerfEventHelper ## __LINE__("%s" message "\n", __FUNCTION__, __VA_ARGS__);
#else
@@ -73,6 +95,10 @@ namespace gl
#define EVENT(message, ...) (void(0))
#endif
+#if defined(ANGLE_TRACE_ENABLED)
+#undef ANGLE_TRACE_ENABLED
+#endif
+
// A macro asserting a condition and outputting failures to the debug log
#if !defined(NDEBUG)
#define ASSERT(expression) do { \
@@ -130,14 +156,4 @@ namespace gl
#define HAS_DYNAMIC_TYPE(type, obj) true
#endif
-// A macro functioning as a compile-time assert to validate constant conditions
-#if (defined(_MSC_VER) && _MSC_VER >= 1600) || (defined(__GNUC__) && (__GNUC__ > 4 || __GNUC_MINOR__ >= 3))
-#define META_ASSERT_MSG(condition, msg) static_assert(condition, msg)
-#else
-#define META_ASSERT_CONCAT(a, b) a ## b
-#define META_ASSERT_CONCAT2(a, b) META_ASSERT_CONCAT(a, b)
-#define META_ASSERT_MSG(condition, msg) typedef int META_ASSERT_CONCAT2(COMPILE_TIME_ASSERT_, __LINE__)[static_cast<bool>(condition)?1:-1]
-#endif
-#define META_ASSERT(condition) META_ASSERT_MSG(condition, "compile time assertion failed.")
-
#endif // COMMON_DEBUG_H_
diff --git a/src/3rdparty/angle/src/common/event_tracer.cpp b/src/3rdparty/angle/src/common/event_tracer.cpp
new file mode 100644
index 0000000000..eb0c98c9e5
--- /dev/null
+++ b/src/3rdparty/angle/src/common/event_tracer.cpp
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "common/event_tracer.h"
+
+namespace gl
+{
+
+GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
+AddTraceEventFunc g_addTraceEvent;
+
+} // namespace gl
+
+namespace gl
+{
+
+const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name)
+{
+ if (g_getCategoryEnabledFlag)
+ {
+ return g_getCategoryEnabledFlag(name);
+ }
+ static unsigned char disabled = 0;
+ return &disabled;
+}
+
+void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
+ int numArgs, const char** argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues, unsigned char flags)
+{
+ if (g_addTraceEvent)
+ {
+ g_addTraceEvent(phase, categoryGroupEnabled, name, id, numArgs, argNames, argTypes, argValues, flags);
+ }
+}
+
+} // namespace gl
diff --git a/src/3rdparty/angle/src/common/event_tracer.h b/src/3rdparty/angle/src/common/event_tracer.h
new file mode 100644
index 0000000000..dbe4c1bef9
--- /dev/null
+++ b/src/3rdparty/angle/src/common/event_tracer.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef COMMON_EVENT_TRACER_H_
+#define COMMON_EVENT_TRACER_H_
+
+#include "common/platform.h"
+
+extern "C" {
+
+typedef const unsigned char* (*GetCategoryEnabledFlagFunc)(const char* name);
+typedef void (*AddTraceEventFunc)(char phase, const unsigned char* categoryGroupEnabled, const char* name,
+ unsigned long long id, int numArgs, const char** argNames,
+ const unsigned char* argTypes, const unsigned long long* argValues,
+ unsigned char flags);
+
+}
+
+namespace gl
+{
+
+extern GetCategoryEnabledFlagFunc g_getCategoryEnabledFlag;
+extern AddTraceEventFunc g_addTraceEvent;
+
+const unsigned char* TraceGetTraceCategoryEnabledFlag(const char* name);
+
+void TraceAddTraceEvent(char phase, const unsigned char* categoryGroupEnabled, const char* name, unsigned long long id,
+ int numArgs, const char** argNames, const unsigned char* argTypes,
+ const unsigned long long* argValues, unsigned char flags);
+
+}
+
+#endif // COMMON_EVENT_TRACER_H_
diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
index a1717892fd..1015bd2312 100644
--- a/src/3rdparty/angle/src/common/mathutil.h
+++ b/src/3rdparty/angle/src/common/mathutil.h
@@ -6,8 +6,8 @@
// mathutil.h: Math and bit manipulation functions.
-#ifndef LIBGLESV2_MATHUTIL_H_
-#define LIBGLESV2_MATHUTIL_H_
+#ifndef COMMON_MATHUTIL_H_
+#define COMMON_MATHUTIL_H_
#include "common/debug.h"
#include "common/platform.h"
@@ -15,6 +15,7 @@
#include <limits>
#include <algorithm>
#include <string.h>
+#include <stdlib.h>
namespace gl
{
@@ -118,6 +119,9 @@ inline bool supportsSSE2()
return supports;
}
+#if defined(__GNUC__)
+ supports = __builtin_cpu_supports("sse2");
+#else
int info[4];
__cpuid(info, 0);
@@ -127,6 +131,7 @@ inline bool supportsSSE2()
supports = (info[3] >> 26) & 1;
}
+#endif
checked = true;
@@ -353,7 +358,7 @@ inline float float11ToFloat32(unsigned short fp11)
}
else // The value is zero
{
- exponent = -112;
+ exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 17));
@@ -392,7 +397,7 @@ inline float float10ToFloat32(unsigned short fp11)
}
else // The value is zero
{
- exponent = -112;
+ exponent = static_cast<unsigned short>(-112);
}
return bitCast<float>(((exponent + 112) << 23) | (mantissa << 18));
@@ -402,7 +407,7 @@ inline float float10ToFloat32(unsigned short fp11)
template <typename T>
inline float normalizedToFloat(T input)
{
- META_ASSERT(std::numeric_limits<T>::is_integer);
+ static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
const float inverseMax = 1.0f / std::numeric_limits<T>::max();
return input * inverseMax;
@@ -411,8 +416,8 @@ inline float normalizedToFloat(T input)
template <unsigned int inputBitCount, typename T>
inline float normalizedToFloat(T input)
{
- META_ASSERT(std::numeric_limits<T>::is_integer);
- META_ASSERT(inputBitCount < (sizeof(T) * 8));
+ static_assert(std::numeric_limits<T>::is_integer, "T must be an integer.");
+ static_assert(inputBitCount < (sizeof(T) * 8), "T must have more bits than inputBitCount.");
const float inverseMax = 1.0f / ((1 << inputBitCount) - 1);
return input * inverseMax;
@@ -427,14 +432,15 @@ inline T floatToNormalized(float input)
template <unsigned int outputBitCount, typename T>
inline T floatToNormalized(float input)
{
- META_ASSERT(outputBitCount < (sizeof(T) * 8));
+ static_assert(outputBitCount < (sizeof(T) * 8), "T must have more bits than outputBitCount.");
return ((1 << outputBitCount) - 1) * input + 0.5f;
}
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T getShiftedData(T input)
{
- META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
+ static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+ "T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input >> inputBitStart) & mask;
}
@@ -442,7 +448,8 @@ inline T getShiftedData(T input)
template <unsigned int inputBitCount, unsigned int inputBitStart, typename T>
inline T shiftData(T input)
{
- META_ASSERT(inputBitCount + inputBitStart <= (sizeof(T) * 8));
+ static_assert(inputBitCount + inputBitStart <= (sizeof(T) * 8),
+ "T must have at least as many bits as inputBitCount + inputBitStart.");
const T mask = (1 << inputBitCount) - 1;
return (input & mask) << inputBitStart;
}
@@ -503,6 +510,7 @@ inline unsigned int averageFloat10(unsigned int a, unsigned int b)
namespace rx
{
+// Represents intervals of the type [a, b)
template <typename T>
struct Range
{
@@ -513,6 +521,18 @@ struct Range
T end;
T length() const { return end - start; }
+
+ bool intersects(Range<T> other)
+ {
+ if (start <= other.start)
+ {
+ return other.start < end;
+ }
+ else
+ {
+ return start < other.end;
+ }
+ }
};
typedef Range<int> RangeI;
@@ -533,14 +553,14 @@ inline unsigned int UnsignedCeilDivide(unsigned int value, unsigned int divisor)
template <class T>
inline bool IsUnsignedAdditionSafe(T lhs, T rhs)
{
- META_ASSERT(!std::numeric_limits<T>::is_signed);
+ static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (rhs <= std::numeric_limits<T>::max() - lhs);
}
template <class T>
inline bool IsUnsignedMultiplicationSafe(T lhs, T rhs)
{
- META_ASSERT(!std::numeric_limits<T>::is_signed);
+ static_assert(!std::numeric_limits<T>::is_signed, "T must be unsigned.");
return (lhs == T(0) || rhs == T(0) || (rhs <= std::numeric_limits<T>::max() / lhs));
}
@@ -550,6 +570,21 @@ inline bool IsIntegerCastSafe(BigIntT bigValue)
return (static_cast<BigIntT>(static_cast<SmallIntT>(bigValue)) == bigValue);
}
+#if defined(_MSC_VER)
+
+#define ANGLE_ROTL(x,y) _rotl(x,y)
+
+#else
+
+inline uint32_t RotL(uint32_t x, int8_t r)
+{
+ return (x << r) | (x >> (32 - r));
+}
+
+#define ANGLE_ROTL(x,y) RotL(x,y)
+
+#endif // namespace rx
+
}
-#endif // LIBGLESV2_MATHUTIL_H_
+#endif // COMMON_MATHUTIL_H_
diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
index 5bf97f9184..3a2aa91bed 100644
--- a/src/3rdparty/angle/src/common/platform.h
+++ b/src/3rdparty/angle/src/common/platform.h
@@ -14,12 +14,12 @@
#elif defined(__APPLE__)
# define ANGLE_PLATFORM_APPLE 1
# define ANGLE_PLATFORM_POSIX 1
-#elif defined(__linux__)
-# define ANGLE_PLATFORM_LINUX 1
-# define ANGLE_PLATFORM_POSIX 1
#elif defined(ANDROID)
# define ANGLE_PLATFORM_ANDROID 1
# define ANGLE_PLATFORM_POSIX 1
+#elif defined(__linux__) || defined(EMSCRIPTEN)
+# define ANGLE_PLATFORM_LINUX 1
+# define ANGLE_PLATFORM_POSIX 1
#elif defined(__FreeBSD__) || \
defined(__OpenBSD__) || \
defined(__NetBSD__) || \
@@ -34,9 +34,6 @@
#endif
#ifdef ANGLE_PLATFORM_WINDOWS
-# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-# define ANGLE_ENABLE_WINDOWS_STORE 1
-# endif
# ifndef STRICT
# define STRICT 1
# endif
@@ -50,24 +47,32 @@
# include <windows.h>
# include <intrin.h>
+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
+# define ANGLE_ENABLE_WINDOWS_STORE 1
+# endif
+
# if defined(ANGLE_ENABLE_D3D9)
# include <d3d9.h>
-# include <dxgi.h>
-# if !defined(COMPILER_IMPLEMENTATION)
+# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
# if defined(ANGLE_ENABLE_D3D11)
# include <d3d10_1.h>
-# include <d3d10.h>
# include <d3d11.h>
# include <dxgi.h>
-# if defined(_MSC_VER) && (_MSC_VER >= 1700)
+# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
+# define ANGLE_MINGW32_COMPAT
+# endif
+# if defined(_MSC_VER) && _MSC_VER >= 1800
+# define ANGLE_ENABLE_D3D11_1
+# endif
+# if defined(ANGLE_ENABLE_D3D11_1)
# include <d3d11_1.h>
# include <dxgi1_2.h>
# endif
-# if !defined(COMPILER_IMPLEMENTATION)
+# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
# include <d3dcompiler.h>
# endif
# endif
@@ -75,88 +80,24 @@
# if defined(ANGLE_ENABLE_WINDOWS_STORE)
# include <dxgi1_3.h>
# if defined(_DEBUG)
-# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
# include <DXProgrammableCapture.h>
# endif
# include <dxgidebug.h>
# endif
# endif
-# if defined(__MINGW32__) // Missing defines on MinGW
-typedef enum D3D11_MAP_FLAG
-{
- D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
-} D3D11_MAP_FLAG;
-typedef struct D3D11_QUERY_DATA_SO_STATISTICS
-{
- UINT64 NumPrimitivesWritten;
- UINT64 PrimitivesStorageNeeded;
-} D3D11_QUERY_DATA_SO_STATISTICS;
-typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
- IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
- UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
-#define D3D11_MESSAGE_CATEGORY UINT
-#define D3D11_MESSAGE_SEVERITY UINT
-#define D3D11_MESSAGE_ID UINT
-struct D3D11_MESSAGE;
-typedef struct D3D11_INFO_QUEUE_FILTER_DESC
-{
- UINT NumCategories;
- D3D11_MESSAGE_CATEGORY *pCategoryList;
- UINT NumSeverities;
- D3D11_MESSAGE_SEVERITY *pSeverityList;
- UINT NumIDs;
- D3D11_MESSAGE_ID *pIDList;
-} D3D11_INFO_QUEUE_FILTER_DESC;
-typedef struct D3D11_INFO_QUEUE_FILTER
-{
- D3D11_INFO_QUEUE_FILTER_DESC AllowList;
- D3D11_INFO_QUEUE_FILTER_DESC DenyList;
-} D3D11_INFO_QUEUE_FILTER;
-static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
-MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
-{
-public:
- virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
- virtual void __stdcall ClearStoredMessages() = 0;
- virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
- virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
- virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
- virtual UINT64 __stdcall GetNumStoredMessages() = 0;
- virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
- virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
- virtual UINT64 __stdcall GetMessageCountLimit() = 0;
- virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
- virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
- virtual void __stdcall ClearStorageFilter() = 0;
- virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
- virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
- virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
- virtual void __stdcall PopStorageFilter() = 0;
- virtual UINT __stdcall GetStorageFilterStackSize() = 0;
- virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
- virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
- virtual void __stdcall ClearRetrievalFilter() = 0;
- virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
- virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
- virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
- virtual void __stdcall PopRetrievalFilter() = 0;
- virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
- virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
- virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
- virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
- virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
- virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
- virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
- virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
- virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
- virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
- virtual BOOL __stdcall GetMuteDebugOutput() = 0;
-};
-#endif // __MINGW32__
+# if defined(_MSC_VER) && (_MSC_VER <= 1600)
+# define final
+# define override
+# endif
# undef near
# undef far
#endif
+#if !defined(_M_ARM) && !defined(ANGLE_PLATFORM_ANDROID)
+# define ANGLE_USE_SSE
+#endif
+
#endif // COMMON_PLATFORM_H_
diff --git a/src/3rdparty/angle/src/common/tls.h b/src/3rdparty/angle/src/common/tls.h
index 8a06e92d1a..ca9e07ab70 100644
--- a/src/3rdparty/angle/src/common/tls.h
+++ b/src/3rdparty/angle/src/common/tls.h
@@ -15,7 +15,9 @@
// TLS does not exist for Windows Store and needs to be emulated
# ifdef ANGLE_ENABLE_WINDOWS_STORE
-# define TLS_OUT_OF_INDEXES -1
+# ifndef TLS_OUT_OF_INDEXES
+# define TLS_OUT_OF_INDEXES static_cast<DWORD>(0xFFFFFFFF)
+# endif
# ifndef CREATE_SUSPENDED
# define CREATE_SUSPENDED 0x00000004
# endif
diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp
index 0eae42cac2..501e9c2564 100644
--- a/src/3rdparty/angle/src/common/utilities.cpp
+++ b/src/3rdparty/angle/src/common/utilities.cpp
@@ -254,7 +254,7 @@ int VariableColumnCount(GLenum type)
return 0;
}
-bool IsSampler(GLenum type)
+bool IsSamplerType(GLenum type)
{
switch (type)
{
@@ -343,9 +343,27 @@ int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsig
return -1;
}
-bool IsCubemapTextureTarget(GLenum target)
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4, "Unexpected GL cube map enum value.");
+static_assert(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5, "Unexpected GL cube map enum value.");
+
+bool IsCubeMapTextureTarget(GLenum target)
+{
+ return (target >= FirstCubeMapTextureTarget && target <= LastCubeMapTextureTarget);
+}
+
+size_t CubeMapTextureTargetToLayerIndex(GLenum target)
{
- return (target >= GL_TEXTURE_CUBE_MAP_POSITIVE_X && target <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z);
+ ASSERT(IsCubeMapTextureTarget(target));
+ return target - static_cast<size_t>(FirstCubeMapTextureTarget);
+}
+
+GLenum LayerIndexToCubeMapTextureTarget(size_t index)
+{
+ ASSERT(index <= (LastCubeMapTextureTarget - FirstCubeMapTextureTarget));
+ return FirstCubeMapTextureTarget + static_cast<GLenum>(index);
}
bool IsTriangleMode(GLenum drawMode)
@@ -486,10 +504,15 @@ void writeFile(const char* path, const void* content, size_t size)
}
#endif // !ANGLE_ENABLE_WINDOWS_STORE
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
+#if defined (ANGLE_PLATFORM_WINDOWS)
-void Sleep(unsigned long dwMilliseconds)
+// Causes the thread to relinquish the remainder of its time slice to any
+// other thread that is ready to run.If there are no other threads ready
+// to run, the function returns immediately, and the thread continues execution.
+void ScheduleYield()
{
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
+ // This implementation of Sleep exists because it is not available prior to Update 4.
static HANDLE singletonEvent = nullptr;
HANDLE sleepEvent = singletonEvent;
if (!sleepEvent)
@@ -510,7 +533,10 @@ void Sleep(unsigned long dwMilliseconds)
}
// Emulate sleep by waiting with timeout on an event that is never signalled.
- WaitForSingleObjectEx(sleepEvent, dwMilliseconds, false);
+ WaitForSingleObjectEx(sleepEvent, 0, false);
+#else
+ Sleep(0);
+#endif
}
-#endif // ANGLE_ENABLE_WINDOWS_STORE
+#endif
diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h
index 7583d3e160..9f7f5e03c0 100644
--- a/src/3rdparty/angle/src/common/utilities.h
+++ b/src/3rdparty/angle/src/common/utilities.h
@@ -6,8 +6,8 @@
// utilities.h: Conversion functions and other utility routines.
-#ifndef LIBGLESV2_UTILITIES_H
-#define LIBGLESV2_UTILITIES_H
+#ifndef COMMON_UTILITIES_H_
+#define COMMON_UTILITIES_H_
#include "angle_gl.h"
#include <string>
@@ -24,7 +24,7 @@ size_t VariableExternalSize(GLenum type);
GLenum VariableBoolVectorType(GLenum type);
int VariableRowCount(GLenum type);
int VariableColumnCount(GLenum type);
-bool IsSampler(GLenum type);
+bool IsSamplerType(GLenum type);
bool IsMatrixType(GLenum type);
GLenum TransposeMatrixType(GLenum type);
int VariableRegisterCount(GLenum type);
@@ -34,7 +34,11 @@ int VariableSortOrder(GLenum type);
int AllocateFirstFreeBits(unsigned int *bits, unsigned int allocationSize, unsigned int bitsSize);
-bool IsCubemapTextureTarget(GLenum target);
+static const GLenum FirstCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_POSITIVE_X;
+static const GLenum LastCubeMapTextureTarget = GL_TEXTURE_CUBE_MAP_NEGATIVE_Z;
+bool IsCubeMapTextureTarget(GLenum target);
+size_t CubeMapTextureTargetToLayerIndex(GLenum target);
+GLenum LayerIndexToCubeMapTextureTarget(size_t index);
bool IsTriangleMode(GLenum drawMode);
@@ -51,8 +55,8 @@ std::string getTempPath();
void writeFile(const char* path, const void* data, size_t size);
#endif
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
-void Sleep(_In_ unsigned long dwMilliseconds);
+#if defined (ANGLE_PLATFORM_WINDOWS)
+void ScheduleYield();
#endif
-#endif // LIBGLESV2_UTILITIES_H
+#endif // COMMON_UTILITIES_H_
diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h
index f01e0242cb..758c78d44a 100644
--- a/src/3rdparty/angle/src/common/version.h
+++ b/src/3rdparty/angle/src/common/version.h
@@ -1,4 +1,13 @@
-#include "../commit.h"
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMMON_VERSION_H_
+#define COMMON_VERSION_H_
+
+#include "id/commit.h"
#define ANGLE_MAJOR_VERSION 2
#define ANGLE_MINOR_VERSION 1
@@ -10,3 +19,5 @@
ANGLE_MACRO_STRINGIFY(ANGLE_MAJOR_VERSION) "." \
ANGLE_MACRO_STRINGIFY(ANGLE_MINOR_VERSION) "." \
ANGLE_COMMIT_HASH
+
+#endif // COMMON_VERSION_H_
diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
deleted file mode 100644
index 1c5512417d..0000000000
--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
-
-#ifndef COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
-#define COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
-
-#include "common/winrt/InspectableNativeWindow.h"
-#include <memory>
-#include <windows.graphics.display.h>
-
-namespace rx
-{
-
-class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
-{
- public:
- ~CoreWindowNativeWindow();
-
- bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
- bool registerForSizeChangeEvents();
- void unregisterForSizeChangeEvents();
- HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
-
- private:
- HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
-
- ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
- ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
- ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
-};
-
-}
-
-#endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
index a7587ed657..5922d03857 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DiagnosticsBase.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
-#define COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+#ifndef COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
+#define COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
#include <string>
@@ -84,4 +84,5 @@ class Diagnostics
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_DIAGNOSTICS_H_
+
+#endif // COMPILER_PREPROCESSOR_DIAGNOSTICSBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
index eec0d5e5f0..cf67895764 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveHandlerBase.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
-#define COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
#include <string>
@@ -41,4 +41,5 @@ class DirectiveHandler
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_DIRECTIVE_HANDLER_H_
+
+#endif // COMPILER_PREPROCESSOR_DIRECTIVEHANDLERBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
index 335091781c..e1acdbb8d0 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/DirectiveParser.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
-#define COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+#ifndef COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
+#define COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
#include "Lexer.h"
#include "Macro.h"
@@ -78,5 +78,5 @@ class DirectiveParser : public Lexer
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_DIRECTIVE_PARSER_H_
+#endif // COMPILER_PREPROCESSOR_DIRECTIVEPARSER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
index f040cb01fa..4b80ba7261 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
-#define COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+#ifndef COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
+#define COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
#include "pp_utils.h"
@@ -31,4 +31,5 @@ class ExpressionParser
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_EXPRESSION_PARSER_H_
+
+#endif // COMPILER_PREPROCESSOR_EXPRESSIONPARSER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
index 662a31b650..8caf36bfc8 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
+++ b/src/3rdparty/angle/src/compiler/preprocessor/ExpressionParser.y
@@ -28,7 +28,7 @@ WHICH GENERATES THE GLSL ES preprocessor expression parser.
#pragma GCC diagnostic ignored "-Wuninitialized"
#endif
#elif defined(_MSC_VER)
-#pragma warning(disable: 4065 4701)
+#pragma warning(disable: 4065 4701 4702)
#endif
#include "ExpressionParser.h"
@@ -69,7 +69,7 @@ struct Context
%}
%pure-parser
-%name-prefix="pp"
+%name-prefix "pp"
%parse-param {Context *context}
%lex-param {Context *context}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Input.h b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
index 2ac4f0c170..e951cb4d5f 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Input.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Input.h
@@ -58,5 +58,5 @@ class Input
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_INPUT_H_
+#endif // COMPILER_PREPROCESSOR_INPUT_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
index d42d3db7e0..990dc5e21d 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Lexer.h
@@ -21,5 +21,5 @@ class Lexer
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_LEXER_H_
+#endif // COMPILER_PREPROCESSOR_LEXER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
index b77e7bc15c..7662a9c5a2 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Macro.h
@@ -46,4 +46,5 @@ struct Macro
typedef std::map<std::string, Macro> MacroSet;
} // namespace pp
+
#endif // COMPILER_PREPROCESSOR_MACRO_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
index d4fd091786..5a0c7751a8 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/MacroExpander.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
-#define COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+#ifndef COMPILER_PREPROCESSOR_MACROEXPANDER_H_
+#define COMPILER_PREPROCESSOR_MACROEXPANDER_H_
#include <cassert>
#include <memory>
@@ -85,5 +85,5 @@ class MacroExpander : public Lexer
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_MACRO_EXPANDER_H_
+#endif // COMPILER_PREPROCESSOR_MACROEXPANDER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
index 0a55f1c9c1..fe25daa123 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Preprocessor.h
@@ -50,5 +50,5 @@ class Preprocessor
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
+#endif // COMPILER_PREPROCESSOR_PREPROCESSOR_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
index d4c1a5e178..af8a8d5d19 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/SourceLocation.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
-#define COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+#ifndef COMPILER_PREPROCESSOR_SOURCELOCATION_H_
+#define COMPILER_PREPROCESSOR_SOURCELOCATION_H_
namespace pp
{
@@ -43,4 +43,5 @@ inline bool operator!=(const SourceLocation &lhs, const SourceLocation &rhs)
}
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_SOURCE_LOCATION_H_
+
+#endif // COMPILER_PREPROCESSOR_SOURCELOCATION_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Token.h b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
index 8832e279c7..347c47e307 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Token.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Token.h
@@ -116,4 +116,5 @@ inline bool operator!=(const Token &lhs, const Token &rhs)
extern std::ostream &operator<<(std::ostream &out, const Token &token);
} // namepsace pp
+
#endif // COMPILER_PREPROCESSOR_TOKEN_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
index 07ad93da05..78eb86dd3b 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.h
@@ -55,5 +55,5 @@ class Tokenizer : public Lexer
};
} // namespace pp
-#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_
+#endif // COMPILER_PREPROCESSOR_TOKENIZER_H_
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
index 2a77b905a4..89cb5c8596 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
+++ b/src/3rdparty/angle/src/compiler/preprocessor/Tokenizer.l
@@ -267,7 +267,9 @@ FRACTIONAL_CONSTANT ({DIGIT}*"."{DIGIT}+)|({DIGIT}+".")
namespace pp {
-Tokenizer::Tokenizer(Diagnostics *diagnostics) : mHandle(0)
+Tokenizer::Tokenizer(Diagnostics *diagnostics)
+ : mHandle(0),
+ mMaxTokenSize(256)
{
mContext.diagnostics = diagnostics;
}
diff --git a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
index 8a24540696..58c51b0961 100644
--- a/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
+++ b/src/3rdparty/angle/src/compiler/preprocessor/numeric_lex.h
@@ -6,8 +6,8 @@
// numeric_lex.h: Functions to extract numeric values from string.
-#ifndef COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
-#define COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+#ifndef COMPILER_PREPROCESSOR_NUMERICLEX_H_
+#define COMPILER_PREPROCESSOR_NUMERICLEX_H_
#include <sstream>
@@ -58,4 +58,5 @@ bool numeric_lex_float(const std::string &str, FloatType *value)
}
} // namespace pp.
-#endif // COMPILER_PREPROCESSOR_NUMERIC_LEX_H_
+
+#endif // COMPILER_PREPROCESSOR_NUMERICLEX_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
index 324b0669f4..ee1428b2d3 100644
--- a/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
+++ b/src/3rdparty/angle/src/compiler/translator/BaseTypes.h
@@ -4,10 +4,10 @@
// found in the LICENSE file.
//
-#ifndef _BASICTYPES_INCLUDED_
-#define _BASICTYPES_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_BASETYPES_H_
+#define COMPILER_TRANSLATOR_BASETYPES_H_
-#include <assert.h>
+#include "compiler/translator/compilerdebug.h"
//
// Precision qualifiers
@@ -42,7 +42,15 @@ enum TBasicType
EbtInt,
EbtUInt,
EbtBool,
- EbtGVec4, // non type: represents vec4, ivec4 and uvec4
+ EbtGVec4, // non type: represents vec4, ivec4, and uvec4
+ EbtGenType, // non type: represents float, vec2, vec3, and vec4
+ EbtGenIType, // non type: represents int, ivec2, ivec3, and ivec4
+ EbtGenUType, // non type: represents uint, uvec2, uvec3, and uvec4
+ EbtGenBType, // non type: represents bool, bvec2, bvec3, and bvec4
+ EbtVec, // non type: represents vec2, vec3, and vec4
+ EbtIVec, // non type: represents ivec2, ivec3, and ivec4
+ EbtUVec, // non type: represents uvec2, uvec3, and uvec4
+ EbtBVec, // non type: represents bvec2, bvec3, and bvec4
EbtGuardSamplerBegin, // non type: see implementation of IsSampler()
EbtSampler2D,
EbtSampler3D,
@@ -62,10 +70,10 @@ enum TBasicType
EbtSamplerCubeShadow,
EbtSampler2DArrayShadow,
EbtGuardSamplerEnd, // non type: see implementation of IsSampler()
- EbtGSampler2D, // non type: represents sampler2D, isampler2D and usampler2D
- EbtGSampler3D, // non type: represents sampler3D, isampler3D and usampler3D
- EbtGSamplerCube, // non type: represents samplerCube, isamplerCube and usamplerCube
- EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray and usampler2DArray
+ EbtGSampler2D, // non type: represents sampler2D, isampler2D, and usampler2D
+ EbtGSampler3D, // non type: represents sampler3D, isampler3D, and usampler3D
+ EbtGSamplerCube, // non type: represents samplerCube, isamplerCube, and usamplerCube
+ EbtGSampler2DArray, // non type: represents sampler2DArray, isampler2DArray, and usampler2DArray
EbtStruct,
EbtInterfaceBlock,
EbtAddress, // should be deprecated??
@@ -258,6 +266,11 @@ inline bool IsShadowSampler(TBasicType type)
return false;
}
+inline bool IsInteger(TBasicType type)
+{
+ return type == EbtInt || type == EbtUInt;
+}
+
inline bool SupportsPrecision(TBasicType type)
{
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
@@ -293,6 +306,9 @@ enum TQualifier
EvqInOut,
EvqConstReadOnly,
+ // built-ins read by vertex shader
+ EvqInstanceID,
+
// built-ins written by vertex shader
EvqPosition,
EvqPointSize,
@@ -307,6 +323,10 @@ enum TQualifier
EvqFragData,
EvqFragDepth,
+ // built-ins written by the shader_framebuffer_fetch extension(s)
+ EvqLastFragColor,
+ EvqLastFragData,
+
// GLSL ES 3.0 vertex output and fragment input
EvqSmooth, // Incomplete qualifier, smooth is the default
EvqFlat, // Incomplete qualifier
@@ -383,6 +403,7 @@ inline const char* getQualifierString(TQualifier q)
case EvqIn: return "in"; break;
case EvqOut: return "out"; break;
case EvqInOut: return "inout"; break;
+ case EvqInstanceID: return "InstanceID"; break;
case EvqPosition: return "Position"; break;
case EvqPointSize: return "PointSize"; break;
case EvqFragCoord: return "FragCoord"; break;
@@ -396,7 +417,9 @@ inline const char* getQualifierString(TQualifier q)
case EvqSmoothIn: return "smooth in"; break;
case EvqCentroidIn: return "centroid in"; break;
case EvqFlatIn: return "flat in"; break;
- default: return "unknown qualifier";
+ case EvqLastFragColor: return "LastFragColor"; break;
+ case EvqLastFragData: return "LastFragData"; break;
+ default: UNREACHABLE(); return "unknown qualifier";
}
}
@@ -407,7 +430,7 @@ inline const char* getMatrixPackingString(TLayoutMatrixPacking mpq)
case EmpUnspecified: return "mp_unspecified";
case EmpRowMajor: return "row_major";
case EmpColumnMajor: return "column_major";
- default: return "unknown matrix packing";
+ default: UNREACHABLE(); return "unknown matrix packing";
}
}
@@ -419,7 +442,7 @@ inline const char* getBlockStorageString(TLayoutBlockStorage bsq)
case EbsShared: return "shared";
case EbsPacked: return "packed";
case EbsStd140: return "std140";
- default: return "unknown block storage";
+ default: UNREACHABLE(); return "unknown block storage";
}
}
@@ -433,8 +456,8 @@ inline const char* getInterpolationString(TQualifier q)
case EvqSmoothIn: return "smooth"; break;
case EvqCentroidIn: return "centroid"; break;
case EvqFlatIn: return "flat"; break;
- default: return "unknown interpolation";
+ default: UNREACHABLE(); return "unknown interpolation";
}
}
-#endif // _BASICTYPES_INCLUDED_
+#endif // COMPILER_TRANSLATOR_BASETYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
index 0e8239cc1e..51461207c5 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -8,193 +8,9 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
-namespace {
-
-// we use macros here instead of function definitions to work around more GLSL
-// compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
-// problematic because if the argument has side-effects they will be repeatedly
-// evaluated. This is unlikely to show up in real shaders, but is something to
-// consider.
-const char* kFunctionEmulationVertexSource[] = {
- "#error no emulation for cos(float)",
- "#error no emulation for cos(vec2)",
- "#error no emulation for cos(vec3)",
- "#error no emulation for cos(vec4)",
-
- "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
- "#error no emulation for distance(vec2, vec2)",
- "#error no emulation for distance(vec3, vec3)",
- "#error no emulation for distance(vec4, vec4)",
-
- "#define webgl_dot_emu(x, y) ((x) * (y))",
- "#error no emulation for dot(vec2, vec2)",
- "#error no emulation for dot(vec3, vec3)",
- "#error no emulation for dot(vec4, vec4)",
-
- "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
- "#error no emulation for length(vec2)",
- "#error no emulation for length(vec3)",
- "#error no emulation for length(vec4)",
-
- "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
- "#error no emulation for normalize(vec2)",
- "#error no emulation for normalize(vec3)",
- "#error no emulation for normalize(vec4)",
-
- "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
- "#error no emulation for reflect(vec2, vec2)",
- "#error no emulation for reflect(vec3, vec3)",
- "#error no emulation for reflect(vec4, vec4)"
-};
-
-const char* kFunctionEmulationFragmentSource[] = {
- "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }",
- "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }",
- "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }",
- "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }",
-
- "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))",
- "#error no emulation for distance(vec2, vec2)",
- "#error no emulation for distance(vec3, vec3)",
- "#error no emulation for distance(vec4, vec4)",
-
- "#define webgl_dot_emu(x, y) ((x) * (y))",
- "#error no emulation for dot(vec2, vec2)",
- "#error no emulation for dot(vec3, vec3)",
- "#error no emulation for dot(vec4, vec4)",
-
- "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))",
- "#error no emulation for length(vec2)",
- "#error no emulation for length(vec3)",
- "#error no emulation for length(vec4)",
-
- "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))",
- "#error no emulation for normalize(vec2)",
- "#error no emulation for normalize(vec3)",
- "#error no emulation for normalize(vec4)",
-
- "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))",
- "#error no emulation for reflect(vec2, vec2)",
- "#error no emulation for reflect(vec3, vec3)",
- "#error no emulation for reflect(vec4, vec4)"
-};
-
-const bool kFunctionEmulationVertexMask[] = {
-#if defined(__APPLE__)
- // Work around ATI driver bugs in Mac.
- false, // TFunctionCos1
- false, // TFunctionCos2
- false, // TFunctionCos3
- false, // TFunctionCos4
- true, // TFunctionDistance1_1
- false, // TFunctionDistance2_2
- false, // TFunctionDistance3_3
- false, // TFunctionDistance4_4
- true, // TFunctionDot1_1
- false, // TFunctionDot2_2
- false, // TFunctionDot3_3
- false, // TFunctionDot4_4
- true, // TFunctionLength1
- false, // TFunctionLength2
- false, // TFunctionLength3
- false, // TFunctionLength4
- true, // TFunctionNormalize1
- false, // TFunctionNormalize2
- false, // TFunctionNormalize3
- false, // TFunctionNormalize4
- true, // TFunctionReflect1_1
- false, // TFunctionReflect2_2
- false, // TFunctionReflect3_3
- false, // TFunctionReflect4_4
-#else
- // Work around D3D driver bug in Win.
- false, // TFunctionCos1
- false, // TFunctionCos2
- false, // TFunctionCos3
- false, // TFunctionCos4
- false, // TFunctionDistance1_1
- false, // TFunctionDistance2_2
- false, // TFunctionDistance3_3
- false, // TFunctionDistance4_4
- false, // TFunctionDot1_1
- false, // TFunctionDot2_2
- false, // TFunctionDot3_3
- false, // TFunctionDot4_4
- false, // TFunctionLength1
- false, // TFunctionLength2
- false, // TFunctionLength3
- false, // TFunctionLength4
- false, // TFunctionNormalize1
- false, // TFunctionNormalize2
- false, // TFunctionNormalize3
- false, // TFunctionNormalize4
- false, // TFunctionReflect1_1
- false, // TFunctionReflect2_2
- false, // TFunctionReflect3_3
- false, // TFunctionReflect4_4
-#endif
- false // TFunctionUnknown
-};
-
-const bool kFunctionEmulationFragmentMask[] = {
-#if defined(__APPLE__)
- // Work around ATI driver bugs in Mac.
- true, // TFunctionCos1
- true, // TFunctionCos2
- true, // TFunctionCos3
- true, // TFunctionCos4
- true, // TFunctionDistance1_1
- false, // TFunctionDistance2_2
- false, // TFunctionDistance3_3
- false, // TFunctionDistance4_4
- true, // TFunctionDot1_1
- false, // TFunctionDot2_2
- false, // TFunctionDot3_3
- false, // TFunctionDot4_4
- true, // TFunctionLength1
- false, // TFunctionLength2
- false, // TFunctionLength3
- false, // TFunctionLength4
- true, // TFunctionNormalize1
- false, // TFunctionNormalize2
- false, // TFunctionNormalize3
- false, // TFunctionNormalize4
- true, // TFunctionReflect1_1
- false, // TFunctionReflect2_2
- false, // TFunctionReflect3_3
- false, // TFunctionReflect4_4
-#else
- // Work around D3D driver bug in Win.
- false, // TFunctionCos1
- false, // TFunctionCos2
- false, // TFunctionCos3
- false, // TFunctionCos4
- false, // TFunctionDistance1_1
- false, // TFunctionDistance2_2
- false, // TFunctionDistance3_3
- false, // TFunctionDistance4_4
- false, // TFunctionDot1_1
- false, // TFunctionDot2_2
- false, // TFunctionDot3_3
- false, // TFunctionDot4_4
- false, // TFunctionLength1
- false, // TFunctionLength2
- false, // TFunctionLength3
- false, // TFunctionLength4
- false, // TFunctionNormalize1
- false, // TFunctionNormalize2
- false, // TFunctionNormalize3
- false, // TFunctionNormalize4
- false, // TFunctionReflect1_1
- false, // TFunctionReflect2_2
- false, // TFunctionReflect3_3
- false, // TFunctionReflect4_4
-#endif
- false // TFunctionUnknown
-};
-
-class BuiltInFunctionEmulationMarker : public TIntermTraverser {
-public:
+class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
+{
+ public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator& emulator)
: mEmulator(emulator)
{
@@ -238,148 +54,119 @@ public:
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
+ case EOpOuterProduct:
case EOpMul:
break;
default:
return true;
};
const TIntermSequence& sequence = *(node->getSequence());
- // Right now we only handle built-in functions with two parameters.
- if (sequence.size() != 2)
- return true;
- TIntermTyped* param1 = sequence[0]->getAsTyped();
- TIntermTyped* param2 = sequence[1]->getAsTyped();
- if (!param1 || !param2)
+ bool needToEmulate = false;
+ // Right now we only handle built-in functions with two or three parameters.
+ if (sequence.size() == 2)
+ {
+ TIntermTyped* param1 = sequence[0]->getAsTyped();
+ TIntermTyped* param2 = sequence[1]->getAsTyped();
+ if (!param1 || !param2)
+ return true;
+ needToEmulate = mEmulator.SetFunctionCalled(
+ node->getOp(), param1->getType(), param2->getType());
+ }
+ else if (sequence.size() == 3)
+ {
+ TIntermTyped* param1 = sequence[0]->getAsTyped();
+ TIntermTyped* param2 = sequence[1]->getAsTyped();
+ TIntermTyped* param3 = sequence[2]->getAsTyped();
+ if (!param1 || !param2 || !param3)
+ return true;
+ needToEmulate = mEmulator.SetFunctionCalled(
+ node->getOp(), param1->getType(), param2->getType(), param3->getType());
+ }
+ else
+ {
return true;
- bool needToEmulate = mEmulator.SetFunctionCalled(
- node->getOp(), param1->getType(), param2->getType());
+ }
+
if (needToEmulate)
node->setUseEmulatedFunction();
}
return true;
}
-private:
+ private:
BuiltInFunctionEmulator& mEmulator;
};
-} // anonymous namepsace
+BuiltInFunctionEmulator::BuiltInFunctionEmulator()
+{}
-BuiltInFunctionEmulator::BuiltInFunctionEmulator(sh::GLenum shaderType)
+void BuiltInFunctionEmulator::addEmulatedFunction(
+ TOperator op, const TType& param,
+ const char* emulatedFunctionDefinition)
{
- if (shaderType == GL_FRAGMENT_SHADER) {
- mFunctionMask = kFunctionEmulationFragmentMask;
- mFunctionSource = kFunctionEmulationFragmentSource;
- } else {
- mFunctionMask = kFunctionEmulationVertexMask;
- mFunctionSource = kFunctionEmulationVertexSource;
- }
+ mEmulatedFunctions[FunctionId(op, param)] =
+ std::string(emulatedFunctionDefinition);
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(
- TOperator op, const TType& param)
+void BuiltInFunctionEmulator::addEmulatedFunction(
+ TOperator op, const TType& param1, const TType& param2,
+ const char* emulatedFunctionDefinition)
{
- TBuiltInFunction function = IdentifyFunction(op, param);
- return SetFunctionCalled(function);
+ mEmulatedFunctions[FunctionId(op, param1, param2)] =
+ std::string(emulatedFunctionDefinition);
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(
- TOperator op, const TType& param1, const TType& param2)
+void BuiltInFunctionEmulator::addEmulatedFunction(
+ TOperator op, const TType& param1, const TType& param2, const TType& param3,
+ const char* emulatedFunctionDefinition)
{
- TBuiltInFunction function = IdentifyFunction(op, param1, param2);
- return SetFunctionCalled(function);
+ mEmulatedFunctions[FunctionId(op, param1, param2, param3)] =
+ std::string(emulatedFunctionDefinition);
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(
- BuiltInFunctionEmulator::TBuiltInFunction function) {
- if (function == TFunctionUnknown || mFunctionMask[function] == false)
- return false;
- for (size_t i = 0; i < mFunctions.size(); ++i) {
- if (mFunctions[i] == function)
- return true;
- }
- mFunctions.push_back(function);
- return true;
+bool BuiltInFunctionEmulator::IsOutputEmpty() const
+{
+ return (mFunctions.size() == 0);
}
-void BuiltInFunctionEmulator::OutputEmulatedFunctionDefinition(
- TInfoSinkBase& out, bool withPrecision) const
+void BuiltInFunctionEmulator::OutputEmulatedFunctions(
+ TInfoSinkBase& out) const
{
- if (mFunctions.size() == 0)
- return;
- out << "// BEGIN: Generated code for built-in function emulation\n\n";
- if (withPrecision) {
- out << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
- << "#define webgl_emu_precision highp\n"
- << "#else\n"
- << "#define webgl_emu_precision mediump\n"
- << "#endif\n\n";
- } else {
- out << "#define webgl_emu_precision\n\n";
- }
for (size_t i = 0; i < mFunctions.size(); ++i) {
- out << mFunctionSource[mFunctions[i]] << "\n\n";
+ out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
}
- out << "// END: Generated code for built-in function emulation\n\n";
}
-BuiltInFunctionEmulator::TBuiltInFunction
-BuiltInFunctionEmulator::IdentifyFunction(
+bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param)
{
- if (param.getNominalSize() > 4 || param.getSecondarySize() > 4)
- return TFunctionUnknown;
- unsigned int function = TFunctionUnknown;
- switch (op) {
- case EOpCos:
- function = TFunctionCos1;
- break;
- case EOpLength:
- function = TFunctionLength1;
- break;
- case EOpNormalize:
- function = TFunctionNormalize1;
- break;
- default:
- break;
- }
- if (function == TFunctionUnknown)
- return TFunctionUnknown;
- if (param.isVector())
- function += param.getNominalSize() - 1;
- return static_cast<TBuiltInFunction>(function);
+ return SetFunctionCalled(FunctionId(op, param));
}
-BuiltInFunctionEmulator::TBuiltInFunction
-BuiltInFunctionEmulator::IdentifyFunction(
+bool BuiltInFunctionEmulator::SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2)
{
- // Right now for all the emulated functions with two parameters, the two
- // parameters have the same type.
- if (param1.getNominalSize() != param2.getNominalSize() ||
- param1.getSecondarySize() != param2.getSecondarySize() ||
- param1.getNominalSize() > 4 || param1.getSecondarySize() > 4)
- return TFunctionUnknown;
+ return SetFunctionCalled(FunctionId(op, param1, param2));
+}
+
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+ TOperator op, const TType& param1, const TType& param2, const TType& param3)
+{
+ return SetFunctionCalled(FunctionId(op, param1, param2, param3));
+}
- unsigned int function = TFunctionUnknown;
- switch (op) {
- case EOpDistance:
- function = TFunctionDistance1_1;
- break;
- case EOpDot:
- function = TFunctionDot1_1;
- break;
- case EOpReflect:
- function = TFunctionReflect1_1;
- break;
- default:
- break;
+bool BuiltInFunctionEmulator::SetFunctionCalled(
+ const FunctionId& functionId) {
+ if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
+ {
+ for (size_t i = 0; i < mFunctions.size(); ++i) {
+ if (mFunctions[i] == functionId)
+ return true;
+ }
+ mFunctions.push_back(functionId);
+ return true;
}
- if (function == TFunctionUnknown)
- return TFunctionUnknown;
- if (param1.isVector())
- function += param1.getNominalSize() - 1;
- return static_cast<TBuiltInFunction>(function);
+ return false;
}
void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
@@ -387,6 +174,9 @@ void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(
{
ASSERT(root);
+ if (mEmulatedFunctions.empty())
+ return;
+
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
@@ -404,3 +194,52 @@ TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}
+BuiltInFunctionEmulator::FunctionId::FunctionId
+ (TOperator op, const TType& param)
+ : mOp(op),
+ mParam1(param),
+ mParam2(EbtVoid),
+ mParam3(EbtVoid)
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId
+ (TOperator op, const TType& param1, const TType& param2)
+ : mOp(op),
+ mParam1(param1),
+ mParam2(param2),
+ mParam3(EbtVoid)
+{
+}
+
+BuiltInFunctionEmulator::FunctionId::FunctionId
+ (TOperator op, const TType& param1, const TType& param2, const TType& param3)
+ : mOp(op),
+ mParam1(param1),
+ mParam2(param2),
+ mParam3(param3)
+{
+}
+
+bool BuiltInFunctionEmulator::FunctionId::operator==
+ (const BuiltInFunctionEmulator::FunctionId& other) const
+{
+ return (mOp == other.mOp &&
+ mParam1 == other.mParam1 &&
+ mParam2 == other.mParam2 &&
+ mParam3 == other.mParam3);
+}
+
+bool BuiltInFunctionEmulator::FunctionId::operator<
+ (const BuiltInFunctionEmulator::FunctionId& other) const
+{
+ if (mOp != other.mOp)
+ return mOp < other.mOp;
+ if (mParam1 != other.mParam1)
+ return mParam1 < other.mParam1;
+ if (mParam2 != other.mParam2)
+ return mParam2 < other.mParam2;
+ if (mParam3 != other.mParam3)
+ return mParam3 < other.mParam3;
+ return false; // all fields are equal
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
index c6bf77c386..df556985e1 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
-#define COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
@@ -13,23 +13,13 @@
//
// This class decides which built-in functions need to be replaced with the
// emulated ones.
-// It's only a workaround for OpenGL driver bugs, and isn't needed in general.
+// It can be used to work around driver bugs or implement functions that are
+// not natively implemented on a specific platform.
//
-class BuiltInFunctionEmulator {
-public:
- BuiltInFunctionEmulator(sh::GLenum shaderType);
- // Records that a function is called by the shader and might needs to be
- // emulated. If the function's group is not in mFunctionGroupFilter, this
- // becomes an no-op.
- // Returns true if the function call needs to be replaced with an emulated
- // one.
- bool SetFunctionCalled(TOperator op, const TType& param);
- bool SetFunctionCalled(
- TOperator op, const TType& param1, const TType& param2);
-
- // Output function emulation definition. This should be before any other
- // shader source.
- void OutputEmulatedFunctionDefinition(TInfoSinkBase& out, bool withPrecision) const;
+class BuiltInFunctionEmulator
+{
+ public:
+ BuiltInFunctionEmulator();
void MarkBuiltInFunctionsForEmulation(TIntermNode* root);
@@ -38,54 +28,52 @@ public:
// "name(" becomes "webgl_name_emu(".
static TString GetEmulatedFunctionName(const TString& name);
-private:
- //
- // Built-in functions.
- //
- enum TBuiltInFunction {
- TFunctionCos1 = 0, // float cos(float);
- TFunctionCos2, // vec2 cos(vec2);
- TFunctionCos3, // vec3 cos(vec3);
- TFunctionCos4, // vec4 cos(vec4);
-
- TFunctionDistance1_1, // float distance(float, float);
- TFunctionDistance2_2, // vec2 distance(vec2, vec2);
- TFunctionDistance3_3, // vec3 distance(vec3, vec3);
- TFunctionDistance4_4, // vec4 distance(vec4, vec4);
-
- TFunctionDot1_1, // float dot(float, float);
- TFunctionDot2_2, // vec2 dot(vec2, vec2);
- TFunctionDot3_3, // vec3 dot(vec3, vec3);
- TFunctionDot4_4, // vec4 dot(vec4, vec4);
-
- TFunctionLength1, // float length(float);
- TFunctionLength2, // float length(vec2);
- TFunctionLength3, // float length(vec3);
- TFunctionLength4, // float length(vec4);
-
- TFunctionNormalize1, // float normalize(float);
- TFunctionNormalize2, // vec2 normalize(vec2);
- TFunctionNormalize3, // vec3 normalize(vec3);
- TFunctionNormalize4, // vec4 normalize(vec4);
-
- TFunctionReflect1_1, // float reflect(float, float);
- TFunctionReflect2_2, // vec2 reflect(vec2, vec2);
- TFunctionReflect3_3, // vec3 reflect(vec3, vec3);
- TFunctionReflect4_4, // vec4 reflect(vec4, vec4);
-
- TFunctionUnknown
- };
+ bool IsOutputEmpty() const;
+
+ // Output function emulation definition. This should be before any other
+ // shader source.
+ void OutputEmulatedFunctions(TInfoSinkBase& out) const;
+
+ // Add functions that need to be emulated.
+ void addEmulatedFunction(TOperator op, const TType& param, const char* emulatedFunctionDefinition);
+ void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const char* emulatedFunctionDefinition);
+ void addEmulatedFunction(TOperator op, const TType& param1, const TType& param2, const TType& param3, const char* emulatedFunctionDefinition);
- TBuiltInFunction IdentifyFunction(TOperator op, const TType& param);
- TBuiltInFunction IdentifyFunction(
+ private:
+ class BuiltInFunctionEmulationMarker;
+
+ // Records that a function is called by the shader and might need to be
+ // emulated. If the function is not in mEmulatedFunctions, this becomes a
+ // no-op. Returns true if the function call needs to be replaced with an
+ // emulated one.
+ bool SetFunctionCalled(TOperator op, const TType& param);
+ bool SetFunctionCalled(
TOperator op, const TType& param1, const TType& param2);
+ bool SetFunctionCalled(
+ TOperator op, const TType& param1, const TType& param2, const TType& param3);
+
+ class FunctionId {
+ public:
+ FunctionId(TOperator op, const TType& param);
+ FunctionId(TOperator op, const TType& param1, const TType& param2);
+ FunctionId(TOperator op, const TType& param1, const TType& param2, const TType& param3);
+
+ bool operator==(const FunctionId& other) const;
+ bool operator<(const FunctionId& other) const;
+ private:
+ TOperator mOp;
+ TType mParam1;
+ TType mParam2;
+ TType mParam3;
+ };
- bool SetFunctionCalled(TBuiltInFunction function);
+ bool SetFunctionCalled(const FunctionId& functionId);
- std::vector<TBuiltInFunction> mFunctions;
+ // Map from function id to emulated function definition
+ std::map<FunctionId, std::string> mEmulatedFunctions;
- const bool* mFunctionMask; // a boolean flag for each function.
- const char** mFunctionSource;
+ // Called function ids
+ std::vector<FunctionId> mFunctions;
};
-#endif // COMPILIER_BUILT_IN_FUNCTION_EMULATOR_H_
+#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
new file mode 100644
index 0000000000..9de99831ad
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp
@@ -0,0 +1,37 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/SymbolTable.h"
+
+void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType)
+{
+ // we use macros here instead of function definitions to work around more GLSL
+ // compiler bugs, in particular on NVIDIA hardware on Mac OSX. Macros are
+ // problematic because if the argument has side-effects they will be repeatedly
+ // evaluated. This is unlikely to show up in real shaders, but is something to
+ // consider.
+
+ TType float1(EbtFloat);
+ TType float2(EbtFloat, 2);
+ TType float3(EbtFloat, 3);
+ TType float4(EbtFloat, 4);
+
+ if (shaderType == GL_FRAGMENT_SHADER)
+ {
+ emu->addEmulatedFunction(EOpCos, float1, "webgl_emu_precision float webgl_cos_emu(webgl_emu_precision float a) { return cos(a); }");
+ emu->addEmulatedFunction(EOpCos, float2, "webgl_emu_precision vec2 webgl_cos_emu(webgl_emu_precision vec2 a) { return cos(a); }");
+ emu->addEmulatedFunction(EOpCos, float3, "webgl_emu_precision vec3 webgl_cos_emu(webgl_emu_precision vec3 a) { return cos(a); }");
+ emu->addEmulatedFunction(EOpCos, float4, "webgl_emu_precision vec4 webgl_cos_emu(webgl_emu_precision vec4 a) { return cos(a); }");
+ }
+ emu->addEmulatedFunction(EOpDistance, float1, float1, "#define webgl_distance_emu(x, y) ((x) >= (y) ? (x) - (y) : (y) - (x))");
+ emu->addEmulatedFunction(EOpDot, float1, float1, "#define webgl_dot_emu(x, y) ((x) * (y))");
+ emu->addEmulatedFunction(EOpLength, float1, "#define webgl_length_emu(x) ((x) >= 0.0 ? (x) : -(x))");
+ emu->addEmulatedFunction(EOpNormalize, float1, "#define webgl_normalize_emu(x) ((x) == 0.0 ? 0.0 : ((x) > 0.0 ? 1.0 : -1.0))");
+ emu->addEmulatedFunction(EOpReflect, float1, float1, "#define webgl_reflect_emu(I, N) ((I) - 2.0 * (N) * (I) * (N))");
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
new file mode 100644
index 0000000000..5707a4b35a
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h
@@ -0,0 +1,19 @@
+//
+// Copyright (c) 2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+class BuiltInFunctionEmulator;
+
+//
+// This is only a workaround for OpenGL driver bugs, and isn't needed in general.
+//
+void InitBuiltInFunctionEmulatorForGLSL(BuiltInFunctionEmulator *emu, sh::GLenum shaderType);
+
+#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
new file mode 100644
index 0000000000..7123a0d5c0
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp
@@ -0,0 +1,410 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
+#include "compiler/translator/SymbolTable.h"
+
+void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
+{
+ TType float1(EbtFloat);
+ TType float2(EbtFloat, 2);
+ TType float3(EbtFloat, 3);
+ TType float4(EbtFloat, 4);
+
+ emu->addEmulatedFunction(EOpMod, float1, float1,
+ "float webgl_mod_emu(float x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float2, float2,
+ "float2 webgl_mod_emu(float2 x, float2 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float2, float1,
+ "float2 webgl_mod_emu(float2 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float3, float3,
+ "float3 webgl_mod_emu(float3 x, float3 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float3, float1,
+ "float3 webgl_mod_emu(float3 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float4, float4,
+ "float4 webgl_mod_emu(float4 x, float4 y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpMod, float4, float1,
+ "float4 webgl_mod_emu(float4 x, float y)\n"
+ "{\n"
+ " return x - y * floor(x / y);\n"
+ "}\n"
+ "\n");
+
+ emu->addEmulatedFunction(EOpFaceForward, float1, float1, float1,
+ "float webgl_faceforward_emu(float N, float I, float Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpFaceForward, float2, float2, float2,
+ "float2 webgl_faceforward_emu(float2 N, float2 I, float2 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpFaceForward, float3, float3, float3,
+ "float3 webgl_faceforward_emu(float3 N, float3 I, float3 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n");
+ emu->addEmulatedFunction(EOpFaceForward, float4, float4, float4,
+ "float4 webgl_faceforward_emu(float4 N, float4 I, float4 Nref)\n"
+ "{\n"
+ " if(dot(Nref, I) >= 0)\n"
+ " {\n"
+ " return -N;\n"
+ " }\n"
+ " else\n"
+ " {\n"
+ " return N;\n"
+ " }\n"
+ "}\n"
+ "\n");
+
+ emu->addEmulatedFunction(EOpAtan, float1, float1,
+ "float webgl_atan_emu(float y, float x)\n"
+ "{\n"
+ " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
+ " return atan2(y, x);\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtan, float2, float2,
+ "float2 webgl_atan_emu(float2 y, float2 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtan, float3, float3,
+ "float3 webgl_atan_emu(float3 y, float3 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtan, float4, float4,
+ "float4 webgl_atan_emu(float4 y, float4 x)\n"
+ "{\n"
+ " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
+ " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
+ " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
+ " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
+ " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpAsinh, float1,
+ "float webgl_asinh_emu(in float x) {\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAsinh, float2,
+ "float2 webgl_asinh_emu(in float2 x) {\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAsinh, float3,
+ "float3 webgl_asinh_emu(in float3 x) {\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAsinh, float4,
+ "float4 webgl_asinh_emu(in float4 x) {\n"
+ " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpAcosh, float1,
+ "float webgl_acosh_emu(in float x) {\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAcosh, float2,
+ "float2 webgl_acosh_emu(in float2 x) {\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAcosh, float3,
+ "float3 webgl_acosh_emu(in float3 x) {\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAcosh, float4,
+ "float4 webgl_acosh_emu(in float4 x) {\n"
+ " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpAtanh, float1,
+ "float webgl_atanh_emu(in float x) {\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtanh, float2,
+ "float2 webgl_atanh_emu(in float2 x) {\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtanh, float3,
+ "float3 webgl_atanh_emu(in float3 x) {\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpAtanh, float4,
+ "float4 webgl_atanh_emu(in float4 x) {\n"
+ " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpRoundEven, float1,
+ "float webgl_roundEven_emu(in float x) {\n"
+ " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpRoundEven, float2,
+ "float2 webgl_roundEven_emu(in float2 x) {\n"
+ " float2 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " return v;\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpRoundEven, float3,
+ "float3 webgl_roundEven_emu(in float3 x) {\n"
+ " float3 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+ " return v;\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpRoundEven, float4,
+ "float4 webgl_roundEven_emu(in float4 x) {\n"
+ " float4 v;\n"
+ " v[0] = (frac(x[0]) == 0.5 && trunc(x[0]) % 2.0 == 0.0) ? trunc(x[0]) : round(x[0]);\n"
+ " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
+ " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
+ " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
+ " return v;\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
+ "int webgl_toSnorm(in float x) {\n"
+ " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
+ "}\n"
+ "\n"
+ "uint webgl_packSnorm2x16_emu(in float2 v) {\n"
+ " int x = webgl_toSnorm(v.x);\n"
+ " int y = webgl_toSnorm(v.y);\n"
+ " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
+ "uint webgl_toUnorm(in float x) {\n"
+ " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
+ "}\n"
+ "\n"
+ "uint webgl_packUnorm2x16_emu(in float2 v) {\n"
+ " uint x = webgl_toUnorm(v.x);\n"
+ " uint y = webgl_toUnorm(v.y);\n"
+ " return (y << 16) | x;\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpPackHalf2x16, float2,
+ "uint webgl_packHalf2x16_emu(in float2 v) {\n"
+ " uint x = f32tof16(v.x);\n"
+ " uint y = f32tof16(v.y);\n"
+ " return (y << 16) | x;\n"
+ "}\n");
+
+ TType uint1(EbtUInt);
+
+ emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
+ "float webgl_fromSnorm(in uint x) {\n"
+ " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
+ " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
+ "}\n"
+ "\n"
+ "float2 webgl_unpackSnorm2x16_emu(in uint u) {\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u;\n"
+ " return float2(webgl_fromSnorm(x), webgl_fromSnorm(y));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
+ "float webgl_fromUnorm(in uint x) {\n"
+ " return float(x) / 65535.0;\n"
+ "}\n"
+ "\n"
+ "float2 webgl_unpackUnorm2x16_emu(in uint u) {\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u & 0xffffu;\n"
+ " return float2(webgl_fromUnorm(x), webgl_fromUnorm(y));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
+ "float2 webgl_unpackHalf2x16_emu(in uint u) {\n"
+ " uint y = (u >> 16);\n"
+ " uint x = u & 0xffffu;\n"
+ " return float2(f16tof32(x), f16tof32(y));\n"
+ "}\n");
+
+ // The matrix resulting from outer product needs to be transposed
+ // (matrices are stored as transposed to simplify element access in HLSL).
+ // So the function should return transpose(c * r) where c is a column vector
+ // and r is a row vector. This can be simplified by using the following
+ // formula:
+ // transpose(c * r) = transpose(r) * transpose(c)
+ // transpose(r) and transpose(c) are in a sense free, since to get the
+ // transpose of r, we simply can build a column matrix out of the original
+ // vector instead of a row matrix.
+ emu->addEmulatedFunction(EOpOuterProduct, float2, float2,
+ "float2x2 webgl_outerProduct_emu(in float2 c, in float2 r) {\n"
+ " return mul(float2x1(r), float1x2(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float3, float3,
+ "float3x3 webgl_outerProduct_emu(in float3 c, in float3 r) {\n"
+ " return mul(float3x1(r), float1x3(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float4, float4,
+ "float4x4 webgl_outerProduct_emu(in float4 c, in float4 r) {\n"
+ " return mul(float4x1(r), float1x4(c));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpOuterProduct, float3, float2,
+ "float2x3 webgl_outerProduct_emu(in float3 c, in float2 r) {\n"
+ " return mul(float2x1(r), float1x3(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float2, float3,
+ "float3x2 webgl_outerProduct_emu(in float2 c, in float3 r) {\n"
+ " return mul(float3x1(r), float1x2(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float4, float2,
+ "float2x4 webgl_outerProduct_emu(in float4 c, in float2 r) {\n"
+ " return mul(float2x1(r), float1x4(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float2, float4,
+ "float4x2 webgl_outerProduct_emu(in float2 c, in float4 r) {\n"
+ " return mul(float4x1(r), float1x2(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float4, float3,
+ "float3x4 webgl_outerProduct_emu(in float4 c, in float3 r) {\n"
+ " return mul(float3x1(r), float1x4(c));\n"
+ "}\n");
+ emu->addEmulatedFunction(EOpOuterProduct, float3, float4,
+ "float4x3 webgl_outerProduct_emu(in float3 c, in float4 r) {\n"
+ " return mul(float4x1(r), float1x3(c));\n"
+ "}\n");
+
+ TType mat2(EbtFloat, 2, 2);
+ TType mat3(EbtFloat, 3, 3);
+ TType mat4(EbtFloat, 4, 4);
+
+ // Remember here that the parameter matrix is actually the transpose
+ // of the matrix that we're trying to invert, and the resulting matrix
+ // should also be the transpose of the inverse.
+
+ // When accessing the parameter matrix with m[a][b] it can be thought of so
+ // that a is the column and b is the row of the matrix that we're inverting.
+
+ // We calculate the inverse as the adjugate matrix divided by the
+ // determinant of the matrix being inverted. However, as the result needs
+ // to be transposed, we actually use of the transpose of the adjugate matrix
+ // which happens to be the cofactor matrix. That's stored in "cof".
+
+ // We don't need to care about divide-by-zero since results are undefined
+ // for singular or poorly-conditioned matrices.
+
+ emu->addEmulatedFunction(EOpInverse, mat2,
+ "float2x2 webgl_inverse_emu(in float2x2 m) {\n"
+ " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n");
+
+ // cofAB is the cofactor for column A and row B.
+
+ emu->addEmulatedFunction(EOpInverse, mat3,
+ "float3x3 webgl_inverse_emu(in float3x3 m) {\n"
+ " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
+ " float cof01 = -(m[1][0] * m[2][2] - m[2][0] * m[1][2]);\n"
+ " float cof02 = m[1][0] * m[2][1] - m[2][0] * m[1][1];\n"
+ " float cof10 = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]);\n"
+ " float cof11 = m[0][0] * m[2][2] - m[2][0] * m[0][2];\n"
+ " float cof12 = -(m[0][0] * m[2][1] - m[2][0] * m[0][1]);\n"
+ " float cof20 = m[0][1] * m[1][2] - m[1][1] * m[0][2];\n"
+ " float cof21 = -(m[0][0] * m[1][2] - m[1][0] * m[0][2]);\n"
+ " float cof22 = m[0][0] * m[1][1] - m[1][0] * m[0][1];\n"
+ " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n");
+
+ emu->addEmulatedFunction(EOpInverse, mat4,
+ "float4x4 webgl_inverse_emu(in float4x4 m) {\n"
+ " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * m[1][2] * m[2][3]"
+ " - m[1][1] * m[3][2] * m[2][3] - m[2][1] * m[1][2] * m[3][3] - m[3][1] * m[2][2] * m[1][3];\n"
+ " float cof01 = -(m[1][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[1][3] + m[3][0] * m[1][2] * m[2][3]"
+ " - m[1][0] * m[3][2] * m[2][3] - m[2][0] * m[1][2] * m[3][3] - m[3][0] * m[2][2] * m[1][3]);\n"
+ " float cof02 = m[1][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[1][3] + m[3][0] * m[1][1] * m[2][3]"
+ " - m[1][0] * m[3][1] * m[2][3] - m[2][0] * m[1][1] * m[3][3] - m[3][0] * m[2][1] * m[1][3];\n"
+ " float cof03 = -(m[1][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[1][2] + m[3][0] * m[1][1] * m[2][2]"
+ " - m[1][0] * m[3][1] * m[2][2] - m[2][0] * m[1][1] * m[3][2] - m[3][0] * m[2][1] * m[1][2]);\n"
+ " float cof10 = -(m[0][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[2][3]"
+ " - m[0][1] * m[3][2] * m[2][3] - m[2][1] * m[0][2] * m[3][3] - m[3][1] * m[2][2] * m[0][3]);\n"
+ " float cof11 = m[0][0] * m[2][2] * m[3][3] + m[2][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[2][3]"
+ " - m[0][0] * m[3][2] * m[2][3] - m[2][0] * m[0][2] * m[3][3] - m[3][0] * m[2][2] * m[0][3];\n"
+ " float cof12 = -(m[0][0] * m[2][1] * m[3][3] + m[2][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[2][3]"
+ " - m[0][0] * m[3][1] * m[2][3] - m[2][0] * m[0][1] * m[3][3] - m[3][0] * m[2][1] * m[0][3]);\n"
+ " float cof13 = m[0][0] * m[2][1] * m[3][2] + m[2][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[2][2]"
+ " - m[0][0] * m[3][1] * m[2][2] - m[2][0] * m[0][1] * m[3][2] - m[3][0] * m[2][1] * m[0][2];\n"
+ " float cof20 = m[0][1] * m[1][2] * m[3][3] + m[1][1] * m[3][2] * m[0][3] + m[3][1] * m[0][2] * m[1][3]"
+ " - m[0][1] * m[3][2] * m[1][3] - m[1][1] * m[0][2] * m[3][3] - m[3][1] * m[1][2] * m[0][3];\n"
+ " float cof21 = -(m[0][0] * m[1][2] * m[3][3] + m[1][0] * m[3][2] * m[0][3] + m[3][0] * m[0][2] * m[1][3]"
+ " - m[0][0] * m[3][2] * m[1][3] - m[1][0] * m[0][2] * m[3][3] - m[3][0] * m[1][2] * m[0][3]);\n"
+ " float cof22 = m[0][0] * m[1][1] * m[3][3] + m[1][0] * m[3][1] * m[0][3] + m[3][0] * m[0][1] * m[1][3]"
+ " - m[0][0] * m[3][1] * m[1][3] - m[1][0] * m[0][1] * m[3][3] - m[3][0] * m[1][1] * m[0][3];\n"
+ " float cof23 = -(m[0][0] * m[1][1] * m[3][2] + m[1][0] * m[3][1] * m[0][2] + m[3][0] * m[0][1] * m[1][2]"
+ " - m[0][0] * m[3][1] * m[1][2] - m[1][0] * m[0][1] * m[3][2] - m[3][0] * m[1][1] * m[0][2]);\n"
+ " float cof30 = -(m[0][1] * m[1][2] * m[2][3] + m[1][1] * m[2][2] * m[0][3] + m[2][1] * m[0][2] * m[1][3]"
+ " - m[0][1] * m[2][2] * m[1][3] - m[1][1] * m[0][2] * m[2][3] - m[2][1] * m[1][2] * m[0][3]);\n"
+ " float cof31 = m[0][0] * m[1][2] * m[2][3] + m[1][0] * m[2][2] * m[0][3] + m[2][0] * m[0][2] * m[1][3]"
+ " - m[0][0] * m[2][2] * m[1][3] - m[1][0] * m[0][2] * m[2][3] - m[2][0] * m[1][2] * m[0][3];\n"
+ " float cof32 = -(m[0][0] * m[1][1] * m[2][3] + m[1][0] * m[2][1] * m[0][3] + m[2][0] * m[0][1] * m[1][3]"
+ " - m[0][0] * m[2][1] * m[1][3] - m[1][0] * m[0][1] * m[2][3] - m[2][0] * m[1][1] * m[0][3]);\n"
+ " float cof33 = m[0][0] * m[1][1] * m[2][2] + m[1][0] * m[2][1] * m[0][2] + m[2][0] * m[0][1] * m[1][2]"
+ " - m[0][0] * m[2][1] * m[1][2] - m[1][0] * m[0][1] * m[2][2] - m[2][0] * m[1][1] * m[0][2];\n"
+ " float4x4 cof = { cof00, cof10, cof20, cof30, cof01, cof11, cof21, cof31,"
+ " cof02, cof12, cof22, cof32, cof03, cof13, cof23, cof33 };\n"
+ " return cof / determinant(transpose(m));\n"
+ "}\n");
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
new file mode 100644
index 0000000000..4c45a93dc4
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h
@@ -0,0 +1,16 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
+#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
+
+#include "GLSLANG/ShaderLang.h"
+
+class BuiltInFunctionEmulator;
+
+void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu);
+
+#endif // COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
index 71056f4297..5e3eb1cc05 100644
--- a/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/CodeGen.cpp
@@ -6,7 +6,9 @@
#include "compiler/translator/TranslatorESSL.h"
#include "compiler/translator/TranslatorGLSL.h"
+#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
+#endif // ANGLE_ENABLE_HLSL
//
// This function must be provided to create the actual
@@ -17,14 +19,22 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
{
switch (output) {
- case SH_ESSL_OUTPUT:
+ case SH_ESSL_OUTPUT:
return new TranslatorESSL(type, spec);
- case SH_GLSL_OUTPUT:
- return new TranslatorGLSL(type, spec);
- case SH_HLSL9_OUTPUT:
- case SH_HLSL11_OUTPUT:
+ case SH_GLSL_CORE_OUTPUT:
+ case SH_GLSL_COMPATIBILITY_OUTPUT:
+ return new TranslatorGLSL(type, spec, output);
+ case SH_HLSL9_OUTPUT:
+ case SH_HLSL11_OUTPUT:
+#ifdef ANGLE_ENABLE_HLSL
return new TranslatorHLSL(type, spec, output);
- default:
+#else
+ // This compiler is not supported in this
+ // configuration. Return NULL per the ShConstructCompiler API.
+ return NULL;
+#endif // ANGLE_ENABLE_HLSL
+ default:
+ // Unknown format. Return NULL per the ShConstructCompiler API.
return NULL;
}
}
diff --git a/src/3rdparty/angle/src/compiler/translator/Common.h b/src/3rdparty/angle/src/compiler/translator/Common.h
index 1e4503e340..ac1aef0f4c 100644
--- a/src/3rdparty/angle/src/compiler/translator/Common.h
+++ b/src/3rdparty/angle/src/compiler/translator/Common.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _COMMON_INCLUDED_
-#define _COMMON_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_COMMON_H_
+#define COMPILER_TRANSLATOR_COMMON_H_
#include <map>
#include <sstream>
@@ -89,4 +89,4 @@ inline TString str(T i)
return buffer;
}
-#endif // _COMMON_INCLUDED_
+#endif // COMPILER_TRANSLATOR_COMMON_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
index 5c62a64d10..534861ca70 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.cpp
@@ -4,7 +4,6 @@
// found in the LICENSE file.
//
-#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/Compiler.h"
#include "compiler/translator/DetectCallDepth.h"
#include "compiler/translator/ForLoopUnroll.h"
@@ -126,7 +125,8 @@ TCompiler::TCompiler(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
maxCallStackDepth(0),
fragmentPrecisionHigh(false),
clampingStrategy(SH_CLAMP_WITH_CLAMP_INTRINSIC),
- builtInFunctionEmulator(type)
+ builtInFunctionEmulator(),
+ mSourcePath(NULL)
{
}
@@ -159,33 +159,41 @@ bool TCompiler::Init(const ShBuiltInResources& resources)
return true;
}
-bool TCompiler::compile(const char* const shaderStrings[],
- size_t numStrings,
- int compileOptions)
+TIntermNode *TCompiler::compileTreeForTesting(const char* const shaderStrings[],
+ size_t numStrings, int compileOptions)
+{
+ return compileTreeImpl(shaderStrings, numStrings, compileOptions);
+}
+
+TIntermNode *TCompiler::compileTreeImpl(const char* const shaderStrings[],
+ size_t numStrings, int compileOptions)
{
- TScopedPoolAllocator scopedAlloc(&allocator);
clearResults();
- if (numStrings == 0)
- return true;
+ ASSERT(numStrings > 0);
+ ASSERT(GetGlobalPoolAllocator());
+
+ // Reset the extension behavior for each compilation unit.
+ ResetExtensionBehavior(extensionBehavior);
// If compiling for WebGL, validate loop and indexing as well.
if (IsWebGLBasedSpec(shaderSpec))
compileOptions |= SH_VALIDATE_LOOP_INDEXING;
// First string is path of source file if flag is set. The actual source follows.
- const char* sourcePath = NULL;
size_t firstSource = 0;
if (compileOptions & SH_SOURCE_PATH)
{
- sourcePath = shaderStrings[0];
+ mSourcePath = shaderStrings[0];
++firstSource;
}
+ bool debugShaderPrecision = getResources().WEBGL_debug_shader_precision == 1;
TIntermediate intermediate(infoSink);
TParseContext parseContext(symbolTable, extensionBehavior, intermediate,
shaderType, shaderSpec, compileOptions, true,
- sourcePath, infoSink);
+ infoSink, debugShaderPrecision);
+
parseContext.fragmentPrecisionHigh = fragmentPrecisionHigh;
SetGlobalParseContext(&parseContext);
@@ -206,6 +214,8 @@ bool TCompiler::compile(const char* const shaderStrings[],
success = false;
}
+ TIntermNode *root = NULL;
+
if (success)
{
mPragma = parseContext.pragma();
@@ -214,7 +224,7 @@ bool TCompiler::compile(const char* const shaderStrings[],
symbolTable.setGlobalInvariant();
}
- TIntermNode* root = parseContext.treeRoot;
+ root = parseContext.treeRoot;
success = intermediate.postProcess(root);
// Disallow expressions deemed too complex.
@@ -255,8 +265,11 @@ bool TCompiler::compile(const char* const shaderStrings[],
}
// Built-in function emulation needs to happen after validateLimitations pass.
- if (success && (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS))
+ if (success)
+ {
+ initBuiltInFunctionEmulator(&builtInFunctionEmulator, compileOptions);
builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(root);
+ }
// Clamping uniform array bounds needs to happen after validateLimitations pass.
if (success && (compileOptions & SH_CLAMP_INDIRECT_ARRAY_BOUNDS))
@@ -301,18 +314,37 @@ bool TCompiler::compile(const char* const shaderStrings[],
RegenerateStructNames gen(symbolTable, shaderVersion);
root->traverse(&gen);
}
-
- if (success && (compileOptions & SH_INTERMEDIATE_TREE))
- intermediate.outputTree(root);
-
- if (success && (compileOptions & SH_OBJECT_CODE))
- translate(root);
}
- // Cleanup memory.
- intermediate.remove(parseContext.treeRoot);
SetGlobalParseContext(NULL);
- return success;
+ if (success)
+ return root;
+
+ return NULL;
+}
+
+bool TCompiler::compile(const char* const shaderStrings[],
+ size_t numStrings, int compileOptions)
+{
+ if (numStrings == 0)
+ return true;
+
+ TScopedPoolAllocator scopedAlloc(&allocator);
+ TIntermNode *root = compileTreeImpl(shaderStrings, numStrings, compileOptions);
+
+ if (root)
+ {
+ if (compileOptions & SH_INTERMEDIATE_TREE)
+ TIntermediate::outputTree(root, infoSink.info);
+
+ if (compileOptions & SH_OBJECT_CODE)
+ translate(root, compileOptions);
+
+ // The IntermNode tree doesn't need to be deleted here, since the
+ // memory will be freed in a big chunk by the PoolAllocator.
+ return true;
+ }
+ return false;
}
bool TCompiler::InitBuiltInSymbolTable(const ShBuiltInResources &resources)
@@ -390,11 +422,15 @@ void TCompiler::setResourceString()
<< ":MaxCallStackDepth:" << compileResources.MaxCallStackDepth
<< ":EXT_frag_depth:" << compileResources.EXT_frag_depth
<< ":EXT_shader_texture_lod:" << compileResources.EXT_shader_texture_lod
+ << ":EXT_shader_framebuffer_fetch:" << compileResources.EXT_shader_framebuffer_fetch
+ << ":NV_shader_framebuffer_fetch:" << compileResources.NV_shader_framebuffer_fetch
+ << ":ARM_shader_framebuffer_fetch:" << compileResources.ARM_shader_framebuffer_fetch
<< ":MaxVertexOutputVectors:" << compileResources.MaxVertexOutputVectors
<< ":MaxFragmentInputVectors:" << compileResources.MaxFragmentInputVectors
<< ":MinProgramTexelOffset:" << compileResources.MinProgramTexelOffset
<< ":MaxProgramTexelOffset:" << compileResources.MaxProgramTexelOffset
- << ":NV_draw_buffers:" << compileResources.NV_draw_buffers;
+ << ":NV_draw_buffers:" << compileResources.NV_draw_buffers
+ << ":WEBGL_debug_shader_precision:" << compileResources.WEBGL_debug_shader_precision;
builtInResourcesString = strstream.str();
}
@@ -416,27 +452,29 @@ void TCompiler::clearResults()
builtInFunctionEmulator.Cleanup();
nameMap.clear();
+
+ mSourcePath = NULL;
}
-bool TCompiler::detectCallDepth(TIntermNode* root, TInfoSink& infoSink, bool limitCallStackDepth)
+bool TCompiler::detectCallDepth(TIntermNode* inputRoot, TInfoSink& inputInfoSink, bool limitCallStackDepth)
{
- DetectCallDepth detect(infoSink, limitCallStackDepth, maxCallStackDepth);
- root->traverse(&detect);
+ DetectCallDepth detect(inputInfoSink, limitCallStackDepth, maxCallStackDepth);
+ inputRoot->traverse(&detect);
switch (detect.detectCallDepth())
{
case DetectCallDepth::kErrorNone:
return true;
case DetectCallDepth::kErrorMissingMain:
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Missing main()";
+ inputInfoSink.info.prefix(EPrefixError);
+ inputInfoSink.info << "Missing main()";
return false;
case DetectCallDepth::kErrorRecursion:
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Function recursion detected";
+ inputInfoSink.info.prefix(EPrefixError);
+ inputInfoSink.info << "Function recursion detected";
return false;
case DetectCallDepth::kErrorMaxDepthExceeded:
- infoSink.info.prefix(EPrefixError);
- infoSink.info << "Function call stack too deep";
+ inputInfoSink.info.prefix(EPrefixError);
+ inputInfoSink.info << "Function call stack too deep";
return false;
default:
UNREACHABLE();
@@ -594,6 +632,11 @@ const TExtensionBehavior& TCompiler::getExtensionBehavior() const
return extensionBehavior;
}
+const char *TCompiler::getSourcePath() const
+{
+ return mSourcePath;
+}
+
const ShBuiltInResources& TCompiler::getResources() const
{
return compileResources;
diff --git a/src/3rdparty/angle/src/compiler/translator/Compiler.h b/src/3rdparty/angle/src/compiler/translator/Compiler.h
index b6c9d13ed0..bcdb0d4c9d 100644
--- a/src/3rdparty/angle/src/compiler/translator/Compiler.h
+++ b/src/3rdparty/angle/src/compiler/translator/Compiler.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _SHHANDLE_INCLUDED_
-#define _SHHANDLE_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_COMPILER_H_
+#define COMPILER_TRANSLATOR_COMPILER_H_
//
// Machine independent part of the compiler private objects
@@ -25,7 +25,9 @@
class TCompiler;
class TDependencyGraph;
+#ifdef ANGLE_ENABLE_HLSL
class TranslatorHLSL;
+#endif // ANGLE_ENABLE_HLSL
//
// Helper function to identify specs that are based on the WebGL spec,
@@ -41,7 +43,9 @@ public:
TShHandleBase();
virtual ~TShHandleBase();
virtual TCompiler* getAsCompiler() { return 0; }
+#ifdef ANGLE_ENABLE_HLSL
virtual TranslatorHLSL* getAsTranslatorHLSL() { return 0; }
+#endif // ANGLE_ENABLE_HLSL
protected:
// Memory allocator. Allocates and tracks memory required by the compiler.
@@ -61,9 +65,15 @@ class TCompiler : public TShHandleBase
virtual TCompiler* getAsCompiler() { return this; }
bool Init(const ShBuiltInResources& resources);
+
+ // compileTreeForTesting should be used only when tests require access to
+ // the AST. Users of this function need to manually manage the global pool
+ // allocator. Returns NULL whenever there are compilation errors.
+ TIntermNode *compileTreeForTesting(const char* const shaderStrings[],
+ size_t numStrings, int compileOptions);
+
bool compile(const char* const shaderStrings[],
- size_t numStrings,
- int compileOptions);
+ size_t numStrings, int compileOptions);
// Get results of the last compilation.
int getShaderVersion() const { return shaderVersion; }
@@ -104,8 +114,10 @@ class TCompiler : public TShHandleBase
bool validateLimitations(TIntermNode* root);
// Collect info for all attribs, uniforms, varyings.
void collectVariables(TIntermNode* root);
+ // Add emulated functions to the built-in function emulator.
+ virtual void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) {};
// Translate to object code.
- virtual void translate(TIntermNode* root) = 0;
+ virtual void translate(TIntermNode *root, int compileOptions) = 0;
// Returns true if, after applying the packing rules in the GLSL 1.017 spec
// Appendix A, section 7, the shader does not use too many uniforms.
bool enforcePackingRestrictions();
@@ -130,6 +142,7 @@ class TCompiler : public TShHandleBase
bool limitExpressionComplexity(TIntermNode* root);
// Get built-in extensions with default behavior.
const TExtensionBehavior& getExtensionBehavior() const;
+ const char *getSourcePath() const;
const TPragma& getPragma() const { return mPragma; }
void writePragma();
@@ -145,6 +158,9 @@ class TCompiler : public TShHandleBase
std::vector<sh::InterfaceBlock> interfaceBlocks;
private:
+ TIntermNode *compileTreeImpl(const char* const shaderStrings[],
+ size_t numStrings, int compileOptions);
+
sh::GLenum shaderType;
ShShaderSpec shaderSpec;
ShShaderOutput outputType;
@@ -170,6 +186,7 @@ class TCompiler : public TShHandleBase
// Results of compilation.
int shaderVersion;
TInfoSink infoSink; // Output sink.
+ const char *mSourcePath; // Path of source file or NULL
// name hashing.
ShHashFunction64 hashFunction;
@@ -191,4 +208,4 @@ TCompiler* ConstructCompiler(
sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
void DeleteCompiler(TCompiler*);
-#endif // _SHHANDLE_INCLUDED_
+#endif // COMPILER_TRANSLATOR_COMPILER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
index 5e86c64805..31ff2ccfa7 100644
--- a/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
+++ b/src/3rdparty/angle/src/compiler/translator/ConstantUnion.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _CONSTANT_UNION_INCLUDED_
-#define _CONSTANT_UNION_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_CONSTANTUNION_H_
+#define COMPILER_TRANSLATOR_CONSTANTUNION_H_
#include <assert.h>
@@ -254,7 +254,10 @@ public:
ConstantUnion operator<<(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
- assert(type == constant.type);
+ // The signedness of the second parameter might be different, but we
+ // don't care, since the result is undefined if the second parameter is
+ // negative, and aliasing should not be a problem with unions.
+ assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
@@ -267,7 +270,7 @@ public:
ConstantUnion operator&(const ConstantUnion& constant) const
{
ConstantUnion returnValue;
- assert(type == constant.type);
+ assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) {
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
@@ -340,4 +343,4 @@ private:
TBasicType type;
};
-#endif // _CONSTANT_UNION_INCLUDED_
+#endif // COMPILER_TRANSLATOR_CONSTANTUNION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp
index bfc1d5852f..0dc5d22709 100644
--- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.cpp
@@ -33,7 +33,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
ASSERT(visit == PreVisit);
ASSERT(detectCallDepth);
- int maxDepth = depth;
+ int retMaxDepth = depth;
visit = InVisit;
for (size_t i = 0; i < callees.size(); ++i) {
switch (callees[i]->visit) {
@@ -52,7 +52,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
detectCallDepth->getInfoSink().info << "<-" << callees[i]->getName();
return callDepth;
}
- maxDepth = std::max(callDepth, maxDepth);
+ retMaxDepth = std::max(callDepth, retMaxDepth);
break;
}
default:
@@ -61,7 +61,7 @@ int DetectCallDepth::FunctionNode::detectCallDepth(DetectCallDepth* detectCallDe
}
}
visit = PostVisit;
- return maxDepth;
+ return retMaxDepth;
}
void DetectCallDepth::FunctionNode::reset()
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h
index 86810650dc..8dd1391e67 100644
--- a/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h
+++ b/src/3rdparty/angle/src/compiler/translator/DetectCallDepth.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_DETECT_RECURSION_H_
-#define COMPILER_DETECT_RECURSION_H_
+#ifndef COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
+#define COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
#include <limits.h>
#include "compiler/translator/IntermNode.h"
@@ -75,4 +75,4 @@ private:
void operator=(const DetectCallDepth&);
};
-#endif // COMPILER_DETECT_RECURSION_H_
+#endif // COMPILER_TRANSLATOR_DETECTCALLDEPTH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
index 67e37be398..623be13533 100644
--- a/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
+++ b/src/3rdparty/angle/src/compiler/translator/DetectDiscontinuity.h
@@ -8,8 +8,8 @@
// gradients of functions with discontinuities.
//
-#ifndef COMPILER_DETECTDISCONTINUITY_H_
-#define COMPILER_DETECTDISCONTINUITY_H_
+#ifndef COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
+#define COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
#include "compiler/translator/IntermNode.h"
@@ -68,4 +68,4 @@ bool containsGradientOperation(TIntermNode *node);
}
-#endif // COMPILER_DETECTDISCONTINUITY_H_
+#endif // COMPILER_TRANSLATOR_DETECTDISCONTINUITY_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
index 664da7803b..078bc97772 100644
--- a/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
+++ b/src/3rdparty/angle/src/compiler/translator/Diagnostics.h
@@ -4,14 +4,15 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_DIAGNOSTICS_H_
-#define COMPILER_DIAGNOSTICS_H_
+#ifndef COMPILER_TRANSLATOR_DIAGNOSTICS_H_
+#define COMPILER_TRANSLATOR_DIAGNOSTICS_H_
+#include "common/angleutils.h"
#include "compiler/preprocessor/DiagnosticsBase.h"
class TInfoSink;
-class TDiagnostics : public pp::Diagnostics
+class TDiagnostics : public pp::Diagnostics, angle::NonCopyable
{
public:
TDiagnostics(TInfoSink& infoSink);
@@ -41,4 +42,4 @@ class TDiagnostics : public pp::Diagnostics
int mNumWarnings;
};
-#endif // COMPILER_DIAGNOSTICS_H_
+#endif // COMPILER_TRANSLATOR_DIAGNOSTICS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
index f67a03aa93..936c00a56c 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.cpp
@@ -27,10 +27,12 @@ static TBehavior getBehavior(const std::string& str)
TDirectiveHandler::TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
- int& shaderVersion)
+ int& shaderVersion,
+ bool debugShaderPrecisionSupported)
: mExtensionBehavior(extBehavior),
mDiagnostics(diagnostics),
- mShaderVersion(shaderVersion)
+ mShaderVersion(shaderVersion),
+ mDebugShaderPrecisionSupported(debugShaderPrecisionSupported)
{
}
@@ -65,6 +67,7 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
{
const char kOptimize[] = "optimize";
const char kDebug[] = "debug";
+ const char kDebugShaderPrecision[] = "webgl_debug_shader_precision";
const char kOn[] = "on";
const char kOff[] = "off";
@@ -81,6 +84,12 @@ void TDirectiveHandler::handlePragma(const pp::SourceLocation& loc,
else if (value == kOff) mPragma.debug = false;
else invalidValue = true;
}
+ else if (name == kDebugShaderPrecision && mDebugShaderPrecisionSupported)
+ {
+ if (value == kOn) mPragma.debugShaderPrecision = true;
+ else if (value == kOff) mPragma.debugShaderPrecision = false;
+ else invalidValue = true;
+ }
else
{
mDiagnostics.report(pp::Diagnostics::PP_UNRECOGNIZED_PRAGMA, loc, name);
diff --git a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
index 0433c3bf89..2a81ee5707 100644
--- a/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
+++ b/src/3rdparty/angle/src/compiler/translator/DirectiveHandler.h
@@ -4,21 +4,23 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_DIRECTIVE_HANDLER_H_
-#define COMPILER_DIRECTIVE_HANDLER_H_
+#ifndef COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
+#define COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
+#include "common/angleutils.h"
#include "compiler/translator/ExtensionBehavior.h"
#include "compiler/translator/Pragma.h"
#include "compiler/preprocessor/DirectiveHandlerBase.h"
class TDiagnostics;
-class TDirectiveHandler : public pp::DirectiveHandler
+class TDirectiveHandler : public pp::DirectiveHandler, angle::NonCopyable
{
public:
TDirectiveHandler(TExtensionBehavior& extBehavior,
TDiagnostics& diagnostics,
- int& shaderVersion);
+ int& shaderVersion,
+ bool debugShaderPrecisionSupported);
virtual ~TDirectiveHandler();
const TPragma& pragma() const { return mPragma; }
@@ -44,6 +46,7 @@ class TDirectiveHandler : public pp::DirectiveHandler
TExtensionBehavior& mExtensionBehavior;
TDiagnostics& mDiagnostics;
int& mShaderVersion;
+ bool mDebugShaderPrecisionSupported;
};
-#endif // COMPILER_DIRECTIVE_HANDLER_H_
+#endif // COMPILER_TRANSLATOR_DIRECTIVEHANDLER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
new file mode 100644
index 0000000000..697e042954
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.cpp
@@ -0,0 +1,528 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/EmulatePrecision.h"
+
+namespace
+{
+
+static void writeVectorPrecisionEmulationHelpers(
+ TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size)
+{
+ std::stringstream vecTypeStrStr;
+ if (outputLanguage == SH_ESSL_OUTPUT)
+ vecTypeStrStr << "highp ";
+ vecTypeStrStr << "vec" << size;
+ std::string vecType = vecTypeStrStr.str();
+
+ sink <<
+ vecType << " angle_frm(in " << vecType << " v) {\n"
+ " v = clamp(v, -65504.0, 65504.0);\n"
+ " " << vecType << " exponent = floor(log2(abs(v) + 1e-30)) - 10.0;\n"
+ " bvec" << size << " isNonZero = greaterThanEqual(exponent, vec" << size << "(-25.0));\n"
+ " v = v * exp2(-exponent);\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * exp2(exponent) * vec" << size << "(isNonZero);\n"
+ "}\n";
+
+ sink <<
+ vecType << " angle_frl(in " << vecType << " v) {\n"
+ " v = clamp(v, -2.0, 2.0);\n"
+ " v = v * 256.0;\n"
+ " v = sign(v) * floor(abs(v));\n"
+ " return v * 0.00390625;\n"
+ "}\n";
+}
+
+static void writeMatrixPrecisionEmulationHelper(
+ TInfoSinkBase& sink, ShShaderOutput outputLanguage, unsigned int size, const char *functionName)
+{
+ std::stringstream matTypeStrStr;
+ if (outputLanguage == SH_ESSL_OUTPUT)
+ matTypeStrStr << "highp ";
+ matTypeStrStr << "mat" << size;
+ std::string matType = matTypeStrStr.str();
+
+ sink << matType << " " << functionName << "(in " << matType << " m) {\n"
+ " " << matType << " rounded;\n";
+
+ for (unsigned int i = 0; i < size; ++i)
+ {
+ sink << " rounded[" << i << "] = " << functionName << "(m[" << i << "]);\n";
+ }
+
+ sink << " return rounded;\n"
+ "}\n";
+}
+
+static void writeCommonPrecisionEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
+{
+ // Write the angle_frm functions that round floating point numbers to
+ // half precision, and angle_frl functions that round them to minimum lowp
+ // precision.
+
+ // Unoptimized version of angle_frm for single floats:
+ //
+ // int webgl_maxNormalExponent(in int exponentBits) {
+ // int possibleExponents = int(exp2(float(exponentBits)));
+ // int exponentBias = possibleExponents / 2 - 1;
+ // int allExponentBitsOne = possibleExponents - 1;
+ // return (allExponentBitsOne - 1) - exponentBias;
+ // }
+ //
+ // float angle_frm(in float x) {
+ // int mantissaBits = 10;
+ // int exponentBits = 5;
+ // float possibleMantissas = exp2(float(mantissaBits));
+ // float mantissaMax = 2.0 - 1.0 / possibleMantissas;
+ // int maxNE = webgl_maxNormalExponent(exponentBits);
+ // float max = exp2(float(maxNE)) * mantissaMax;
+ // if (x > max) {
+ // return max;
+ // }
+ // if (x < -max) {
+ // return -max;
+ // }
+ // float exponent = floor(log2(abs(x)));
+ // if (abs(x) == 0.0 || exponent < -float(maxNE)) {
+ // return 0.0 * sign(x)
+ // }
+ // x = x * exp2(-(exponent - float(mantissaBits)));
+ // x = sign(x) * floor(abs(x));
+ // return x * exp2(exponent - float(mantissaBits));
+ // }
+
+ // All numbers with a magnitude less than 2^-15 are subnormal, and are
+ // flushed to zero.
+
+ // Note the constant numbers below:
+ // a) 65504 is the maximum possible mantissa (1.1111111111 in binary) times
+ // 2^15, the maximum normal exponent.
+ // b) 10.0 is the number of mantissa bits.
+ // c) -25.0 is the minimum normal half-float exponent -15.0 minus the number
+ // of mantissa bits.
+ // d) + 1e-30 is to make sure the argument of log2() won't be zero. It can
+ // only affect the result of log2 on x where abs(x) < 1e-22. Since these
+ // numbers will be flushed to zero either way (2^-15 is the smallest
+ // normal positive number), this does not introduce any error.
+
+ std::string floatType = "float";
+ if (outputLanguage == SH_ESSL_OUTPUT)
+ floatType = "highp float";
+
+ sink <<
+ floatType << " angle_frm(in " << floatType << " x) {\n"
+ " x = clamp(x, -65504.0, 65504.0);\n"
+ " " << floatType << " exponent = floor(log2(abs(x) + 1e-30)) - 10.0;\n"
+ " bool isNonZero = (exponent >= -25.0);\n"
+ " x = x * exp2(-exponent);\n"
+ " x = sign(x) * floor(abs(x));\n"
+ " return x * exp2(exponent) * float(isNonZero);\n"
+ "}\n";
+
+ sink <<
+ floatType << " angle_frl(in " << floatType << " x) {\n"
+ " x = clamp(x, -2.0, 2.0);\n"
+ " x = x * 256.0;\n"
+ " x = sign(x) * floor(abs(x));\n"
+ " return x * 0.00390625;\n"
+ "}\n";
+
+ writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 2);
+ writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 3);
+ writeVectorPrecisionEmulationHelpers(sink, outputLanguage, 4);
+ for (unsigned int size = 2; size <= 4; ++size)
+ {
+ writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frm");
+ writeMatrixPrecisionEmulationHelper(sink, outputLanguage, size, "angle_frl");
+ }
+}
+
+static void writeCompoundAssignmentPrecisionEmulation(
+ TInfoSinkBase& sink, ShShaderOutput outputLanguage,
+ const char *lType, const char *rType, const char *opStr, const char *opNameStr)
+{
+ std::string lTypeStr = lType;
+ std::string rTypeStr = rType;
+ if (outputLanguage == SH_ESSL_OUTPUT)
+ {
+ std::stringstream lTypeStrStr;
+ lTypeStrStr << "highp " << lType;
+ lTypeStr = lTypeStrStr.str();
+ std::stringstream rTypeStrStr;
+ rTypeStrStr << "highp " << rType;
+ rTypeStr = rTypeStrStr.str();
+ }
+
+ // Note that y should be passed through angle_frm at the function call site,
+ // but x can't be passed through angle_frm there since it is an inout parameter.
+ // So only pass x and the result through angle_frm here.
+ sink <<
+ lTypeStr << " angle_compound_" << opNameStr << "_frm(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+ " x = angle_frm(angle_frm(x) " << opStr << " y);\n"
+ " return x;\n"
+ "}\n";
+ sink <<
+ lTypeStr << " angle_compound_" << opNameStr << "_frl(inout " << lTypeStr << " x, in " << rTypeStr << " y) {\n"
+ " x = angle_frl(angle_frm(x) " << opStr << " y);\n"
+ " return x;\n"
+ "}\n";
+}
+
+const char *getFloatTypeStr(const TType& type)
+{
+ switch (type.getNominalSize())
+ {
+ case 1:
+ return "float";
+ case 2:
+ return type.getSecondarySize() > 1 ? "mat2" : "vec2";
+ case 3:
+ return type.getSecondarySize() > 1 ? "mat3" : "vec3";
+ case 4:
+ return type.getSecondarySize() > 1 ? "mat4" : "vec4";
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+}
+
+bool canRoundFloat(const TType &type)
+{
+ return type.getBasicType() == EbtFloat && !type.isNonSquareMatrix() && !type.isArray() &&
+ (type.getPrecision() == EbpLow || type.getPrecision() == EbpMedium);
+}
+
+TIntermAggregate *createInternalFunctionCallNode(TString name, TIntermNode *child)
+{
+ TIntermAggregate *callNode = new TIntermAggregate();
+ callNode->setOp(EOpInternalFunctionCall);
+ callNode->setName(name);
+ callNode->getSequence()->push_back(child);
+ return callNode;
+}
+
+TIntermAggregate *createRoundingFunctionCallNode(TIntermTyped *roundedChild)
+{
+ TString roundFunctionName;
+ if (roundedChild->getPrecision() == EbpMedium)
+ roundFunctionName = "angle_frm";
+ else
+ roundFunctionName = "angle_frl";
+ return createInternalFunctionCallNode(roundFunctionName, roundedChild);
+}
+
+TIntermAggregate *createCompoundAssignmentFunctionCallNode(TIntermTyped *left, TIntermTyped *right, const char *opNameStr)
+{
+ std::stringstream strstr;
+ if (left->getPrecision() == EbpMedium)
+ strstr << "angle_compound_" << opNameStr << "_frm";
+ else
+ strstr << "angle_compound_" << opNameStr << "_frl";
+ TString functionName = strstr.str().c_str();
+ TIntermAggregate *callNode = createInternalFunctionCallNode(functionName, left);
+ callNode->getSequence()->push_back(right);
+ return callNode;
+}
+
+bool parentUsesResult(TIntermNode* parent, TIntermNode* node)
+{
+ if (!parent)
+ {
+ return false;
+ }
+
+ TIntermAggregate *aggParent = parent->getAsAggregate();
+ // If the parent's op is EOpSequence, the result is not assigned anywhere,
+ // so rounding it is not needed. In particular, this can avoid a lot of
+ // unnecessary rounding of unused return values of assignment.
+ if (aggParent && aggParent->getOp() == EOpSequence)
+ {
+ return false;
+ }
+ if (aggParent && aggParent->getOp() == EOpComma && (aggParent->getSequence()->back() != node))
+ {
+ return false;
+ }
+ return true;
+}
+
+} // namespace anonymous
+
+EmulatePrecision::EmulatePrecision()
+ : TIntermTraverser(true, true, true),
+ mDeclaringVariables(false),
+ mInLValue(false),
+ mInFunctionCallOutParameter(false)
+{}
+
+void EmulatePrecision::visitSymbol(TIntermSymbol *node)
+{
+ if (canRoundFloat(node->getType()) &&
+ !mDeclaringVariables && !mInLValue && !mInFunctionCallOutParameter)
+ {
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ }
+}
+
+
+bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
+{
+ bool visitChildren = true;
+
+ if (node->isAssignment())
+ {
+ if (visit == PreVisit)
+ mInLValue = true;
+ else if (visit == InVisit)
+ mInLValue = false;
+ }
+
+ TOperator op = node->getOp();
+
+ // RHS of initialize is not being declared.
+ if (op == EOpInitialize && visit == InVisit)
+ mDeclaringVariables = false;
+
+ if ((op == EOpIndexDirectStruct || op == EOpVectorSwizzle) && visit == InVisit)
+ visitChildren = false;
+
+ if (visit != PreVisit)
+ return visitChildren;
+
+ const TType& type = node->getType();
+ bool roundFloat = canRoundFloat(type);
+
+ if (roundFloat) {
+ switch (op) {
+ // Math operators that can result in a float may need to apply rounding to the return
+ // value. Note that in the case of assignment, the rounding is applied to its return
+ // value here, not the value being assigned.
+ case EOpAssign:
+ case EOpAdd:
+ case EOpSub:
+ case EOpMul:
+ case EOpDiv:
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar:
+ case EOpMatrixTimesMatrix:
+ {
+ TIntermNode *parent = getParentNode();
+ if (!parentUsesResult(parent, node))
+ {
+ break;
+ }
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ break;
+ }
+
+ // Compound assignment cases need to replace the operator with a function call.
+ case EOpAddAssign:
+ {
+ mEmulateCompoundAdd.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "add");
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
+ break;
+ }
+ case EOpSubAssign:
+ {
+ mEmulateCompoundSub.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "sub");
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
+ break;
+ }
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign:
+ {
+ mEmulateCompoundMul.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "mul");
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
+ break;
+ }
+ case EOpDivAssign:
+ {
+ mEmulateCompoundDiv.insert(TypePair(getFloatTypeStr(type), getFloatTypeStr(node->getRight()->getType())));
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createCompoundAssignmentFunctionCallNode(node->getLeft(), node->getRight(), "div");
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, false));
+ break;
+ }
+ default:
+ // The rest of the binary operations should not need precision emulation.
+ break;
+ }
+ }
+ return visitChildren;
+}
+
+bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
+{
+ bool visitChildren = true;
+ switch (node->getOp())
+ {
+ case EOpSequence:
+ case EOpConstructStruct:
+ // No special handling
+ break;
+ case EOpFunction:
+ if (visit == PreVisit)
+ {
+ const TIntermSequence &sequence = *(node->getSequence());
+ TIntermSequence::const_iterator seqIter = sequence.begin();
+ TIntermAggregate *params = (*seqIter)->getAsAggregate();
+ ASSERT(params != NULL);
+ ASSERT(params->getOp() == EOpParameters);
+ mFunctionMap[node->getName()] = params->getSequence();
+ }
+ break;
+ case EOpPrototype:
+ if (visit == PreVisit)
+ mFunctionMap[node->getName()] = node->getSequence();
+ visitChildren = false;
+ break;
+ case EOpParameters:
+ visitChildren = false;
+ break;
+ case EOpInvariantDeclaration:
+ visitChildren = false;
+ break;
+ case EOpDeclaration:
+ // Variable declaration.
+ if (visit == PreVisit)
+ {
+ mDeclaringVariables = true;
+ }
+ else if (visit == InVisit)
+ {
+ mDeclaringVariables = true;
+ }
+ else
+ {
+ mDeclaringVariables = false;
+ }
+ break;
+ case EOpFunctionCall:
+ {
+ // Function call.
+ bool inFunctionMap = (mFunctionMap.find(node->getName()) != mFunctionMap.end());
+ if (visit == PreVisit)
+ {
+ // User-defined function return values are not rounded, this relies on that
+ // calculations producing the value were rounded.
+ TIntermNode *parent = getParentNode();
+ if (canRoundFloat(node->getType()) && !inFunctionMap && parentUsesResult(parent, node))
+ {
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ }
+
+ if (inFunctionMap)
+ {
+ mSeqIterStack.push_back(mFunctionMap[node->getName()]->begin());
+ if (mSeqIterStack.back() != mFunctionMap[node->getName()]->end())
+ {
+ TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
+ mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
+ }
+ }
+ else
+ {
+ // The function is not user-defined - it is likely built-in texture function.
+ // Assume that those do not have out parameters.
+ mInFunctionCallOutParameter = false;
+ }
+ }
+ else if (visit == InVisit)
+ {
+ if (inFunctionMap)
+ {
+ ++mSeqIterStack.back();
+ TQualifier qualifier = (*mSeqIterStack.back())->getAsTyped()->getQualifier();
+ mInFunctionCallOutParameter = (qualifier == EvqOut || qualifier == EvqInOut);
+ }
+ }
+ else
+ {
+ if (inFunctionMap)
+ {
+ mSeqIterStack.pop_back();
+ mInFunctionCallOutParameter = false;
+ }
+ }
+ break;
+ }
+ default:
+ TIntermNode *parent = getParentNode();
+ if (canRoundFloat(node->getType()) && visit == PreVisit && parentUsesResult(parent, node))
+ {
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ }
+ break;
+ }
+ return visitChildren;
+}
+
+bool EmulatePrecision::visitUnary(Visit visit, TIntermUnary *node)
+{
+ switch (node->getOp())
+ {
+ case EOpNegative:
+ case EOpVectorLogicalNot:
+ case EOpLogicalNot:
+ break;
+ case EOpPostIncrement:
+ case EOpPostDecrement:
+ case EOpPreIncrement:
+ case EOpPreDecrement:
+ if (visit == PreVisit)
+ mInLValue = true;
+ else if (visit == PostVisit)
+ mInLValue = false;
+ break;
+ default:
+ if (canRoundFloat(node->getType()) && visit == PreVisit)
+ {
+ TIntermNode *parent = getParentNode();
+ TIntermNode *replacement = createRoundingFunctionCallNode(node);
+ mReplacements.push_back(NodeUpdateEntry(parent, node, replacement, true));
+ }
+ break;
+ }
+
+ return true;
+}
+
+void EmulatePrecision::writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage)
+{
+ // Other languages not yet supported
+ ASSERT(outputLanguage == SH_GLSL_COMPATIBILITY_OUTPUT ||
+ outputLanguage == SH_GLSL_CORE_OUTPUT ||
+ outputLanguage == SH_ESSL_OUTPUT);
+ writeCommonPrecisionEmulationHelpers(sink, outputLanguage);
+
+ EmulationSet::const_iterator it;
+ for (it = mEmulateCompoundAdd.begin(); it != mEmulateCompoundAdd.end(); it++)
+ writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "+", "add");
+ for (it = mEmulateCompoundSub.begin(); it != mEmulateCompoundSub.end(); it++)
+ writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "-", "sub");
+ for (it = mEmulateCompoundDiv.begin(); it != mEmulateCompoundDiv.end(); it++)
+ writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "/", "div");
+ for (it = mEmulateCompoundMul.begin(); it != mEmulateCompoundMul.end(); it++)
+ writeCompoundAssignmentPrecisionEmulation(sink, outputLanguage, it->lType, it->rType, "*", "mul");
+}
+
diff --git a/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
new file mode 100644
index 0000000000..f1f560aa85
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/EmulatePrecision.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+#define COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/IntermNode.h"
+#include "GLSLANG/ShaderLang.h"
+
+// This class gathers all compound assignments from the AST and can then write
+// the functions required for their precision emulation. This way there is no
+// need to write a huge number of variations of the emulated compound assignment
+// to every translated shader with emulation enabled.
+
+class EmulatePrecision : public TIntermTraverser
+{
+ public:
+ EmulatePrecision();
+
+ virtual void visitSymbol(TIntermSymbol *node);
+ virtual bool visitBinary(Visit visit, TIntermBinary *node);
+ virtual bool visitUnary(Visit visit, TIntermUnary *node);
+ virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
+
+ void writeEmulationHelpers(TInfoSinkBase& sink, ShShaderOutput outputLanguage);
+
+ private:
+ struct TypePair
+ {
+ TypePair(const char *l, const char *r)
+ : lType(l), rType(r) { }
+
+ const char *lType;
+ const char *rType;
+ };
+
+ struct TypePairComparator
+ {
+ bool operator() (const TypePair& l, const TypePair& r) const
+ {
+ if (l.lType == r.lType)
+ return l.rType < r.rType;
+ return l.lType < r.lType;
+ }
+ };
+
+ typedef std::set<TypePair, TypePairComparator> EmulationSet;
+ EmulationSet mEmulateCompoundAdd;
+ EmulationSet mEmulateCompoundSub;
+ EmulationSet mEmulateCompoundMul;
+ EmulationSet mEmulateCompoundDiv;
+
+ // Stack of function call parameter iterators
+ std::vector<TIntermSequence::const_iterator> mSeqIterStack;
+
+ bool mDeclaringVariables;
+ bool mInLValue;
+ bool mInFunctionCallOutParameter;
+
+ struct TStringComparator
+ {
+ bool operator() (const TString& a, const TString& b) const { return a.compare(b) < 0; }
+ };
+
+ // Map from function names to their parameter sequences
+ std::map<TString, TIntermSequence*, TStringComparator> mFunctionMap;
+};
+
+#endif // COMPILER_TRANSLATOR_EMULATE_PRECISION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
index 5c1595fb21..cf4d7fba31 100644
--- a/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
+++ b/src/3rdparty/angle/src/compiler/translator/ExtensionBehavior.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _EXTENSION_BEHAVIOR_INCLUDED_
-#define _EXTENSION_BEHAVIOR_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
+#define COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
#include <map>
#include <string>
@@ -34,4 +34,4 @@ inline const char* getBehaviorString(TBehavior b)
// Mapping between extension name and behavior.
typedef std::map<std::string, TBehavior> TExtensionBehavior;
-#endif // _EXTENSION_TABLE_INCLUDED_
+#endif // COMPILER_TRANSLATOR_EXTENSIONBEHAVIOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
index c93a6f808e..07b9a72c5c 100644
--- a/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
+++ b/src/3rdparty/angle/src/compiler/translator/FlagStd140Structs.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_FLAGSTD140STRUCTS_H_
-#define COMPILER_FLAGSTD140STRUCTS_H_
+#ifndef COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
+#define COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
#include "compiler/translator/IntermNode.h"
@@ -34,4 +34,4 @@ std::vector<TIntermTyped *> FlagStd140ValueStructs(TIntermNode *node);
}
-#endif // COMPILER_FLAGSTD140STRUCTS_H_
+#endif // COMPILER_TRANSLATOR_FLAGSTD140STRUCTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h
index a820d2a20d..c8787d55a0 100644
--- a/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h
+++ b/src/3rdparty/angle/src/compiler/translator/ForLoopUnroll.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_FORLOOPUNROLL_H_
-#define COMPILER_FORLOOPUNROLL_H_
+#ifndef COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
+#define COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
#include "compiler/translator/LoopInfo.h"
@@ -47,4 +47,4 @@ class ForLoopUnrollMarker : public TIntermTraverser
bool mVisitSamplerArrayIndexNodeInsideLoop;
};
-#endif
+#endif // COMPILER_TRANSLATOR_FORLOOPUNROLL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/HashNames.h b/src/3rdparty/angle/src/compiler/translator/HashNames.h
index 26546a3e7b..09c959f9da 100644
--- a/src/3rdparty/angle/src/compiler/translator/HashNames.h
+++ b/src/3rdparty/angle/src/compiler/translator/HashNames.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_HASH_NAMES_H_
-#define COMPILER_HASH_NAMES_H_
+#ifndef COMPILER_TRANSLATOR_HASHNAMES_H_
+#define COMPILER_TRANSLATOR_HASHNAMES_H_
#include <map>
@@ -15,4 +15,4 @@
typedef std::map<TPersistString, TPersistString> NameMap;
-#endif // COMPILER_HASH_NAMES_H_
+#endif // COMPILER_TRANSLATOR_HASHNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InfoSink.h b/src/3rdparty/angle/src/compiler/translator/InfoSink.h
index 698a8b454b..f47fafa8ee 100644
--- a/src/3rdparty/angle/src/compiler/translator/InfoSink.h
+++ b/src/3rdparty/angle/src/compiler/translator/InfoSink.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _INFOSINK_INCLUDED_
-#define _INFOSINK_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_INFOSINK_H_
+#define COMPILER_TRANSLATOR_INFOSINK_H_
#include <math.h>
#include <stdlib.h>
@@ -113,4 +113,4 @@ public:
TInfoSinkBase obj;
};
-#endif // _INFOSINK_INCLUDED_
+#endif // COMPILER_TRANSLATOR_INFOSINK_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
index 10b21e6d28..9e11405758 100644
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Initialize.cpp
@@ -21,307 +21,208 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
-
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
- TType *int4 = new TType(EbtInt, 4);
+ TType *uint1 = new TType(EbtUInt);
+ TType *bool1 = new TType(EbtBool);
+ TType *genType = new TType(EbtGenType);
+ TType *genIType = new TType(EbtGenIType);
+ TType *genUType = new TType(EbtGenUType);
+ TType *genBType = new TType(EbtGenBType);
//
// Angle and Trigonometric Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "radians", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "radians", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "radians", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "radians", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "degrees", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "degrees", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "degrees", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "degrees", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sin", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sin", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sin", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sin", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "cos", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "cos", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cos", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "cos", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "tan", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "tan", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "tan", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "tan", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "asin", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "asin", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "asin", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "asin", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "acos", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "acos", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "acos", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "acos", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "atan", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "atan", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "atan", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "atan", float4);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRadians, genType, "radians", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDegrees, genType, "degrees", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSin, genType, "sin", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCos, genType, "cos", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpTan, genType, "tan", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAsin, genType, "asin", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAcos, genType, "acos", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAtan, genType, "atan", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSinh, genType, "sinh", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpCosh, genType, "cosh", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTanh, genType, "tanh", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAsinh, genType, "asinh", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAcosh, genType, "acosh", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAtanh, genType, "atanh", genType);
//
// Exponential Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "pow", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "pow", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "pow", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "pow", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "exp2", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "exp2", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "exp2", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "exp2", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "log2", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "log2", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "log2", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "log2", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sqrt", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sqrt", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sqrt", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sqrt", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "inversesqrt", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "inversesqrt", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "inversesqrt", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "inversesqrt", float4);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpPow, genType, "pow", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp, genType, "exp", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog, genType, "log", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpExp2, genType, "exp2", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLog2, genType, "log2", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSqrt, genType, "sqrt", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpInverseSqrt, genType, "inversesqrt", genType);
//
// Common Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "abs", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "abs", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "abs", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "abs", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "sign", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "sign", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "sign", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "sign", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "floor", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "floor", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "floor", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "floor", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "ceil", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "ceil", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "ceil", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "ceil", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "fract", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "fract", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "fract", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "fract", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mod", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mod", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mod", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mod", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "min", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "min", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "min", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "min", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "max", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "max", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "max", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "max", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "clamp", float1, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "clamp", float2, float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "clamp", float3, float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "clamp", float4, float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "mix", float1, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "mix", float2, float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "mix", float3, float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "mix", float4, float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "step", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float4, float4);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "step", float1, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "step", float1, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "step", float1, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "smoothstep", float1, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float2, float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float3, float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float4, float4, float4);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "smoothstep", float1, float1, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "smoothstep", float1, float1, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "smoothstep", float1, float1, float4);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAbs, genType, "abs", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpAbs, genIType, "abs", genIType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSign, genType, "sign", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpSign, genIType, "sign", genIType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFloor, genType, "floor", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTrunc, genType, "trunc", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRound, genType, "round", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpRoundEven, genType, "roundEven", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCeil, genType, "ceil", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFract, genType, "fract", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMod, genType, "mod", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMin, genType, "min", genType, genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, genIType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genIType, "min", genIType, int1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, genUType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMin, genUType, "min", genUType, uint1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMax, genType, "max", genType, genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, genIType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genIType, "max", genIType, int1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, genUType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMax, genUType, "max", genUType, uint1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, float1, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpClamp, genType, "clamp", genType, genType, genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, int1, int1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genIType, "clamp", genIType, genIType, genIType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, uint1, uint1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpClamp, genUType, "clamp", genUType, genUType, genUType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMix, genType, "mix", genType, genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpStep, genType, "step", float1, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", genType, genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpSmoothStep, genType, "smoothstep", float1, float1, genType);
+
+ TType *outFloat1 = new TType(EbtFloat);
+ TType *outFloat2 = new TType(EbtFloat, 2);
+ TType *outFloat3 = new TType(EbtFloat, 3);
+ TType *outFloat4 = new TType(EbtFloat, 4);
+ outFloat1->setQualifier(EvqOut);
+ outFloat2->setQualifier(EvqOut);
+ outFloat3->setQualifier(EvqOut);
+ outFloat4->setQualifier(EvqOut);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float1, "modf", float1, outFloat1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float2, "modf", float2, outFloat2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float3, "modf", float3, outFloat3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpModf, float4, "modf", float4, outFloat4);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsNan, genBType, "isnan", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIsInf, genBType, "isinf", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToInt, genIType, "floatBitsToInt", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFloatBitsToUint, genUType, "floatBitsToUint", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpIntBitsToFloat, genType, "intBitsToFloat", genIType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUintBitsToFloat, genType, "uintBitsToFloat", genUType);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackSnorm2x16, uint1, "packSnorm2x16", float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackUnorm2x16, uint1, "packUnorm2x16", float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpPackHalf2x16, uint1, "packHalf2x16", float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackSnorm2x16, float2, "unpackSnorm2x16", uint1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackUnorm2x16, float2, "unpackUnorm2x16", uint1);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpUnpackHalf2x16, float2, "unpackHalf2x16", uint1);
//
// Geometric Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "length", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "distance", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "dot", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "cross", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "normalize", float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "normalize", float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "normalize", float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "normalize", float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "faceforward", float1, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "faceforward", float2, float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "faceforward", float3, float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "faceforward", float4, float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "reflect", float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "reflect", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "reflect", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "reflect", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float1, "refract", float1, float1, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float2, "refract", float2, float2, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float3, "refract", float3, float3, float1);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, float4, "refract", float4, float4, float1);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLength, float1, "length", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDistance, float1, "distance", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpDot, float1, "dot", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpCross, float3, "cross", float3, float3);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpNormalize, genType, "normalize", genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpFaceForward, genType, "faceforward", genType, genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpReflect, genType, "reflect", genType, genType);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpRefract, genType, "refract", genType, genType, float1);
TType *mat2 = new TType(EbtFloat, 2, 2);
TType *mat3 = new TType(EbtFloat, 3, 3);
TType *mat4 = new TType(EbtFloat, 4, 4);
+ TType *mat2x3 = new TType(EbtFloat, 2, 3);
+ TType *mat3x2 = new TType(EbtFloat, 3, 2);
+ TType *mat2x4 = new TType(EbtFloat, 2, 4);
+ TType *mat4x2 = new TType(EbtFloat, 4, 2);
+ TType *mat3x4 = new TType(EbtFloat, 3, 4);
+ TType *mat4x3 = new TType(EbtFloat, 4, 3);
//
// Matrix Functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, mat2, "matrixCompMult", mat2, mat2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, mat3, "matrixCompMult", mat3, mat3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, mat4, "matrixCompMult", mat4, mat4);
-
- TType *bool1 = new TType(EbtBool);
- TType *bool2 = new TType(EbtBool, 2);
- TType *bool3 = new TType(EbtBool, 3);
- TType *bool4 = new TType(EbtBool, 4);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat2, "matrixCompMult", mat2, mat2);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat3, "matrixCompMult", mat3, mat3);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpMul, mat4, "matrixCompMult", mat4, mat4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x3, "matrixCompMult", mat2x3, mat2x3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x2, "matrixCompMult", mat3x2, mat3x2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat2x4, "matrixCompMult", mat2x4, mat2x4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x2, "matrixCompMult", mat4x2, mat4x2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat3x4, "matrixCompMult", mat3x4, mat3x4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpMul, mat4x3, "matrixCompMult", mat4x3, mat4x3);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2, "outerProduct", float2, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3, "outerProduct", float3, float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4, "outerProduct", float4, float4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x3, "outerProduct", float3, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x2, "outerProduct", float2, float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat2x4, "outerProduct", float4, float2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x2, "outerProduct", float2, float4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat3x4, "outerProduct", float4, float3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpOuterProduct, mat4x3, "outerProduct", float3, float4);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2, "transpose", mat2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3, "transpose", mat3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4, "transpose", mat4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x3, "transpose", mat3x2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x2, "transpose", mat2x3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat2x4, "transpose", mat4x2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x2, "transpose", mat2x4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat3x4, "transpose", mat4x3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpTranspose, mat4x3, "transpose", mat3x4);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDeterminant, float1, "determinant", mat4);
+
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat2, "inverse", mat2);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat3, "inverse", mat3);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpInverse, mat4, "inverse", mat4);
+
+ TType *vec = new TType(EbtVec);
+ TType *ivec = new TType(EbtIVec);
+ TType *uvec = new TType(EbtUVec);
+ TType *bvec = new TType(EbtBVec);
//
// Vector relational functions.
//
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThan", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThan", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThan", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "lessThanEqual", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "lessThanEqual", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "lessThanEqual", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThan", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThan", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThan", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "greaterThanEqual", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "greaterThanEqual", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "greaterThanEqual", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "equal", bool2, bool2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "equal", bool3, bool3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "equal", bool4, bool4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", float2, float2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", float3, float3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", float4, float4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", int2, int2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", int3, int3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", int4, int4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "notEqual", bool2, bool2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "notEqual", bool3, bool3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "notEqual", bool4, bool4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "any", bool4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool1, "all", bool4);
-
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool2, "not", bool2);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool3, "not", bool3);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, bool4, "not", bool4);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThan, bvec, "lessThan", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThan, bvec, "lessThan", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpLessThanEqual, bvec, "lessThanEqual", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThan, bvec, "greaterThan", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThan, bvec, "greaterThan", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpGreaterThanEqual, bvec, "greaterThanEqual", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorEqual, bvec, "equal", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorEqual, bvec, "equal", bvec, bvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", vec, vec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", ivec, ivec);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", uvec, uvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorNotEqual, bvec, "notEqual", bvec, bvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec);
TType *sampler2D = new TType(EbtSampler2D);
TType *samplerCube = new TType(EbtSamplerCube);
@@ -357,10 +258,10 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
/* The *Grad* variants are new to both vertex and fragment shaders; the fragment
* shader specific pieces are added separately below.
*/
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DGradEXT", sampler2D, float2, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float3, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjGradEXT", sampler2D, float4, float2, float2);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeGradEXT", samplerCube, float3, float3, float3);
}
if (type == GL_FRAGMENT_SHADER)
@@ -372,32 +273,21 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
if (resources.OES_standard_derivatives)
{
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdx", float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdx", float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdx", float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdx", float4);
-
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "dFdy", float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "dFdy", float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "dFdy", float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "dFdy", float4);
-
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float1, "fwidth", float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float2, "fwidth", float2);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float3, "fwidth", float3);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "fwidth", float4);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdx, "GL_OES_standard_derivatives", genType, "dFdx", genType);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpDFdy, "GL_OES_standard_derivatives", genType, "dFdy", genType);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, EOpFwidth, "GL_OES_standard_derivatives", genType, "fwidth", genType);
}
if (resources.EXT_shader_texture_lod)
{
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLodEXT", sampler2D, float2, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float3, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLodEXT", sampler2D, float4, float1);
- symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "textureCubeLodEXT", samplerCube, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DLodEXT", sampler2D, float2, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float3, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "texture2DProjLodEXT", sampler2D, float4, float1);
+ symbolTable.insertBuiltIn(ESSL1_BUILTINS, "GL_EXT_shader_texture_lod", float4, "textureCubeLodEXT", samplerCube, float3, float1);
}
}
- if(type == GL_VERTEX_SHADER)
+ if (type == GL_VERTEX_SHADER)
{
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DLod", sampler2D, float2, float1);
symbolTable.insertBuiltIn(ESSL1_BUILTINS, float4, "texture2DProjLod", sampler2D, float3, float1);
@@ -463,22 +353,11 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int2, "textureSize", samplerCubeShadow, int1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, int3, "textureSize", sampler2DArrayShadow, int1);
- if(type == GL_FRAGMENT_SHADER)
+ if (type == GL_FRAGMENT_SHADER)
{
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdx", float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdx", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdx", float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdx", float4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "dFdy", float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "dFdy", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "dFdy", float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "dFdy", float4);
-
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "fwidth", float1);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float2, "fwidth", float2);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float3, "fwidth", float3);
- symbolTable.insertBuiltIn(ESSL3_BUILTINS, float4, "fwidth", float4);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdx, genType, "dFdx", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpDFdy, genType, "dFdy", genType);
+ symbolTable.insertBuiltIn(ESSL3_BUILTINS, EOpFwidth, genType, "fwidth", genType);
}
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2);
@@ -486,7 +365,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureOffset", sampler2DShadow, float3, int2);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2DArray, float3, int2);
- if(type == GL_FRAGMENT_SHADER)
+ if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler2D, float2, int2, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureOffset", gsampler3D, float3, int3, float1);
@@ -499,7 +378,7 @@ void InsertBuiltInFunctions(sh::GLenum type, ShShaderSpec spec, const ShBuiltInR
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler3D, float4, int3);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, float1, "textureProjOffset", sampler2DShadow, float4, int2);
- if(type == GL_FRAGMENT_SHADER)
+ if (type == GL_FRAGMENT_SHADER)
{
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float3, int2, float1);
symbolTable.insertBuiltIn(ESSL3_BUILTINS, gvec4, "textureProjOffset", gsampler2D, float4, int2, float1);
@@ -600,146 +479,84 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
TSymbolTable &symbolTable)
{
//
- // First, insert some special built-in variables that are not in
+ // Insert some special built-in variables that are not in
// the built-in header files.
//
- switch(type) {
- case GL_FRAGMENT_SHADER:
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"), TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"), TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"), TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
+ switch (type)
+ {
+ case GL_FRAGMENT_SHADER:
+ symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FragCoord"),
+ TType(EbtFloat, EbpMedium, EvqFragCoord, 4)));
+ symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_FrontFacing"),
+ TType(EbtBool, EbpUndefined, EvqFrontFacing, 1)));
+ symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointCoord"),
+ TType(EbtFloat, EbpMedium, EvqPointCoord, 2)));
//
// In CSS Shaders, gl_FragColor, gl_FragData, and gl_MaxDrawBuffers are not available.
// Instead, css_MixColor and css_ColorMatrix are available.
//
- if (spec != SH_CSS_SHADERS_SPEC) {
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"), TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData[gl_MaxDrawBuffers]"), TType(EbtFloat, EbpMedium, EvqFragData, 4)));
- if (resources.EXT_frag_depth) {
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragDepthEXT"), TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
- symbolTable.relateToExtension(ESSL1_BUILTINS, "gl_FragDepthEXT", "GL_EXT_frag_depth");
- }
- } else {
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"), TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"), TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
- }
-
- break;
-
- case GL_VERTEX_SHADER:
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"), TType(EbtFloat, EbpHigh, EvqPosition, 4)));
- symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"), TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
- break;
-
- default: assert(false && "Language not supported");
- }
-
- //
- // Next, identify which built-ins from the already loaded headers have
- // a mapping to an operator. Those that are not identified as such are
- // expected to be resolved through a library of functions, versus as
- // operations.
- //
- symbolTable.relateToOperator(COMMON_BUILTINS, "matrixCompMult", EOpMul);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "equal", EOpVectorEqual);
- symbolTable.relateToOperator(COMMON_BUILTINS, "notEqual", EOpVectorNotEqual);
- symbolTable.relateToOperator(COMMON_BUILTINS, "lessThan", EOpLessThan);
- symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThan", EOpGreaterThan);
- symbolTable.relateToOperator(COMMON_BUILTINS, "lessThanEqual", EOpLessThanEqual);
- symbolTable.relateToOperator(COMMON_BUILTINS, "greaterThanEqual", EOpGreaterThanEqual);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "radians", EOpRadians);
- symbolTable.relateToOperator(COMMON_BUILTINS, "degrees", EOpDegrees);
- symbolTable.relateToOperator(COMMON_BUILTINS, "sin", EOpSin);
- symbolTable.relateToOperator(COMMON_BUILTINS, "cos", EOpCos);
- symbolTable.relateToOperator(COMMON_BUILTINS, "tan", EOpTan);
- symbolTable.relateToOperator(COMMON_BUILTINS, "asin", EOpAsin);
- symbolTable.relateToOperator(COMMON_BUILTINS, "acos", EOpAcos);
- symbolTable.relateToOperator(COMMON_BUILTINS, "atan", EOpAtan);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "pow", EOpPow);
- symbolTable.relateToOperator(COMMON_BUILTINS, "exp2", EOpExp2);
- symbolTable.relateToOperator(COMMON_BUILTINS, "log", EOpLog);
- symbolTable.relateToOperator(COMMON_BUILTINS, "exp", EOpExp);
- symbolTable.relateToOperator(COMMON_BUILTINS, "log2", EOpLog2);
- symbolTable.relateToOperator(COMMON_BUILTINS, "sqrt", EOpSqrt);
- symbolTable.relateToOperator(COMMON_BUILTINS, "inversesqrt", EOpInverseSqrt);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "abs", EOpAbs);
- symbolTable.relateToOperator(COMMON_BUILTINS, "sign", EOpSign);
- symbolTable.relateToOperator(COMMON_BUILTINS, "floor", EOpFloor);
- symbolTable.relateToOperator(COMMON_BUILTINS, "ceil", EOpCeil);
- symbolTable.relateToOperator(COMMON_BUILTINS, "fract", EOpFract);
- symbolTable.relateToOperator(COMMON_BUILTINS, "mod", EOpMod);
- symbolTable.relateToOperator(COMMON_BUILTINS, "min", EOpMin);
- symbolTable.relateToOperator(COMMON_BUILTINS, "max", EOpMax);
- symbolTable.relateToOperator(COMMON_BUILTINS, "clamp", EOpClamp);
- symbolTable.relateToOperator(COMMON_BUILTINS, "mix", EOpMix);
- symbolTable.relateToOperator(COMMON_BUILTINS, "step", EOpStep);
- symbolTable.relateToOperator(COMMON_BUILTINS, "smoothstep", EOpSmoothStep);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "length", EOpLength);
- symbolTable.relateToOperator(COMMON_BUILTINS, "distance", EOpDistance);
- symbolTable.relateToOperator(COMMON_BUILTINS, "dot", EOpDot);
- symbolTable.relateToOperator(COMMON_BUILTINS, "cross", EOpCross);
- symbolTable.relateToOperator(COMMON_BUILTINS, "normalize", EOpNormalize);
- symbolTable.relateToOperator(COMMON_BUILTINS, "faceforward", EOpFaceForward);
- symbolTable.relateToOperator(COMMON_BUILTINS, "reflect", EOpReflect);
- symbolTable.relateToOperator(COMMON_BUILTINS, "refract", EOpRefract);
-
- symbolTable.relateToOperator(COMMON_BUILTINS, "any", EOpAny);
- symbolTable.relateToOperator(COMMON_BUILTINS, "all", EOpAll);
- symbolTable.relateToOperator(COMMON_BUILTINS, "not", EOpVectorLogicalNot);
-
- // Map language-specific operators.
- switch(type) {
- case GL_VERTEX_SHADER:
- break;
- case GL_FRAGMENT_SHADER:
- if (resources.OES_standard_derivatives)
+ if (spec != SH_CSS_SHADERS_SPEC)
{
- symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdx", EOpDFdx);
- symbolTable.relateToOperator(ESSL1_BUILTINS, "dFdy", EOpDFdy);
- symbolTable.relateToOperator(ESSL1_BUILTINS, "fwidth", EOpFwidth);
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragColor"),
+ TType(EbtFloat, EbpMedium, EvqFragColor, 4)));
+ TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
+ fragData.setArraySize(resources.MaxDrawBuffers);
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));
+
+ if (resources.EXT_frag_depth)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_frag_depth", new TVariable(NewPoolTString("gl_FragDepthEXT"),
+ TType(EbtFloat, resources.FragmentPrecisionHigh ? EbpHigh : EbpMedium, EvqFragDepth, 1)));
+ }
- symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdx", "GL_OES_standard_derivatives");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "dFdy", "GL_OES_standard_derivatives");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "fwidth", "GL_OES_standard_derivatives");
+ if (resources.EXT_shader_framebuffer_fetch || resources.NV_shader_framebuffer_fetch)
+ {
+ TType lastFragData(EbtFloat, EbpMedium, EvqLastFragData, 4, 1, true);
+ lastFragData.setArraySize(resources.MaxDrawBuffers);
+
+ if (resources.EXT_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, "GL_EXT_shader_framebuffer_fetch",
+ new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+ }
+ else if (resources.NV_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
+ new TVariable(NewPoolTString("gl_LastFragColor"),
+ TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+ symbolTable.insert(ESSL1_BUILTINS, "GL_NV_shader_framebuffer_fetch",
+ new TVariable(NewPoolTString("gl_LastFragData"), lastFragData));
+ }
+ }
+ else if (resources.ARM_shader_framebuffer_fetch)
+ {
+ symbolTable.insert(ESSL1_BUILTINS, "GL_ARM_shader_framebuffer_fetch",
+ new TVariable(NewPoolTString("gl_LastFragColorARM"),
+ TType(EbtFloat, EbpMedium, EvqLastFragColor, 4)));
+ }
}
- if (resources.EXT_shader_texture_lod)
+ else
{
- symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DLodEXT", "GL_EXT_shader_texture_lod");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjLodEXT", "GL_EXT_shader_texture_lod");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeLodEXT", "GL_EXT_shader_texture_lod");
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_MixColor"),
+ TType(EbtFloat, EbpMedium, EvqGlobal, 4)));
+ symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("css_ColorMatrix"),
+ TType(EbtFloat, EbpMedium, EvqGlobal, 4, 4)));
}
- break;
- default: break;
- }
- symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdx", EOpDFdx);
- symbolTable.relateToOperator(ESSL3_BUILTINS, "dFdy", EOpDFdy);
- symbolTable.relateToOperator(ESSL3_BUILTINS, "fwidth", EOpFwidth);
-
- if (resources.EXT_shader_texture_lod)
- {
- symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DGradEXT", "GL_EXT_shader_texture_lod");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "texture2DProjGradEXT", "GL_EXT_shader_texture_lod");
- symbolTable.relateToExtension(ESSL1_BUILTINS, "textureCubeGradEXT", "GL_EXT_shader_texture_lod");
- }
+ break;
- // Finally add resource-specific variables.
- switch(type) {
- case GL_FRAGMENT_SHADER:
- if (spec != SH_CSS_SHADERS_SPEC) {
- // Set up gl_FragData. The array size.
- TType fragData(EbtFloat, EbpMedium, EvqFragData, 4, 1, true);
- fragData.setArraySize(resources.MaxDrawBuffers);
- symbolTable.insert(ESSL1_BUILTINS, new TVariable(NewPoolTString("gl_FragData"), fragData));
- }
+ case GL_VERTEX_SHADER:
+ symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_Position"),
+ TType(EbtFloat, EbpHigh, EvqPosition, 4)));
+ symbolTable.insert(COMMON_BUILTINS, new TVariable(NewPoolTString("gl_PointSize"),
+ TType(EbtFloat, EbpMedium, EvqPointSize, 1)));
+ symbolTable.insert(ESSL3_BUILTINS, new TVariable(NewPoolTString("gl_InstanceID"),
+ TType(EbtInt, EbpHigh, EvqInstanceID, 1)));
break;
- default: break;
+
+ default:
+ assert(false && "Language not supported");
}
}
@@ -758,4 +575,20 @@ void InitExtensionBehavior(const ShBuiltInResources& resources,
extBehavior["GL_EXT_frag_depth"] = EBhUndefined;
if (resources.EXT_shader_texture_lod)
extBehavior["GL_EXT_shader_texture_lod"] = EBhUndefined;
+ if (resources.EXT_shader_framebuffer_fetch)
+ extBehavior["GL_EXT_shader_framebuffer_fetch"] = EBhUndefined;
+ if (resources.NV_shader_framebuffer_fetch)
+ extBehavior["GL_NV_shader_framebuffer_fetch"] = EBhUndefined;
+ if (resources.ARM_shader_framebuffer_fetch)
+ extBehavior["GL_ARM_shader_framebuffer_fetch"] = EBhUndefined;
+}
+
+void ResetExtensionBehavior(TExtensionBehavior &extBehavior)
+{
+ for (auto ext_iter = extBehavior.begin();
+ ext_iter != extBehavior.end();
+ ++ext_iter)
+ {
+ ext_iter->second = EBhUndefined;
+ }
}
diff --git a/src/3rdparty/angle/src/compiler/translator/Initialize.h b/src/3rdparty/angle/src/compiler/translator/Initialize.h
index cc1862c90e..c43ce3417a 100644
--- a/src/3rdparty/angle/src/compiler/translator/Initialize.h
+++ b/src/3rdparty/angle/src/compiler/translator/Initialize.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _INITIALIZE_INCLUDED_
-#define _INITIALIZE_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_INITIALIZE_H_
+#define COMPILER_TRANSLATOR_INITIALIZE_H_
#include "compiler/translator/Common.h"
#include "compiler/translator/Compiler.h"
@@ -20,4 +20,10 @@ void IdentifyBuiltIns(sh::GLenum type, ShShaderSpec spec,
void InitExtensionBehavior(const ShBuiltInResources& resources,
TExtensionBehavior& extensionBehavior);
-#endif // _INITIALIZE_INCLUDED_
+// Resets the behavior of the extensions listed in |extensionBehavior| to the
+// undefined state. These extensions will only be those initially supported in
+// the ShBuiltInResources object for this compiler instance. All other
+// extensions will remain unsupported.
+void ResetExtensionBehavior(TExtensionBehavior &extensionBehavior);
+
+#endif // COMPILER_TRANSLATOR_INITIALIZE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
index 43070cc3ff..4c400760f6 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeDll.h
@@ -3,11 +3,11 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-#ifndef __INITIALIZEDLL_H
-#define __INITIALIZEDLL_H
+#ifndef COMPILER_TRANSLATOR_INITIALIZEDLL_H_
+#define COMPILER_TRANSLATOR_INITIALIZEDLL_H_
bool InitProcess();
void DetachProcess();
-#endif // __INITIALIZEDLL_H
+#endif // COMPILER_TRANSLATOR_INITIALIZEDLL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
index 0715941424..8c65cb28da 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeGlobals.h
@@ -4,10 +4,10 @@
// found in the LICENSE file.
//
-#ifndef __INITIALIZE_GLOBALS_INCLUDED_
-#define __INITIALIZE_GLOBALS_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
+#define COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
bool InitializePoolIndex();
void FreePoolIndex();
-#endif // __INITIALIZE_GLOBALS_INCLUDED_
+#endif // COMPILER_TRANSLATOR_INITIALIZEGLOBALS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h
index bffbab87d0..fa9b885e80 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeParseContext.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef __INITIALIZE_PARSE_CONTEXT_INCLUDED_
-#define __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
+#define COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
bool InitializeParseContextIndex();
void FreeParseContextIndex();
@@ -14,4 +14,4 @@ struct TParseContext;
extern void SetGlobalParseContext(TParseContext* context);
extern TParseContext* GetGlobalParseContext();
-#endif // __INITIALIZE_PARSE_CONTEXT_INCLUDED_
+#endif // COMPILER_TRANSLATOR_INITIALIZEPARSECONTEXT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
index 59c3ea0a39..4a81266498 100644
--- a/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
+++ b/src/3rdparty/angle/src/compiler/translator/InitializeVariables.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_INITIALIZE_VARIABLES_H_
-#define COMPILER_INITIALIZE_VARIABLES_H_
+#ifndef COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
+#define COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
#include "compiler/translator/IntermNode.h"
@@ -47,4 +47,4 @@ class InitializeVariables : public TIntermTraverser
bool mCodeInserted;
};
-#endif // COMPILER_INITIALIZE_VARIABLES_H_
+#endif // COMPILER_TRANSLATOR_INITIALIZEVARIABLES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
index aa0f31d170..266e3c8e3d 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp
@@ -157,26 +157,6 @@ bool TIntermLoop::replaceChildNode(
return false;
}
-void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mInit)
- {
- nodeQueue->push(mInit);
- }
- if (mCond)
- {
- nodeQueue->push(mCond);
- }
- if (mExpr)
- {
- nodeQueue->push(mExpr);
- }
- if (mBody)
- {
- nodeQueue->push(mBody);
- }
-}
-
bool TIntermBranch::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@@ -184,14 +164,6 @@ bool TIntermBranch::replaceChildNode(
return false;
}
-void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mExpression)
- {
- nodeQueue->push(mExpression);
- }
-}
-
bool TIntermBinary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@@ -200,18 +172,6 @@ bool TIntermBinary::replaceChildNode(
return false;
}
-void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mLeft)
- {
- nodeQueue->push(mLeft);
- }
- if (mRight)
- {
- nodeQueue->push(mRight);
- }
-}
-
bool TIntermUnary::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@@ -219,14 +179,6 @@ bool TIntermUnary::replaceChildNode(
return false;
}
-void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- if (mOperand)
- {
- nodeQueue->push(mOperand);
- }
-}
-
bool TIntermAggregate::replaceChildNode(
TIntermNode *original, TIntermNode *replacement)
{
@@ -237,14 +189,6 @@ bool TIntermAggregate::replaceChildNode(
return false;
}
-void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
-{
- for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++)
- {
- nodeQueue->push(mSequence[childIndex]);
- }
-}
-
void TIntermAggregate::setPrecisionFromChildren()
{
if (getBasicType() == EbtBool)
@@ -300,20 +244,19 @@ bool TIntermSelection::replaceChildNode(
return false;
}
-void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const
+bool TIntermSwitch::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
{
- if (mCondition)
- {
- nodeQueue->push(mCondition);
- }
- if (mTrueBlock)
- {
- nodeQueue->push(mTrueBlock);
- }
- if (mFalseBlock)
- {
- nodeQueue->push(mFalseBlock);
- }
+ REPLACE_IF_IS(mInit, TIntermTyped, original, replacement);
+ REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement);
+ return false;
+}
+
+bool TIntermCase::replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement)
+{
+ REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
+ return false;
}
//
@@ -336,6 +279,12 @@ bool TIntermOperator::isAssignment() const
case EOpMatrixTimesScalarAssign:
case EOpMatrixTimesMatrixAssign:
case EOpDivAssign:
+ case EOpIModAssign:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
return true;
default:
return false;
@@ -379,65 +328,55 @@ bool TIntermOperator::isConstructor() const
// Make sure the type of a unary operator is appropriate for its
// combination of operation and operand type.
//
-// Returns false in nothing makes sense.
-//
-bool TIntermUnary::promote(TInfoSink &)
+void TIntermUnary::promote(const TType *funcReturnType)
{
switch (mOp)
{
- case EOpLogicalNot:
- if (mOperand->getBasicType() != EbtBool)
- return false;
+ case EOpFloatBitsToInt:
+ case EOpFloatBitsToUint:
+ case EOpIntBitsToFloat:
+ case EOpUintBitsToFloat:
+ case EOpPackSnorm2x16:
+ case EOpPackUnorm2x16:
+ case EOpPackHalf2x16:
+ case EOpUnpackSnorm2x16:
+ case EOpUnpackUnorm2x16:
+ mType.setPrecision(EbpHigh);
break;
- case EOpNegative:
- case EOpPositive:
- case EOpPostIncrement:
- case EOpPostDecrement:
- case EOpPreIncrement:
- case EOpPreDecrement:
- if (mOperand->getBasicType() == EbtBool)
- return false;
+ case EOpUnpackHalf2x16:
+ mType.setPrecision(EbpMedium);
break;
-
- // operators for built-ins are already type checked against their prototype
- case EOpAny:
- case EOpAll:
- case EOpVectorLogicalNot:
- return true;
-
default:
- if (mOperand->getBasicType() != EbtFloat)
- return false;
+ setType(mOperand->getType());
}
- setType(mOperand->getType());
- mType.setQualifier(EvqTemporary);
+ if (funcReturnType != nullptr)
+ {
+ if (funcReturnType->getBasicType() == EbtBool)
+ {
+ // Bool types should not have precision.
+ setType(*funcReturnType);
+ }
+ else
+ {
+ // Precision of the node has been set based on the operand.
+ setTypePreservePrecision(*funcReturnType);
+ }
+ }
- return true;
+ mType.setQualifier(EvqTemporary);
}
//
// Establishes the type of the resultant operation, as well as
// makes the operator the correct one for the operands.
//
-// Returns false if operator can't work on operands.
+// For lots of operations it should already be established that the operand
+// combination is valid, but returns false if operator can't work on operands.
//
bool TIntermBinary::promote(TInfoSink &infoSink)
{
- // This function only handles scalars, vectors, and matrices.
- if (mLeft->isArray() || mRight->isArray())
- {
- infoSink.info.message(EPrefixInternalError, getLine(),
- "Invalid operation for arrays");
- return false;
- }
-
- // GLSL ES 2.0 does not support implicit type casting.
- // So the basic type should always match.
- if (mLeft->getBasicType() != mRight->getBasicType())
- {
- return false;
- }
+ ASSERT(mLeft->isArray() == mRight->isArray());
//
// Base assumption: just make the type the same as the left
@@ -483,12 +422,9 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
// And and Or operate on conditionals
//
case EOpLogicalAnd:
+ case EOpLogicalXor:
case EOpLogicalOr:
- // Both operands must be of type bool.
- if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool)
- {
- return false;
- }
+ ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool);
setType(TType(EbtBool, EbpUndefined));
break;
@@ -625,12 +561,28 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
case EOpAssign:
case EOpInitialize:
+ // No more additional checks are needed.
+ ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+ (mLeft->getSecondarySize() == mRight->getSecondarySize()));
+ break;
case EOpAdd:
case EOpSub:
case EOpDiv:
+ case EOpIMod:
+ case EOpBitShiftLeft:
+ case EOpBitShiftRight:
+ case EOpBitwiseAnd:
+ case EOpBitwiseXor:
+ case EOpBitwiseOr:
case EOpAddAssign:
case EOpSubAssign:
case EOpDivAssign:
+ case EOpIModAssign:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
if ((mLeft->isMatrix() && mRight->isVector()) ||
(mLeft->isVector() && mRight->isMatrix()))
{
@@ -641,13 +593,19 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
if (mLeft->getNominalSize() != mRight->getNominalSize() ||
mLeft->getSecondarySize() != mRight->getSecondarySize())
{
- // If the nominal size of operands do not match:
- // One of them must be scalar.
+ // If the nominal sizes of operands do not match:
+ // One of them must be a scalar.
if (!mLeft->isScalar() && !mRight->isScalar())
return false;
- // Operator cannot be of type pure assignment.
- if (mOp == EOpAssign || mOp == EOpInitialize)
+ // In the case of compound assignment other than multiply-assign,
+ // the right side needs to be a scalar. Otherwise a vector/matrix
+ // would be assigned to a scalar. A scalar can't be shifted by a
+ // vector either.
+ if (!mRight->isScalar() &&
+ (isAssignment() ||
+ mOp == EOpBitShiftLeft ||
+ mOp == EOpBitShiftRight))
return false;
}
@@ -656,6 +614,11 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
mLeft->getSecondarySize(), mRight->getSecondarySize());
setType(TType(basicType, higherPrecision, EvqTemporary,
nominalSize, secondarySize));
+ if (mLeft->isArray())
+ {
+ ASSERT(mLeft->getArraySize() == mRight->getArraySize());
+ mType.setArraySize(mLeft->getArraySize());
+ }
}
break;
@@ -665,11 +628,8 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
case EOpGreaterThan:
case EOpLessThanEqual:
case EOpGreaterThanEqual:
- if ((mLeft->getNominalSize() != mRight->getNominalSize()) ||
- (mLeft->getSecondarySize() != mRight->getSecondarySize()))
- {
- return false;
- }
+ ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) &&
+ (mLeft->getSecondarySize() == mRight->getSecondarySize()));
setType(TType(EbtBool, EbpUndefined));
break;
@@ -793,6 +753,7 @@ TIntermTyped *TIntermConstantUnion::fold(
break;
case EOpDiv:
+ case EOpIMod:
{
tempConstArray = new ConstantUnion[objectSize];
for (size_t i = 0; i < objectSize; i++)
@@ -810,6 +771,7 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
+ ASSERT(op == EOpDiv);
tempConstArray[i].setFConst(
unionArray[i].getFConst() /
rightUnionArray[i].getFConst());
@@ -826,9 +788,19 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
- tempConstArray[i].setIConst(
- unionArray[i].getIConst() /
- rightUnionArray[i].getIConst());
+ if (op == EOpDiv)
+ {
+ tempConstArray[i].setIConst(
+ unionArray[i].getIConst() /
+ rightUnionArray[i].getIConst());
+ }
+ else
+ {
+ ASSERT(op == EOpIMod);
+ tempConstArray[i].setIConst(
+ unionArray[i].getIConst() %
+ rightUnionArray[i].getIConst());
+ }
}
break;
@@ -842,9 +814,19 @@ TIntermTyped *TIntermConstantUnion::fold(
}
else
{
- tempConstArray[i].setUConst(
- unionArray[i].getUConst() /
- rightUnionArray[i].getUConst());
+ if (op == EOpDiv)
+ {
+ tempConstArray[i].setUConst(
+ unionArray[i].getUConst() /
+ rightUnionArray[i].getUConst());
+ }
+ else
+ {
+ ASSERT(op == EOpIMod);
+ tempConstArray[i].setUConst(
+ unionArray[i].getUConst() %
+ rightUnionArray[i].getUConst());
+ }
}
break;
@@ -968,6 +950,32 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
+ case EOpBitwiseAnd:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] & rightUnionArray[i];
+ break;
+ case EOpBitwiseXor:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] ^ rightUnionArray[i];
+ break;
+ case EOpBitwiseOr:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] | rightUnionArray[i];
+ break;
+ case EOpBitShiftLeft:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] << rightUnionArray[i];
+ break;
+ case EOpBitShiftRight:
+ tempConstArray = new ConstantUnion[objectSize];
+ for (size_t i = 0; i < objectSize; i++)
+ tempConstArray[i] = unionArray[i] >> rightUnionArray[i];
+ break;
+
case EOpLessThan:
ASSERT(objectSize == 1);
tempConstArray = new ConstantUnion[1];
@@ -1160,6 +1168,23 @@ TIntermTyped *TIntermConstantUnion::fold(
}
break;
+ case EOpBitwiseNot:
+ switch (getType().getBasicType())
+ {
+ case EbtInt:
+ tempConstArray[i].setIConst(~unionArray[i].getIConst());
+ break;
+ case EbtUInt:
+ tempConstArray[i].setUConst(~unionArray[i].getUConst());
+ break;
+ default:
+ infoSink.info.message(
+ EPrefixInternalError, getLine(),
+ "Unary operation not folded into constant");
+ return NULL;
+ }
+ break;
+
default:
return NULL;
}
@@ -1181,3 +1206,29 @@ TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunctio
TString hashedName = stream.str();
return hashedName;
}
+
+void TIntermTraverser::updateTree()
+{
+ for (size_t ii = 0; ii < mReplacements.size(); ++ii)
+ {
+ const NodeUpdateEntry& entry = mReplacements[ii];
+ ASSERT(entry.parent);
+ bool replaced = entry.parent->replaceChildNode(
+ entry.original, entry.replacement);
+ ASSERT(replaced);
+
+ if (!entry.originalBecomesChildOfReplacement)
+ {
+ // In AST traversing, a parent is visited before its children.
+ // After we replace a node, if an immediate child is to
+ // be replaced, we need to make sure we don't update the replaced
+ // node; instead, we update the replacement node.
+ for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj)
+ {
+ NodeUpdateEntry& entry2 = mReplacements[jj];
+ if (entry2.parent == entry.original)
+ entry2.parent = entry.replacement;
+ }
+ }
+ }
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.h b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
index 32c70f4671..9f732cbb00 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermNode.h
+++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.h
@@ -13,182 +13,19 @@
// each node can have it's own type of list of children.
//
-#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
-#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#ifndef COMPILER_TRANSLATOR_INTERMNODE_H_
+#define COMPILER_TRANSLATOR_INTERMNODE_H_
#include "GLSLANG/ShaderLang.h"
#include <algorithm>
#include <queue>
+#include "common/angleutils.h"
#include "compiler/translator/Common.h"
#include "compiler/translator/Types.h"
#include "compiler/translator/ConstantUnion.h"
-
-//
-// Operators used by the high-level (parse tree) representation.
-//
-enum TOperator
-{
- EOpNull, // if in a node, should only mean a node is still being built
- EOpSequence, // denotes a list of statements, or parameters, etc.
- EOpFunctionCall,
- EOpFunction, // For function definition
- EOpParameters, // an aggregate listing the parameters to a function
-
- EOpDeclaration,
- EOpInvariantDeclaration, // Specialized declarations for attributing invariance
- EOpPrototype,
-
- //
- // Unary operators
- //
-
- EOpNegative,
- EOpPositive,
- EOpLogicalNot,
- EOpVectorLogicalNot,
-
- EOpPostIncrement,
- EOpPostDecrement,
- EOpPreIncrement,
- EOpPreDecrement,
-
- //
- // binary operations
- //
-
- EOpAdd,
- EOpSub,
- EOpMul,
- EOpDiv,
- EOpEqual,
- EOpNotEqual,
- EOpVectorEqual,
- EOpVectorNotEqual,
- EOpLessThan,
- EOpGreaterThan,
- EOpLessThanEqual,
- EOpGreaterThanEqual,
- EOpComma,
-
- EOpVectorTimesScalar,
- EOpVectorTimesMatrix,
- EOpMatrixTimesVector,
- EOpMatrixTimesScalar,
-
- EOpLogicalOr,
- EOpLogicalXor,
- EOpLogicalAnd,
-
- EOpIndexDirect,
- EOpIndexIndirect,
- EOpIndexDirectStruct,
- EOpIndexDirectInterfaceBlock,
-
- EOpVectorSwizzle,
-
- //
- // Built-in functions potentially mapped to operators
- //
-
- EOpRadians,
- EOpDegrees,
- EOpSin,
- EOpCos,
- EOpTan,
- EOpAsin,
- EOpAcos,
- EOpAtan,
-
- EOpPow,
- EOpExp,
- EOpLog,
- EOpExp2,
- EOpLog2,
- EOpSqrt,
- EOpInverseSqrt,
-
- EOpAbs,
- EOpSign,
- EOpFloor,
- EOpCeil,
- EOpFract,
- EOpMod,
- EOpMin,
- EOpMax,
- EOpClamp,
- EOpMix,
- EOpStep,
- EOpSmoothStep,
-
- EOpLength,
- EOpDistance,
- EOpDot,
- EOpCross,
- EOpNormalize,
- EOpFaceForward,
- EOpReflect,
- EOpRefract,
-
- EOpDFdx, // Fragment only, OES_standard_derivatives extension
- EOpDFdy, // Fragment only, OES_standard_derivatives extension
- EOpFwidth, // Fragment only, OES_standard_derivatives extension
-
- EOpMatrixTimesMatrix,
-
- EOpAny,
- EOpAll,
-
- //
- // Branch
- //
-
- EOpKill, // Fragment only
- EOpReturn,
- EOpBreak,
- EOpContinue,
-
- //
- // Constructors
- //
-
- EOpConstructInt,
- EOpConstructUInt,
- EOpConstructBool,
- EOpConstructFloat,
- EOpConstructVec2,
- EOpConstructVec3,
- EOpConstructVec4,
- EOpConstructBVec2,
- EOpConstructBVec3,
- EOpConstructBVec4,
- EOpConstructIVec2,
- EOpConstructIVec3,
- EOpConstructIVec4,
- EOpConstructUVec2,
- EOpConstructUVec3,
- EOpConstructUVec4,
- EOpConstructMat2,
- EOpConstructMat3,
- EOpConstructMat4,
- EOpConstructStruct,
-
- //
- // moves
- //
-
- EOpAssign,
- EOpInitialize,
- EOpAddAssign,
- EOpSubAssign,
- EOpMulAssign,
- EOpVectorTimesMatrixAssign,
- EOpVectorTimesScalarAssign,
- EOpMatrixTimesScalarAssign,
- EOpMatrixTimesMatrixAssign,
- EOpDivAssign
-};
+#include "compiler/translator/Operator.h"
class TIntermTraverser;
class TIntermAggregate;
@@ -196,10 +33,13 @@ class TIntermBinary;
class TIntermUnary;
class TIntermConstantUnion;
class TIntermSelection;
+class TIntermSwitch;
+class TIntermCase;
class TIntermTyped;
class TIntermSymbol;
class TIntermLoop;
class TInfoSink;
+class TInfoSinkBase;
class TIntermRaw;
//
@@ -228,6 +68,8 @@ class TIntermNode
virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; }
virtual TIntermSelection *getAsSelectionNode() { return 0; }
+ virtual TIntermSwitch *getAsSwitchNode() { return 0; }
+ virtual TIntermCase *getAsCaseNode() { return 0; }
virtual TIntermSymbol *getAsSymbolNode() { return 0; }
virtual TIntermLoop *getAsLoopNode() { return 0; }
virtual TIntermRaw *getAsRawNode() { return 0; }
@@ -237,10 +79,6 @@ class TIntermNode
virtual bool replaceChildNode(
TIntermNode *original, TIntermNode *replacement) = 0;
- // For traversing a tree in no particular order, but using
- // heap memory.
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const = 0;
-
protected:
TSourceLoc mLine;
};
@@ -331,8 +169,6 @@ class TIntermLoop : public TIntermNode
void setUnrollFlag(bool flag) { mUnrollFlag = flag; }
bool getUnrollFlag() const { return mUnrollFlag; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
protected:
TLoopType mType;
TIntermNode *mInit; // for-loop initialization
@@ -360,8 +196,6 @@ class TIntermBranch : public TIntermNode
TOperator getFlowOp() { return mFlowOp; }
TIntermTyped* getExpression() { return mExpression; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
protected:
TOperator mFlowOp;
TIntermTyped *mExpression; // non-zero except for "return exp;" statements
@@ -394,8 +228,6 @@ class TIntermSymbol : public TIntermTyped
virtual TIntermSymbol *getAsSymbolNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
-
protected:
int mId;
TString mSymbol;
@@ -419,7 +251,6 @@ class TIntermRaw : public TIntermTyped
virtual TIntermRaw *getAsRawNode() { return this; }
virtual bool replaceChildNode(TIntermNode *, TIntermNode *) { return false; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
protected:
TString mRawText;
@@ -459,8 +290,6 @@ class TIntermConstantUnion : public TIntermTyped
TIntermTyped *fold(TOperator, TIntermTyped *, TInfoSink &);
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const {}
-
protected:
ConstantUnion *mUnionArrayPointer;
};
@@ -519,8 +348,6 @@ class TIntermBinary : public TIntermOperator
void setAddIndexClamp() { mAddIndexClamp = true; }
bool getAddIndexClamp() { return mAddIndexClamp; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
protected:
TIntermTyped* mLeft;
TIntermTyped* mRight;
@@ -556,13 +383,11 @@ class TIntermUnary : public TIntermOperator
void setOperand(TIntermTyped *operand) { mOperand = operand; }
TIntermTyped *getOperand() { return mOperand; }
- bool promote(TInfoSink &);
+ void promote(const TType *funcReturnType);
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
protected:
TIntermTyped *mOperand;
@@ -613,8 +438,6 @@ class TIntermAggregate : public TIntermOperator
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
void setPrecisionFromChildren();
void setBuiltInFunctionPrecision();
@@ -634,7 +457,7 @@ class TIntermAggregate : public TIntermOperator
};
//
-// For if tests. Simplified since there is no switch statement.
+// For if tests.
//
class TIntermSelection : public TIntermTyped
{
@@ -664,14 +487,64 @@ class TIntermSelection : public TIntermTyped
TIntermNode *getFalseBlock() const { return mFalseBlock; }
TIntermSelection *getAsSelectionNode() { return this; }
- virtual void enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const;
-
protected:
TIntermTyped *mCondition;
TIntermNode *mTrueBlock;
TIntermNode *mFalseBlock;
};
+//
+// Switch statement.
+//
+class TIntermSwitch : public TIntermNode
+{
+ public:
+ TIntermSwitch(TIntermTyped *init, TIntermAggregate *statementList)
+ : TIntermNode(),
+ mInit(init),
+ mStatementList(statementList)
+ {
+ }
+
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement) override;
+
+ TIntermSwitch *getAsSwitchNode() override { return this; }
+
+ TIntermAggregate *getStatementList() { return mStatementList; }
+ void setStatementList(TIntermAggregate *statementList) { mStatementList = statementList; }
+
+ protected:
+ TIntermTyped *mInit;
+ TIntermAggregate *mStatementList;
+};
+
+//
+// Case label.
+//
+class TIntermCase : public TIntermNode
+{
+ public:
+ TIntermCase(TIntermTyped *condition)
+ : TIntermNode(),
+ mCondition(condition)
+ {
+ }
+
+ void traverse(TIntermTraverser *it) override;
+ bool replaceChildNode(
+ TIntermNode *original, TIntermNode *replacement) override;
+
+ TIntermCase *getAsCaseNode() override { return this; }
+
+ bool hasCondition() const { return mCondition != nullptr; }
+ TIntermTyped *getCondition() const { return mCondition; }
+
+ protected:
+ TIntermTyped *mCondition;
+};
+
enum Visit
{
PreVisit,
@@ -687,7 +560,7 @@ enum Visit
// When using this, just fill in the methods for nodes you want visited.
// Return false from a pre-visit to skip visiting that node's subtree.
//
-class TIntermTraverser
+class TIntermTraverser : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
@@ -708,6 +581,8 @@ class TIntermTraverser
virtual bool visitBinary(Visit, TIntermBinary *) { return true; }
virtual bool visitUnary(Visit, TIntermUnary *) { return true; }
virtual bool visitSelection(Visit, TIntermSelection *) { return true; }
+ virtual bool visitSwitch(Visit, TIntermSwitch *) { return true; }
+ virtual bool visitCase(Visit, TIntermCase *) { return true; }
virtual bool visitAggregate(Visit, TIntermAggregate *) { return true; }
virtual bool visitLoop(Visit, TIntermLoop *) { return true; }
virtual bool visitBranch(Visit, TIntermBranch *) { return true; }
@@ -741,12 +616,38 @@ class TIntermTraverser
const bool postVisit;
const bool rightToLeft;
+ // If traversers need to replace nodes, they can add the replacements in
+ // mReplacements during traversal and the user of the traverser should call
+ // this function after traversal to perform them.
+ void updateTree();
+
protected:
int mDepth;
int mMaxDepth;
// All the nodes from root to the current node's parent during traversing.
TVector<TIntermNode *> mPath;
+
+ struct NodeUpdateEntry
+ {
+ NodeUpdateEntry(TIntermNode *_parent,
+ TIntermNode *_original,
+ TIntermNode *_replacement,
+ bool _originalBecomesChildOfReplacement)
+ : parent(_parent),
+ original(_original),
+ replacement(_replacement),
+ originalBecomesChildOfReplacement(_originalBecomesChildOfReplacement) {}
+
+ TIntermNode *parent;
+ TIntermNode *original;
+ TIntermNode *replacement;
+ bool originalBecomesChildOfReplacement;
+ };
+
+ // During traversing, save all the changes that need to happen into
+ // mReplacements, then do them by calling updateTree().
+ std::vector<NodeUpdateEntry> mReplacements;
};
//
@@ -768,10 +669,10 @@ class TMaxDepthTraverser : public TIntermTraverser
virtual bool visitLoop(Visit, TIntermLoop *) { return depthCheck(); }
virtual bool visitBranch(Visit, TIntermBranch *) { return depthCheck(); }
-protected:
+ protected:
bool depthCheck() const { return mMaxDepth < mDepthLimit; }
int mDepthLimit;
};
-#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#endif // COMPILER_TRANSLATOR_INTERMNODE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
index 72b2033fb3..7a7efb71f5 100644
--- a/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/IntermTraverse.cpp
@@ -194,6 +194,60 @@ void TIntermSelection::traverse(TIntermTraverser *it)
}
//
+// Traverse a switch node. Same comments in binary node apply here.
+//
+void TIntermSwitch::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitSwitch(PreVisit, this);
+
+ if (visit)
+ {
+ it->incrementDepth(this);
+ if (it->rightToLeft)
+ {
+ if (mStatementList)
+ mStatementList->traverse(it);
+ if (it->inVisit)
+ visit = it->visitSwitch(InVisit, this);
+ if (visit)
+ mInit->traverse(it);
+ }
+ else
+ {
+ mInit->traverse(it);
+ if (it->inVisit)
+ visit = it->visitSwitch(InVisit, this);
+ if (visit && mStatementList)
+ mStatementList->traverse(it);
+ }
+ it->decrementDepth();
+ }
+
+ if (visit && it->postVisit)
+ it->visitSwitch(PostVisit, this);
+}
+
+//
+// Traverse a switch node. Same comments in binary node apply here.
+//
+void TIntermCase::traverse(TIntermTraverser *it)
+{
+ bool visit = true;
+
+ if (it->preVisit)
+ visit = it->visitCase(PreVisit, this);
+
+ if (visit && mCondition)
+ mCondition->traverse(it);
+
+ if (visit && it->postVisit)
+ it->visitCase(PostVisit, this);
+}
+
+//
// Traverse a loop node. Same comments in binary node apply here.
//
void TIntermLoop::traverse(TIntermTraverser *it)
diff --git a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
index e558683c55..320056f8ce 100644
--- a/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.cpp
@@ -13,7 +13,6 @@
#include <algorithm>
#include "compiler/translator/Intermediate.h"
-#include "compiler/translator/RemoveTree.h"
#include "compiler/translator/SymbolTable.h"
////////////////////////////////////////////////////////////////////////////
@@ -46,47 +45,6 @@ TIntermSymbol *TIntermediate::addSymbol(
TIntermTyped *TIntermediate::addBinaryMath(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line)
{
- switch (op)
- {
- case EOpEqual:
- case EOpNotEqual:
- if (left->isArray())
- return NULL;
- break;
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- if (left->isMatrix() || left->isArray() || left->isVector() ||
- left->getBasicType() == EbtStruct)
- {
- return NULL;
- }
- break;
- case EOpLogicalOr:
- case EOpLogicalXor:
- case EOpLogicalAnd:
- if (left->getBasicType() != EbtBool ||
- left->isMatrix() || left->isArray() || left->isVector())
- {
- return NULL;
- }
- break;
- case EOpAdd:
- case EOpSub:
- case EOpDiv:
- case EOpMul:
- if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
- return NULL;
- default:
- break;
- }
-
- if (left->getBasicType() != right->getBasicType())
- {
- return NULL;
- }
-
//
// Need a new node holding things together then. Make
// one and promote it to the right type.
@@ -169,45 +127,8 @@ TIntermTyped *TIntermediate::addIndex(
// Returns the added node.
//
TIntermTyped *TIntermediate::addUnaryMath(
- TOperator op, TIntermNode *childNode, const TSourceLoc &line)
+ TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
{
- TIntermUnary *node;
- TIntermTyped *child = childNode->getAsTyped();
-
- if (child == NULL)
- {
- mInfoSink.info.message(EPrefixInternalError, line,
- "Bad type in AddUnaryMath");
- return NULL;
- }
-
- switch (op)
- {
- case EOpLogicalNot:
- if (child->getType().getBasicType() != EbtBool ||
- child->getType().isMatrix() ||
- child->getType().isArray() ||
- child->getType().isVector())
- {
- return NULL;
- }
- break;
-
- case EOpPostIncrement:
- case EOpPreIncrement:
- case EOpPostDecrement:
- case EOpPreDecrement:
- case EOpNegative:
- case EOpPositive:
- if (child->getType().getBasicType() == EbtStruct ||
- child->getType().isArray())
- {
- return NULL;
- }
- default:
- break;
- }
-
TIntermConstantUnion *childTempConstant = 0;
if (child->getAsConstantUnion())
childTempConstant = child->getAsConstantUnion();
@@ -215,12 +136,10 @@ TIntermTyped *TIntermediate::addUnaryMath(
//
// Make a new node for the operator.
//
- node = new TIntermUnary(op);
+ TIntermUnary *node = new TIntermUnary(op);
node->setLine(line);
node->setOperand(child);
-
- if (!node->promote(mInfoSink))
- return 0;
+ node->promote(funcReturnType);
if (childTempConstant)
{
@@ -423,6 +342,24 @@ TIntermTyped *TIntermediate::addSelection(
return node;
}
+TIntermSwitch *TIntermediate::addSwitch(
+ TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
+{
+ TIntermSwitch *node = new TIntermSwitch(init, statementList);
+ node->setLine(line);
+
+ return node;
+}
+
+TIntermCase *TIntermediate::addCase(
+ TIntermTyped *condition, const TSourceLoc &line)
+{
+ TIntermCase *node = new TIntermCase(condition);
+ node->setLine(line);
+
+ return node;
+}
+
//
// Constant terminal nodes. Has a union that contains bool, float or int constants
//
@@ -510,12 +447,3 @@ bool TIntermediate::postProcess(TIntermNode *root)
return true;
}
-
-//
-// This deletes the tree.
-//
-void TIntermediate::remove(TIntermNode *root)
-{
- if (root)
- RemoveAllTreeNodes(root);
-}
diff --git a/src/3rdparty/angle/src/compiler/translator/intermediate.h b/src/3rdparty/angle/src/compiler/translator/Intermediate.h
index 3b7e7bd802..ec73e22834 100644
--- a/src/3rdparty/angle/src/compiler/translator/intermediate.h
+++ b/src/3rdparty/angle/src/compiler/translator/Intermediate.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
-#define COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
+#ifndef COMPILER_TRANSLATOR_INTERMEDIATE_H_
+#define COMPILER_TRANSLATOR_INTERMEDIATE_H_
#include "compiler/translator/IntermNode.h"
@@ -35,7 +35,7 @@ class TIntermediate
TIntermTyped *addIndex(
TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &);
TIntermTyped *addUnaryMath(
- TOperator op, TIntermNode *child, const TSourceLoc &);
+ TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType);
TIntermAggregate *growAggregate(
TIntermNode *left, TIntermNode *right, const TSourceLoc &);
TIntermAggregate *makeAggregate(TIntermNode *node, const TSourceLoc &);
@@ -43,6 +43,10 @@ class TIntermediate
TIntermNode *addSelection(TIntermTyped *cond, TIntermNodePair code, const TSourceLoc &);
TIntermTyped *addSelection(
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &);
+ TIntermSwitch *addSwitch(
+ TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line);
+ TIntermCase *addCase(
+ TIntermTyped *condition, const TSourceLoc &line);
TIntermTyped *addComma(
TIntermTyped *left, TIntermTyped *right, const TSourceLoc &);
TIntermConstantUnion *addConstantUnion(ConstantUnion *, const TType &, const TSourceLoc &);
@@ -55,8 +59,8 @@ class TIntermediate
TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
bool postProcess(TIntermNode *);
- void remove(TIntermNode *);
- void outputTree(TIntermNode *);
+
+ static void outputTree(TIntermNode *, TInfoSinkBase &);
private:
void operator=(TIntermediate &); // prevent assignments
@@ -64,4 +68,4 @@ class TIntermediate
TInfoSink & mInfoSink;
};
-#endif // COMPILER_TRANSLATOR_LOCAL_INTERMEDIATE_H_
+#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h
index 5f72a6e944..ec73fd0fa5 100644
--- a/src/3rdparty/angle/src/compiler/translator/LoopInfo.h
+++ b/src/3rdparty/angle/src/compiler/translator/LoopInfo.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATOR_LOOP_INFO_H_
-#define COMPILER_TRANSLATOR_LOOP_INFO_H_
+#ifndef COMPILER_TRANSLATOR_LOOPINFO_H_
+#define COMPILER_TRANSLATOR_LOOPINFO_H_
#include "compiler/translator/IntermNode.h"
@@ -76,5 +76,5 @@ class TLoopStack : public TVector<TLoopInfo>
void pop();
};
-#endif // COMPILER_TRANSLATOR_LOOP_INDEX_H_
+#endif // COMPILER_TRANSLATOR_LOOPINFO_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/MMap.h b/src/3rdparty/angle/src/compiler/translator/MMap.h
index a308671514..fca843992b 100644
--- a/src/3rdparty/angle/src/compiler/translator/MMap.h
+++ b/src/3rdparty/angle/src/compiler/translator/MMap.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _MMAP_INCLUDED_
-#define _MMAP_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_MMAP_H_
+#define COMPILER_TRANSLATOR_MMAP_H_
//
// Encapsulate memory mapped files
@@ -53,4 +53,4 @@ private:
char* fBuff; // the actual data;
};
-#endif // _MMAP_INCLUDED_
+#endif // COMPILER_TRANSLATOR_MMAP_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
index 60070c9d33..8ffed614c3 100644
--- a/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
+++ b/src/3rdparty/angle/src/compiler/translator/NodeSearch.h
@@ -6,8 +6,8 @@
// NodeSearch.h: Utilities for searching translator node graphs
//
-#ifndef TRANSLATOR_NODESEARCH_H_
-#define TRANSLATOR_NODESEARCH_H_
+#ifndef COMPILER_TRANSLATOR_NODESEARCH_H_
+#define COMPILER_TRANSLATOR_NODESEARCH_H_
#include "compiler/translator/IntermNode.h"
@@ -77,4 +77,4 @@ class FindSideEffectRewriting : public NodeSearchTraverser<FindSideEffectRewriti
}
-#endif // TRANSLATOR_NODESEARCH_H_
+#endif // COMPILER_TRANSLATOR_NODESEARCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.cpp b/src/3rdparty/angle/src/compiler/translator/Operator.cpp
new file mode 100644
index 0000000000..ae4512bd44
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/Operator.cpp
@@ -0,0 +1,195 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/Operator.h"
+
+const char *GetOperatorString(TOperator op)
+{
+ switch (op)
+ {
+ // Note: ops from EOpNull to EOpPrototype can't be handled here.
+
+ case EOpNegative: return "-";
+ case EOpPositive: return "+";
+ case EOpLogicalNot: return "!";
+ case EOpVectorLogicalNot: return "not";
+ case EOpBitwiseNot: return "~";
+
+ case EOpPostIncrement: return "++";
+ case EOpPostDecrement: return "--";
+ case EOpPreIncrement: return "++";
+ case EOpPreDecrement: return "--";
+
+ case EOpAdd: return "+";
+ case EOpSub: return "-";
+ case EOpMul: return "*";
+ case EOpDiv: return "/";
+ case EOpIMod: return "%";
+ case EOpEqual: return "==";
+ case EOpNotEqual: return "!=";
+ case EOpVectorEqual: return "equal";
+ case EOpVectorNotEqual: return "notEqual";
+ case EOpLessThan: return "<";
+ case EOpGreaterThan: return ">";
+ case EOpLessThanEqual: return "<=";
+ case EOpGreaterThanEqual: return ">=";
+ case EOpComma: return ",";
+
+ // Fall-through.
+ case EOpVectorTimesScalar:
+ case EOpVectorTimesMatrix:
+ case EOpMatrixTimesVector:
+ case EOpMatrixTimesScalar: return "*";
+
+ case EOpLogicalOr: return "||";
+ case EOpLogicalXor: return "^^";
+ case EOpLogicalAnd: return "&&";
+
+ case EOpBitShiftLeft: return "<<";
+ case EOpBitShiftRight: return ">>";
+
+ case EOpBitwiseAnd: return "&";
+ case EOpBitwiseXor: return "^";
+ case EOpBitwiseOr: return "|";
+
+ // Fall-through.
+ case EOpIndexDirect:
+ case EOpIndexIndirect: return "[]";
+
+ case EOpIndexDirectStruct:
+ case EOpIndexDirectInterfaceBlock: return ".";
+
+ case EOpVectorSwizzle: return ".";
+
+ case EOpRadians: return "radians";
+ case EOpDegrees: return "degrees";
+ case EOpSin: return "sin";
+ case EOpCos: return "cos";
+ case EOpTan: return "tan";
+ case EOpAsin: return "asin";
+ case EOpAcos: return "acos";
+ case EOpAtan: return "atan";
+
+ case EOpSinh: return "sinh";
+ case EOpCosh: return "cosh";
+ case EOpTanh: return "tanh";
+ case EOpAsinh: return "asinh";
+ case EOpAcosh: return "acosh";
+ case EOpAtanh: return "atanh";
+
+ case EOpPow: return "pow";
+ case EOpExp: return "exp";
+ case EOpLog: return "log";
+ case EOpExp2: return "exp2";
+ case EOpLog2: return "log2";
+ case EOpSqrt: return "sqrt";
+ case EOpInverseSqrt: return "inversesqrt";
+
+ case EOpAbs: return "abs";
+ case EOpSign: return "sign";
+ case EOpFloor: return "floor";
+ case EOpTrunc: return "trunc";
+ case EOpRound: return "round";
+ case EOpRoundEven: return "roundEven";
+ case EOpCeil: return "ceil";
+ case EOpFract: return "fract";
+ case EOpMod: return "mod";
+ case EOpModf: return "modf";
+ case EOpMin: return "min";
+ case EOpMax: return "max";
+ case EOpClamp: return "clamp";
+ case EOpMix: return "mix";
+ case EOpStep: return "step";
+ case EOpSmoothStep: return "smoothstep";
+ case EOpIsNan: return "isnan";
+ case EOpIsInf: return "isinf";
+
+ case EOpFloatBitsToInt: return "floatBitsToInt";
+ case EOpFloatBitsToUint: return "floatBitsToUint";
+ case EOpIntBitsToFloat: return "intBitsToFloat";
+ case EOpUintBitsToFloat: return "uintBitsToFloat";
+
+ case EOpPackSnorm2x16: return "packSnorm2x16";
+ case EOpPackUnorm2x16: return "packUnorm2x16";
+ case EOpPackHalf2x16: return "packHalf2x16";
+ case EOpUnpackSnorm2x16: return "unpackSnorm2x16";
+ case EOpUnpackUnorm2x16: return "unpackUnorm2x16";
+ case EOpUnpackHalf2x16: return "unpackHalf2x16";
+
+ case EOpLength: return "length";
+ case EOpDistance: return "distance";
+ case EOpDot: return "dot";
+ case EOpCross: return "cross";
+ case EOpNormalize: return "normalize";
+ case EOpFaceForward: return "faceforward";
+ case EOpReflect: return "reflect";
+ case EOpRefract: return "refract";
+
+ case EOpDFdx: return "dFdx";
+ case EOpDFdy: return "dFdy";
+ case EOpFwidth: return "fwidth";
+
+ case EOpMatrixTimesMatrix: return "*";
+
+ case EOpOuterProduct: return "outerProduct";
+ case EOpTranspose: return "transpose";
+ case EOpDeterminant: return "determinant";
+ case EOpInverse: return "inverse";
+
+ case EOpAny: return "any";
+ case EOpAll: return "all";
+
+ case EOpKill: return "kill";
+ case EOpReturn: return "return";
+ case EOpBreak: return "break";
+ case EOpContinue: return "continue";
+
+ case EOpConstructInt: return "int";
+ case EOpConstructUInt: return "uint";
+ case EOpConstructBool: return "bool";
+ case EOpConstructFloat: return "float";
+ case EOpConstructVec2: return "vec2";
+ case EOpConstructVec3: return "vec3";
+ case EOpConstructVec4: return "vec4";
+ case EOpConstructBVec2: return "bvec2";
+ case EOpConstructBVec3: return "bvec3";
+ case EOpConstructBVec4: return "bvec4";
+ case EOpConstructIVec2: return "ivec2";
+ case EOpConstructIVec3: return "ivec3";
+ case EOpConstructIVec4: return "ivec4";
+ case EOpConstructUVec2: return "uvec2";
+ case EOpConstructUVec3: return "uvec3";
+ case EOpConstructUVec4: return "uvec4";
+ case EOpConstructMat2: return "mat2";
+ case EOpConstructMat3: return "mat3";
+ case EOpConstructMat4: return "mat4";
+ // Note: EOpConstructStruct can't be handled here
+
+ case EOpAssign: return "=";
+ case EOpInitialize: return "=";
+ case EOpAddAssign: return "+=";
+ case EOpSubAssign: return "-=";
+
+ // Fall-through.
+ case EOpMulAssign:
+ case EOpVectorTimesMatrixAssign:
+ case EOpVectorTimesScalarAssign:
+ case EOpMatrixTimesScalarAssign:
+ case EOpMatrixTimesMatrixAssign: return "*=";
+
+ case EOpDivAssign: return "/=";
+ case EOpIModAssign: return "%=";
+ case EOpBitShiftLeftAssign: return "<<=";
+ case EOpBitShiftRightAssign: return ">>=";
+ case EOpBitwiseAndAssign: return "&=";
+ case EOpBitwiseXorAssign: return "^=";
+ case EOpBitwiseOrAssign: return "|=";
+
+ default: break;
+ }
+ return "";
+}
+
diff --git a/src/3rdparty/angle/src/compiler/translator/Operator.h b/src/3rdparty/angle/src/compiler/translator/Operator.h
new file mode 100644
index 0000000000..8290f952fc
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/Operator.h
@@ -0,0 +1,226 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_OPERATOR_H_
+#define COMPILER_TRANSLATOR_OPERATOR_H_
+
+//
+// Operators used by the high-level (parse tree) representation.
+//
+enum TOperator
+{
+ EOpNull, // if in a node, should only mean a node is still being built
+ EOpSequence, // denotes a list of statements, or parameters, etc.
+ EOpFunctionCall,
+ EOpInternalFunctionCall, // Call to an internal helper function
+ EOpFunction, // For function definition
+ EOpParameters, // an aggregate listing the parameters to a function
+
+ EOpDeclaration,
+ EOpInvariantDeclaration, // Specialized declarations for attributing invariance
+ EOpPrototype,
+
+ //
+ // Unary operators
+ //
+
+ EOpNegative,
+ EOpPositive,
+ EOpLogicalNot,
+ EOpVectorLogicalNot,
+ EOpBitwiseNot,
+
+ EOpPostIncrement,
+ EOpPostDecrement,
+ EOpPreIncrement,
+ EOpPreDecrement,
+
+ //
+ // binary operations
+ //
+
+ EOpAdd,
+ EOpSub,
+ EOpMul,
+ EOpDiv,
+ EOpIMod,
+ EOpEqual,
+ EOpNotEqual,
+ EOpVectorEqual,
+ EOpVectorNotEqual,
+ EOpLessThan,
+ EOpGreaterThan,
+ EOpLessThanEqual,
+ EOpGreaterThanEqual,
+ EOpComma,
+
+ EOpVectorTimesScalar,
+ EOpVectorTimesMatrix,
+ EOpMatrixTimesVector,
+ EOpMatrixTimesScalar,
+
+ EOpLogicalOr,
+ EOpLogicalXor,
+ EOpLogicalAnd,
+
+ EOpBitShiftLeft,
+ EOpBitShiftRight,
+
+ EOpBitwiseAnd,
+ EOpBitwiseXor,
+ EOpBitwiseOr,
+
+ EOpIndexDirect,
+ EOpIndexIndirect,
+ EOpIndexDirectStruct,
+ EOpIndexDirectInterfaceBlock,
+
+ EOpVectorSwizzle,
+
+ //
+ // Built-in functions potentially mapped to operators
+ //
+
+ EOpRadians,
+ EOpDegrees,
+ EOpSin,
+ EOpCos,
+ EOpTan,
+ EOpAsin,
+ EOpAcos,
+ EOpAtan,
+
+ EOpSinh,
+ EOpCosh,
+ EOpTanh,
+ EOpAsinh,
+ EOpAcosh,
+ EOpAtanh,
+
+ EOpPow,
+ EOpExp,
+ EOpLog,
+ EOpExp2,
+ EOpLog2,
+ EOpSqrt,
+ EOpInverseSqrt,
+
+ EOpAbs,
+ EOpSign,
+ EOpFloor,
+ EOpTrunc,
+ EOpRound,
+ EOpRoundEven,
+ EOpCeil,
+ EOpFract,
+ EOpMod,
+ EOpModf,
+ EOpMin,
+ EOpMax,
+ EOpClamp,
+ EOpMix,
+ EOpStep,
+ EOpSmoothStep,
+ EOpIsNan,
+ EOpIsInf,
+
+ EOpFloatBitsToInt,
+ EOpFloatBitsToUint,
+ EOpIntBitsToFloat,
+ EOpUintBitsToFloat,
+
+ EOpPackSnorm2x16,
+ EOpPackUnorm2x16,
+ EOpPackHalf2x16,
+ EOpUnpackSnorm2x16,
+ EOpUnpackUnorm2x16,
+ EOpUnpackHalf2x16,
+
+ EOpLength,
+ EOpDistance,
+ EOpDot,
+ EOpCross,
+ EOpNormalize,
+ EOpFaceForward,
+ EOpReflect,
+ EOpRefract,
+
+ EOpDFdx, // Fragment only, OES_standard_derivatives extension
+ EOpDFdy, // Fragment only, OES_standard_derivatives extension
+ EOpFwidth, // Fragment only, OES_standard_derivatives extension
+
+ EOpMatrixTimesMatrix,
+
+ EOpOuterProduct,
+ EOpTranspose,
+ EOpDeterminant,
+ EOpInverse,
+
+ EOpAny,
+ EOpAll,
+
+ //
+ // Branch
+ //
+
+ EOpKill, // Fragment only
+ EOpReturn,
+ EOpBreak,
+ EOpContinue,
+
+ //
+ // Constructors
+ //
+
+ EOpConstructInt,
+ EOpConstructUInt,
+ EOpConstructBool,
+ EOpConstructFloat,
+ EOpConstructVec2,
+ EOpConstructVec3,
+ EOpConstructVec4,
+ EOpConstructBVec2,
+ EOpConstructBVec3,
+ EOpConstructBVec4,
+ EOpConstructIVec2,
+ EOpConstructIVec3,
+ EOpConstructIVec4,
+ EOpConstructUVec2,
+ EOpConstructUVec3,
+ EOpConstructUVec4,
+ EOpConstructMat2,
+ EOpConstructMat3,
+ EOpConstructMat4,
+ EOpConstructStruct,
+
+ //
+ // moves
+ //
+
+ EOpAssign,
+ EOpInitialize,
+ EOpAddAssign,
+ EOpSubAssign,
+
+ EOpMulAssign,
+ EOpVectorTimesMatrixAssign,
+ EOpVectorTimesScalarAssign,
+ EOpMatrixTimesScalarAssign,
+ EOpMatrixTimesMatrixAssign,
+
+ EOpDivAssign,
+ EOpIModAssign,
+ EOpBitShiftLeftAssign,
+ EOpBitShiftRightAssign,
+ EOpBitwiseAndAssign,
+ EOpBitwiseXorAssign,
+ EOpBitwiseOrAssign
+};
+
+// Returns the string corresponding to the operator in GLSL
+const char* GetOperatorString(TOperator op);
+
+#endif // COMPILER_TRANSLATOR_OPERATOR_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
index 65635af1ff..77e0a8fb37 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.cpp
@@ -6,13 +6,21 @@
#include "compiler/translator/OutputESSL.h"
-TOutputESSL::TOutputESSL(TInfoSinkBase& objSink,
+TOutputESSL::TOutputESSL(TInfoSinkBase &objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
- NameMap& nameMap,
- TSymbolTable& symbolTable,
- int shaderVersion)
- : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion)
+ NameMap &nameMap,
+ TSymbolTable &symbolTable,
+ int shaderVersion,
+ bool forceHighp)
+ : TOutputGLSLBase(objSink,
+ clampingStrategy,
+ hashFunction,
+ nameMap,
+ symbolTable,
+ shaderVersion,
+ SH_ESSL_OUTPUT),
+ mForceHighp(forceHighp)
{
}
@@ -22,6 +30,9 @@ bool TOutputESSL::writeVariablePrecision(TPrecision precision)
return false;
TInfoSinkBase& out = objSink();
- out << getPrecisionString(precision);
+ if (mForceHighp)
+ out << getPrecisionString(EbpHigh);
+ else
+ out << getPrecisionString(precision);
return true;
}
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
index 8a567fb8aa..813f1e944b 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputESSL.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef CROSSCOMPILERGLSL_OUTPUTESSL_H_
-#define CROSSCOMPILERGLSL_OUTPUTESSL_H_
+#ifndef COMPILER_TRANSLATOR_OUTPUTESSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTESSL_H_
#include "compiler/translator/OutputGLSLBase.h"
@@ -17,10 +17,13 @@ public:
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
- int shaderVersion);
+ int shaderVersion,
+ bool forceHighp);
protected:
virtual bool writeVariablePrecision(TPrecision precision);
+private:
+ bool mForceHighp;
};
-#endif // CROSSCOMPILERGLSL_OUTPUTESSL_H_
+#endif // COMPILER_TRANSLATOR_OUTPUTESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
index eb7cbb4ae8..9badf0e2fc 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.cpp
@@ -11,8 +11,15 @@ TOutputGLSL::TOutputGLSL(TInfoSinkBase& objSink,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
- int shaderVersion)
- : TOutputGLSLBase(objSink, clampingStrategy, hashFunction, nameMap, symbolTable, shaderVersion)
+ int shaderVersion,
+ ShShaderOutput output)
+ : TOutputGLSLBase(objSink,
+ clampingStrategy,
+ hashFunction,
+ nameMap,
+ symbolTable,
+ shaderVersion,
+ output)
{
}
@@ -21,21 +28,30 @@ bool TOutputGLSL::writeVariablePrecision(TPrecision)
return false;
}
-void TOutputGLSL::visitSymbol(TIntermSymbol* node)
+void TOutputGLSL::visitSymbol(TIntermSymbol *node)
{
TInfoSinkBase& out = objSink();
- if (node->getSymbol() == "gl_FragDepthEXT")
+ const TString &symbol = node->getSymbol();
+ if (symbol == "gl_FragDepthEXT")
{
out << "gl_FragDepth";
}
+ else if (symbol == "gl_FragColor" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
+ {
+ out << "webgl_FragColor";
+ }
+ else if (symbol == "gl_FragData" && getShaderOutput() == SH_GLSL_CORE_OUTPUT)
+ {
+ out << "webgl_FragData";
+ }
else
{
TOutputGLSLBase::visitSymbol(node);
}
}
-TString TOutputGLSL::translateTextureFunction(TString& name)
+TString TOutputGLSL::translateTextureFunction(TString &name)
{
static const char *simpleRename[] = {
"texture2DLodEXT", "texture2DLod",
@@ -46,10 +62,30 @@ TString TOutputGLSL::translateTextureFunction(TString& name)
"textureCubeGradEXT", "textureCubeGradARB",
NULL, NULL
};
+ static const char *legacyToCoreRename[] = {
+ "texture2D", "texture",
+ "texture2DProj", "textureProj",
+ "texture2DLod", "textureLod",
+ "texture2DProjLod", "textureProjLod",
+ "textureCube", "texture",
+ "textureCubeLod", "textureLod",
+ // Extensions
+ "texture2DLodEXT", "textureLod",
+ "texture2DProjLodEXT", "textureProjLod",
+ "textureCubeLodEXT", "textureLod",
+ "texture2DGradEXT", "textureGrad",
+ "texture2DProjGradEXT", "textureProjGrad",
+ "textureCubeGradEXT", "textureGrad",
+ NULL, NULL
+ };
+ const char **mapping = (getShaderOutput() == SH_GLSL_CORE_OUTPUT) ?
+ legacyToCoreRename : simpleRename;
- for (int i = 0; simpleRename[i] != NULL; i += 2) {
- if (name == simpleRename[i]) {
- return simpleRename[i+1];
+ for (int i = 0; mapping[i] != NULL; i += 2)
+ {
+ if (name == mapping[i])
+ {
+ return mapping[i+1];
}
}
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
index bceebe397d..21b2d079d3 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSL.h
@@ -4,25 +4,26 @@
// found in the LICENSE file.
//
-#ifndef CROSSCOMPILERGLSL_OUTPUTGLSL_H_
-#define CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#ifndef COMPILER_TRANSLATOR_OUTPUTGLSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTGLSL_H_
#include "compiler/translator/OutputGLSLBase.h"
class TOutputGLSL : public TOutputGLSLBase
{
-public:
+ public:
TOutputGLSL(TInfoSinkBase& objSink,
ShArrayIndexClampingStrategy clampingStrategy,
ShHashFunction64 hashFunction,
NameMap& nameMap,
TSymbolTable& symbolTable,
- int shaderVersion);
+ int shaderVersion,
+ ShShaderOutput output);
-protected:
+ protected:
virtual bool writeVariablePrecision(TPrecision);
virtual void visitSymbol(TIntermSymbol* node);
virtual TString translateTextureFunction(TString& name);
};
-#endif // CROSSCOMPILERGLSL_OUTPUTGLSL_H_
+#endif // COMPILER_TRANSLATOR_OUTPUTGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
index ed590967b1..4bb6305d05 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
@@ -36,8 +36,17 @@ bool isSingleStatement(TIntermNode *node)
{
return false;
}
+ else if (node->getAsSwitchNode())
+ {
+ return false;
+ }
+ else if (node->getAsCaseNode())
+ {
+ return false;
+ }
return true;
}
+
} // namespace
TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
@@ -45,7 +54,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable &symbolTable,
- int shaderVersion)
+ int shaderVersion,
+ ShShaderOutput output)
: TIntermTraverser(true, true, true),
mObjSink(objSink),
mDeclaringVariables(false),
@@ -53,7 +63,8 @@ TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
mHashFunction(hashFunction),
mNameMap(nameMap),
mSymbolTable(symbolTable),
- mShaderVersion(shaderVersion)
+ mShaderVersion(shaderVersion),
+ mOutput(output)
{
}
@@ -83,7 +94,34 @@ void TOutputGLSLBase::writeVariableType(const TType &type)
TQualifier qualifier = type.getQualifier();
if (qualifier != EvqTemporary && qualifier != EvqGlobal)
{
- out << type.getQualifierString() << " ";
+ if (mOutput == SH_GLSL_CORE_OUTPUT)
+ {
+ switch (qualifier)
+ {
+ case EvqAttribute:
+ out << "in" << " ";
+ break;
+ case EvqVaryingIn:
+ out << "in" << " ";
+ break;
+ case EvqVaryingOut:
+ out << "out" << " ";
+ break;
+ case EvqInvariantVaryingIn:
+ out << "invariant in" << " ";
+ break;
+ case EvqInvariantVaryingOut:
+ out << "invariant out" << " ";
+ break;
+ default:
+ out << type.getQualifierString() << " ";
+ break;
+ }
+ }
+ else
+ {
+ out << type.getQualifierString() << " ";
+ }
}
// Declare the struct if we have not done so already.
if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
@@ -166,6 +204,9 @@ const ConstantUnion *TOutputGLSLBase::writeConstantUnion(
case EbtInt:
out << pConstUnion->getIConst();
break;
+ case EbtUInt:
+ out << pConstUnion->getUConst() << "u";
+ break;
case EbtBool:
out << pConstUnion->getBConst();
break;
@@ -223,6 +264,9 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpDivAssign:
writeTriplet(visit, "(", " /= ", ")");
break;
+ case EOpIModAssign:
+ writeTriplet(visit, "(", " %= ", ")");
+ break;
// Notice the fall-through.
case EOpMulAssign:
case EOpVectorTimesMatrixAssign:
@@ -231,6 +275,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpMatrixTimesMatrixAssign:
writeTriplet(visit, "(", " *= ", ")");
break;
+ case EOpBitShiftLeftAssign:
+ writeTriplet(visit, "(", " <<= ", ")");
+ break;
+ case EOpBitShiftRightAssign:
+ writeTriplet(visit, "(", " >>= ", ")");
+ break;
+ case EOpBitwiseAndAssign:
+ writeTriplet(visit, "(", " &= ", ")");
+ break;
+ case EOpBitwiseXorAssign:
+ writeTriplet(visit, "(", " ^= ", ")");
+ break;
+ case EOpBitwiseOrAssign:
+ writeTriplet(visit, "(", " |= ", ")");
+ break;
case EOpIndexDirect:
writeTriplet(visit, NULL, "[", "]");
@@ -340,9 +399,25 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpDiv:
writeTriplet(visit, "(", " / ", ")");
break;
- case EOpMod:
- UNIMPLEMENTED();
+ case EOpIMod:
+ writeTriplet(visit, "(", " % ", ")");
+ break;
+ case EOpBitShiftLeft:
+ writeTriplet(visit, "(", " << ", ")");
break;
+ case EOpBitShiftRight:
+ writeTriplet(visit, "(", " >> ", ")");
+ break;
+ case EOpBitwiseAnd:
+ writeTriplet(visit, "(", " & ", ")");
+ break;
+ case EOpBitwiseXor:
+ writeTriplet(visit, "(", " ^ ", ")");
+ break;
+ case EOpBitwiseOr:
+ writeTriplet(visit, "(", " | ", ")");
+ break;
+
case EOpEqual:
writeTriplet(visit, "(", " == ", ")");
break;
@@ -398,6 +473,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: preString = "(+"; break;
case EOpVectorLogicalNot: preString = "not("; break;
case EOpLogicalNot: preString = "(!"; break;
+ case EOpBitwiseNot: preString = "(~"; break;
case EOpPostIncrement: preString = "("; postString = "++)"; break;
case EOpPostDecrement: preString = "("; postString = "--)"; break;
@@ -429,6 +505,25 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
preString = "atan(";
break;
+ case EOpSinh:
+ preString = "sinh(";
+ break;
+ case EOpCosh:
+ preString = "cosh(";
+ break;
+ case EOpTanh:
+ preString = "tanh(";
+ break;
+ case EOpAsinh:
+ preString = "asinh(";
+ break;
+ case EOpAcosh:
+ preString = "acosh(";
+ break;
+ case EOpAtanh:
+ preString = "atanh(";
+ break;
+
case EOpExp:
preString = "exp(";
break;
@@ -457,12 +552,59 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpFloor:
preString = "floor(";
break;
+ case EOpTrunc:
+ preString = "trunc(";
+ break;
+ case EOpRound:
+ preString = "round(";
+ break;
+ case EOpRoundEven:
+ preString = "roundEven(";
+ break;
case EOpCeil:
preString = "ceil(";
break;
case EOpFract:
preString = "fract(";
break;
+ case EOpIsNan:
+ preString = "isnan(";
+ break;
+ case EOpIsInf:
+ preString = "isinf(";
+ break;
+
+ case EOpFloatBitsToInt:
+ preString = "floatBitsToInt(";
+ break;
+ case EOpFloatBitsToUint:
+ preString = "floatBitsToUint(";
+ break;
+ case EOpIntBitsToFloat:
+ preString = "intBitsToFloat(";
+ break;
+ case EOpUintBitsToFloat:
+ preString = "uintBitsToFloat(";
+ break;
+
+ case EOpPackSnorm2x16:
+ preString = "packSnorm2x16(";
+ break;
+ case EOpPackUnorm2x16:
+ preString = "packUnorm2x16(";
+ break;
+ case EOpPackHalf2x16:
+ preString = "packHalf2x16(";
+ break;
+ case EOpUnpackSnorm2x16:
+ preString = "unpackSnorm2x16(";
+ break;
+ case EOpUnpackUnorm2x16:
+ preString = "unpackUnorm2x16(";
+ break;
+ case EOpUnpackHalf2x16:
+ preString = "unpackHalf2x16(";
+ break;
case EOpLength:
preString = "length(";
@@ -481,6 +623,16 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
preString = "fwidth(";
break;
+ case EOpTranspose:
+ preString = "transpose(";
+ break;
+ case EOpDeterminant:
+ preString = "determinant(";
+ break;
+ case EOpInverse:
+ preString = "inverse(";
+ break;
+
case EOpAny:
preString = "any(";
break;
@@ -536,6 +688,36 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node)
return false;
}
+bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+ if (node->getStatementList())
+ {
+ writeTriplet(visit, "switch (", ") ", nullptr);
+ // The curly braces get written when visiting the statementList aggregate
+ }
+ else
+ {
+ // No statementList, so it won't output curly braces
+ writeTriplet(visit, "switch (", ") {", "}\n");
+ }
+ return true;
+}
+
+bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
+{
+ if (node->hasCondition())
+ {
+ writeTriplet(visit, "case (", nullptr, "):\n");
+ return true;
+ }
+ else
+ {
+ TInfoSinkBase &out = objSink();
+ out << "default:\n";
+ return false;
+ }
+}
+
bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
{
bool visitChildren = true;
@@ -555,11 +737,11 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
iter != node->getSequence()->end(); ++iter)
{
- TIntermNode *node = *iter;
- ASSERT(node != NULL);
- node->traverse(this);
+ TIntermNode *curNode = *iter;
+ ASSERT(curNode != NULL);
+ curNode->traverse(this);
- if (isSingleStatement(node))
+ if (isSingleStatement(curNode))
out << ";\n";
}
decrementDepth();
@@ -622,6 +804,15 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
else
out << ")";
break;
+ case EOpInternalFunctionCall:
+ // Function call to an internal helper function.
+ if (visit == PreVisit)
+ out << node->getName() << "(";
+ else if (visit == InVisit)
+ out << ", ";
+ else
+ out << ")";
+ break;
case EOpParameters:
// Function parameters.
ASSERT(visit == PreVisit);
@@ -724,6 +915,10 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
}
break;
+ case EOpOuterProduct:
+ writeBuiltInFunctionTriplet(visit, "outerProduct(", useEmulatedFunction);
+ break;
+
case EOpLessThan:
writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction);
break;
@@ -749,6 +944,9 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpMod:
writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction);
break;
+ case EOpModf:
+ writeBuiltInFunctionTriplet(visit, "modf(", useEmulatedFunction);
+ break;
case EOpPow:
writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction);
break;
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
index e5174f5660..4e66059c21 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
-#define CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+#ifndef COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
+#define COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
#include <set>
@@ -21,7 +21,13 @@ class TOutputGLSLBase : public TIntermTraverser
ShHashFunction64 hashFunction,
NameMap &nameMap,
TSymbolTable& symbolTable,
- int shaderVersion);
+ int shaderVersion,
+ ShShaderOutput output);
+
+ ShShaderOutput getShaderOutput() const
+ {
+ return mOutput;
+ }
protected:
TInfoSinkBase &objSink() { return mObjSink; }
@@ -37,6 +43,8 @@ class TOutputGLSLBase : public TIntermTraverser
virtual bool visitBinary(Visit visit, TIntermBinary *node);
virtual bool visitUnary(Visit visit, TIntermUnary *node);
virtual bool visitSelection(Visit visit, TIntermSelection *node);
+ virtual bool visitSwitch(Visit visit, TIntermSwitch *node);
+ virtual bool visitCase(Visit visit, TIntermCase *node);
virtual bool visitAggregate(Visit visit, TIntermAggregate *node);
virtual bool visitLoop(Visit visit, TIntermLoop *node);
virtual bool visitBranch(Visit visit, TIntermBranch *node);
@@ -78,6 +86,8 @@ class TOutputGLSLBase : public TIntermTraverser
TSymbolTable &mSymbolTable;
const int mShaderVersion;
+
+ ShShaderOutput mOutput;
};
-#endif // CROSSCOMPILERGLSL_OUTPUTGLSLBASE_H_
+#endif // COMPILER_TRANSLATOR_OUTPUTGLSLBASE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
index 30bbbff0f5..94225b81c4 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
@@ -6,26 +6,29 @@
#include "compiler/translator/OutputHLSL.h"
+#include <algorithm>
+#include <cfloat>
+#include <stdio.h>
+
#include "common/angleutils.h"
#include "common/utilities.h"
-#include "common/blocklayout.h"
-#include "compiler/translator/compilerdebug.h"
-#include "compiler/translator/InfoSink.h"
+#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/DetectDiscontinuity.h"
-#include "compiler/translator/SearchSymbol.h"
-#include "compiler/translator/UnfoldShortCircuit.h"
#include "compiler/translator/FlagStd140Structs.h"
+#include "compiler/translator/InfoSink.h"
#include "compiler/translator/NodeSearch.h"
+#include "compiler/translator/RemoveSwitchFallThrough.h"
#include "compiler/translator/RewriteElseBlocks.h"
-#include "compiler/translator/UtilsHLSL.h"
-#include "compiler/translator/util.h"
-#include "compiler/translator/UniformHLSL.h"
+#include "compiler/translator/SearchSymbol.h"
#include "compiler/translator/StructureHLSL.h"
#include "compiler/translator/TranslatorHLSL.h"
-
-#include <algorithm>
-#include <cfloat>
-#include <stdio.h>
+#include "compiler/translator/UnfoldShortCircuit.h"
+#include "compiler/translator/UniformHLSL.h"
+#include "compiler/translator/UtilsHLSL.h"
+#include "compiler/translator/blocklayout.h"
+#include "compiler/translator/compilerdebug.h"
+#include "compiler/translator/util.h"
namespace sh
{
@@ -94,12 +97,21 @@ bool OutputHLSL::TextureFunction::operator<(const TextureFunction &rhs) const
return false;
}
-OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
+OutputHLSL::OutputHLSL(sh::GLenum shaderType, int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ const char *sourcePath, ShShaderOutput outputType,
+ int numRenderTargets, const std::vector<Uniform> &uniforms,
+ int compileOptions)
: TIntermTraverser(true, true, true),
- mContext(context),
- mOutputType(parentTranslator->getOutputType())
+ mShaderType(shaderType),
+ mShaderVersion(shaderVersion),
+ mExtensionBehavior(extensionBehavior),
+ mSourcePath(sourcePath),
+ mOutputType(outputType),
+ mNumRenderTargets(numRenderTargets),
+ mCompileOptions(compileOptions)
{
- mUnfoldShortCircuit = new UnfoldShortCircuit(context, this);
+ mUnfoldShortCircuit = new UnfoldShortCircuit(this);
mInsideFunction = false;
mUsesFragColor = false;
@@ -109,28 +121,12 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
mUsesPointCoord = false;
mUsesFrontFacing = false;
mUsesPointSize = false;
+ mUsesInstanceID = false;
mUsesFragDepth = false;
mUsesXor = false;
- mUsesMod1 = false;
- mUsesMod2v = false;
- mUsesMod2f = false;
- mUsesMod3v = false;
- mUsesMod3f = false;
- mUsesMod4v = false;
- mUsesMod4f = false;
- mUsesFaceforward1 = false;
- mUsesFaceforward2 = false;
- mUsesFaceforward3 = false;
- mUsesFaceforward4 = false;
- mUsesAtan2_1 = false;
- mUsesAtan2_2 = false;
- mUsesAtan2_3 = false;
- mUsesAtan2_4 = false;
mUsesDiscardRewriting = false;
mUsesNestedBreak = false;
-
- const ShBuiltInResources &resources = parentTranslator->getResources();
- mNumRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
+ mRequiresIEEEStrictCompiling = false;
mUniqueIndex = 0;
@@ -143,20 +139,14 @@ OutputHLSL::OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator)
mExcessiveLoopIndex = NULL;
mStructureHLSL = new StructureHLSL;
- mUniformHLSL = new UniformHLSL(mStructureHLSL, parentTranslator);
+ mUniformHLSL = new UniformHLSL(mStructureHLSL, outputType, uniforms);
if (mOutputType == SH_HLSL9_OUTPUT)
{
- if (mContext.shaderType == GL_FRAGMENT_SHADER)
- {
- // Reserve registers for dx_DepthRange, dx_ViewCoords and dx_DepthFront
- mUniformHLSL->reserveUniformRegisters(3);
- }
- else
- {
- // Reserve registers for dx_DepthRange and dx_ViewAdjust
- mUniformHLSL->reserveUniformRegisters(2);
- }
+ // Fragment shaders need dx_DepthRange, dx_ViewCoords and dx_DepthFront.
+ // Vertex shaders need a slightly different set: dx_DepthRange, dx_ViewCoords and dx_ViewAdjust.
+ // In both cases total 3 uniform registers need to be reserved.
+ mUniformHLSL->reserveUniformRegisters(3);
}
// Reserve registers for the default uniform block and driver constants
@@ -168,27 +158,55 @@ OutputHLSL::~OutputHLSL()
SafeDelete(mUnfoldShortCircuit);
SafeDelete(mStructureHLSL);
SafeDelete(mUniformHLSL);
+ for (auto it = mStructEqualityFunctions.begin(); it != mStructEqualityFunctions.end(); ++it)
+ {
+ SafeDelete(*it);
+ }
+ for (auto it = mArrayEqualityFunctions.begin(); it != mArrayEqualityFunctions.end(); ++it)
+ {
+ SafeDelete(*it);
+ }
}
-void OutputHLSL::output()
+void OutputHLSL::output(TIntermNode *treeRoot, TInfoSinkBase &objSink)
{
- mContainsLoopDiscontinuity = mContext.shaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(mContext.treeRoot);
- mContainsAnyLoop = containsAnyLoop(mContext.treeRoot);
- const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(mContext.treeRoot);
+ mContainsLoopDiscontinuity = mShaderType == GL_FRAGMENT_SHADER && containsLoopDiscontinuity(treeRoot);
+ mContainsAnyLoop = containsAnyLoop(treeRoot);
+ const std::vector<TIntermTyped*> &flaggedStructs = FlagStd140ValueStructs(treeRoot);
makeFlaggedStructMaps(flaggedStructs);
// Work around D3D9 bug that would manifest in vertex shaders with selection blocks which
// use a vertex attribute as a condition, and some related computation in the else block.
- if (mOutputType == SH_HLSL9_OUTPUT && mContext.shaderType == GL_VERTEX_SHADER)
+ if (mOutputType == SH_HLSL9_OUTPUT && mShaderType == GL_VERTEX_SHADER)
+ {
+ RewriteElseBlocks(treeRoot);
+ }
+
+ BuiltInFunctionEmulator builtInFunctionEmulator;
+ InitBuiltInFunctionEmulatorForHLSL(&builtInFunctionEmulator);
+ builtInFunctionEmulator.MarkBuiltInFunctionsForEmulation(treeRoot);
+
+ // Output the body and footer first to determine what has to go in the header
+ mInfoSinkStack.push(&mBody);
+ treeRoot->traverse(this);
+ mInfoSinkStack.pop();
+
+ mInfoSinkStack.push(&mFooter);
+ if (!mDeferredGlobalInitializers.empty())
{
- RewriteElseBlocks(mContext.treeRoot);
+ writeDeferredGlobalInitializers(mFooter);
}
+ mInfoSinkStack.pop();
+
+ mInfoSinkStack.push(&mHeader);
+ header(&builtInFunctionEmulator);
+ mInfoSinkStack.pop();
- mContext.treeRoot->traverse(this); // Output the body first to determine what has to go in the header
- header();
+ objSink << mHeader.c_str();
+ objSink << mBody.c_str();
+ objSink << mFooter.c_str();
- mContext.infoSink().obj << mHeader.c_str();
- mContext.infoSink().obj << mBody.c_str();
+ builtInFunctionEmulator.Cleanup();
}
void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs)
@@ -197,10 +215,14 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flagge
{
TIntermTyped *flaggedNode = flaggedStructs[structIndex];
+ TInfoSinkBase structInfoSink;
+ mInfoSinkStack.push(&structInfoSink);
+
// This will mark the necessary block elements as referenced
flaggedNode->traverse(this);
- TString structName(mBody.c_str());
- mBody.erase();
+
+ TString structName(structInfoSink.c_str());
+ mInfoSinkStack.pop();
mFlaggedStructOriginalNames[flaggedNode] = structName;
@@ -213,11 +235,6 @@ void OutputHLSL::makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flagge
}
}
-TInfoSinkBase &OutputHLSL::getBodyStream()
-{
- return mBody;
-}
-
const std::map<std::string, unsigned int> &OutputHLSL::getInterfaceBlockRegisterMap() const
{
return mUniformHLSL->getInterfaceBlockRegisterMap();
@@ -277,9 +294,9 @@ TString OutputHLSL::structInitializerString(int indent, const TStructure &struct
return init;
}
-void OutputHLSL::header()
+void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
{
- TInfoSinkBase &out = mHeader;
+ TInfoSinkBase &out = getInfoSink();
TString varyings;
TString attributes;
@@ -320,6 +337,23 @@ void OutputHLSL::header()
out << mUniformHLSL->uniformsHeader(mOutputType, mReferencedUniforms);
out << mUniformHLSL->interfaceBlocksHeader(mReferencedInterfaceBlocks);
+ if (!mEqualityFunctions.empty())
+ {
+ out << "\n// Equality functions\n\n";
+ for (auto it = mEqualityFunctions.cbegin(); it != mEqualityFunctions.cend(); ++it)
+ {
+ out << (*it)->functionDefinition << "\n";
+ }
+ }
+ if (!mArrayAssignmentFunctions.empty())
+ {
+ out << "\n// Assignment functions\n\n";
+ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it)
+ {
+ out << it->functionDefinition << "\n";
+ }
+ }
+
if (mUsesDiscardRewriting)
{
out << "#define ANGLE_USES_DISCARD_REWRITING\n";
@@ -330,6 +364,11 @@ void OutputHLSL::header()
out << "#define ANGLE_USES_NESTED_BREAK\n";
}
+ if (mRequiresIEEEStrictCompiling)
+ {
+ out << "#define ANGLE_REQUIRES_IEEE_STRICT_COMPILING\n";
+ }
+
out << "#ifdef ANGLE_ENABLE_LOOP_FLATTEN\n"
"#define LOOP [loop]\n"
"#define FLATTEN [flatten]\n"
@@ -338,16 +377,16 @@ void OutputHLSL::header()
"#define FLATTEN\n"
"#endif\n";
- if (mContext.shaderType == GL_FRAGMENT_SHADER)
+ if (mShaderType == GL_FRAGMENT_SHADER)
{
- TExtensionBehavior::const_iterator iter = mContext.extensionBehavior().find("GL_EXT_draw_buffers");
- const bool usingMRTExtension = (iter != mContext.extensionBehavior().end() && (iter->second == EBhEnable || iter->second == EBhRequire));
+ TExtensionBehavior::const_iterator iter = mExtensionBehavior.find("GL_EXT_draw_buffers");
+ const bool usingMRTExtension = (iter != mExtensionBehavior.end() && (iter->second == EBhEnable || iter->second == EBhRequire));
out << "// Varyings\n";
out << varyings;
out << "\n";
- if (mContext.getShaderVersion() >= 300)
+ if (mShaderVersion >= 300)
{
for (ReferencedSymbols::const_iterator outputVariableIt = mReferencedOutputVariables.begin(); outputVariableIt != mReferencedOutputVariables.end(); outputVariableIt++)
{
@@ -493,6 +532,11 @@ void OutputHLSL::header()
out << "static float gl_PointSize = float(1);\n";
}
+ if (mUsesInstanceID)
+ {
+ out << "static int gl_InstanceID;";
+ }
+
out << "\n"
"// Varyings\n";
out << varyings;
@@ -511,14 +555,22 @@ void OutputHLSL::header()
if (mOutputType == SH_HLSL11_OUTPUT)
{
+ out << "cbuffer DriverConstants : register(b1)\n"
+ "{\n";
+
if (mUsesDepthRange)
{
- out << "cbuffer DriverConstants : register(b1)\n"
- "{\n"
- " float3 dx_DepthRange : packoffset(c0);\n"
- "};\n"
- "\n";
+ out << " float3 dx_DepthRange : packoffset(c0);\n";
}
+
+ // dx_ViewAdjust and dx_ViewCoords will only be used in Feature Level 9 shaders.
+ // However, we declare it for all shaders (including Feature Level 10+).
+ // The bytecode is the same whether we declare it or not, since D3DCompiler removes it if it's unused.
+ out << " float4 dx_ViewAdjust : packoffset(c1);\n";
+ out << " float2 dx_ViewCoords : packoffset(c2);\n";
+
+ out << "};\n"
+ "\n";
}
else
{
@@ -527,7 +579,8 @@ void OutputHLSL::header()
out << "uniform float3 dx_DepthRange : register(c0);\n";
}
- out << "uniform float4 dx_ViewAdjust : register(c1);\n"
+ out << "uniform float4 dx_ViewAdjust : register(c1);\n";
+ out << "uniform float2 dx_ViewCoords : register(c2);\n"
"\n";
}
@@ -980,7 +1033,15 @@ void OutputHLSL::header()
}
else if (IsShadowSampler(textureFunction->sampler))
{
- out << "x.SampleCmp(s, ";
+ switch(textureFunction->method)
+ {
+ case TextureFunction::IMPLICIT: out << "x.SampleCmp(s, "; break;
+ case TextureFunction::BIAS: out << "x.SampleCmp(s, "; break;
+ case TextureFunction::LOD: out << "x.SampleCmp(s, "; break;
+ case TextureFunction::LOD0: out << "x.SampleCmpLevelZero(s, "; break;
+ case TextureFunction::LOD0BIAS: out << "x.SampleCmpLevelZero(s, "; break;
+ default: UNREACHABLE();
+ }
}
else
{
@@ -1111,11 +1172,20 @@ void OutputHLSL::header()
else if (IsShadowSampler(textureFunction->sampler))
{
// Compare value
- switch(textureFunction->coords)
+ if (textureFunction->proj)
{
- case 3: out << "), t.z"; break;
- case 4: out << "), t.w"; break;
- default: UNREACHABLE();
+ // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+ // The resulting third component of P' in the shadow forms is used as Dref
+ out << "), t.z" << proj;
+ }
+ else
+ {
+ switch(textureFunction->coords)
+ {
+ case 3: out << "), t.z"; break;
+ case 4: out << "), t.w"; break;
+ default: UNREACHABLE();
+ }
}
}
else
@@ -1131,11 +1201,20 @@ void OutputHLSL::header()
else if (IsShadowSampler(textureFunction->sampler))
{
// Compare value
- switch(textureFunction->coords)
+ if (textureFunction->proj)
{
- case 3: out << "), t.z"; break;
- case 4: out << "), t.w"; break;
- default: UNREACHABLE();
+ // According to ESSL 3.00.4 sec 8.8 p95 on textureProj:
+ // The resulting third component of P' in the shadow forms is used as Dref
+ out << "), t.z" << proj;
+ }
+ else
+ {
+ switch(textureFunction->coords)
+ {
+ case 3: out << "), t.z"; break;
+ case 4: out << "), t.w"; break;
+ default: UNREACHABLE();
+ }
}
}
else
@@ -1205,179 +1284,12 @@ void OutputHLSL::header()
"\n";
}
- if (mUsesMod1)
- {
- out << "float mod(float x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod2v)
- {
- out << "float2 mod(float2 x, float2 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod2f)
- {
- out << "float2 mod(float2 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod3v)
- {
- out << "float3 mod(float3 x, float3 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod3f)
- {
- out << "float3 mod(float3 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod4v)
- {
- out << "float4 mod(float4 x, float4 y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesMod4f)
- {
- out << "float4 mod(float4 x, float y)\n"
- "{\n"
- " return x - y * floor(x / y);\n"
- "}\n"
- "\n";
- }
-
- if (mUsesFaceforward1)
- {
- out << "float faceforward(float N, float I, float Nref)\n"
- "{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n";
- }
-
- if (mUsesFaceforward2)
- {
- out << "float2 faceforward(float2 N, float2 I, float2 Nref)\n"
- "{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n";
- }
-
- if (mUsesFaceforward3)
- {
- out << "float3 faceforward(float3 N, float3 I, float3 Nref)\n"
- "{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n";
- }
-
- if (mUsesFaceforward4)
- {
- out << "float4 faceforward(float4 N, float4 I, float4 Nref)\n"
- "{\n"
- " if(dot(Nref, I) >= 0)\n"
- " {\n"
- " return -N;\n"
- " }\n"
- " else\n"
- " {\n"
- " return N;\n"
- " }\n"
- "}\n"
- "\n";
- }
-
- if (mUsesAtan2_1)
- {
- out << "float atanyx(float y, float x)\n"
- "{\n"
- " if(x == 0 && y == 0) x = 1;\n" // Avoid producing a NaN
- " return atan2(y, x);\n"
- "}\n";
- }
-
- if (mUsesAtan2_2)
- {
- out << "float2 atanyx(float2 y, float2 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
- "}\n";
- }
-
- if (mUsesAtan2_3)
- {
- out << "float3 atanyx(float3 y, float3 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
- " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
- "}\n";
- }
-
- if (mUsesAtan2_4)
- {
- out << "float4 atanyx(float4 y, float4 x)\n"
- "{\n"
- " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
- " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
- " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
- " if(x[3] == 0 && y[3] == 0) x[3] = 1;\n"
- " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]), atan2(y[3], x[3]));\n"
- "}\n";
- }
+ builtInFunctionEmulator->OutputEmulatedFunctions(out);
}
void OutputHLSL::visitSymbol(TIntermSymbol *node)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
// Handle accessing std140 structs by value
if (mFlaggedStructMappedNames.count(node) > 0)
@@ -1458,6 +1370,11 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
mUsesPointSize = true;
out << name;
}
+ else if (qualifier == EvqInstanceID)
+ {
+ mUsesInstanceID = true;
+ out << name;
+ }
else if (name == "gl_FragDepthEXT")
{
mUsesFragDepth = true;
@@ -1476,12 +1393,51 @@ void OutputHLSL::visitSymbol(TIntermSymbol *node)
void OutputHLSL::visitRaw(TIntermRaw *node)
{
- mBody << node->getRawText();
+ getInfoSink() << node->getRawText();
+}
+
+void OutputHLSL::outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out)
+{
+ if (type.isScalar() && !type.isArray())
+ {
+ if (op == EOpEqual)
+ {
+ outputTriplet(visit, "(", " == ", ")", out);
+ }
+ else
+ {
+ outputTriplet(visit, "(", " != ", ")", out);
+ }
+ }
+ else
+ {
+ if (visit == PreVisit && op == EOpNotEqual)
+ {
+ out << "!";
+ }
+
+ if (type.isArray())
+ {
+ const TString &functionName = addArrayEqualityFunction(type);
+ outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out);
+ }
+ else if (type.getBasicType() == EbtStruct)
+ {
+ const TStructure &structure = *type.getStruct();
+ const TString &functionName = addStructEqualityFunction(structure);
+ outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out);
+ }
+ else
+ {
+ ASSERT(type.isMatrix() || type.isVector());
+ outputTriplet(visit, "all(", " == ", ")", out);
+ }
+ }
}
bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
// Handle accessing std140 structs by value
if (mFlaggedStructMappedNames.count(node) > 0)
@@ -1492,7 +1448,17 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
switch (node->getOp())
{
- case EOpAssign: outputTriplet(visit, "(", " = ", ")"); break;
+ case EOpAssign:
+ if (node->getLeft()->isArray())
+ {
+ const TString &functionName = addArrayAssignmentFunction(node->getType());
+ outputTriplet(visit, (functionName + "(").c_str(), ", ", ")");
+ }
+ else
+ {
+ outputTriplet(visit, "(", " = ", ")");
+ }
+ break;
case EOpInitialize:
if (visit == PreVisit)
{
@@ -1502,22 +1468,21 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
// this to "float t = x, x = t;".
TIntermSymbol *symbolNode = node->getLeft()->getAsSymbolNode();
+ ASSERT(symbolNode);
TIntermTyped *expression = node->getRight();
- sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
- expression->traverse(&searchSymbol);
- bool sameSymbol = searchSymbol.foundMatch();
-
- if (sameSymbol)
+ // TODO (jmadill): do a 'deep' scan to know if an expression is statically const
+ if (symbolNode->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst)
{
- // Type already printed
- out << "t" + str(mUniqueIndex) + " = ";
- expression->traverse(this);
- out << ", ";
- symbolNode->traverse(this);
- out << " = t" + str(mUniqueIndex);
-
- mUniqueIndex++;
+ // For variables which are not constant, defer their real initialization until
+ // after we initialize other globals: uniforms, attributes and varyings.
+ mDeferredGlobalInitializers.push_back(std::make_pair(symbolNode, expression));
+ const TString &initString = initializer(node->getType());
+ node->setRight(new TIntermRaw(node->getType(), initString));
+ }
+ else if (writeSameSymbolInitializer(out, symbolNode, expression))
+ {
+ // Skip initializing the rest of the expression
return false;
}
}
@@ -1554,16 +1519,22 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
}
else if (visit == InVisit)
{
- out << " = mul(";
+ out << " = transpose(mul(transpose(";
node->getLeft()->traverse(this);
- out << ", ";
+ out << "), transpose(";
}
else
{
- out << "))";
+ out << "))))";
}
break;
case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
+ case EOpIModAssign: outputTriplet(visit, "(", " %= ", ")"); break;
+ case EOpBitShiftLeftAssign: outputTriplet(visit, "(", " <<= ", ")"); break;
+ case EOpBitShiftRightAssign: outputTriplet(visit, "(", " >>= ", ")"); break;
+ case EOpBitwiseAndAssign: outputTriplet(visit, "(", " &= ", ")"); break;
+ case EOpBitwiseXorAssign: outputTriplet(visit, "(", " ^= ", ")"); break;
+ case EOpBitwiseOrAssign: outputTriplet(visit, "(", " |= ", ")"); break;
case EOpIndexDirect:
{
const TType& leftType = node->getLeft()->getType();
@@ -1651,65 +1622,15 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
+ case EOpIMod: outputTriplet(visit, "(", " % ", ")"); break;
+ case EOpBitShiftLeft: outputTriplet(visit, "(", " << ", ")"); break;
+ case EOpBitShiftRight: outputTriplet(visit, "(", " >> ", ")"); break;
+ case EOpBitwiseAnd: outputTriplet(visit, "(", " & ", ")"); break;
+ case EOpBitwiseXor: outputTriplet(visit, "(", " ^ ", ")"); break;
+ case EOpBitwiseOr: outputTriplet(visit, "(", " | ", ")"); break;
case EOpEqual:
case EOpNotEqual:
- if (node->getLeft()->isScalar())
- {
- if (node->getOp() == EOpEqual)
- {
- outputTriplet(visit, "(", " == ", ")");
- }
- else
- {
- outputTriplet(visit, "(", " != ", ")");
- }
- }
- else if (node->getLeft()->getBasicType() == EbtStruct)
- {
- if (node->getOp() == EOpEqual)
- {
- out << "(";
- }
- else
- {
- out << "!(";
- }
-
- const TStructure &structure = *node->getLeft()->getType().getStruct();
- const TFieldList &fields = structure.fields();
-
- for (size_t i = 0; i < fields.size(); i++)
- {
- const TField *field = fields[i];
-
- node->getLeft()->traverse(this);
- out << "." + DecorateField(field->name(), structure) + " == ";
- node->getRight()->traverse(this);
- out << "." + DecorateField(field->name(), structure);
-
- if (i < fields.size() - 1)
- {
- out << " && ";
- }
- }
-
- out << ")";
-
- return false;
- }
- else
- {
- ASSERT(node->getLeft()->isMatrix() || node->getLeft()->isVector());
-
- if (node->getOp() == EOpEqual)
- {
- outputTriplet(visit, "all(", " == ", ")");
- }
- else
- {
- outputTriplet(visit, "!all(", " == ", ")");
- }
- }
+ outputEqual(visit, node->getLeft()->getType(), node->getOp(), out);
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
@@ -1760,6 +1681,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: outputTriplet(visit, "(+", "", ")"); break;
case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
+ case EOpBitwiseNot: outputTriplet(visit, "(~", "", ")"); break;
case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
@@ -1772,6 +1694,21 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
+ case EOpSinh: outputTriplet(visit, "sinh(", "", ")"); break;
+ case EOpCosh: outputTriplet(visit, "cosh(", "", ")"); break;
+ case EOpTanh: outputTriplet(visit, "tanh(", "", ")"); break;
+ case EOpAsinh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "asinh(");
+ break;
+ case EOpAcosh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "acosh(");
+ break;
+ case EOpAtanh:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "atanh(");
+ break;
case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
@@ -1781,8 +1718,47 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
+ case EOpTrunc: outputTriplet(visit, "trunc(", "", ")"); break;
+ case EOpRound: outputTriplet(visit, "round(", "", ")"); break;
+ case EOpRoundEven:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "roundEven(");
+ break;
case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
+ case EOpIsNan:
+ outputTriplet(visit, "isnan(", "", ")");
+ mRequiresIEEEStrictCompiling = true;
+ break;
+ case EOpIsInf: outputTriplet(visit, "isinf(", "", ")"); break;
+ case EOpFloatBitsToInt: outputTriplet(visit, "asint(", "", ")"); break;
+ case EOpFloatBitsToUint: outputTriplet(visit, "asuint(", "", ")"); break;
+ case EOpIntBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break;
+ case EOpUintBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break;
+ case EOpPackSnorm2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "packSnorm2x16(");
+ break;
+ case EOpPackUnorm2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "packUnorm2x16(");
+ break;
+ case EOpPackHalf2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "packHalf2x16(");
+ break;
+ case EOpUnpackSnorm2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "unpackSnorm2x16(");
+ break;
+ case EOpUnpackUnorm2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "unpackUnorm2x16(");
+ break;
+ case EOpUnpackHalf2x16:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "unpackHalf2x16(");
+ break;
case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
case EOpDFdx:
@@ -1815,6 +1791,13 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
outputTriplet(visit, "fwidth(", "", ")");
}
break;
+ case EOpTranspose: outputTriplet(visit, "transpose(", "", ")"); break;
+ case EOpDeterminant: outputTriplet(visit, "determinant(transpose(", "", "))"); break;
+ case EOpInverse:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "inverse(");
+ break;
+
case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
default: UNREACHABLE();
@@ -1825,7 +1808,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
switch (node->getOp())
{
@@ -1843,7 +1826,11 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
traverseStatements(*sit);
- out << ";\n";
+ // Don't output ; after case labels, they're terminated by :
+ // This is needed especially since outputting a ; after a case statement would turn empty
+ // case statements into non-empty case statements, disallowing fall-through from them.
+ if ((*sit)->getAsCaseNode() == nullptr)
+ out << ";\n";
}
if (mInsideFunction)
@@ -1871,11 +1858,12 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{
- for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
+ for (auto it = sequence->cbegin(); it != sequence->cend(); ++it)
{
- if (isSingleStatement(*sit))
+ const auto &seqElement = *it;
+ if (isSingleStatement(seqElement))
{
- mUnfoldShortCircuit->traverse(*sit);
+ mUnfoldShortCircuit->traverse(seqElement);
}
if (!mInsideFunction)
@@ -1885,7 +1873,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
out << TypeString(variable->getType()) + " ";
- TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
+ TIntermSymbol *symbol = seqElement->getAsSymbolNode();
if (symbol)
{
@@ -1895,10 +1883,10 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
}
else
{
- (*sit)->traverse(this);
+ seqElement->traverse(this);
}
- if (*sit != sequence->back())
+ if (seqElement != sequence->back())
{
out << ";\n";
}
@@ -2149,7 +2137,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
bool bias = (arguments->size() > mandatoryArgumentCount); // Bias argument is optional
- if (lod0 || mContext.shaderType == GL_VERTEX_SHADER)
+ if (lod0 || mShaderType == GL_VERTEX_SHADER)
{
if (bias)
{
@@ -2217,7 +2205,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
const TString &structName = StructNameString(*node->getType().getStruct());
mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
- outputTriplet(visit, structName + "_ctor(", ", ", ")");
+ outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")");
}
break;
case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
@@ -2227,37 +2215,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
case EOpMod:
- {
- // We need to look at the number of components in both arguments
- const int modValue = (*node->getSequence())[0]->getAsTyped()->getNominalSize() * 10 +
- (*node->getSequence())[1]->getAsTyped()->getNominalSize();
- switch (modValue)
- {
- case 11: mUsesMod1 = true; break;
- case 22: mUsesMod2v = true; break;
- case 21: mUsesMod2f = true; break;
- case 33: mUsesMod3v = true; break;
- case 31: mUsesMod3f = true; break;
- case 44: mUsesMod4v = true; break;
- case 41: mUsesMod4f = true; break;
- default: UNREACHABLE();
- }
-
- outputTriplet(visit, "mod(", ", ", ")");
- }
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "mod(");
break;
+ case EOpModf: outputTriplet(visit, "modf(", ", ", ")"); break;
case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
case EOpAtan:
ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator
- switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize())
- {
- case 1: mUsesAtan2_1 = true; break;
- case 2: mUsesAtan2_2 = true; break;
- case 3: mUsesAtan2_3 = true; break;
- case 4: mUsesAtan2_4 = true; break;
- default: UNREACHABLE();
- }
- outputTriplet(visit, "atanyx(", ", ", ")");
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "atan(");
break;
case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
@@ -2269,21 +2235,15 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
case EOpFaceForward:
- {
- switch ((*node->getSequence())[0]->getAsTyped()->getNominalSize()) // Number of components in the first argument
- {
- case 1: mUsesFaceforward1 = true; break;
- case 2: mUsesFaceforward2 = true; break;
- case 3: mUsesFaceforward3 = true; break;
- case 4: mUsesFaceforward4 = true; break;
- default: UNREACHABLE();
- }
-
- outputTriplet(visit, "faceforward(", ", ", ")");
- }
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "faceforward(");
break;
case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
+ case EOpOuterProduct:
+ ASSERT(node->getUseEmulatedFunction());
+ writeEmulatedFunctionTriplet(visit, "outerProduct(");
+ break;
case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
default: UNREACHABLE();
}
@@ -2293,7 +2253,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
if (node->usesTernaryOperator())
{
@@ -2307,7 +2267,7 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
// however flattening all the ifs in branch heavy shaders made D3D error too.
// As a temporary workaround we flatten the ifs only if there is at least a loop
// present somewhere in the shader.
- if (mContext.shaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
+ if (mShaderType == GL_FRAGMENT_SHADER && mContainsAnyLoop)
{
out << "FLATTEN ";
}
@@ -2361,6 +2321,37 @@ bool OutputHLSL::visitSelection(Visit visit, TIntermSelection *node)
return false;
}
+bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node)
+{
+ if (node->getStatementList())
+ {
+ node->setStatementList(RemoveSwitchFallThrough::removeFallThrough(node->getStatementList()));
+ outputTriplet(visit, "switch (", ") ", "");
+ // The curly braces get written when visiting the statementList aggregate
+ }
+ else
+ {
+ // No statementList, so it won't output curly braces
+ outputTriplet(visit, "switch (", ") {", "}\n");
+ }
+ return true;
+}
+
+bool OutputHLSL::visitCase(Visit visit, TIntermCase *node)
+{
+ if (node->hasCondition())
+ {
+ outputTriplet(visit, "case (", "", "):\n");
+ return true;
+ }
+ else
+ {
+ TInfoSinkBase &out = getInfoSink();
+ out << "default:\n";
+ return false;
+ }
+}
+
void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
{
writeConstantUnion(node->getType(), node->getUnionArrayPointer());
@@ -2388,7 +2379,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
}
}
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
if (node->getType() == ELoopDoWhile)
{
@@ -2454,7 +2445,7 @@ bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
switch (node->getFlowOp())
{
@@ -2556,7 +2547,7 @@ bool OutputHLSL::isSingleStatement(TIntermNode *node)
bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
{
const int MAX_LOOP_ITERATIONS = 254;
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
// Parse loops of the form:
// for(int index = initial; index [comparator] limit; index += increment)
@@ -2756,10 +2747,8 @@ bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
return false; // Not handled as an excessive loop
}
-void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString)
+void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out)
{
- TInfoSinkBase &out = mBody;
-
if (visit == PreVisit)
{
out << preString;
@@ -2774,19 +2763,26 @@ void OutputHLSL::outputTriplet(Visit visit, const TString &preString, const TStr
}
}
+void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString)
+{
+ outputTriplet(visit, preString, inString, postString, getInfoSink());
+}
+
void OutputHLSL::outputLineDirective(int line)
{
- if ((mContext.compileOptions & SH_LINE_DIRECTIVES) && (line > 0))
+ if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0))
{
- mBody << "\n";
- mBody << "#line " << line;
+ TInfoSinkBase &out = getInfoSink();
+
+ out << "\n";
+ out << "#line " << line;
- if (mContext.sourcePath)
+ if (mSourcePath)
{
- mBody << " \"" << mContext.sourcePath << "\"";
+ out << " \"" << mSourcePath << "\"";
}
- mBody << "\n";
+ out << "\n";
}
}
@@ -2832,15 +2828,15 @@ TString OutputHLSL::initializer(const TType &type)
return "{" + string + "}";
}
-void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters)
+void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
if (visit == PreVisit)
{
mStructureHLSL->addConstructor(type, name, parameters);
- out << name + "(";
+ out << name << "(";
}
else if (visit == InVisit)
{
@@ -2854,7 +2850,7 @@ void OutputHLSL::outputConstructor(Visit visit, const TType &type, const TString
const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const ConstantUnion *constUnion)
{
- TInfoSinkBase &out = mBody;
+ TInfoSinkBase &out = getInfoSink();
const TStructure* structure = type.getStruct();
if (structure)
@@ -2912,4 +2908,209 @@ const ConstantUnion *OutputHLSL::writeConstantUnion(const TType &type, const Con
return constUnion;
}
+void OutputHLSL::writeEmulatedFunctionTriplet(Visit visit, const char *preStr)
+{
+ TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr);
+ outputTriplet(visit, preString.c_str(), ", ", ")");
+}
+
+bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression)
+{
+ sh::SearchSymbol searchSymbol(symbolNode->getSymbol());
+ expression->traverse(&searchSymbol);
+
+ if (searchSymbol.foundMatch())
+ {
+ // Type already printed
+ out << "t" + str(mUniqueIndex) + " = ";
+ expression->traverse(this);
+ out << ", ";
+ symbolNode->traverse(this);
+ out << " = t" + str(mUniqueIndex);
+
+ mUniqueIndex++;
+ return true;
+ }
+
+ return false;
+}
+
+void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out)
+{
+ out << "#define ANGLE_USES_DEFERRED_INIT\n"
+ << "\n"
+ << "void initializeDeferredGlobals()\n"
+ << "{\n";
+
+ for (auto it = mDeferredGlobalInitializers.cbegin(); it != mDeferredGlobalInitializers.cend(); ++it)
+ {
+ const auto &deferredGlobal = *it;
+ TIntermSymbol *symbol = deferredGlobal.first;
+ TIntermTyped *expression = deferredGlobal.second;
+ ASSERT(symbol);
+ ASSERT(symbol->getQualifier() == EvqGlobal && expression->getQualifier() != EvqConst);
+
+ out << " " << Decorate(symbol->getSymbol()) << " = ";
+
+ if (!writeSameSymbolInitializer(out, symbol, expression))
+ {
+ ASSERT(mInfoSinkStack.top() == &out);
+ expression->traverse(this);
+ }
+
+ out << ";\n";
+ }
+
+ out << "}\n"
+ << "\n";
+}
+
+TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
+{
+ const TFieldList &fields = structure.fields();
+
+ for (auto it = mStructEqualityFunctions.cbegin(); it != mStructEqualityFunctions.cend(); ++it)
+ {
+ auto *eqFunction = *it;
+ if (eqFunction->structure == &structure)
+ {
+ return eqFunction->functionName;
+ }
+ }
+
+ const TString &structNameString = StructNameString(structure);
+
+ StructEqualityFunction *function = new StructEqualityFunction();
+ function->structure = &structure;
+ function->functionName = "angle_eq_" + structNameString;
+
+ TInfoSinkBase fnOut;
+
+ fnOut << "bool " << function->functionName << "(" << structNameString << " a, " << structNameString + " b)\n"
+ << "{\n"
+ " return ";
+
+ for (size_t i = 0; i < fields.size(); i++)
+ {
+ const TField *field = fields[i];
+ const TType *fieldType = field->type();
+
+ const TString &fieldNameA = "a." + Decorate(field->name());
+ const TString &fieldNameB = "b." + Decorate(field->name());
+
+ if (i > 0)
+ {
+ fnOut << " && ";
+ }
+
+ fnOut << "(";
+ outputEqual(PreVisit, *fieldType, EOpEqual, fnOut);
+ fnOut << fieldNameA;
+ outputEqual(InVisit, *fieldType, EOpEqual, fnOut);
+ fnOut << fieldNameB;
+ outputEqual(PostVisit, *fieldType, EOpEqual, fnOut);
+ fnOut << ")";
+ }
+
+ fnOut << ";\n" << "}\n";
+
+ function->functionDefinition = fnOut.c_str();
+
+ mStructEqualityFunctions.push_back(function);
+ mEqualityFunctions.push_back(function);
+
+ return function->functionName;
+}
+
+TString OutputHLSL::addArrayEqualityFunction(const TType& type)
+{
+ for (auto it = mArrayEqualityFunctions.cbegin(); it != mArrayEqualityFunctions.cend(); ++it)
+ {
+ const auto &eqFunction = *it;
+ if (eqFunction->type == type)
+ {
+ return eqFunction->functionName;
+ }
+ }
+
+ const TString &typeName = TypeString(type);
+
+ ArrayHelperFunction *function = new ArrayHelperFunction();
+ function->type = type;
+
+ TInfoSinkBase fnNameOut;
+ fnNameOut << "angle_eq_" << type.getArraySize() << "_" << typeName;
+ function->functionName = fnNameOut.c_str();
+
+ TType nonArrayType = type;
+ nonArrayType.clearArrayness();
+
+ TInfoSinkBase fnOut;
+
+ fnOut << "bool " << function->functionName << "("
+ << typeName << " a[" << type.getArraySize() << "], "
+ << typeName << " b[" << type.getArraySize() << "])\n"
+ << "{\n"
+ " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n"
+ " {\n"
+ " if (";
+
+ outputEqual(PreVisit, nonArrayType, EOpNotEqual, fnOut);
+ fnOut << "a[i]";
+ outputEqual(InVisit, nonArrayType, EOpNotEqual, fnOut);
+ fnOut << "b[i]";
+ outputEqual(PostVisit, nonArrayType, EOpNotEqual, fnOut);
+
+ fnOut << ") { return false; }\n"
+ " }\n"
+ " return true;\n"
+ "}\n";
+
+ function->functionDefinition = fnOut.c_str();
+
+ mArrayEqualityFunctions.push_back(function);
+ mEqualityFunctions.push_back(function);
+
+ return function->functionName;
+}
+
+TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
+{
+ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it)
+ {
+ const auto &assignFunction = *it;
+ if (assignFunction.type == type)
+ {
+ return assignFunction.functionName;
+ }
+ }
+
+ const TString &typeName = TypeString(type);
+
+ ArrayHelperFunction function;
+ function.type = type;
+
+ TInfoSinkBase fnNameOut;
+ fnNameOut << "angle_assign_" << type.getArraySize() << "_" << typeName;
+ function.functionName = fnNameOut.c_str();
+
+ TInfoSinkBase fnOut;
+
+ fnOut << "void " << function.functionName << "(out "
+ << typeName << " a[" << type.getArraySize() << "], "
+ << typeName << " b[" << type.getArraySize() << "])\n"
+ << "{\n"
+ " for (int i = 0; i < " << type.getArraySize() << "; ++i)\n"
+ " {\n"
+ " a[i] = b[i];\n"
+ " }\n"
+ "}\n";
+
+ function.functionDefinition = fnOut.c_str();
+
+ mArrayAssignmentFunctions.push_back(function);
+
+ return function.functionName;
+}
+
}
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
index 5525e6eaa6..51da877c72 100644
--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.h
@@ -4,18 +4,20 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_OUTPUTHLSL_H_
-#define COMPILER_OUTPUTHLSL_H_
+#ifndef COMPILER_TRANSLATOR_OUTPUTHLSL_H_
+#define COMPILER_TRANSLATOR_OUTPUTHLSL_H_
#include <list>
#include <set>
#include <map>
+#include <stack>
#include "angle_gl.h"
-
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
+class BuiltInFunctionEmulator;
+
namespace sh
{
class UnfoldShortCircuit;
@@ -27,20 +29,25 @@ typedef std::map<TString, TIntermSymbol*> ReferencedSymbols;
class OutputHLSL : public TIntermTraverser
{
public:
- OutputHLSL(TParseContext &context, TranslatorHLSL *parentTranslator);
- ~OutputHLSL();
+ OutputHLSL(sh::GLenum shaderType, int shaderVersion,
+ const TExtensionBehavior &extensionBehavior,
+ const char *sourcePath, ShShaderOutput outputType,
+ int numRenderTargets, const std::vector<Uniform> &uniforms,
+ int compileOptions);
- void output();
+ ~OutputHLSL();
- TInfoSinkBase &getBodyStream();
+ void output(TIntermNode *treeRoot, TInfoSinkBase &objSink);
const std::map<std::string, unsigned int> &getInterfaceBlockRegisterMap() const;
const std::map<std::string, unsigned int> &getUniformRegisterMap() const;
static TString initializer(const TType &type);
+ TInfoSinkBase &getInfoSink() { ASSERT(!mInfoSinkStack.empty()); return *mInfoSinkStack.top(); }
+
protected:
- void header();
+ void header(const BuiltInFunctionEmulator *builtInFunctionEmulator);
// Visit AST nodes and output their code to the body stream
void visitSymbol(TIntermSymbol*);
@@ -49,6 +56,8 @@ class OutputHLSL : public TIntermTraverser
bool visitBinary(Visit visit, TIntermBinary*);
bool visitUnary(Visit visit, TIntermUnary*);
bool visitSelection(Visit visit, TIntermSelection*);
+ bool visitSwitch(Visit visit, TIntermSwitch *);
+ bool visitCase(Visit visit, TIntermCase *);
bool visitAggregate(Visit visit, TIntermAggregate*);
bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*);
@@ -56,16 +65,39 @@ class OutputHLSL : public TIntermTraverser
void traverseStatements(TIntermNode *node);
bool isSingleStatement(TIntermNode *node);
bool handleExcessiveLoop(TIntermLoop *node);
- void outputTriplet(Visit visit, const TString &preString, const TString &inString, const TString &postString);
+
+ // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
+ void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out);
+ void outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString);
void outputLineDirective(int line);
TString argumentString(const TIntermSymbol *symbol);
int vectorSize(const TType &type) const;
- void outputConstructor(Visit visit, const TType &type, const TString &name, const TIntermSequence *parameters);
+ // Emit constructor. Called with literal names so using const char* instead of TString.
+ void outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters);
const ConstantUnion *writeConstantUnion(const TType &type, const ConstantUnion *constUnion);
- TParseContext &mContext;
+ void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
+
+ void writeEmulatedFunctionTriplet(Visit visit, const char *preStr);
+ void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
+
+ // Returns true if it found a 'same symbol' initializer (initializer that references the variable it's initting)
+ bool writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression);
+ void writeDeferredGlobalInitializers(TInfoSinkBase &out);
+
+ // Returns the function name
+ TString addStructEqualityFunction(const TStructure &structure);
+ TString addArrayEqualityFunction(const TType &type);
+ TString addArrayAssignmentFunction(const TType &type);
+
+ sh::GLenum mShaderType;
+ int mShaderVersion;
+ const TExtensionBehavior &mExtensionBehavior;
+ const char *mSourcePath;
const ShShaderOutput mOutputType;
+ int mCompileOptions;
+
UnfoldShortCircuit *mUnfoldShortCircuit;
bool mInsideFunction;
@@ -74,6 +106,11 @@ class OutputHLSL : public TIntermTraverser
TInfoSinkBase mBody;
TInfoSinkBase mFooter;
+ // A stack is useful when we want to traverse in the header, or in helper functions, but not always
+ // write to the body. Instead use an InfoSink stack to keep our current state intact.
+ // TODO (jmadill): Just passing an InfoSink in function parameters would be simpler.
+ std::stack<TInfoSinkBase *> mInfoSinkStack;
+
ReferencedSymbols mReferencedUniforms;
ReferencedSymbols mReferencedInterfaceBlocks;
ReferencedSymbols mReferencedAttributes;
@@ -119,25 +156,13 @@ class OutputHLSL : public TIntermTraverser
bool mUsesPointCoord;
bool mUsesFrontFacing;
bool mUsesPointSize;
+ bool mUsesInstanceID;
bool mUsesFragDepth;
bool mUsesXor;
- bool mUsesMod1;
- bool mUsesMod2v;
- bool mUsesMod2f;
- bool mUsesMod3v;
- bool mUsesMod3f;
- bool mUsesMod4v;
- bool mUsesMod4f;
- bool mUsesFaceforward1;
- bool mUsesFaceforward2;
- bool mUsesFaceforward3;
- bool mUsesFaceforward4;
- bool mUsesAtan2_1;
- bool mUsesAtan2_2;
- bool mUsesAtan2_3;
- bool mUsesAtan2_4;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
+ bool mRequiresIEEEStrictCompiling;
+
int mNumRenderTargets;
@@ -156,9 +181,41 @@ class OutputHLSL : public TIntermTraverser
std::map<TIntermTyped*, TString> mFlaggedStructMappedNames;
std::map<TIntermTyped*, TString> mFlaggedStructOriginalNames;
- void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
+ // Some initializers use varyings, uniforms or attributes, thus we can't evaluate some variables
+ // at global static scope in HLSL. These variables depend on values which we retrieve from the
+ // shader input structure, which we set in the D3D main function. Instead, we can initialize
+ // these static globals after we initialize our other globals.
+ std::vector<std::pair<TIntermSymbol*, TIntermTyped*>> mDeferredGlobalInitializers;
+
+ struct HelperFunction
+ {
+ TString functionName;
+ TString functionDefinition;
+
+ virtual ~HelperFunction() {}
+ };
+
+ // A list of all equality comparison functions. It's important to preserve the order at
+ // which we add the functions, since nested structures call each other recursively, and
+ // structure equality functions may need to call array equality functions and vice versa.
+ // The ownership of the pointers is maintained by the type-specific arrays.
+ std::vector<HelperFunction*> mEqualityFunctions;
+
+ struct StructEqualityFunction : public HelperFunction
+ {
+ const TStructure *structure;
+ };
+ std::vector<StructEqualityFunction*> mStructEqualityFunctions;
+
+ struct ArrayHelperFunction : public HelperFunction
+ {
+ TType type;
+ };
+ std::vector<ArrayHelperFunction*> mArrayEqualityFunctions;
+
+ std::vector<ArrayHelperFunction> mArrayAssignmentFunctions;
};
}
-#endif // COMPILER_OUTPUTHLSL_H_
+#endif // COMPILER_TRANSLATOR_OUTPUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
index 37969b5468..7ad3f817ad 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.cpp
@@ -9,8 +9,9 @@
#include <stdarg.h>
#include <stdio.h>
-#include "compiler/translator/glslang.h"
#include "compiler/preprocessor/SourceLocation.h"
+#include "compiler/translator/glslang.h"
+#include "compiler/translator/ValidateSwitch.h"
///////////////////////////////////////////////////////////////////////
//
@@ -796,9 +797,24 @@ bool TParseContext::arrayErrorCheck(const TSourceLoc& line, const TString& ident
bool sameScope = false;
TSymbol* symbol = symbolTable.find(identifier, 0, &builtIn, &sameScope);
if (symbol == 0 || !sameScope) {
- if (reservedErrorCheck(line, identifier))
- return true;
-
+ bool needsReservedErrorCheck = true;
+
+ // gl_LastFragData may be redeclared with a new precision qualifier
+ if (identifier.compare(0, 15, "gl_LastFragData") == 0) {
+ if (type.arraySize == static_cast<const TVariable*>(symbolTable.findBuiltIn("gl_MaxDrawBuffers", shaderVersion))->getConstPointer()->getIConst()) {
+ if (TSymbol* builtInSymbol = symbolTable.findBuiltIn(identifier, shaderVersion)) {
+ needsReservedErrorCheck = extensionErrorCheck(line, builtInSymbol->getExtension());
+ }
+ } else {
+ error(line, "redeclaration of array with size != gl_MaxDrawBuffers", identifier.c_str());
+ return true;
+ }
+ }
+
+ if (needsReservedErrorCheck)
+ if (reservedErrorCheck(line, identifier))
+ return true;
+
variable = new TVariable(&identifier, TType(type));
if (type.arraySize)
@@ -976,6 +992,26 @@ bool TParseContext::layoutLocationErrorCheck(const TSourceLoc& location, const T
return false;
}
+bool TParseContext::functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *aggregate)
+{
+ for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
+ {
+ TQualifier qual = fnCandidate->getParam(i).type->getQualifier();
+ if (qual == EvqOut || qual == EvqInOut)
+ {
+ TIntermTyped *node = (*(aggregate->getSequence()))[i]->getAsTyped();
+ if (lValueErrorCheck(node->getLine(), "assign", node))
+ {
+ error(node->getLine(),
+ "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
+ recover();
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
bool TParseContext::supportsExtension(const char* extension)
{
const TExtensionBehavior& extbehavior = extensionBehavior();
@@ -1062,14 +1098,14 @@ const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
//
// Return the function symbol if found, otherwise 0.
//
-const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int shaderVersion, bool *builtIn)
+const TFunction* TParseContext::findFunction(const TSourceLoc& line, TFunction* call, int inputShaderVersion, bool *builtIn)
{
// First find by unmangled name to check whether the function name has been
// hidden by a variable name or struct typename.
// If a function is found, check for one with a matching argument list.
- const TSymbol* symbol = symbolTable.find(call->getName(), shaderVersion, builtIn);
+ const TSymbol* symbol = symbolTable.find(call->getName(), inputShaderVersion, builtIn);
if (symbol == 0 || symbol->isFunction()) {
- symbol = symbolTable.find(call->getMangledName(), shaderVersion, builtIn);
+ symbol = symbolTable.find(call->getMangledName(), inputShaderVersion, builtIn);
}
if (symbol == 0) {
@@ -1162,7 +1198,7 @@ bool TParseContext::executeInitializer(const TSourceLoc& line, const TString& id
if (qualifier != EvqConst) {
TIntermSymbol* intermSymbol = intermediate.addSymbol(variable->getUniqueId(), variable->getName(), variable->getType(), line);
- intermNode = intermediate.addAssign(EOpInitialize, intermSymbol, initializer, line);
+ intermNode = createAssign(EOpInitialize, intermSymbol, initializer, line);
if (intermNode == 0) {
assignError(line, "=", intermSymbol->getCompleteString(), initializer->getCompleteString());
return true;
@@ -1375,7 +1411,7 @@ TIntermAggregate* TParseContext::parseInvariantDeclaration(const TSourceLoc &inv
recover();
return NULL;
}
- symbolTable.addInvariantVarying(*identifier);
+ symbolTable.addInvariantVarying(std::string(identifier->c_str()));
const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
ASSERT(variable);
const TType &type = variable->getType();
@@ -1605,7 +1641,7 @@ TFunction *TParseContext::addConstructorFunc(TPublicType publicType)
//
// Returns 0 for an error or the constructed node (aggregate or typed) for no error.
//
-TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line)
+TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, TType *type, TOperator op, TFunction *fnCall, const TSourceLoc &line)
{
TIntermAggregate *aggregateArguments = arguments->getAsAggregate();
@@ -1633,13 +1669,21 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments, const TType
}
// Turn the argument list itself into a constructor
- TIntermTyped *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
- TIntermTyped *constConstructor = foldConstConstructor(constructor->getAsAggregate(), *type);
+ TIntermAggregate *constructor = intermediate.setAggregateOperator(aggregateArguments, op, line);
+ TIntermTyped *constConstructor = foldConstConstructor(constructor, *type);
if (constConstructor)
{
return constConstructor;
}
+ // Structs should not be precision qualified, the individual members may be.
+ // Built-in types on the other hand should be precision qualified.
+ if (op != EOpConstructStruct)
+ {
+ constructor->setPrecisionFromChildren();
+ type->setPrecision(constructor->getPrecision());
+ }
+
return constructor;
}
@@ -2028,9 +2072,11 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
recover();
}
- if (indexExpression->getQualifier() == EvqConst)
+ TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
+
+ if (indexExpression->getQualifier() == EvqConst && indexConstantUnion)
{
- int index = indexExpression->getAsConstantUnion()->getIConst(0);
+ int index = indexConstantUnion->getIConst(0);
if (index < 0)
{
std::stringstream infoStream;
@@ -2091,7 +2137,7 @@ TIntermTyped* TParseContext::addIndexExpression(TIntermTyped *baseExpression, co
index = baseExpression->getType().getNominalSize() - 1;
}
- indexExpression->getAsConstantUnion()->getUnionArrayPointer()->setIConst(index);
+ indexConstantUnion->getUnionArrayPointer()->setIConst(index);
indexedExpression = intermediate.addIndex(EOpIndexDirect, baseExpression, indexExpression, location);
}
}
@@ -2520,7 +2566,10 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
TStructure* structure = new TStructure(structName, fieldList);
TType* structureType = new TType(structure);
+ // Store a bool in the struct if we're at global scope, to allow us to
+ // skip the local struct scoping workaround in HLSL.
structure->setUniqueId(TSymbolTable::nextUniqueId());
+ structure->setAtGlobalScope(symbolTable.atGlobalLevel());
if (!structName->empty())
{
@@ -2560,6 +2609,553 @@ TPublicType TParseContext::addStructure(const TSourceLoc& structLine, const TSou
return publicType;
}
+TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc)
+{
+ TBasicType switchType = init->getBasicType();
+ if ((switchType != EbtInt && switchType != EbtUInt) ||
+ init->isMatrix() ||
+ init->isArray() ||
+ init->isVector())
+ {
+ error(init->getLine(), "init-expression in a switch statement must be a scalar integer", "switch");
+ recover();
+ return nullptr;
+ }
+
+ if (statementList)
+ {
+ if (!ValidateSwitch::validate(switchType, this, statementList, loc))
+ {
+ recover();
+ return nullptr;
+ }
+ }
+
+ TIntermSwitch *node = intermediate.addSwitch(init, statementList, loc);
+ if (node == nullptr)
+ {
+ error(loc, "erroneous switch statement", "switch");
+ recover();
+ return nullptr;
+ }
+ return node;
+}
+
+TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
+{
+ if (mSwitchNestingLevel == 0)
+ {
+ error(loc, "case labels need to be inside switch statements", "case");
+ recover();
+ return nullptr;
+ }
+ if (condition == nullptr)
+ {
+ error(loc, "case label must have a condition", "case");
+ recover();
+ return nullptr;
+ }
+ if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
+ condition->isMatrix() ||
+ condition->isArray() ||
+ condition->isVector())
+ {
+ error(condition->getLine(), "case label must be a scalar integer", "case");
+ recover();
+ }
+ TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
+ if (conditionConst == nullptr)
+ {
+ error(condition->getLine(), "case label must be constant", "case");
+ recover();
+ }
+ TIntermCase *node = intermediate.addCase(condition, loc);
+ if (node == nullptr)
+ {
+ error(loc, "erroneous case statement", "case");
+ recover();
+ return nullptr;
+ }
+ return node;
+}
+
+TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
+{
+ if (mSwitchNestingLevel == 0)
+ {
+ error(loc, "default labels need to be inside switch statements", "default");
+ recover();
+ return nullptr;
+ }
+ TIntermCase *node = intermediate.addCase(nullptr, loc);
+ if (node == nullptr)
+ {
+ error(loc, "erroneous default statement", "default");
+ recover();
+ return nullptr;
+ }
+ return node;
+}
+
+TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc,
+ const TType *funcReturnType)
+{
+ if (child == nullptr)
+ {
+ return nullptr;
+ }
+
+ switch (op)
+ {
+ case EOpLogicalNot:
+ if (child->getBasicType() != EbtBool ||
+ child->isMatrix() ||
+ child->isArray() ||
+ child->isVector())
+ {
+ return nullptr;
+ }
+ break;
+ case EOpBitwiseNot:
+ if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
+ child->isMatrix() ||
+ child->isArray())
+ {
+ return nullptr;
+ }
+ break;
+ case EOpPostIncrement:
+ case EOpPreIncrement:
+ case EOpPostDecrement:
+ case EOpPreDecrement:
+ case EOpNegative:
+ case EOpPositive:
+ if (child->getBasicType() == EbtStruct ||
+ child->getBasicType() == EbtBool ||
+ child->isArray())
+ {
+ return nullptr;
+ }
+ // Operators for built-ins are already type checked against their prototype.
+ default:
+ break;
+ }
+
+ return intermediate.addUnaryMath(op, child, loc, funcReturnType);
+}
+
+TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
+{
+ TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
+ if (node == nullptr)
+ {
+ unaryOpError(loc, GetOperatorString(op), child->getCompleteString());
+ recover();
+ return child;
+ }
+ return node;
+}
+
+TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
+{
+ if (lValueErrorCheck(loc, GetOperatorString(op), child))
+ recover();
+ return addUnaryMath(op, child, loc);
+}
+
+bool TParseContext::binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ if (left->isArray() || right->isArray())
+ {
+ if (shaderVersion < 300)
+ {
+ error(loc, "Invalid operation for arrays", GetOperatorString(op));
+ return false;
+ }
+
+ if (left->isArray() != right->isArray())
+ {
+ error(loc, "array / non-array mismatch", GetOperatorString(op));
+ return false;
+ }
+
+ switch (op)
+ {
+ case EOpEqual:
+ case EOpNotEqual:
+ case EOpAssign:
+ case EOpInitialize:
+ break;
+ default:
+ error(loc, "Invalid operation for arrays", GetOperatorString(op));
+ return false;
+ }
+ if (left->getArraySize() != right->getArraySize())
+ {
+ error(loc, "array size mismatch", GetOperatorString(op));
+ return false;
+ }
+ }
+
+ // Check ops which require integer / ivec parameters
+ bool isBitShift = false;
+ switch (op)
+ {
+ case EOpBitShiftLeft:
+ case EOpBitShiftRight:
+ case EOpBitShiftLeftAssign:
+ case EOpBitShiftRightAssign:
+ // Unsigned can be bit-shifted by signed and vice versa, but we need to
+ // check that the basic type is an integer type.
+ isBitShift = true;
+ if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
+ {
+ return false;
+ }
+ break;
+ case EOpBitwiseAnd:
+ case EOpBitwiseXor:
+ case EOpBitwiseOr:
+ case EOpBitwiseAndAssign:
+ case EOpBitwiseXorAssign:
+ case EOpBitwiseOrAssign:
+ // It is enough to check the type of only one operand, since later it
+ // is checked that the operand types match.
+ if (!IsInteger(left->getBasicType()))
+ {
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ // GLSL ES 1.00 and 3.00 do not support implicit type casting.
+ // So the basic type should usually match.
+ if (!isBitShift && left->getBasicType() != right->getBasicType())
+ {
+ return false;
+ }
+
+ // Check that type sizes match exactly on ops that require that.
+ // Also check restrictions for structs that contain arrays or samplers.
+ switch(op)
+ {
+ case EOpAssign:
+ case EOpInitialize:
+ case EOpEqual:
+ case EOpNotEqual:
+ // ESSL 1.00 sections 5.7, 5.8, 5.9
+ if (shaderVersion < 300 && left->getType().isStructureContainingArrays())
+ {
+ error(loc, "undefined operation for structs containing arrays", GetOperatorString(op));
+ return false;
+ }
+ // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
+ // we interpret the spec so that this extends to structs containing samplers,
+ // similarly to ESSL 1.00 spec.
+ if ((shaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
+ left->getType().isStructureContainingSamplers())
+ {
+ error(loc, "undefined operation for structs containing samplers", GetOperatorString(op));
+ return false;
+ }
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ if ((left->getNominalSize() != right->getNominalSize()) ||
+ (left->getSecondarySize() != right->getSecondarySize()))
+ {
+ return false;
+ }
+ default:
+ break;
+ }
+
+ return true;
+}
+
+TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ if (!binaryOpCommonCheck(op, left, right, loc))
+ return nullptr;
+
+ switch (op)
+ {
+ case EOpEqual:
+ case EOpNotEqual:
+ break;
+ case EOpLessThan:
+ case EOpGreaterThan:
+ case EOpLessThanEqual:
+ case EOpGreaterThanEqual:
+ ASSERT(!left->isArray() && !right->isArray());
+ if (left->isMatrix() || left->isVector() ||
+ left->getBasicType() == EbtStruct)
+ {
+ return nullptr;
+ }
+ break;
+ case EOpLogicalOr:
+ case EOpLogicalXor:
+ case EOpLogicalAnd:
+ ASSERT(!left->isArray() && !right->isArray());
+ if (left->getBasicType() != EbtBool ||
+ left->isMatrix() || left->isVector())
+ {
+ return nullptr;
+ }
+ break;
+ case EOpAdd:
+ case EOpSub:
+ case EOpDiv:
+ case EOpMul:
+ ASSERT(!left->isArray() && !right->isArray());
+ if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool)
+ {
+ return nullptr;
+ }
+ break;
+ case EOpIMod:
+ ASSERT(!left->isArray() && !right->isArray());
+ // Note that this is only for the % operator, not for mod()
+ if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
+ {
+ return nullptr;
+ }
+ break;
+ // Note that for bitwise ops, type checking is done in promote() to
+ // share code between ops and compound assignment
+ default:
+ break;
+ }
+
+ return intermediate.addBinaryMath(op, left, right, loc);
+}
+
+TIntermTyped *TParseContext::addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
+ if (node == 0)
+ {
+ binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
+ recover();
+ return left;
+ }
+ return node;
+}
+
+TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
+ if (node == 0)
+ {
+ binaryOpError(loc, GetOperatorString(op), left->getCompleteString(), right->getCompleteString());
+ recover();
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setBConst(false);
+ return intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), loc);
+ }
+ return node;
+}
+
+TIntermTyped *TParseContext::createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ if (binaryOpCommonCheck(op, left, right, loc))
+ {
+ return intermediate.addAssign(op, left, right, loc);
+ }
+ return nullptr;
+}
+
+TIntermTyped *TParseContext::addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc)
+{
+ TIntermTyped *node = createAssign(op, left, right, loc);
+ if (node == nullptr)
+ {
+ assignError(loc, "assign", left->getCompleteString(), right->getCompleteString());
+ recover();
+ return left;
+ }
+ return node;
+}
+
+TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
+{
+ switch (op)
+ {
+ case EOpContinue:
+ if (mLoopNestingLevel <= 0)
+ {
+ error(loc, "continue statement only allowed in loops", "");
+ recover();
+ }
+ break;
+ case EOpBreak:
+ if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
+ {
+ error(loc, "break statement only allowed in loops and switch statements", "");
+ recover();
+ }
+ break;
+ case EOpReturn:
+ if (currentFunctionType->getBasicType() != EbtVoid)
+ {
+ error(loc, "non-void function must return a value", "return");
+ recover();
+ }
+ break;
+ default:
+ // No checks for discard
+ break;
+ }
+ return intermediate.addBranch(op, loc);
+}
+
+TIntermBranch *TParseContext::addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc)
+{
+ ASSERT(op == EOpReturn);
+ mFunctionReturnsValue = true;
+ if (currentFunctionType->getBasicType() == EbtVoid)
+ {
+ error(loc, "void function cannot return a value", "return");
+ recover();
+ }
+ else if (*currentFunctionType != returnValue->getType())
+ {
+ error(loc, "function return is not matching type:", "return");
+ recover();
+ }
+ return intermediate.addBranch(op, returnValue, loc);
+}
+
+TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
+ const TSourceLoc &loc, bool *fatalError)
+{
+ *fatalError = false;
+ TOperator op = fnCall->getBuiltInOp();
+ TIntermTyped *callNode = nullptr;
+
+ if (op != EOpNull)
+ {
+ //
+ // Then this should be a constructor.
+ // Don't go through the symbol table for constructors.
+ // Their parameters will be verified algorithmically.
+ //
+ TType type(EbtVoid, EbpUndefined); // use this to get the type back
+ if (!constructorErrorCheck(loc, node, *fnCall, op, &type))
+ {
+ //
+ // It's a constructor, of type 'type'.
+ //
+ callNode = addConstructor(node, &type, op, fnCall, loc);
+ }
+
+ if (callNode == nullptr)
+ {
+ recover();
+ callNode = intermediate.setAggregateOperator(nullptr, op, loc);
+ }
+ callNode->setType(type);
+ }
+ else
+ {
+ //
+ // Not a constructor. Find it in the symbol table.
+ //
+ const TFunction* fnCandidate;
+ bool builtIn;
+ fnCandidate = findFunction(loc, fnCall, shaderVersion, &builtIn);
+ if (fnCandidate)
+ {
+ //
+ // A declared function.
+ //
+ if (builtIn && !fnCandidate->getExtension().empty() &&
+ extensionErrorCheck(loc, fnCandidate->getExtension()))
+ {
+ recover();
+ }
+ op = fnCandidate->getBuiltInOp();
+ if (builtIn && op != EOpNull)
+ {
+ //
+ // A function call mapped to a built-in operation.
+ //
+ if (fnCandidate->getParamCount() == 1)
+ {
+ //
+ // Treat it like a built-in unary operator.
+ //
+ callNode = createUnaryMath(op, node->getAsTyped(), loc, &fnCandidate->getReturnType());
+ if (callNode == nullptr)
+ {
+ std::stringstream extraInfoStream;
+ extraInfoStream << "built in unary operator function. Type: "
+ << static_cast<TIntermTyped*>(node)->getCompleteString();
+ std::string extraInfo = extraInfoStream.str();
+ error(node->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
+ *fatalError = true;
+ return nullptr;
+ }
+ }
+ else
+ {
+ TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, op, loc);
+ aggregate->setType(fnCandidate->getReturnType());
+ aggregate->setPrecisionFromChildren();
+ callNode = aggregate;
+
+ // Some built-in functions have out parameters too.
+ functionCallLValueErrorCheck(fnCandidate, aggregate);
+ }
+ }
+ else
+ {
+ // This is a real function call
+
+ TIntermAggregate *aggregate = intermediate.setAggregateOperator(node, EOpFunctionCall, loc);
+ aggregate->setType(fnCandidate->getReturnType());
+
+ // this is how we know whether the given function is a builtIn function or a user defined function
+ // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
+ // if builtIn == true, it's definitely a builtIn function with EOpNull
+ if (!builtIn)
+ aggregate->setUserDefined();
+ aggregate->setName(fnCandidate->getMangledName());
+
+ // This needs to happen after the name is set
+ if (builtIn)
+ aggregate->setBuiltInFunctionPrecision();
+
+ callNode = aggregate;
+
+ functionCallLValueErrorCheck(fnCandidate, aggregate);
+ }
+ }
+ else
+ {
+ // error message was put out by findFunction()
+ // Put on a dummy node for error recovery
+ ConstantUnion *unionArray = new ConstantUnion[1];
+ unionArray->setFConst(0.0f);
+ callNode = intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), loc);
+ recover();
+ }
+ }
+ delete fnCall;
+ return callNode;
+}
+
+
//
// Parse an array of strings using yyparse.
//
diff --git a/src/3rdparty/angle/src/compiler/translator/ParseContext.h b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
index 414c475cbb..b6a0f4a637 100644
--- a/src/3rdparty/angle/src/compiler/translator/ParseContext.h
+++ b/src/3rdparty/angle/src/compiler/translator/ParseContext.h
@@ -3,8 +3,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
-#ifndef _PARSER_HELPER_INCLUDED_
-#define _PARSER_HELPER_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_PARSECONTEXT_H_
+#define COMPILER_TRANSLATOR_PARSECONTEXT_H_
#include "compiler/translator/Compiler.h"
#include "compiler/translator/Diagnostics.h"
@@ -25,24 +25,25 @@ struct TMatrixFields {
// they can be passed to the parser without needing a global.
//
struct TParseContext {
- TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, const char* sourcePath, TInfoSink& is) :
+ TParseContext(TSymbolTable& symt, TExtensionBehavior& ext, TIntermediate& interm, sh::GLenum type, ShShaderSpec spec, int options, bool checksPrecErrors, TInfoSink& is, bool debugShaderPrecisionSupported) :
intermediate(interm),
symbolTable(symt),
shaderType(type),
shaderSpec(spec),
compileOptions(options),
- sourcePath(sourcePath),
treeRoot(0),
- loopNestingLevel(0),
+ mLoopNestingLevel(0),
structNestingLevel(0),
+ mSwitchNestingLevel(0),
currentFunctionType(NULL),
- functionReturnsValue(false),
+ mFunctionReturnsValue(false),
checksPrecisionErrors(checksPrecErrors),
+ fragmentPrecisionHigh(false),
defaultMatrixPacking(EmpColumnMajor),
defaultBlockStorage(EbsShared),
diagnostics(is),
shaderVersion(100),
- directiveHandler(ext, diagnostics, shaderVersion),
+ directiveHandler(ext, diagnostics, shaderVersion, debugShaderPrecisionSupported),
preprocessor(&diagnostics, &directiveHandler),
scanner(NULL) { }
TIntermediate& intermediate; // to hold and build a parse tree
@@ -51,12 +52,12 @@ struct TParseContext {
ShShaderSpec shaderSpec; // The language specification compiler conforms to - GLES2 or WebGL.
int shaderVersion;
int compileOptions;
- const char* sourcePath; // Path of source file or NULL.
TIntermNode* treeRoot; // root of parse tree being created
- int loopNestingLevel; // 0 if outside all loops
+ int mLoopNestingLevel; // 0 if outside all loops
int structNestingLevel; // incremented while parsing a struct declaration
+ int mSwitchNestingLevel; // 0 if outside all switch statements
const TType* currentFunctionType; // the return type of the function that's currently being parsed
- bool functionReturnsValue; // true if a non-void function has a return
+ bool mFunctionReturnsValue; // true if a non-void function has a return
bool checksPrecisionErrors; // true if an error will be generated when a variable is declared without precision, explicit or implicit.
bool fragmentPrecisionHigh; // true if highp precision is supported in the fragment language.
TLayoutMatrixPacking defaultMatrixPacking;
@@ -110,6 +111,7 @@ struct TParseContext {
bool extensionErrorCheck(const TSourceLoc& line, const TString&);
bool singleDeclarationErrorCheck(TPublicType &publicType, const TSourceLoc& identifierLocation, const TString &identifier);
bool layoutLocationErrorCheck(const TSourceLoc& location, const TLayoutQualifier &layoutQualifier);
+ bool functionCallLValueErrorCheck(const TFunction *fnCandidate, TIntermAggregate *);
const TPragma& pragma() const { return directiveHandler.pragma(); }
const TExtensionBehavior& extensionBehavior() const { return directiveHandler.extensionBehavior(); }
@@ -120,7 +122,7 @@ struct TParseContext {
bool containsSampler(TType& type);
bool areAllChildConst(TIntermAggregate* aggrNode);
- const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int shaderVersion, bool *builtIn = 0);
+ const TFunction* findFunction(const TSourceLoc& line, TFunction* pfnCall, int inputShaderVersion, bool *builtIn = 0);
bool executeInitializer(const TSourceLoc& line, const TString& identifier, TPublicType& pType,
TIntermTyped* initializer, TIntermNode*& intermNode, TVariable* variable = 0);
@@ -136,7 +138,7 @@ struct TParseContext {
TIntermAggregate* parseInitDeclarator(TPublicType &publicType, TIntermAggregate *declaratorList, const TSourceLoc& identifierLocation, const TString &identifier, const TSourceLoc& initLocation, TIntermTyped *initializer);
void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
TFunction *addConstructorFunc(TPublicType publicType);
- TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, const TSourceLoc&);
+ TIntermTyped* addConstructor(TIntermNode*, TType*, TOperator, TFunction*, const TSourceLoc&);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addConstMatrixNode(int , TIntermTyped*, const TSourceLoc&);
@@ -164,9 +166,42 @@ struct TParseContext {
void exitStructDeclaration();
bool structNestingErrorCheck(const TSourceLoc& line, const TField& field);
+
+ TIntermSwitch *addSwitch(TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &loc);
+ TIntermCase *addCase(TIntermTyped *condition, const TSourceLoc &loc);
+ TIntermCase *addDefault(const TSourceLoc &loc);
+
+ TIntermTyped *addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &);
+ TIntermTyped *addUnaryMathLValue(TOperator op, TIntermTyped *child, const TSourceLoc &);
+ TIntermTyped *addBinaryMath(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &);
+ TIntermTyped *addBinaryMathBooleanResult(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &);
+ TIntermTyped *addAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc);
+
+ TIntermBranch *addBranch(TOperator op, const TSourceLoc &loc);
+ TIntermBranch *addBranch(TOperator op, TIntermTyped *returnValue, const TSourceLoc &loc);
+
+ TIntermTyped *addFunctionCallOrMethod(TFunction *fnCall, TIntermNode *node,
+ const TSourceLoc &loc, bool *fatalError);
+
+ private:
+ TIntermTyped *addBinaryMathInternal(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc);
+ TIntermTyped *createAssign(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc);
+ // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
+ // It is expected to be null for other unary operators.
+ TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc,
+ const TType *funcReturnType);
+
+ // Return true if the checks pass
+ bool binaryOpCommonCheck(TOperator op, TIntermTyped *left, TIntermTyped *right,
+ const TSourceLoc &loc);
};
int PaParseStrings(size_t count, const char* const string[], const int length[],
TParseContext* context);
-#endif // _PARSER_HELPER_INCLUDED_
+#endif // COMPILER_TRANSLATOR_PARSECONTEXT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
index edd249c4d3..6cd8d30114 100644
--- a/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
+++ b/src/3rdparty/angle/src/compiler/translator/PoolAlloc.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _POOLALLOC_INCLUDED_
-#define _POOLALLOC_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_POOLALLOC_H_
+#define COMPILER_TRANSLATOR_POOLALLOC_H_
#ifdef _DEBUG
#define GUARD_BLOCKS // define to enable guard block sanity checking
@@ -297,4 +297,4 @@ protected:
TPoolAllocator* allocator;
};
-#endif // _POOLALLOC_INCLUDED_
+#endif // COMPILER_TRANSLATOR_POOLALLOC_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Pragma.h b/src/3rdparty/angle/src/compiler/translator/Pragma.h
index 4a930a2962..57b1134970 100644
--- a/src/3rdparty/angle/src/compiler/translator/Pragma.h
+++ b/src/3rdparty/angle/src/compiler/translator/Pragma.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_PRAGMA_H_
-#define COMPILER_PRAGMA_H_
+#ifndef COMPILER_TRANSLATOR_PRAGMA_H_
+#define COMPILER_TRANSLATOR_PRAGMA_H_
struct TPragma
{
@@ -18,12 +18,15 @@ struct TPragma
// By default optimization is turned on and debug is turned off.
- TPragma() : optimize(true), debug(false) { }
- TPragma(bool o, bool d) : optimize(o), debug(d) { }
+ // Precision emulation is turned on by default, but has no effect unless
+ // the extension is enabled.
+ TPragma() : optimize(true), debug(false), debugShaderPrecision(true) { }
+ TPragma(bool o, bool d) : optimize(o), debug(d), debugShaderPrecision(true) { }
bool optimize;
bool debug;
+ bool debugShaderPrecision;
STDGL stdgl;
};
-#endif // COMPILER_PRAGMA_H_
+#endif // COMPILER_TRANSLATOR_PRAGMA_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp
index 1f6fb75821..3d950aab5a 100644
--- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.cpp
@@ -49,7 +49,7 @@ void TAliveTraverser::visitSymbol(TIntermSymbol* node)
found = true;
}
-bool TAliveTraverser::visitSelection(Visit preVisit, TIntermSelection* node)
+bool TAliveTraverser::visitSelection(Visit, TIntermSelection*)
{
if (wasFound())
return false;
diff --git a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h
index 872a06f721..3e4f18012a 100644
--- a/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h
+++ b/src/3rdparty/angle/src/compiler/translator/QualifierAlive.h
@@ -4,4 +4,9 @@
// found in the LICENSE file.
//
+#ifndef COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
+#define COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
+
bool QualifierWritten(TIntermNode* root, TQualifier);
+
+#endif // COMPILER_TRANSLATOR_QUALIFIERALIVE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
index ac87600347..2acd68be34 100644
--- a/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
+++ b/src/3rdparty/angle/src/compiler/translator/RegenerateStructNames.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
-#define COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
+#ifndef COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
+#define COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
#include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h"
@@ -37,4 +37,4 @@ class RegenerateStructNames : public TIntermTraverser
std::set<int> mDeclaredGlobalStructs;
};
-#endif // COMPILER_TRANSLATOR_REGENERATE_STRUCT_NAMES_H_
+#endif // COMPILER_TRANSLATOR_REGENERATESTRUCTNAMES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
new file mode 100644
index 0000000000..b278b53436
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.cpp
@@ -0,0 +1,157 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/RemoveSwitchFallThrough.h"
+
+TIntermAggregate *RemoveSwitchFallThrough::removeFallThrough(TIntermAggregate *statementList)
+{
+ RemoveSwitchFallThrough rm(statementList);
+ ASSERT(statementList);
+ statementList->traverse(&rm);
+ bool lastStatementWasBreak = rm.mLastStatementWasBreak;
+ rm.mLastStatementWasBreak = true;
+ rm.handlePreviousCase();
+ if (!lastStatementWasBreak)
+ {
+ TIntermBranch *finalBreak = new TIntermBranch(EOpBreak, nullptr);
+ rm.mStatementListOut->getSequence()->push_back(finalBreak);
+ }
+ return rm.mStatementListOut;
+}
+
+RemoveSwitchFallThrough::RemoveSwitchFallThrough(TIntermAggregate *statementList)
+ : TIntermTraverser(true, false, false),
+ mStatementList(statementList),
+ mLastStatementWasBreak(false),
+ mPreviousCase(nullptr)
+{
+ mStatementListOut = new TIntermAggregate();
+ mStatementListOut->setOp(EOpSequence);
+}
+
+void RemoveSwitchFallThrough::visitSymbol(TIntermSymbol *node)
+{
+ // Note that this assumes that switch statements which don't begin by a case statement
+ // have already been weeded out in validation.
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+}
+
+void RemoveSwitchFallThrough::visitConstantUnion(TIntermConstantUnion *node)
+{
+ // Conditions of case labels are not traversed, so this is some other constant
+ // Could be just a statement like "0;"
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+}
+
+bool RemoveSwitchFallThrough::visitBinary(Visit, TIntermBinary *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitUnary(Visit, TIntermUnary *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitSelection(Visit, TIntermSelection *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitSwitch(Visit, TIntermSwitch *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ // Don't go into nested switch statements
+ return false;
+}
+
+void RemoveSwitchFallThrough::outputSequence(TIntermSequence *sequence, size_t startIndex)
+{
+ for (size_t i = startIndex; i < sequence->size(); ++i)
+ {
+ mStatementListOut->getSequence()->push_back(sequence->at(i));
+ }
+}
+
+void RemoveSwitchFallThrough::handlePreviousCase()
+{
+ if (mPreviousCase)
+ mCasesSharingBreak.push_back(mPreviousCase);
+ if (mLastStatementWasBreak)
+ {
+ bool labelsWithNoStatements = true;
+ for (size_t i = 0; i < mCasesSharingBreak.size(); ++i)
+ {
+ if (mCasesSharingBreak.at(i)->getSequence()->size() > 1)
+ {
+ labelsWithNoStatements = false;
+ }
+ if (labelsWithNoStatements)
+ {
+ // Fall-through is allowed in case the label has no statements.
+ outputSequence(mCasesSharingBreak.at(i)->getSequence(), 0);
+ }
+ else
+ {
+ // Include all the statements that this case can fall through under the same label.
+ for (size_t j = i; j < mCasesSharingBreak.size(); ++j)
+ {
+ size_t startIndex = j > i ? 1 : 0; // Add the label only from the first sequence.
+ outputSequence(mCasesSharingBreak.at(j)->getSequence(), startIndex);
+
+ }
+ }
+ }
+ mCasesSharingBreak.clear();
+ }
+ mLastStatementWasBreak = false;
+ mPreviousCase = nullptr;
+}
+
+bool RemoveSwitchFallThrough::visitCase(Visit, TIntermCase *node)
+{
+ handlePreviousCase();
+ mPreviousCase = new TIntermAggregate();
+ mPreviousCase->setOp(EOpSequence);
+ mPreviousCase->getSequence()->push_back(node);
+ // Don't traverse the condition of the case statement
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitAggregate(Visit, TIntermAggregate *node)
+{
+ if (node != mStatementList)
+ {
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+ }
+ return true;
+}
+
+bool RemoveSwitchFallThrough::visitLoop(Visit, TIntermLoop *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ mLastStatementWasBreak = false;
+ return false;
+}
+
+bool RemoveSwitchFallThrough::visitBranch(Visit, TIntermBranch *node)
+{
+ mPreviousCase->getSequence()->push_back(node);
+ // TODO: Verify that accepting return or continue statements here doesn't cause problems.
+ mLastStatementWasBreak = true;
+ return false;
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
new file mode 100644
index 0000000000..db8699327c
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/RemoveSwitchFallThrough.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
+#define COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
+
+#include "compiler/translator/IntermNode.h"
+
+class RemoveSwitchFallThrough : public TIntermTraverser
+{
+ public:
+ // When given a statementList from a switch AST node, return an updated
+ // statementList that has fall-through removed.
+ static TIntermAggregate *removeFallThrough(TIntermAggregate *statementList);
+
+ private:
+ RemoveSwitchFallThrough(TIntermAggregate *statementList);
+
+ void visitSymbol(TIntermSymbol *node) override;
+ void visitConstantUnion(TIntermConstantUnion *node) override;
+ bool visitBinary(Visit, TIntermBinary *node) override;
+ bool visitUnary(Visit, TIntermUnary *node) override;
+ bool visitSelection(Visit visit, TIntermSelection *node) override;
+ bool visitSwitch(Visit, TIntermSwitch *node) override;
+ bool visitCase(Visit, TIntermCase *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *node) override;
+ bool visitLoop(Visit, TIntermLoop *node) override;
+ bool visitBranch(Visit, TIntermBranch *node) override;
+
+ void outputSequence(TIntermSequence *sequence, size_t startIndex);
+ void handlePreviousCase();
+
+ TIntermAggregate *mStatementList;
+ TIntermAggregate *mStatementListOut;
+ bool mLastStatementWasBreak;
+ TIntermAggregate *mPreviousCase;
+ std::vector<TIntermAggregate *> mCasesSharingBreak;
+};
+
+#endif // COMPILER_TRANSLATOR_REMOVESWITCHFALLTHROUGH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp b/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp
deleted file mode 100644
index 0cf6910aa2..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.cpp
+++ /dev/null
@@ -1,29 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-#include "compiler/translator/IntermNode.h"
-#include "compiler/translator/RemoveTree.h"
-
-//
-// Code to delete the intermediate tree.
-//
-void RemoveAllTreeNodes(TIntermNode* root)
-{
- std::queue<TIntermNode*> nodeQueue;
-
- nodeQueue.push(root);
-
- while (!nodeQueue.empty())
- {
- TIntermNode *node = nodeQueue.front();
- nodeQueue.pop();
-
- node->enqueueChildren(&nodeQueue);
-
- delete node;
- }
-}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h b/src/3rdparty/angle/src/compiler/translator/RemoveTree.h
deleted file mode 100644
index 97a821679c..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/RemoveTree.h
+++ /dev/null
@@ -1,7 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-void RemoveAllTreeNodes(TIntermNode*);
diff --git a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h
index d43e6ef7be..868e5d566b 100644
--- a/src/3rdparty/angle/src/compiler/translator/RenameFunction.h
+++ b/src/3rdparty/angle/src/compiler/translator/RenameFunction.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_RENAME_FUNCTION
-#define COMPILER_RENAME_FUNCTION
+#ifndef COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
+#define COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
#include "compiler/translator/IntermNode.h"
@@ -33,4 +33,4 @@ private:
const TString mNewFunctionName;
};
-#endif // COMPILER_RENAME_FUNCTION
+#endif // COMPILER_TRANSLATOR_RENAMEFUNCTION_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
index d87baea0fe..5527d27f83 100644
--- a/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
+++ b/src/3rdparty/angle/src/compiler/translator/RewriteElseBlocks.h
@@ -7,8 +7,8 @@
// all if-else blocks to if-if blocks.
//
-#ifndef COMPILER_REWRITE_ELSE_BLOCKS_H_
-#define COMPILER_REWRITE_ELSE_BLOCKS_H_
+#ifndef COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
+#define COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
#include "compiler/translator/IntermNode.h"
@@ -19,4 +19,4 @@ void RewriteElseBlocks(TIntermNode *node);
}
-#endif // COMPILER_REWRITE_ELSE_BLOCKS_H_
+#endif // COMPILER_TRANSLATOR_REWRITEELSEBLOCKS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
index 7c6d09c1bb..0726ed4c64 100644
--- a/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
+++ b/src/3rdparty/angle/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_
-#define COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_
+#ifndef COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
+#define COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
#include "compiler/translator/IntermNode.h"
@@ -44,4 +44,4 @@ class ScalarizeVecAndMatConstructorArgs : public TIntermTraverser
bool mFragmentPrecisionHigh;
};
-#endif // COMPILER_TRANSLATOR_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS_H_
+#endif // COMPILER_TRANSLATOR_SCALARIZEVECANDMATCONSTRUCTORARGS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
index f78c84e370..fb7a6cdb9b 100644
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.cpp
@@ -9,7 +9,6 @@
#include "compiler/translator/SearchSymbol.h"
#include "compiler/translator/InfoSink.h"
-#include "compiler/translator/OutputHLSL.h"
namespace sh
{
diff --git a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
index 029ac30b9a..36d5191058 100644
--- a/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
+++ b/src/3rdparty/angle/src/compiler/translator/SearchSymbol.h
@@ -6,8 +6,8 @@
// SearchSymbol is an AST traverser to detect the use of a given symbol name
//
-#ifndef COMPILER_SEARCHSYMBOL_H_
-#define COMPILER_SEARCHSYMBOL_H_
+#ifndef COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
+#define COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
@@ -30,4 +30,4 @@ class SearchSymbol : public TIntermTraverser
};
}
-#endif // COMPILER_SEARCHSYMBOL_H_
+#endif // COMPILER_TRANSLATOR_SEARCHSYMBOL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
index 0d6a1d64cf..b8040da7f9 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderLang.cpp
@@ -14,7 +14,9 @@
#include "compiler/translator/Compiler.h"
#include "compiler/translator/InitializeDll.h"
#include "compiler/translator/length_limits.h"
+#ifdef ANGLE_ENABLE_HLSL
#include "compiler/translator/TranslatorHLSL.h"
+#endif // ANGLE_ENABLE_HLSL
#include "compiler/translator/VariablePacker.h"
#include "angle_gl.h"
@@ -92,6 +94,7 @@ TCompiler *GetCompilerFromHandle(ShHandle handle)
return base->getAsCompiler();
}
+#ifdef ANGLE_ENABLE_HLSL
TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
{
if (!handle)
@@ -99,6 +102,7 @@ TranslatorHLSL *GetTranslatorHLSLFromHandle(ShHandle handle)
TShHandleBase *base = static_cast<TShHandleBase *>(handle);
return base->getAsTranslatorHLSL();
}
+#endif // ANGLE_ENABLE_HLSL
} // namespace anonymous
@@ -153,6 +157,10 @@ void ShInitBuiltInResources(ShBuiltInResources* resources)
resources->EXT_draw_buffers = 0;
resources->EXT_frag_depth = 0;
resources->EXT_shader_texture_lod = 0;
+ resources->WEBGL_debug_shader_precision = 0;
+ resources->EXT_shader_framebuffer_fetch = 0;
+ resources->NV_shader_framebuffer_fetch = 0;
+ resources->ARM_shader_framebuffer_fetch = 0;
resources->NV_draw_buffers = 0;
@@ -323,6 +331,7 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
const std::string &interfaceBlockName,
unsigned int *indexOut)
{
+#ifdef ANGLE_ENABLE_HLSL
ASSERT(indexOut);
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
@@ -335,12 +344,16 @@ bool ShGetInterfaceBlockRegister(const ShHandle handle,
*indexOut = translator->getInterfaceBlockRegister(interfaceBlockName);
return true;
+#else
+ return false;
+#endif // ANGLE_ENABLE_HLSL
}
bool ShGetUniformRegister(const ShHandle handle,
const std::string &uniformName,
unsigned int *indexOut)
{
+#ifdef ANGLE_ENABLE_HLSL
ASSERT(indexOut);
TranslatorHLSL *translator = GetTranslatorHLSLFromHandle(handle);
ASSERT(translator);
@@ -352,4 +365,7 @@ bool ShGetUniformRegister(const ShHandle handle,
*indexOut = translator->getUniformRegister(uniformName);
return true;
+#else
+ return false;
+#endif // ANGLE_ENABLE_HLSL
}
diff --git a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
index 3098a7f0c9..0dbbc9e7f6 100644
--- a/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ShaderVars.cpp
@@ -14,6 +14,23 @@
namespace sh
{
+namespace
+{
+
+InterpolationType GetNonAuxiliaryInterpolationType(InterpolationType interpolation)
+{
+ return (interpolation == INTERPOLATION_CENTROID ? INTERPOLATION_SMOOTH : interpolation);
+}
+
+}
+// The ES 3.0 spec is not clear on this point, but the ES 3.1 spec, and discussion
+// on Khronos.org, clarifies that a smooth/flat mismatch produces a link error,
+// but auxiliary qualifier mismatch (centroid) does not.
+bool InterpolationTypesMatch(InterpolationType a, InterpolationType b)
+{
+ return (GetNonAuxiliaryInterpolationType(a) == GetNonAuxiliaryInterpolationType(b));
+}
+
ShaderVariable::ShaderVariable()
: type(0),
precision(0),
@@ -86,7 +103,6 @@ bool ShaderVariable::findInfoByMappedName(
// 2) the top variable is an array;
// 3) otherwise.
size_t pos = mappedFullName.find_first_of(".[");
- std::string topName;
if (pos == std::string::npos)
{
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp
new file mode 100644
index 0000000000..ac5eb67070
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/SimplifyArrayAssignment.h"
+
+bool SimplifyArrayAssignment::visitBinary(Visit visit, TIntermBinary *node)
+{
+ switch (node->getOp())
+ {
+ case EOpAssign:
+ {
+ TIntermNode *parent = getParentNode();
+ if (node->getLeft()->isArray() && parent != nullptr)
+ {
+ TIntermAggregate *parentAgg = parent->getAsAggregate();
+ if (parentAgg != nullptr && parentAgg->getOp() == EOpSequence)
+ {
+ // This case is fine, the result of the assignment is not used.
+ break;
+ }
+
+ // The result of the assignment needs to be stored into a temporary variable,
+ // the assignment needs to be replaced with a reference to the temporary variable,
+ // and the temporary variable needs to finally be assigned to the target variable.
+
+ // This also needs to interact correctly with unfolding short circuiting operators.
+ UNIMPLEMENTED();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h
new file mode 100644
index 0000000000..247eb88d72
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/SimplifyArrayAssignment.h
@@ -0,0 +1,25 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// SimplifyArrayAssignment is an AST traverser to replace statements where
+// the return value of array assignment is used with statements where
+// the return value of array assignment is not used.
+//
+
+#ifndef COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
+#define COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
+
+#include "common/angleutils.h"
+#include "compiler/translator/IntermNode.h"
+
+class SimplifyArrayAssignment : public TIntermTraverser
+{
+ public:
+ SimplifyArrayAssignment() { }
+
+ virtual bool visitBinary(Visit visit, TIntermBinary *node);
+};
+
+#endif // COMPILER_TRANSLATOR_SIMPLIFYARRAYASSIGNMENT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
index 48929affe6..fd1a29c1cd 100644
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.cpp
@@ -21,9 +21,23 @@ Std140PaddingHelper::Std140PaddingHelper(const std::map<TString, int> &structEle
unsigned *uniqueCounter)
: mPaddingCounter(uniqueCounter),
mElementIndex(0),
- mStructElementIndexes(structElementIndexes)
+ mStructElementIndexes(&structElementIndexes)
{}
+Std140PaddingHelper::Std140PaddingHelper(const Std140PaddingHelper &other)
+ : mPaddingCounter(other.mPaddingCounter),
+ mElementIndex(other.mElementIndex),
+ mStructElementIndexes(other.mStructElementIndexes)
+{}
+
+Std140PaddingHelper &Std140PaddingHelper::operator=(const Std140PaddingHelper &other)
+{
+ mPaddingCounter = other.mPaddingCounter;
+ mElementIndex = other.mElementIndex;
+ mStructElementIndexes = other.mStructElementIndexes;
+ return *this;
+}
+
TString Std140PaddingHelper::next()
{
unsigned value = (*mPaddingCounter)++;
@@ -107,7 +121,7 @@ TString Std140PaddingHelper::postPaddingString(const TType &type, bool useHLSLRo
{
const TString &structName = QualifiedStructNameString(*structure,
useHLSLRowMajorPacking, true);
- numComponents = mStructElementIndexes.find(structName)->second;
+ numComponents = mStructElementIndexes->find(structName)->second;
if (numComponents == 0)
{
@@ -274,9 +288,9 @@ void StructureHLSL::addConstructor(const TType &type, const TString &name, const
for (unsigned int parameter = 0; parameter < ctorParameters.size(); parameter++)
{
- const TType &type = ctorParameters[parameter];
+ const TType &paramType = ctorParameters[parameter];
- constructor += TypeString(type) + " x" + str(parameter) + ArrayString(type);
+ constructor += TypeString(paramType) + " x" + str(parameter) + ArrayString(paramType);
if (parameter < ctorParameters.size() - 1)
{
diff --git a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
index ed002fef30..cffe2a41ae 100644
--- a/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/StructureHLSL.h
@@ -7,8 +7,8 @@
// Interfaces of methods for HLSL translation of GLSL structures.
//
-#ifndef TRANSLATOR_STRUCTUREHLSL_H_
-#define TRANSLATOR_STRUCTUREHLSL_H_
+#ifndef COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
+#define COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
#include "compiler/translator/Common.h"
#include "compiler/translator/IntermNode.h"
@@ -27,7 +27,9 @@ class Std140PaddingHelper
{
public:
explicit Std140PaddingHelper(const std::map<TString, int> &structElementIndexes,
- unsigned *uniqueCounter);
+ unsigned int *uniqueCounter);
+ Std140PaddingHelper(const Std140PaddingHelper &other);
+ Std140PaddingHelper &operator=(const Std140PaddingHelper &other);
int elementIndex() const { return mElementIndex; }
int prePadding(const TType &type);
@@ -39,10 +41,10 @@ class Std140PaddingHelper
unsigned *mPaddingCounter;
int mElementIndex;
- const std::map<TString, int> &mStructElementIndexes;
+ const std::map<TString, int> *mStructElementIndexes;
};
-class StructureHLSL
+class StructureHLSL : angle::NonCopyable
{
public:
StructureHLSL();
@@ -76,4 +78,4 @@ class StructureHLSL
}
-#endif // COMPILER_STRUCTUREHLSL_H_
+#endif // COMPILER_TRANSLATOR_STRUCTUREHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
index 028da21151..0eb663f018 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.cpp
@@ -48,6 +48,16 @@ bool TSymbolTableLevel::insert(TSymbol *symbol)
return result.second;
}
+bool TSymbolTableLevel::insertUnmangled(TFunction *function)
+{
+ function->setUniqueId(TSymbolTable::nextUniqueId());
+
+ // returning true means symbol was added to the table
+ tInsertResult result = level.insert(tLevelPair(function->getName(), function));
+
+ return result.second;
+}
+
TSymbol *TSymbolTableLevel::find(const TString &name) const
{
tLevel::const_iterator it = level.find(name);
@@ -57,47 +67,6 @@ TSymbol *TSymbolTableLevel::find(const TString &name) const
return (*it).second;
}
-//
-// Change all function entries in the table with the non-mangled name
-// to be related to the provided built-in operation. This is a low
-// performance operation, and only intended for symbol tables that
-// live across a large number of compiles.
-//
-void TSymbolTableLevel::relateToOperator(const char *name, TOperator op)
-{
- for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
- {
- if ((*it).second->isFunction())
- {
- TFunction *function = static_cast<TFunction*>((*it).second);
- if (function->getName() == name)
- function->relateToOperator(op);
- }
- }
-}
-
-//
-// Change all function entries in the table with the non-mangled name
-// to be related to the provided built-in extension. This is a low
-// performance operation, and only intended for symbol tables that
-// live across a large number of compiles.
-//
-void TSymbolTableLevel::relateToExtension(const char *name, const TString &ext)
-{
- for (tLevel::iterator it = level.begin(); it != level.end(); ++it)
- {
- TSymbol *symbol = it->second;
- if (symbol->getName() == name)
- symbol->relateToExtension(ext);
- }
-}
-
-TSymbol::TSymbol(const TSymbol &copyOf)
-{
- name = NewPoolTString(copyOf.name->c_str());
- uniqueId = copyOf.uniqueId;
-}
-
TSymbol *TSymbolTable::find(const TString &name, int shaderVersion,
bool *builtIn, bool *sameScope) const
{
@@ -148,68 +117,149 @@ TSymbolTable::~TSymbolTable()
pop();
}
-void TSymbolTable::insertBuiltIn(
- ESymbolLevel level, TType *rvalue, const char *name,
- TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5)
+bool IsGenType(const TType *type)
+{
+ if (type)
+ {
+ TBasicType basicType = type->getBasicType();
+ return basicType == EbtGenType || basicType == EbtGenIType || basicType == EbtGenUType || basicType == EbtGenBType;
+ }
+
+ return false;
+}
+
+bool IsVecType(const TType *type)
+{
+ if (type)
+ {
+ TBasicType basicType = type->getBasicType();
+ return basicType == EbtVec || basicType == EbtIVec || basicType == EbtUVec || basicType == EbtBVec;
+ }
+
+ return false;
+}
+
+TType *SpecificType(TType *type, int size)
+{
+ ASSERT(size >= 1 && size <= 4);
+
+ if (!type)
+ {
+ return nullptr;
+ }
+
+ ASSERT(!IsVecType(type));
+
+ switch(type->getBasicType())
+ {
+ case EbtGenType: return new TType(EbtFloat, size);
+ case EbtGenIType: return new TType(EbtInt, size);
+ case EbtGenUType: return new TType(EbtUInt, size);
+ case EbtGenBType: return new TType(EbtBool, size);
+ default: return type;
+ }
+}
+
+TType *VectorType(TType *type, int size)
+{
+ ASSERT(size >= 2 && size <= 4);
+
+ if (!type)
+ {
+ return nullptr;
+ }
+
+ ASSERT(!IsGenType(type));
+
+ switch(type->getBasicType())
+ {
+ case EbtVec: return new TType(EbtFloat, size);
+ case EbtIVec: return new TType(EbtInt, size);
+ case EbtUVec: return new TType(EbtUInt, size);
+ case EbtBVec: return new TType(EbtBool, size);
+ default: return type;
+ }
+}
+
+void TSymbolTable::insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name,
+ TType *ptype1, TType *ptype2, TType *ptype3, TType *ptype4, TType *ptype5)
{
if (ptype1->getBasicType() == EbtGSampler2D)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
- new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
- new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
- new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
- return;
+ insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2D), ptype2, ptype3, ptype4, ptype5);
}
- if (ptype1->getBasicType() == EbtGSampler3D)
+ else if (ptype1->getBasicType() == EbtGSampler3D)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
- new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
- new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
- new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
- return;
+ insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler3D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler3D), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler3D), ptype2, ptype3, ptype4, ptype5);
}
- if (ptype1->getBasicType() == EbtGSamplerCube)
+ else if (ptype1->getBasicType() == EbtGSamplerCube)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
- new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
- new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
- new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
- return;
+ insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSamplerCube), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISamplerCube), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSamplerCube), ptype2, ptype3, ptype4, ptype5);
}
- if (ptype1->getBasicType() == EbtGSampler2DArray)
+ else if (ptype1->getBasicType() == EbtGSampler2DArray)
{
bool gvec4 = (rvalue->getBasicType() == EbtGVec4);
- insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name,
- new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name,
- new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
- insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name,
- new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
- return;
+ insertBuiltIn(level, gvec4 ? new TType(EbtFloat, 4) : rvalue, name, new TType(EbtSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtInt, 4) : rvalue, name, new TType(EbtISampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ insertBuiltIn(level, gvec4 ? new TType(EbtUInt, 4) : rvalue, name, new TType(EbtUSampler2DArray), ptype2, ptype3, ptype4, ptype5);
+ }
+ else if (IsGenType(rvalue) || IsGenType(ptype1) || IsGenType(ptype2) || IsGenType(ptype3))
+ {
+ ASSERT(!ptype4 && !ptype5);
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 1), name, SpecificType(ptype1, 1), SpecificType(ptype2, 1), SpecificType(ptype3, 1));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 2), name, SpecificType(ptype1, 2), SpecificType(ptype2, 2), SpecificType(ptype3, 2));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 3), name, SpecificType(ptype1, 3), SpecificType(ptype2, 3), SpecificType(ptype3, 3));
+ insertBuiltIn(level, op, ext, SpecificType(rvalue, 4), name, SpecificType(ptype1, 4), SpecificType(ptype2, 4), SpecificType(ptype3, 4));
+ }
+ else if (IsVecType(rvalue) || IsVecType(ptype1) || IsVecType(ptype2) || IsVecType(ptype3))
+ {
+ ASSERT(!ptype4 && !ptype5);
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 2), name, VectorType(ptype1, 2), VectorType(ptype2, 2), VectorType(ptype3, 2));
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 3), name, VectorType(ptype1, 3), VectorType(ptype2, 3), VectorType(ptype3, 3));
+ insertBuiltIn(level, op, ext, VectorType(rvalue, 4), name, VectorType(ptype1, 4), VectorType(ptype2, 4), VectorType(ptype3, 4));
}
+ else
+ {
+ TFunction *function = new TFunction(NewPoolTString(name), *rvalue, op, ext);
- TFunction *function = new TFunction(NewPoolTString(name), *rvalue);
+ TParameter param1 = {0, ptype1};
+ function->addParameter(param1);
- TType *types[] = {ptype1, ptype2, ptype3, ptype4, ptype5};
- for (size_t ii = 0; ii < sizeof(types) / sizeof(types[0]); ++ii)
- {
- if (types[ii])
+ if (ptype2)
{
- TParameter param = {NULL, types[ii]};
- function->addParameter(param);
+ TParameter param2 = {0, ptype2};
+ function->addParameter(param2);
}
- }
- insert(level, function);
+ if (ptype3)
+ {
+ TParameter param3 = {0, ptype3};
+ function->addParameter(param3);
+ }
+
+ if (ptype4)
+ {
+ TParameter param4 = {0, ptype4};
+ function->addParameter(param4);
+ }
+
+ if (ptype5)
+ {
+ TParameter param5 = {0, ptype5};
+ function->addParameter(param5);
+ }
+
+ insert(level, function);
+ }
}
TPrecision TSymbolTable::getDefaultPrecision(TBasicType type) const
diff --git a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
index 9cd74218dc..dfc65cb957 100644
--- a/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
+++ b/src/3rdparty/angle/src/compiler/translator/SymbolTable.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _SYMBOL_TABLE_INCLUDED_
-#define _SYMBOL_TABLE_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_SYMBOLTABLE_H_
+#define COMPILER_TRANSLATOR_SYMBOLTABLE_H_
//
// Symbol table for parsing. Has these design characteristics:
@@ -38,7 +38,7 @@
#include "compiler/translator/IntermNode.h"
// Symbol base class. (Can build functions or variables out of these...)
-class TSymbol
+class TSymbol : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
@@ -86,8 +86,6 @@ class TSymbol
}
private:
- DISALLOW_COPY_AND_ASSIGN(TSymbol);
-
int uniqueId; // For real comparing during code generation
const TString *name;
TString extension;
@@ -158,8 +156,6 @@ class TVariable : public TSymbol
}
private:
- DISALLOW_COPY_AND_ASSIGN(TVariable);
-
TType type;
bool userType;
// we are assuming that Pool Allocator will free the memory
@@ -186,13 +182,14 @@ class TFunction : public TSymbol
defined(false)
{
}
- TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull)
+ TFunction(const TString *name, const TType &retType, TOperator tOp = EOpNull, const char *ext = "")
: TSymbol(name),
returnType(retType),
mangledName(TFunction::mangleName(*name)),
op(tOp),
defined(false)
{
+ relateToExtension(ext);
}
virtual ~TFunction();
virtual bool isFunction() const
@@ -224,10 +221,6 @@ class TFunction : public TSymbol
return returnType;
}
- void relateToOperator(TOperator o)
- {
- op = o;
- }
TOperator getBuiltInOp() const
{
return op;
@@ -252,8 +245,6 @@ class TFunction : public TSymbol
}
private:
- DISALLOW_COPY_AND_ASSIGN(TFunction);
-
typedef TVector<TParameter> TParamList;
TParamList parameters;
TType returnType;
@@ -291,10 +282,10 @@ class TSymbolTableLevel
bool insert(TSymbol *symbol);
- TSymbol *find(const TString &name) const;
+ // Insert a function using its unmangled name as the key.
+ bool insertUnmangled(TFunction *function);
- void relateToOperator(const char *name, TOperator op);
- void relateToExtension(const char *name, const TString &ext);
+ TSymbol *find(const TString &name) const;
protected:
tLevel level;
@@ -310,7 +301,7 @@ const int ESSL3_BUILTINS = 2;
const int LAST_BUILTIN_LEVEL = ESSL3_BUILTINS;
const int GLOBAL_LEVEL = 3;
-class TSymbolTable
+class TSymbolTable : angle::NonCopyable
{
public:
TSymbolTable()
@@ -363,6 +354,12 @@ class TSymbolTable
return table[level]->insert(symbol);
}
+ bool insert(ESymbolLevel level, const char *ext, TSymbol *symbol)
+ {
+ symbol->relateToExtension(ext);
+ return table[level]->insert(symbol);
+ }
+
bool insertConstInt(ESymbolLevel level, const char *name, int value)
{
TVariable *constant = new TVariable(
@@ -371,9 +368,26 @@ class TSymbolTable
return insert(level, constant);
}
+ void insertBuiltIn(ESymbolLevel level, TOperator op, const char *ext, TType *rvalue, const char *name,
+ TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0);
+
void insertBuiltIn(ESymbolLevel level, TType *rvalue, const char *name,
- TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0,
- TType *ptype4 = 0, TType *ptype5 = 0);
+ TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+ {
+ insertBuiltIn(level, EOpNull, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+ }
+
+ void insertBuiltIn(ESymbolLevel level, const char *ext, TType *rvalue, const char *name,
+ TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+ {
+ insertBuiltIn(level, EOpNull, ext, rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+ }
+
+ void insertBuiltIn(ESymbolLevel level, TOperator op, TType *rvalue, const char *name,
+ TType *ptype1, TType *ptype2 = 0, TType *ptype3 = 0, TType *ptype4 = 0, TType *ptype5 = 0)
+ {
+ insertBuiltIn(level, op, "", rvalue, name, ptype1, ptype2, ptype3, ptype4, ptype5);
+ }
TSymbol *find(const TString &name, int shaderVersion,
bool *builtIn = NULL, bool *sameScope = NULL) const;
@@ -385,14 +399,6 @@ class TSymbolTable
return table[currentLevel() - 1];
}
- void relateToOperator(ESymbolLevel level, const char *name, TOperator op)
- {
- table[level]->relateToOperator(name, op);
- }
- void relateToExtension(ESymbolLevel level, const char *name, const TString &ext)
- {
- table[level]->relateToExtension(name, ext);
- }
void dump(TInfoSink &infoSink) const;
bool setDefaultPrecision(const TPublicType &type, TPrecision prec)
@@ -413,7 +419,7 @@ class TSymbolTable
// This records invariant varyings declared through
// "invariant varying_name;".
- void addInvariantVarying(const TString &originalName)
+ void addInvariantVarying(const std::string &originalName)
{
mInvariantVaryings.insert(originalName);
}
@@ -421,7 +427,7 @@ class TSymbolTable
// if it is set as invariant during the varying variable
// declaration - this piece of information is stored in the
// variable's type, not here.
- bool isVaryingInvariant(const TString &originalName) const
+ bool isVaryingInvariant(const std::string &originalName) const
{
return (mGlobalInvariant ||
mInvariantVaryings.count(originalName) > 0);
@@ -445,10 +451,10 @@ class TSymbolTable
typedef TMap<TBasicType, TPrecision> PrecisionStackLevel;
std::vector< PrecisionStackLevel *> precisionStack;
- std::set<TString> mInvariantVaryings;
+ std::set<std::string> mInvariantVaryings;
bool mGlobalInvariant;
static int uniqueIdCounter;
};
-#endif // _SYMBOL_TABLE_INCLUDED_
+#endif // COMPILER_TRANSLATOR_SYMBOLTABLE_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
index dcbf3cea1d..238bc97576 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.cpp
@@ -6,40 +6,91 @@
#include "compiler/translator/TranslatorESSL.h"
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/OutputESSL.h"
#include "angle_gl.h"
TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
- : TCompiler(type, spec, SH_ESSL_OUTPUT) {
+ : TCompiler(type, spec, SH_ESSL_OUTPUT)
+{
}
-void TranslatorESSL::translate(TIntermNode* root) {
+void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions)
+{
+ if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)
+ InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType());
+}
+
+void TranslatorESSL::translate(TIntermNode *root, int) {
TInfoSinkBase& sink = getInfoSink().obj;
+ int shaderVersion = getShaderVersion();
+ if (shaderVersion > 100)
+ {
+ sink << "#version " << shaderVersion << " es\n";
+ }
+
writePragma();
// Write built-in extension behaviors.
writeExtensionBehavior();
+ bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+ if (precisionEmulation)
+ {
+ EmulatePrecision emulatePrecision;
+ root->traverse(&emulatePrecision);
+ emulatePrecision.updateTree();
+ emulatePrecision.writeEmulationHelpers(sink, SH_ESSL_OUTPUT);
+ }
+
// Write emulated built-in functions if needed.
- getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
- sink, getShaderType() == GL_FRAGMENT_SHADER);
+ if (!getBuiltInFunctionEmulator().IsOutputEmpty())
+ {
+ sink << "// BEGIN: Generated code for built-in function emulation\n\n";
+ if (getShaderType() == GL_FRAGMENT_SHADER)
+ {
+ sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
+ << "#define webgl_emu_precision highp\n"
+ << "#else\n"
+ << "#define webgl_emu_precision mediump\n"
+ << "#endif\n\n";
+ }
+ else
+ {
+ sink << "#define webgl_emu_precision highp\n";
+ }
+
+ getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink);
+ sink << "// END: Generated code for built-in function emulation\n\n";
+ }
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
// Write translated shader.
- TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion());
+ TOutputESSL outputESSL(sink,
+ getArrayIndexClampingStrategy(),
+ getHashFunction(),
+ getNameMap(),
+ getSymbolTable(),
+ shaderVersion,
+ precisionEmulation);
root->traverse(&outputESSL);
}
void TranslatorESSL::writeExtensionBehavior() {
TInfoSinkBase& sink = getInfoSink().obj;
- const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
- for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
- iter != extensionBehavior.end(); ++iter) {
+ const TExtensionBehavior& extBehavior = getExtensionBehavior();
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+ iter != extBehavior.end(); ++iter) {
if (iter->second != EBhUndefined) {
- if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
+ if (getResources().NV_shader_framebuffer_fetch && iter->first == "GL_EXT_shader_framebuffer_fetch") {
+ sink << "#extension GL_NV_shader_framebuffer_fetch : "
+ << getBehaviorString(iter->second) << "\n";
+ } else if (getResources().NV_draw_buffers && iter->first == "GL_EXT_draw_buffers") {
sink << "#extension GL_NV_draw_buffers : "
<< getBehaviorString(iter->second) << "\n";
} else {
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
index 55766822d1..89a3e473e9 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorESSL.h
@@ -4,20 +4,23 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATORESSL_H_
-#define COMPILER_TRANSLATORESSL_H_
+#ifndef COMPILER_TRANSLATOR_TRANSLATORESSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORESSL_H_
#include "compiler/translator/Compiler.h"
-class TranslatorESSL : public TCompiler {
-public:
+class TranslatorESSL : public TCompiler
+{
+ public:
TranslatorESSL(sh::GLenum type, ShShaderSpec spec);
-protected:
- virtual void translate(TIntermNode* root);
+ protected:
+ void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override;
-private:
+ virtual void translate(TIntermNode *root, int compileOptions);
+
+ private:
void writeExtensionBehavior();
};
-#endif // COMPILER_TRANSLATORESSL_H_
+#endif // COMPILER_TRANSLATOR_TRANSLATORESSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
index 6acbf7c5a8..aea3f77c4e 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.cpp
@@ -6,14 +6,69 @@
#include "compiler/translator/TranslatorGLSL.h"
+#include "angle_gl.h"
+#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
+#include "compiler/translator/EmulatePrecision.h"
#include "compiler/translator/OutputGLSL.h"
#include "compiler/translator/VersionGLSL.h"
-TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec)
- : TCompiler(type, spec, SH_GLSL_OUTPUT) {
+namespace
+{
+
+// To search for what output variables are used in a fragment shader.
+// We handle gl_FragColor and gl_FragData at the moment.
+class TFragmentOutSearcher : public TIntermTraverser
+{
+ public:
+ TFragmentOutSearcher()
+ : mUsesGlFragColor(false),
+ mUsesGlFragData(false)
+ {
+ }
+
+ bool usesGlFragColor() const
+ {
+ return mUsesGlFragColor;
+ }
+
+ bool usesGlFragData() const
+ {
+ return mUsesGlFragData;
+ }
+
+ protected:
+ virtual void visitSymbol(TIntermSymbol *node) override
+ {
+ if (node->getSymbol() == "gl_FragColor")
+ {
+ mUsesGlFragColor = true;
+ }
+ else if (node->getSymbol() == "gl_FragData")
+ {
+ mUsesGlFragData = true;
+ }
+ }
+
+ private:
+ bool mUsesGlFragColor;
+ bool mUsesGlFragData;
+};
+
+} // namespace anonymous
+
+TranslatorGLSL::TranslatorGLSL(sh::GLenum type,
+ ShShaderSpec spec,
+ ShShaderOutput output)
+ : TCompiler(type, spec, output) {
+}
+
+void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions)
+{
+ if (compileOptions & SH_EMULATE_BUILT_IN_FUNCTIONS)
+ InitBuiltInFunctionEmulatorForGLSL(emu, getShaderType());
}
-void TranslatorGLSL::translate(TIntermNode* root) {
+void TranslatorGLSL::translate(TIntermNode *root, int) {
TInfoSinkBase& sink = getInfoSink().obj;
// Write GLSL version.
@@ -24,21 +79,60 @@ void TranslatorGLSL::translate(TIntermNode* root) {
// Write extension behaviour as needed
writeExtensionBehavior();
+ bool precisionEmulation = getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
+
+ if (precisionEmulation)
+ {
+ EmulatePrecision emulatePrecision;
+ root->traverse(&emulatePrecision);
+ emulatePrecision.updateTree();
+ emulatePrecision.writeEmulationHelpers(sink, getOutputType());
+ }
+
// Write emulated built-in functions if needed.
- getBuiltInFunctionEmulator().OutputEmulatedFunctionDefinition(
- sink, false);
+ if (!getBuiltInFunctionEmulator().IsOutputEmpty())
+ {
+ sink << "// BEGIN: Generated code for built-in function emulation\n\n";
+ sink << "#define webgl_emu_precision\n\n";
+ getBuiltInFunctionEmulator().OutputEmulatedFunctions(sink);
+ sink << "// END: Generated code for built-in function emulation\n\n";
+ }
// Write array bounds clamping emulation if needed.
getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
+ // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
+ // if it's core profile shaders and they are used.
+ if (getShaderType() == GL_FRAGMENT_SHADER &&
+ getOutputType() == SH_GLSL_CORE_OUTPUT)
+ {
+ TFragmentOutSearcher searcher;
+ root->traverse(&searcher);
+ ASSERT(!(searcher.usesGlFragData() && searcher.usesGlFragColor()));
+ if (searcher.usesGlFragColor())
+ {
+ sink << "out vec4 webgl_FragColor;\n";
+ }
+ if (searcher.usesGlFragData())
+ {
+ sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
+ }
+ }
+
// Write translated shader.
- TOutputGLSL outputGLSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(), getSymbolTable(), getShaderVersion());
+ TOutputGLSL outputGLSL(sink,
+ getArrayIndexClampingStrategy(),
+ getHashFunction(),
+ getNameMap(),
+ getSymbolTable(),
+ getShaderVersion(),
+ getOutputType());
root->traverse(&outputGLSL);
}
void TranslatorGLSL::writeVersion(TIntermNode *root)
{
- TVersionGLSL versionGLSL(getShaderType(), getPragma());
+ TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
root->traverse(&versionGLSL);
int version = versionGLSL.getVersion();
// We need to write version directive only if it is greater than 110.
@@ -52,9 +146,9 @@ void TranslatorGLSL::writeVersion(TIntermNode *root)
void TranslatorGLSL::writeExtensionBehavior() {
TInfoSinkBase& sink = getInfoSink().obj;
- const TExtensionBehavior& extensionBehavior = getExtensionBehavior();
- for (TExtensionBehavior::const_iterator iter = extensionBehavior.begin();
- iter != extensionBehavior.end(); ++iter) {
+ const TExtensionBehavior& extBehavior = getExtensionBehavior();
+ for (TExtensionBehavior::const_iterator iter = extBehavior.begin();
+ iter != extBehavior.end(); ++iter) {
if (iter->second == EBhUndefined)
continue;
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
index 766d8d910e..4a5a641096 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorGLSL.h
@@ -4,22 +4,24 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATORGLSL_H_
-#define COMPILER_TRANSLATORGLSL_H_
+#ifndef COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
#include "compiler/translator/Compiler.h"
class TranslatorGLSL : public TCompiler
{
public:
- TranslatorGLSL(sh::GLenum type, ShShaderSpec spec);
+ TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output);
protected:
- virtual void translate(TIntermNode *root);
+ void initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, int compileOptions) override;
+
+ virtual void translate(TIntermNode *root, int compileOptions);
private:
void writeVersion(TIntermNode *root);
void writeExtensionBehavior();
};
-#endif // COMPILER_TRANSLATORGLSL_H_
+#endif // COMPILER_TRANSLATOR_TRANSLATORGLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
index 22bf60e86e..f6275defa1 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.cpp
@@ -6,20 +6,26 @@
#include "compiler/translator/TranslatorHLSL.h"
-#include "compiler/translator/InitializeParseContext.h"
#include "compiler/translator/OutputHLSL.h"
+#include "compiler/translator/SimplifyArrayAssignment.h"
TranslatorHLSL::TranslatorHLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
: TCompiler(type, spec, output)
{
}
-void TranslatorHLSL::translate(TIntermNode *root)
+void TranslatorHLSL::translate(TIntermNode *root, int compileOptions)
{
- TParseContext& parseContext = *GetGlobalParseContext();
- sh::OutputHLSL outputHLSL(parseContext, this);
+ const ShBuiltInResources &resources = getResources();
+ int numRenderTargets = resources.EXT_draw_buffers ? resources.MaxDrawBuffers : 1;
- outputHLSL.output();
+ SimplifyArrayAssignment simplify;
+ root->traverse(&simplify);
+
+ sh::OutputHLSL outputHLSL(getShaderType(), getShaderVersion(), getExtensionBehavior(),
+ getSourcePath(), getOutputType(), numRenderTargets, getUniforms(), compileOptions);
+
+ outputHLSL.output(root, getInfoSink().obj);
mInterfaceBlockRegisterMap = outputHLSL.getInterfaceBlockRegisterMap();
mUniformRegisterMap = outputHLSL.getUniformRegisterMap();
diff --git a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
index 11a042d83a..1920ed5755 100644
--- a/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/TranslatorHLSL.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATORHLSL_H_
-#define COMPILER_TRANSLATORHLSL_H_
+#ifndef COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
+#define COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
#include "compiler/translator/Compiler.h"
@@ -22,10 +22,10 @@ class TranslatorHLSL : public TCompiler
unsigned int getUniformRegister(const std::string &uniformName) const;
protected:
- virtual void translate(TIntermNode* root);
+ virtual void translate(TIntermNode *root, int compileOptions);
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
std::map<std::string, unsigned int> mUniformRegisterMap;
};
-#endif // COMPILER_TRANSLATORHLSL_H_
+#endif // COMPILER_TRANSLATOR_TRANSLATORHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/Types.cpp b/src/3rdparty/angle/src/compiler/translator/Types.cpp
index d36936fb23..b970bf5ac4 100644
--- a/src/3rdparty/angle/src/compiler/translator/Types.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/Types.cpp
@@ -178,11 +178,12 @@ size_t TType::getObjectSize() const
if (isArray())
{
- size_t arraySize = getArraySize();
- if (arraySize > INT_MAX / totalSize)
+ // TODO: getArraySize() returns an int, not a size_t
+ size_t currentArraySize = getArraySize();
+ if (currentArraySize > INT_MAX / totalSize)
totalSize = INT_MAX;
else
- totalSize *= arraySize;
+ totalSize *= currentArraySize;
}
return totalSize;
@@ -199,6 +200,17 @@ bool TStructure::containsArrays() const
return false;
}
+bool TStructure::containsSamplers() const
+{
+ for (size_t i = 0; i < mFields->size(); ++i)
+ {
+ const TType *fieldType = (*mFields)[i]->type();
+ if (IsSampler(fieldType->getBasicType()) || fieldType->isStructureContainingSamplers())
+ return true;
+ }
+ return false;
+}
+
TString TFieldListCollection::buildMangledName() const
{
TString mangledName(mangledNamePrefix());
diff --git a/src/3rdparty/angle/src/compiler/translator/Types.h b/src/3rdparty/angle/src/compiler/translator/Types.h
index 075196daa3..044f22c3c1 100644
--- a/src/3rdparty/angle/src/compiler/translator/Types.h
+++ b/src/3rdparty/angle/src/compiler/translator/Types.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _TYPES_INCLUDED
-#define _TYPES_INCLUDED
+#ifndef COMPILER_TRANSLATOR_TYPES_H_
+#define COMPILER_TRANSLATOR_TYPES_H_
#include "common/angleutils.h"
@@ -17,7 +17,7 @@ struct TPublicType;
class TType;
class TSymbol;
-class TField
+class TField : angle::NonCopyable
{
public:
POOL_ALLOCATOR_NEW_DELETE();
@@ -49,7 +49,6 @@ class TField
}
private:
- DISALLOW_COPY_AND_ASSIGN(TField);
TType *mType;
TString *mName;
TSourceLoc mLine;
@@ -62,7 +61,7 @@ inline TFieldList *NewPoolTFieldList()
return new(memory) TFieldList;
}
-class TFieldListCollection
+class TFieldListCollection : angle::NonCopyable
{
public:
const TString &name() const
@@ -113,7 +112,8 @@ class TStructure : public TFieldListCollection
TStructure(const TString *name, TFieldList *fields)
: TFieldListCollection(name, fields),
mDeepestNesting(0),
- mUniqueId(0)
+ mUniqueId(0),
+ mAtGlobalScope(false)
{
}
@@ -124,6 +124,7 @@ class TStructure : public TFieldListCollection
return mDeepestNesting;
}
bool containsArrays() const;
+ bool containsSamplers() const;
bool equals(const TStructure &other) const;
@@ -138,9 +139,17 @@ class TStructure : public TFieldListCollection
return mUniqueId;
}
- private:
- DISALLOW_COPY_AND_ASSIGN(TStructure);
+ void setAtGlobalScope(bool atGlobalScope)
+ {
+ mAtGlobalScope = atGlobalScope;
+ }
+
+ bool atGlobalScope() const
+ {
+ return mAtGlobalScope;
+ }
+ private:
// TODO(zmo): Find a way to get rid of the const_cast in function
// setName(). At the moment keep this function private so only
// friend class RegenerateStructNames may call it.
@@ -159,6 +168,7 @@ class TStructure : public TFieldListCollection
mutable int mDeepestNesting;
int mUniqueId;
+ bool mAtGlobalScope;
};
class TInterfaceBlock : public TFieldListCollection
@@ -201,7 +211,6 @@ class TInterfaceBlock : public TFieldListCollection
}
private:
- DISALLOW_COPY_AND_ASSIGN(TInterfaceBlock);
virtual TString mangledNamePrefix() const
{
return "iblock-";
@@ -325,6 +334,10 @@ class TType
{
return primarySize > 1 && secondarySize > 1;
}
+ bool isNonSquareMatrix() const
+ {
+ return isMatrix() && primarySize != secondarySize;
+ }
bool isArray() const
{
return array ? true : false;
@@ -464,6 +477,11 @@ class TType
return structure ? structure->containsArrays() : false;
}
+ bool isStructureContainingSamplers() const
+ {
+ return structure ? structure->containsSamplers() : false;
+ }
+
protected:
TString buildMangledName() const;
size_t getStructSize() const;
@@ -584,4 +602,4 @@ struct TPublicType
}
};
-#endif // _TYPES_INCLUDED_
+#endif // COMPILER_TRANSLATOR_TYPES_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp
index 65f50c4cc3..f79f9dd7fb 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.cpp
@@ -16,7 +16,7 @@
namespace sh
{
-UnfoldShortCircuit::UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL) : mContext(context), mOutputHLSL(outputHLSL)
+UnfoldShortCircuit::UnfoldShortCircuit(OutputHLSL *outputHLSL) : mOutputHLSL(outputHLSL)
{
mTemporaryIndex = 0;
}
@@ -30,7 +30,7 @@ void UnfoldShortCircuit::traverse(TIntermNode *node)
bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
{
- TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+ TInfoSinkBase &out = mOutputHLSL->getInfoSink();
// If our right node doesn't have side effects, we know we don't need to unfold this
// expression: there will be no short-circuiting side effects to avoid
@@ -111,7 +111,7 @@ bool UnfoldShortCircuit::visitBinary(Visit visit, TIntermBinary *node)
bool UnfoldShortCircuit::visitSelection(Visit visit, TIntermSelection *node)
{
- TInfoSinkBase &out = mOutputHLSL->getBodyStream();
+ TInfoSinkBase &out = mOutputHLSL->getInfoSink();
// Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
if (node->usesTernaryOperator())
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h
index 6fd3b457bd..eaceb0a0b3 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuit.h
@@ -6,8 +6,8 @@
// UnfoldShortCircuit is an AST traverser to output short-circuiting operators as if-else statements
//
-#ifndef COMPILER_UNFOLDSHORTCIRCUIT_H_
-#define COMPILER_UNFOLDSHORTCIRCUIT_H_
+#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
+#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParseContext.h"
@@ -19,7 +19,7 @@ class OutputHLSL;
class UnfoldShortCircuit : public TIntermTraverser
{
public:
- UnfoldShortCircuit(TParseContext &context, OutputHLSL *outputHLSL);
+ UnfoldShortCircuit(OutputHLSL *outputHLSL);
void traverse(TIntermNode *node);
bool visitBinary(Visit visit, TIntermBinary*);
@@ -29,11 +29,10 @@ class UnfoldShortCircuit : public TIntermTraverser
int getNextTemporaryIndex();
protected:
- TParseContext &mContext;
OutputHLSL *const mOutputHLSL;
int mTemporaryIndex;
};
}
-#endif // COMPILER_UNFOLDSHORTCIRCUIT_H_
+#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUIT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
index 29c4397d56..d548d421d2 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.cpp
@@ -50,32 +50,8 @@ bool UnfoldShortCircuitAST::visitBinary(Visit visit, TIntermBinary *node)
}
if (replacement)
{
- replacements.push_back(
- NodeUpdateEntry(getParentNode(), node, replacement));
+ mReplacements.push_back(
+ NodeUpdateEntry(getParentNode(), node, replacement, false));
}
return true;
}
-
-void UnfoldShortCircuitAST::updateTree()
-{
- for (size_t ii = 0; ii < replacements.size(); ++ii)
- {
- const NodeUpdateEntry& entry = replacements[ii];
- ASSERT(entry.parent);
- bool replaced = entry.parent->replaceChildNode(
- entry.original, entry.replacement);
- ASSERT(replaced);
-
- // In AST traversing, a parent is visited before its children.
- // After we replace a node, if an immediate child is to
- // be replaced, we need to make sure we don't update the replaced
- // node; instead, we update the replacement node.
- for (size_t jj = ii + 1; jj < replacements.size(); ++jj)
- {
- NodeUpdateEntry& entry2 = replacements[jj];
- if (entry2.parent == entry.original)
- entry2.parent = entry.replacement;
- }
- }
-}
-
diff --git a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
index 3acaf7ee7c..7b698ccb63 100644
--- a/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
+++ b/src/3rdparty/angle/src/compiler/translator/UnfoldShortCircuitAST.h
@@ -7,8 +7,8 @@
// operations with ternary operations.
//
-#ifndef COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
-#define COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
+#ifndef COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
+#define COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
#include "common/angleutils.h"
#include "compiler/translator/IntermNode.h"
@@ -23,29 +23,6 @@ class UnfoldShortCircuitAST : public TIntermTraverser
UnfoldShortCircuitAST() { }
virtual bool visitBinary(Visit visit, TIntermBinary *);
-
- void updateTree();
-
- private:
- struct NodeUpdateEntry
- {
- NodeUpdateEntry(TIntermNode *_parent,
- TIntermNode *_original,
- TIntermNode *_replacement)
- : parent(_parent),
- original(_original),
- replacement(_replacement) {}
-
- TIntermNode *parent;
- TIntermNode *original;
- TIntermNode *replacement;
- };
-
- // During traversing, save all the replacements that need to happen;
- // then replace them by calling updateNodes().
- std::vector<NodeUpdateEntry> replacements;
-
- DISALLOW_COPY_AND_ASSIGN(UnfoldShortCircuitAST);
};
-#endif // COMPILER_UNFOLD_SHORT_CIRCUIT_AST_H_
+#endif // COMPILER_TRANSLATOR_UNFOLDSHORTCIRCUITAST_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
index 61b6ed7455..71659fe354 100644
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.cpp
@@ -7,14 +7,13 @@
// Methods for GLSL to HLSL translation for uniforms and interface blocks.
//
-#include "OutputHLSL.h"
-#include "common/blocklayout.h"
-#include "common/utilities.h"
#include "compiler/translator/UniformHLSL.h"
+
+#include "common/utilities.h"
#include "compiler/translator/StructureHLSL.h"
-#include "compiler/translator/util.h"
#include "compiler/translator/UtilsHLSL.h"
-#include "compiler/translator/TranslatorHLSL.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "compiler/translator/util.h"
namespace sh
{
@@ -61,13 +60,13 @@ static TString InterfaceBlockStructName(const TInterfaceBlock &interfaceBlock)
return DecoratePrivate(interfaceBlock.name()) + "_type";
}
-UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator)
+UniformHLSL::UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms)
: mUniformRegister(0),
mInterfaceBlockRegister(0),
mSamplerRegister(0),
mStructureHLSL(structureHLSL),
- mOutputType(translator->getOutputType()),
- mUniforms(translator->getUniforms())
+ mOutputType(outputType),
+ mUniforms(uniforms)
{}
void UniformHLSL::reserveUniformRegisters(unsigned int registerCount)
@@ -105,7 +104,7 @@ unsigned int UniformHLSL::declareUniformAndAssignRegister(const TType &type, con
unsigned int registerCount = HLSLVariableRegisterCount(*uniform, mOutputType);
- if (gl::IsSampler(uniform->type))
+ if (gl::IsSamplerType(uniform->type))
{
mSamplerRegister += registerCount;
}
diff --git a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
index 91fa51588b..4ab9ccdf53 100644
--- a/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/UniformHLSL.h
@@ -7,19 +7,19 @@
// Methods for GLSL to HLSL translation for uniforms and interface blocks.
//
-#ifndef TRANSLATOR_UNIFORMHLSL_H_
-#define TRANSLATOR_UNIFORMHLSL_H_
+#ifndef COMPILER_TRANSLATOR_UNIFORMHLSL_H_
+#define COMPILER_TRANSLATOR_UNIFORMHLSL_H_
-#include "compiler/translator/Types.h"
+#include "compiler/translator/OutputHLSL.h"
namespace sh
{
class StructureHLSL;
-class UniformHLSL
+class UniformHLSL : angle::NonCopyable
{
public:
- UniformHLSL(StructureHLSL *structureHLSL, TranslatorHLSL *translator);
+ UniformHLSL(StructureHLSL *structureHLSL, ShShaderOutput outputType, const std::vector<Uniform> &uniforms);
void reserveUniformRegisters(unsigned int registerCount);
void reserveInterfaceBlockRegisters(unsigned int registerCount);
@@ -60,4 +60,4 @@ class UniformHLSL
}
-#endif // TRANSLATOR_UNIFORMHLSL_H_
+#endif // COMPILER_TRANSLATOR_UNIFORMHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
index de0c36ca65..94e19ac40d 100644
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.cpp
@@ -175,6 +175,13 @@ TString StructNameString(const TStructure &structure)
return "";
}
+ // For structures at global scope we use a consistent
+ // translation so that we can link between shader stages.
+ if (structure.atGlobalScope())
+ {
+ return Decorate(structure.name());
+ }
+
return "ss" + str(structure.uniqueId()) + "_" + structure.name();
}
diff --git a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
index aaa3ddf5d2..9800a3bbf3 100644
--- a/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/UtilsHLSL.h
@@ -7,8 +7,8 @@
// Utility methods for GLSL to HLSL translation.
//
-#ifndef TRANSLATOR_UTILSHLSL_H_
-#define TRANSLATOR_UTILSHLSL_H_
+#ifndef COMPILER_TRANSLATOR_UTILSHLSL_H_
+#define COMPILER_TRANSLATOR_UTILSHLSL_H_
#include <vector>
#include "compiler/translator/Types.h"
@@ -34,4 +34,4 @@ TString QualifierString(TQualifier qualifier);
}
-#endif // TRANSLATOR_UTILSHLSL_H_
+#endif // COMPILER_TRANSLATOR_UTILSHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
index 896e1cd7a0..12367066e8 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.cpp
@@ -47,93 +47,6 @@ class ValidateConstIndexExpr : public TIntermTraverser
TLoopStack& mLoopStack;
};
-const char *GetOperatorString(TOperator op)
-{
- switch (op)
- {
- case EOpInitialize: return "=";
- case EOpAssign: return "=";
- case EOpAddAssign: return "+=";
- case EOpSubAssign: return "-=";
- case EOpDivAssign: return "/=";
-
- // Fall-through.
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign: return "*=";
-
- // Fall-through.
- case EOpIndexDirect:
- case EOpIndexIndirect: return "[]";
-
- case EOpIndexDirectStruct:
- case EOpIndexDirectInterfaceBlock: return ".";
- case EOpVectorSwizzle: return ".";
- case EOpAdd: return "+";
- case EOpSub: return "-";
- case EOpMul: return "*";
- case EOpDiv: return "/";
- case EOpMod: UNIMPLEMENTED(); break;
- case EOpEqual: return "==";
- case EOpNotEqual: return "!=";
- case EOpLessThan: return "<";
- case EOpGreaterThan: return ">";
- case EOpLessThanEqual: return "<=";
- case EOpGreaterThanEqual: return ">=";
-
- // Fall-through.
- case EOpVectorTimesScalar:
- case EOpVectorTimesMatrix:
- case EOpMatrixTimesVector:
- case EOpMatrixTimesScalar:
- case EOpMatrixTimesMatrix: return "*";
-
- case EOpLogicalOr: return "||";
- case EOpLogicalXor: return "^^";
- case EOpLogicalAnd: return "&&";
- case EOpNegative: return "-";
- case EOpPositive: return "+";
- case EOpVectorLogicalNot: return "not";
- case EOpLogicalNot: return "!";
- case EOpPostIncrement: return "++";
- case EOpPostDecrement: return "--";
- case EOpPreIncrement: return "++";
- case EOpPreDecrement: return "--";
-
- case EOpRadians: return "radians";
- case EOpDegrees: return "degrees";
- case EOpSin: return "sin";
- case EOpCos: return "cos";
- case EOpTan: return "tan";
- case EOpAsin: return "asin";
- case EOpAcos: return "acos";
- case EOpAtan: return "atan";
- case EOpExp: return "exp";
- case EOpLog: return "log";
- case EOpExp2: return "exp2";
- case EOpLog2: return "log2";
- case EOpSqrt: return "sqrt";
- case EOpInverseSqrt: return "inversesqrt";
- case EOpAbs: return "abs";
- case EOpSign: return "sign";
- case EOpFloor: return "floor";
- case EOpCeil: return "ceil";
- case EOpFract: return "fract";
- case EOpLength: return "length";
- case EOpNormalize: return "normalize";
- case EOpDFdx: return "dFdx";
- case EOpDFdy: return "dFdy";
- case EOpFwidth: return "fwidth";
- case EOpAny: return "any";
- case EOpAll: return "all";
-
- default: break;
- }
- return "";
-}
-
} // namespace anonymous
ValidateLimitations::ValidateLimitations(sh::GLenum shaderType,
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
index e6e8a9619f..59cccb565f 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateLimitations.h
@@ -4,6 +4,9 @@
// found in the LICENSE file.
//
+#ifndef COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
+#define COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
+
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/LoopInfo.h"
@@ -53,3 +56,4 @@ class ValidateLimitations : public TIntermTraverser
TLoopStack mLoopStack;
};
+#endif // COMPILER_TRANSLATOR_VALIDATELIMITATIONS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
index 0f808dbb97..1538e0f157 100644
--- a/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateOutputs.h
@@ -4,6 +4,9 @@
// found in the LICENSE file.
//
+#ifndef COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
+#define COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
+
#include "compiler/translator/IntermNode.h"
#include <set>
@@ -31,3 +34,5 @@ class ValidateOutputs : public TIntermTraverser
void error(TSourceLoc loc, const char *reason, const char* token);
};
+
+#endif // COMPILER_TRANSLATOR_VALIDATEOUTPUTS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
new file mode 100644
index 0000000000..9a4ed33632
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.cpp
@@ -0,0 +1,200 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#include "compiler/translator/ValidateSwitch.h"
+
+#include "compiler/translator/ParseContext.h"
+
+bool ValidateSwitch::validate(TBasicType switchType, TParseContext *context,
+ TIntermAggregate *statementList, const TSourceLoc &loc)
+{
+ ValidateSwitch validate(switchType, context);
+ ASSERT(statementList);
+ statementList->traverse(&validate);
+ return validate.validateInternal(loc);
+}
+
+ValidateSwitch::ValidateSwitch(TBasicType switchType, TParseContext *context)
+ : TIntermTraverser(true, false, true),
+ mSwitchType(switchType),
+ mContext(context),
+ mCaseTypeMismatch(false),
+ mFirstCaseFound(false),
+ mStatementBeforeCase(false),
+ mLastStatementWasCase(false),
+ mControlFlowDepth(0),
+ mCaseInsideControlFlow(false),
+ mDefaultCount(0),
+ mDuplicateCases(false)
+{}
+
+void ValidateSwitch::visitSymbol(TIntermSymbol *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+}
+
+void ValidateSwitch::visitConstantUnion(TIntermConstantUnion *)
+{
+ // Conditions of case labels are not traversed, so this is some other constant
+ // Could be just a statement like "0;"
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+}
+
+bool ValidateSwitch::visitBinary(Visit, TIntermBinary *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitUnary(Visit, TIntermUnary *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitSelection(Visit visit, TIntermSelection *)
+{
+ if (visit == PreVisit)
+ ++mControlFlowDepth;
+ if (visit == PostVisit)
+ --mControlFlowDepth;
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitSwitch(Visit, TIntermSwitch *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ // Don't go into nested switch statements
+ return false;
+}
+
+bool ValidateSwitch::visitCase(Visit, TIntermCase *node)
+{
+ const char *nodeStr = node->hasCondition() ? "case" : "default";
+ if (mControlFlowDepth > 0)
+ {
+ mContext->error(node->getLine(), "label statement nested inside control flow", nodeStr);
+ mCaseInsideControlFlow = true;
+ }
+ mFirstCaseFound = true;
+ mLastStatementWasCase = true;
+ if (!node->hasCondition())
+ {
+ ++mDefaultCount;
+ if (mDefaultCount > 1)
+ {
+ mContext->error(node->getLine(), "duplicate default label", nodeStr);
+ }
+ }
+ else
+ {
+ TIntermConstantUnion *condition = node->getCondition()->getAsConstantUnion();
+ if (condition == nullptr)
+ {
+ // This can happen in error cases.
+ return false;
+ }
+ TBasicType conditionType = condition->getBasicType();
+ if (conditionType != mSwitchType)
+ {
+ mContext->error(condition->getLine(),
+ "case label type does not match switch init-expression type", nodeStr);
+ mCaseTypeMismatch = true;
+ }
+
+ if (conditionType == EbtInt)
+ {
+ int iConst = condition->getIConst(0);
+ if (mCasesSigned.find(iConst) != mCasesSigned.end())
+ {
+ mContext->error(condition->getLine(), "duplicate case label", nodeStr);
+ mDuplicateCases = true;
+ }
+ else
+ {
+ mCasesSigned.insert(iConst);
+ }
+ }
+ else if (conditionType == EbtUInt)
+ {
+ unsigned int uConst = condition->getUConst(0);
+ if (mCasesUnsigned.find(uConst) != mCasesUnsigned.end())
+ {
+ mContext->error(condition->getLine(), "duplicate case label", nodeStr);
+ mDuplicateCases = true;
+ }
+ else
+ {
+ mCasesUnsigned.insert(uConst);
+ }
+ }
+ // Other types are possible only in error cases, where the error has already been generated
+ // when parsing the case statement.
+ }
+ // Don't traverse the condition of the case statement
+ return false;
+}
+
+bool ValidateSwitch::visitAggregate(Visit visit, TIntermAggregate *)
+{
+ if (getParentNode() != nullptr)
+ {
+ // This is not the statementList node, but some other node.
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ }
+ return true;
+}
+
+bool ValidateSwitch::visitLoop(Visit visit, TIntermLoop *)
+{
+ if (visit == PreVisit)
+ ++mControlFlowDepth;
+ if (visit == PostVisit)
+ --mControlFlowDepth;
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::visitBranch(Visit, TIntermBranch *)
+{
+ if (!mFirstCaseFound)
+ mStatementBeforeCase = true;
+ mLastStatementWasCase = false;
+ return true;
+}
+
+bool ValidateSwitch::validateInternal(const TSourceLoc &loc)
+{
+ if (mStatementBeforeCase)
+ {
+ mContext->error(loc,
+ "statement before the first label", "switch");
+ }
+ if (mLastStatementWasCase)
+ {
+ mContext->error(loc,
+ "no statement between the last label and the end of the switch statement", "switch");
+ }
+ return !mStatementBeforeCase && !mLastStatementWasCase && !mCaseInsideControlFlow &&
+ !mCaseTypeMismatch && mDefaultCount <= 1 && !mDuplicateCases;
+}
diff --git a/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
new file mode 100644
index 0000000000..88b68a500e
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/ValidateSwitch.h
@@ -0,0 +1,52 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+#ifndef COMPILER_TRANSLATOR_VALIDATESWITCH_H_
+#define COMPILER_TRANSLATOR_VALIDATESWITCH_H_
+
+#include "compiler/translator/IntermNode.h"
+
+struct TParseContext;
+
+class ValidateSwitch : public TIntermTraverser
+{
+ public:
+ // Check for errors and output messages any remaining errors on the context.
+ // Returns true if there are no errors.
+ static bool validate(TBasicType switchType, TParseContext *context,
+ TIntermAggregate *statementList, const TSourceLoc &loc);
+
+ void visitSymbol(TIntermSymbol *) override;
+ void visitConstantUnion(TIntermConstantUnion *) override;
+ bool visitBinary(Visit, TIntermBinary *) override;
+ bool visitUnary(Visit, TIntermUnary *) override;
+ bool visitSelection(Visit visit, TIntermSelection *) override;
+ bool visitSwitch(Visit, TIntermSwitch *) override;
+ bool visitCase(Visit, TIntermCase *node) override;
+ bool visitAggregate(Visit, TIntermAggregate *) override;
+ bool visitLoop(Visit visit, TIntermLoop *) override;
+ bool visitBranch(Visit, TIntermBranch *) override;
+
+ private:
+ ValidateSwitch(TBasicType switchType, TParseContext *context);
+
+ bool validateInternal(const TSourceLoc &loc);
+
+ TBasicType mSwitchType;
+ TParseContext *mContext;
+ bool mCaseTypeMismatch;
+ bool mFirstCaseFound;
+ bool mStatementBeforeCase;
+ bool mLastStatementWasCase;
+ int mControlFlowDepth;
+ bool mCaseInsideControlFlow;
+ int mDefaultCount;
+ std::set<int> mCasesSigned;
+ std::set<unsigned int> mCasesUnsigned;
+ bool mDuplicateCases;
+};
+
+#endif // COMPILER_TRANSLATOR_VALIDATESWITCH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
index d8e13788b7..cf229ec96a 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
@@ -142,8 +142,10 @@ CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
+ mInstanceIDAdded(false),
mPositionAdded(false),
mPointSizeAdded(false),
+ mLastFragDataAdded(false),
mHashFunction(hashFunction),
mSymbolTable(symbolTable)
{
@@ -249,6 +251,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
mPointCoordAdded = true;
}
return;
+ case EvqInstanceID:
+ if (!mInstanceIDAdded)
+ {
+ Attribute info;
+ const char kName[] = "gl_InstanceID";
+ info.name = kName;
+ info.mappedName = kName;
+ info.type = GL_INT;
+ info.arraySize = 0;
+ info.precision = GL_HIGH_INT; // Defined by spec.
+ info.staticUse = true;
+ info.location = -1;
+ mAttribs->push_back(info);
+ mInstanceIDAdded = true;
+ }
+ return;
case EvqPosition:
if (!mPositionAdded)
{
@@ -281,6 +299,22 @@ void CollectVariables::visitSymbol(TIntermSymbol *symbol)
mPointSizeAdded = true;
}
return;
+ case EvqLastFragData:
+ if (!mLastFragDataAdded)
+ {
+ Varying info;
+ const char kName[] = "gl_LastFragData";
+ info.name = kName;
+ info.mappedName = kName;
+ info.type = GL_FLOAT_VEC4;
+ info.arraySize = static_cast<const TVariable*>(mSymbolTable.findBuiltIn("gl_MaxDrawBuffers", 100))->getConstPointer()->getIConst();
+ info.precision = GL_MEDIUM_FLOAT; // Defined by spec.
+ info.staticUse = true;
+ info.isInvariant = mSymbolTable.isVaryingInvariant(kName);
+ mVaryings->push_back(info);
+ mLastFragDataAdded = true;
+ }
+ return;
default:
break;
}
@@ -301,8 +335,6 @@ class NameHashingTraverser : public GetVariableTraverser
{}
private:
- DISALLOW_COPY_AND_ASSIGN(NameHashingTraverser);
-
virtual void visitVariable(ShaderVariable *variable)
{
TString stringName = TString(variable->name.c_str());
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
index 92d376d879..bb1328a507 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
+++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_VARIABLE_INFO_H_
-#define COMPILER_VARIABLE_INFO_H_
+#ifndef COMPILER_TRANSLATOR_VARIABLEINFO_H_
+#define COMPILER_TRANSLATOR_VARIABLEINFO_H_
#include <GLSLANG/ShaderLang.h>
@@ -51,8 +51,10 @@ class CollectVariables : public TIntermTraverser
bool mFrontFacingAdded;
bool mFragCoordAdded;
+ bool mInstanceIDAdded;
bool mPositionAdded;
bool mPointSizeAdded;
+ bool mLastFragDataAdded;
ShHashFunction64 mHashFunction;
@@ -65,4 +67,4 @@ void ExpandUniforms(const std::vector<Uniform> &compact,
}
-#endif // COMPILER_VARIABLE_INFO_H_
+#endif // COMPILER_TRANSLATOR_VARIABLEINFO_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
index 1de5332d8a..9c80eea618 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
+++ b/src/3rdparty/angle/src/compiler/translator/VariablePacker.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef _VARIABLEPACKER_INCLUDED_
-#define _VARIABLEPACKER_INCLUDED_
+#ifndef COMPILER_TRANSLATOR_VARIABLEPACKER_H_
+#define COMPILER_TRANSLATOR_VARIABLEPACKER_H_
#include <vector>
#include "compiler/translator/VariableInfo.h"
@@ -38,4 +38,4 @@ class VariablePacker {
std::vector<unsigned> rows_;
};
-#endif // _VARIABLEPACKER_INCLUDED_
+#endif // COMPILER_TRANSLATOR_VARIABLEPACKER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
index 05b111a7a7..f6f568897d 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.cpp
@@ -8,6 +8,7 @@
static const int GLSL_VERSION_110 = 110;
static const int GLSL_VERSION_120 = 120;
+static const int GLSL_VERSION_150 = 150;
// We need to scan for the following:
// 1. "invariant" keyword: This can occur in both - vertex and fragment shaders
@@ -26,12 +27,22 @@ static const int GLSL_VERSION_120 = 120;
// GLSL 1.2 relaxed the restriction on arrays, section 5.8: "Variables that
// are built-in types, entire structures or arrays... are all l-values."
//
-TVersionGLSL::TVersionGLSL(sh::GLenum type, const TPragma &pragma)
+TVersionGLSL::TVersionGLSL(sh::GLenum type,
+ const TPragma &pragma,
+ ShShaderOutput output)
{
- if (pragma.stdgl.invariantAll)
- mVersion = GLSL_VERSION_120;
+ if (output == SH_GLSL_CORE_OUTPUT)
+ {
+ mVersion = GLSL_VERSION_150;
+ }
else
- mVersion = GLSL_VERSION_110;
+ {
+ ASSERT(output == SH_GLSL_COMPATIBILITY_OUTPUT);
+ if (pragma.stdgl.invariantAll)
+ mVersion = GLSL_VERSION_120;
+ else
+ mVersion = GLSL_VERSION_110;
+ }
}
void TVersionGLSL::visitSymbol(TIntermSymbol *node)
diff --git a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
index 72368e39d6..2b63d5f25d 100644
--- a/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
+++ b/src/3rdparty/angle/src/compiler/translator/VersionGLSL.h
@@ -29,14 +29,16 @@
class TVersionGLSL : public TIntermTraverser
{
public:
- TVersionGLSL(sh::GLenum type, const TPragma &pragma);
-
- // Returns 120 if the following is used the shader:
- // - "invariant",
- // - "gl_PointCoord",
- // - matrix/matrix constructors
- // - array "out" parameters
- // Else 110 is returned.
+ TVersionGLSL(sh::GLenum type, const TPragma &pragma, ShShaderOutput output);
+
+ // If output is core profile, returns 150.
+ // If output is legacy profile,
+ // Returns 120 if the following is used the shader:
+ // - "invariant",
+ // - "gl_PointCoord",
+ // - matrix/matrix constructors
+ // - array "out" parameters
+ // Else 110 is returned.
int getVersion() { return mVersion; }
virtual void visitSymbol(TIntermSymbol *);
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
new file mode 100644
index 0000000000..7c74105680
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.cpp
@@ -0,0 +1,123 @@
+//
+// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// blocklayout.cpp:
+// Implementation for block layout classes and methods.
+//
+
+#include "compiler/translator/blocklayout.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace sh
+{
+
+BlockLayoutEncoder::BlockLayoutEncoder()
+ : mCurrentOffset(0)
+{
+}
+
+BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
+{
+ int arrayStride;
+ int matrixStride;
+
+ getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
+
+ const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
+
+ advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
+
+ return memberInfo;
+}
+
+// static
+size_t BlockLayoutEncoder::getBlockRegister(const BlockMemberInfo &info)
+{
+ return (info.offset / BytesPerComponent) / ComponentsPerRegister;
+}
+
+// static
+size_t BlockLayoutEncoder::getBlockRegisterElement(const BlockMemberInfo &info)
+{
+ return (info.offset / BytesPerComponent) % ComponentsPerRegister;
+}
+
+void BlockLayoutEncoder::nextRegister()
+{
+ mCurrentOffset = rx::roundUp<size_t>(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<size_t>(numComponents));
+ }
+
+ mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
+
+ *matrixStrideOut = matrixStride;
+ *arrayStrideOut = arrayStride;
+}
+
+void Std140BlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
+{
+ if (arraySize > 0)
+ {
+ mCurrentOffset += arrayStride * arraySize;
+ }
+ else if (gl::IsMatrixType(type))
+ {
+ ASSERT(matrixStride == ComponentsPerRegister);
+ const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
+ mCurrentOffset += ComponentsPerRegister * numRegisters;
+ }
+ else
+ {
+ mCurrentOffset += gl::VariableComponentCount(type);
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/common/blocklayout.h b/src/3rdparty/angle/src/compiler/translator/blocklayout.h
index d46ac6e547..c11357fe66 100644
--- a/src/3rdparty/angle/src/common/blocklayout.h
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayout.h
@@ -24,7 +24,7 @@ struct Uniform;
struct Varying;
struct InterfaceBlock;
-struct BlockMemberInfo
+struct COMPILER_EXPORT BlockMemberInfo
{
BlockMemberInfo(int offset, int arrayStride, int matrixStride, bool isRowMajorMatrix)
: offset(offset),
@@ -44,7 +44,7 @@ struct BlockMemberInfo
bool isRowMajorMatrix;
};
-class BlockLayoutEncoder
+class COMPILER_EXPORT BlockLayoutEncoder
{
public:
BlockLayoutEncoder();
@@ -61,6 +61,9 @@ class BlockLayoutEncoder
static const size_t BytesPerComponent = 4u;
static const unsigned int ComponentsPerRegister = 4u;
+ static size_t getBlockRegister(const BlockMemberInfo &info);
+ static size_t getBlockRegisterElement(const BlockMemberInfo &info);
+
protected:
size_t mCurrentOffset;
@@ -73,7 +76,7 @@ class BlockLayoutEncoder
// 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
+class COMPILER_EXPORT Std140BlockEncoder : public BlockLayoutEncoder
{
public:
Std140BlockEncoder();
@@ -86,42 +89,6 @@ class Std140BlockEncoder : public BlockLayoutEncoder
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/blocklayout.cpp b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
index e3b2d43566..f32cf2cf89 100644
--- a/src/3rdparty/angle/src/common/blocklayout.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.cpp
@@ -7,108 +7,17 @@
// Implementation for block layout classes and methods.
//
-#include "common/blocklayout.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+
#include "common/mathutil.h"
#include "common/utilities.h"
namespace sh
{
-BlockLayoutEncoder::BlockLayoutEncoder()
- : mCurrentOffset(0)
-{
-}
-
-BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type, unsigned int arraySize, bool isRowMajorMatrix)
-{
- int arrayStride;
- int matrixStride;
-
- getBlockLayoutInfo(type, arraySize, isRowMajorMatrix, &arrayStride, &matrixStride);
-
- const BlockMemberInfo memberInfo(mCurrentOffset * BytesPerComponent, arrayStride * BytesPerComponent, matrixStride * BytesPerComponent, isRowMajorMatrix);
-
- advanceOffset(type, arraySize, isRowMajorMatrix, arrayStride, matrixStride);
-
- return memberInfo;
-}
-
-void BlockLayoutEncoder::nextRegister()
-{
- mCurrentOffset = rx::roundUp<size_t>(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<size_t>(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)
+ : mEncoderStrategy(strategy),
+ mTransposeMatrices(false)
{
}
@@ -121,8 +30,10 @@ void HLSLBlockEncoder::exitAggregateType()
{
}
-void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
+void HLSLBlockEncoder::getBlockLayoutInfo(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut)
{
+ GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
+
// We assume we are only dealing with 4 byte components (no doubles or half-words currently)
ASSERT(gl::VariableComponentSize(gl::VariableComponentType(type)) == BytesPerComponent);
@@ -166,8 +77,10 @@ void HLSLBlockEncoder::getBlockLayoutInfo(GLenum type, unsigned int arraySize, b
*arrayStrideOut = arrayStride;
}
-void HLSLBlockEncoder::advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
+void HLSLBlockEncoder::advanceOffset(GLenum typeIn, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride)
{
+ GLenum type = (mTransposeMatrices ? gl::TransposeMatrixType(typeIn) : typeIn);
+
if (arraySize > 0)
{
mCurrentOffset += arrayStride * (arraySize - 1);
@@ -230,9 +143,10 @@ void HLSLVariableRegisterCount(const ShaderVarType &variable, HLSLBlockEncoder *
}
}
-unsigned int HLSLVariableRegisterCount(const Varying &variable)
+unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices)
{
HLSLBlockEncoder encoder(HLSLBlockEncoder::ENCODE_PACKED);
+ encoder.setTransposeMatrices(transposeMatrices);
HLSLVariableRegisterCount(variable, &encoder);
const size_t registerBytes = (encoder.BytesPerComponent * encoder.ComponentsPerRegister);
diff --git a/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
new file mode 100644
index 0000000000..c61cb1ae57
--- /dev/null
+++ b/src/3rdparty/angle/src/compiler/translator/blocklayoutHLSL.h
@@ -0,0 +1,62 @@
+//
+// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// blocklayout.h:
+// Methods and classes related to uniform layout and packing in GLSL and HLSL.
+//
+
+#ifndef COMMON_BLOCKLAYOUTHLSL_H_
+#define COMMON_BLOCKLAYOUTHLSL_H_
+
+#include <cstddef>
+#include <vector>
+
+#include "angle_gl.h"
+#include "blocklayout.h"
+#include <GLSLANG/ShaderLang.h>
+
+namespace sh
+{
+// Block layout packed according to the D3D9 or default D3D10+ register packing rules
+// See http://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx
+// The strategy should be ENCODE_LOOSE for D3D9 constant blocks, and ENCODE_PACKED
+// for everything else (D3D10+ constant blocks and all attributes/varyings).
+
+class COMPILER_EXPORT HLSLBlockEncoder : public BlockLayoutEncoder
+{
+ public:
+ enum HLSLBlockEncoderStrategy
+ {
+ ENCODE_PACKED,
+ ENCODE_LOOSE
+ };
+
+ HLSLBlockEncoder(HLSLBlockEncoderStrategy strategy);
+
+ virtual void enterAggregateType();
+ virtual void exitAggregateType();
+ void skipRegisters(unsigned int numRegisters);
+
+ bool isPacked() const { return mEncoderStrategy == ENCODE_PACKED; }
+ void setTransposeMatrices(bool enabled) { mTransposeMatrices = enabled; }
+
+ static HLSLBlockEncoderStrategy GetStrategyFor(ShShaderOutput outputType);
+
+ protected:
+ virtual void getBlockLayoutInfo(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int *arrayStrideOut, int *matrixStrideOut);
+ virtual void advanceOffset(GLenum type, unsigned int arraySize, bool isRowMajorMatrix, int arrayStride, int matrixStride);
+
+ HLSLBlockEncoderStrategy mEncoderStrategy;
+ bool mTransposeMatrices;
+};
+
+// This method returns the number of used registers for a ShaderVariable. It is dependent on the HLSLBlockEncoder
+// class to count the number of used registers in a struct (which are individually packed according to the same rules).
+COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Varying &variable, bool transposeMatrices);
+COMPILER_EXPORT unsigned int HLSLVariableRegisterCount(const Uniform &variable, ShShaderOutput outputType);
+
+}
+
+#endif // COMMON_BLOCKLAYOUTHLSL_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h
index 7a371516af..84a12ad2f8 100644
--- a/src/3rdparty/angle/src/compiler/translator/compilerdebug.h
+++ b/src/3rdparty/angle/src/compiler/translator/compilerdebug.h
@@ -6,8 +6,8 @@
// debug.h: Debugging utilities.
-#ifndef COMPILER_DEBUG_H_
-#define COMPILER_DEBUG_H_
+#ifndef COMPILER_TRANSLATOR_COMPILERDEBUG_H_
+#define COMPILER_TRANSLATOR_COMPILERDEBUG_H_
#include <assert.h>
@@ -49,5 +49,5 @@ void Trace(const char* format, ...);
assert(false); \
} while(0)
-#endif // COMPILER_DEBUG_H_
+#endif // COMPILER_TRANSLATOR_COMPILERDEBUG_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h
index bc25fe7cbc..22db633678 100644
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h
+++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraph.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
-#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_H
+#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
+#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
#include "compiler/translator/IntermNode.h"
@@ -186,7 +186,7 @@ private:
//
// When using this, just fill in the methods for nodes you want visited.
//
-class TDependencyGraphTraverser {
+class TDependencyGraphTraverser : angle::NonCopyable {
public:
TDependencyGraphTraverser() : mDepth(0) {}
@@ -209,4 +209,4 @@ private:
TGraphNodeSet mVisited;
};
-#endif
+#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPH_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h
index b76f075e68..f7b3bd4b43 100644
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h
+++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphBuilder.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
-#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
+#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
#include "compiler/translator/depgraph/DependencyGraph.h"
@@ -104,7 +104,7 @@ class TDependencyGraphBuilder : public TIntermTraverser
// An instance of this class pushes a new node set when instantiated.
// When the instance goes out of scope, it and pops the node set.
//
- class TNodeSetMaintainer
+ class TNodeSetMaintainer : angle::NonCopyable
{
public:
TNodeSetMaintainer(TDependencyGraphBuilder *factory)
@@ -122,7 +122,7 @@ class TDependencyGraphBuilder : public TIntermTraverser
// When the instance goes out of scope, it and pops the top node set and adds
// its contents to the new top node set.
//
- class TNodeSetPropagatingMaintainer
+ class TNodeSetPropagatingMaintainer : angle::NonCopyable
{
public:
TNodeSetPropagatingMaintainer(TDependencyGraphBuilder *factory)
@@ -147,7 +147,7 @@ class TDependencyGraphBuilder : public TIntermTraverser
// kRightSubtree will never be replaced by a real symbol because we are tracking
// the leftmost symbol.
//
- class TLeftmostSymbolMaintainer
+ class TLeftmostSymbolMaintainer : angle::NonCopyable
{
public:
TLeftmostSymbolMaintainer(
@@ -196,4 +196,4 @@ class TDependencyGraphBuilder : public TIntermTraverser
TSymbolStack mLeftmostSymbols;
};
-#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCY_GRAPH_BUILDER_H
+#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHBUILDER_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h
index c3a4112278..b201e0a671 100644
--- a/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h
+++ b/src/3rdparty/angle/src/compiler/translator/depgraph/DependencyGraphOutput.h
@@ -4,27 +4,28 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
-#define COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+#ifndef COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
+#define COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
#include "compiler/translator/depgraph/DependencyGraph.h"
#include "compiler/translator/InfoSink.h"
-class TDependencyGraphOutput : public TDependencyGraphTraverser {
-public:
+class TDependencyGraphOutput : public TDependencyGraphTraverser
+{
+ public:
TDependencyGraphOutput(TInfoSinkBase& sink) : mSink(sink) {}
- virtual void visitSymbol(TGraphSymbol* symbol);
- virtual void visitArgument(TGraphArgument* parameter);
- virtual void visitFunctionCall(TGraphFunctionCall* functionCall);
- virtual void visitSelection(TGraphSelection* selection);
- virtual void visitLoop(TGraphLoop* loop);
- virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+ void visitSymbol(TGraphSymbol* symbol) override;
+ void visitArgument(TGraphArgument* parameter) override;
+ void visitFunctionCall(TGraphFunctionCall* functionCall) override;
+ void visitSelection(TGraphSelection* selection) override;
+ void visitLoop(TGraphLoop* loop) override;
+ void visitLogicalOp(TGraphLogicalOp* logicalOp) override;
void outputAllSpanningTrees(TDependencyGraph& graph);
-private:
+ private:
void outputIndentation();
TInfoSinkBase& mSink;
};
-#endif // COMPILER_DEPGRAPH_DEPENDENCY_GRAPH_OUTPUT_H
+#endif // COMPILER_TRANSLATOR_DEPGRAPH_DEPENDENCYGRAPHOUTPUT_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.h b/src/3rdparty/angle/src/compiler/translator/glslang.h
index f221199093..db31e6946c 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.h
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.h
@@ -4,6 +4,9 @@
// found in the LICENSE file.
//
+#ifndef COMPILER_TRANSLATOR_GLSLANG_H_
+#define COMPILER_TRANSLATOR_GLSLANG_H_
+
struct TParseContext;
extern int glslang_initialize(TParseContext* context);
extern int glslang_finalize(TParseContext* context);
@@ -14,3 +17,4 @@ extern int glslang_scan(size_t count,
TParseContext* context);
extern int glslang_parse(TParseContext* context);
+#endif // COMPILER_TRANSLATOR_GLSLANG_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.l b/src/3rdparty/angle/src/compiler/translator/glslang.l
index 518b78df11..ee4d28b6d6 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.l
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.l
@@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES LEXER (glslang_lex.cpp).
#pragma warning(disable: 4189)
#pragma warning(disable: 4505)
#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
#endif
}
@@ -70,6 +71,7 @@ static int floatsuffix_check(TParseContext* context);
%option noyywrap nounput never-interactive
%option yylineno reentrant bison-bridge bison-locations
%option extra-type="TParseContext*"
+%x FIELDS
D [0-9]
L [a-zA-Z_]
@@ -358,7 +360,7 @@ O [0-7]
")" { return RIGHT_PAREN; }
("["|"<:") { return LEFT_BRACKET; }
("]"|":>") { return RIGHT_BRACKET; }
-"." { return DOT; }
+"." { BEGIN(FIELDS); return DOT; }
"!" { return BANG; }
"-" { return DASH; }
"~" { return TILDE; }
@@ -373,9 +375,16 @@ O [0-7]
"&" { return AMPERSAND; }
"?" { return QUESTION; }
+<FIELDS>{L}({L}|{D})* {
+ BEGIN(INITIAL);
+ yylval->lex.string = NewPoolTString(yytext);
+ return FIELD_SELECTION;
+}
+<FIELDS>[ \t\v\f\r] {}
+
[ \t\v\n\f\r] { }
-<<EOF>> { yyterminate(); }
-. { assert(false); return 0; }
+<*><<EOF>> { yyterminate(); }
+<*>. { assert(false); return 0; }
%%
@@ -492,8 +501,8 @@ int floatsuffix_check(TParseContext* context)
return(FLOATCONSTANT);
}
-void yyerror(YYLTYPE* lloc, TParseContext* context, const char* reason) {
- context->error(*lloc, reason, yyget_text(context->scanner));
+void yyerror(YYLTYPE* lloc, TParseContext* context, void *scanner, const char* reason) {
+ context->error(*lloc, reason, yyget_text(scanner));
context->recover();
}
diff --git a/src/3rdparty/angle/src/compiler/translator/glslang.y b/src/3rdparty/angle/src/compiler/translator/glslang.y
index e271de978c..6024898cb0 100644
--- a/src/3rdparty/angle/src/compiler/translator/glslang.y
+++ b/src/3rdparty/angle/src/compiler/translator/glslang.y
@@ -32,6 +32,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
#pragma warning(disable: 4189)
#pragma warning(disable: 4505)
#pragma warning(disable: 4701)
+#pragma warning(disable: 4702)
#endif
#include "angle_gl.h"
@@ -41,12 +42,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
#define YYENABLE_NLS 0
-#define YYLEX_PARAM context->scanner
-
%}
%expect 1 /* One shift reduce conflict because of if | else */
-%pure-parser
%parse-param {TParseContext* context}
+%param {void *scanner}
+%define api.pure full
%locations
%code requires {
@@ -72,6 +72,8 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TIntermNodePair nodePair;
TIntermTyped* intermTypedNode;
TIntermAggregate* intermAggregate;
+ TIntermSwitch* intermSwitch;
+ TIntermCase* intermCase;
};
union {
TPublicType type;
@@ -88,11 +90,11 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
%{
extern int yylex(YYSTYPE* yylval, YYLTYPE* yylloc, void* yyscanner);
-extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason);
+extern void yyerror(YYLTYPE* yylloc, TParseContext* context, void *scanner, const char* reason);
#define YYLLOC_DEFAULT(Current, Rhs, N) \
do { \
- if (YYID(N)) { \
+ if (N) { \
(Current).first_file = YYRHSLOC(Rhs, 1).first_file; \
(Current).first_line = YYRHSLOC(Rhs, 1).first_line; \
(Current).last_file = YYRHSLOC(Rhs, N).last_file; \
@@ -179,6 +181,8 @@ extern void yyerror(YYLTYPE* yylloc, TParseContext* context, const char* reason)
%type <interm.intermNode> declaration external_declaration
%type <interm.intermNode> for_init_statement compound_statement_no_new_scope
%type <interm.nodePair> selection_rest_statement for_rest_statement
+%type <interm.intermSwitch> switch_statement
+%type <interm.intermCase> case_label
%type <interm.intermNode> iteration_statement jump_statement statement_no_new_scope statement_with_scope
%type <interm> single_declaration init_declarator_list
@@ -269,28 +273,14 @@ postfix_expression
| function_call {
$$ = $1;
}
- | postfix_expression DOT identifier {
+ | postfix_expression DOT FIELD_SELECTION {
$$ = context->addFieldSelectionExpression($1, @2, *$3.string, @3);
}
| postfix_expression INC_OP {
- if (context->lValueErrorCheck(@2, "++", $1))
- context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPostIncrement, $1, @2);
- if ($$ == 0) {
- context->unaryOpError(@2, "++", $1->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addUnaryMathLValue(EOpPostIncrement, $1, @2);
}
| postfix_expression DEC_OP {
- if (context->lValueErrorCheck(@2, "--", $1))
- context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPostDecrement, $1, @2);
- if ($$ == 0) {
- context->unaryOpError(@2, "--", $1->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addUnaryMathLValue(EOpPostDecrement, $1, @2);
}
;
@@ -304,118 +294,12 @@ integer_expression
function_call
: function_call_or_method {
- TFunction* fnCall = $1.function;
- TOperator op = fnCall->getBuiltInOp();
-
- if (op != EOpNull)
+ bool fatalError = false;
+ $$ = context->addFunctionCallOrMethod($1.function, $1.intermNode, @1, &fatalError);
+ if (fatalError)
{
- //
- // Then this should be a constructor.
- // Don't go through the symbol table for constructors.
- // Their parameters will be verified algorithmically.
- //
- TType type(EbtVoid, EbpUndefined); // use this to get the type back
- if (context->constructorErrorCheck(@1, $1.intermNode, *fnCall, op, &type)) {
- $$ = 0;
- } else {
- //
- // It's a constructor, of type 'type'.
- //
- $$ = context->addConstructor($1.intermNode, &type, op, fnCall, @1);
- }
-
- if ($$ == 0) {
- context->recover();
- $$ = context->intermediate.setAggregateOperator(0, op, @1);
- }
- $$->setType(type);
- } else {
- //
- // Not a constructor. Find it in the symbol table.
- //
- const TFunction* fnCandidate;
- bool builtIn;
- fnCandidate = context->findFunction(@1, fnCall, context->shaderVersion, &builtIn);
- if (fnCandidate) {
- //
- // A declared function.
- //
- if (builtIn && !fnCandidate->getExtension().empty() &&
- context->extensionErrorCheck(@1, fnCandidate->getExtension())) {
- context->recover();
- }
- op = fnCandidate->getBuiltInOp();
- if (builtIn && op != EOpNull) {
- //
- // A function call mapped to a built-in operation.
- //
- if (fnCandidate->getParamCount() == 1) {
- //
- // Treat it like a built-in unary operator.
- //
- $$ = context->intermediate.addUnaryMath(op, $1.intermNode, @1);
- const TType& returnType = fnCandidate->getReturnType();
- if (returnType.getBasicType() == EbtBool) {
- // Bool types should not have precision, so we'll override any precision
- // that might have been set by addUnaryMath.
- $$->setType(returnType);
- } else {
- // addUnaryMath has set the precision of the node based on the operand.
- $$->setTypePreservePrecision(returnType);
- }
- if ($$ == 0) {
- std::stringstream extraInfoStream;
- extraInfoStream << "built in unary operator function. Type: " << static_cast<TIntermTyped*>($1.intermNode)->getCompleteString();
- std::string extraInfo = extraInfoStream.str();
- context->error($1.intermNode->getLine(), " wrong operand type", "Internal Error", extraInfo.c_str());
- YYERROR;
- }
- } else {
- TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, op, @1);
- aggregate->setType(fnCandidate->getReturnType());
- aggregate->setPrecisionFromChildren();
- $$ = aggregate;
- }
- } else {
- // This is a real function call
-
- TIntermAggregate *aggregate = context->intermediate.setAggregateOperator($1.intermAggregate, EOpFunctionCall, @1);
- aggregate->setType(fnCandidate->getReturnType());
-
- // this is how we know whether the given function is a builtIn function or a user defined function
- // if builtIn == false, it's a userDefined -> could be an overloaded builtIn function also
- // if builtIn == true, it's definitely a builtIn function with EOpNull
- if (!builtIn)
- aggregate->setUserDefined();
- aggregate->setName(fnCandidate->getMangledName());
-
- // This needs to happen after the name is set
- if (builtIn)
- aggregate->setBuiltInFunctionPrecision();
-
- $$ = aggregate;
-
- TQualifier qual;
- for (size_t i = 0; i < fnCandidate->getParamCount(); ++i) {
- qual = fnCandidate->getParam(i).type->getQualifier();
- if (qual == EvqOut || qual == EvqInOut) {
- if (context->lValueErrorCheck($$->getLine(), "assign", (*($$->getAsAggregate()->getSequence()))[i]->getAsTyped())) {
- context->error($1.intermNode->getLine(), "Constant value cannot be passed for 'out' or 'inout' parameters.", "Error");
- context->recover();
- }
- }
- }
- }
- } else {
- // error message was put out by PaFindFunction()
- // Put on a dummy node for error recovery
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setFConst(0.0f);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtFloat, EbpUndefined, EvqConst), @1);
- context->recover();
- }
+ YYERROR;
}
- delete fnCall;
}
;
@@ -484,6 +368,13 @@ function_identifier
TFunction *function = new TFunction($1.string, type);
$$ = function;
}
+ | FIELD_SELECTION {
+ if (context->reservedErrorCheck(@1, *$1.string))
+ context->recover();
+ TType type(EbtVoid, EbpUndefined);
+ TFunction *function = new TFunction($1.string, type);
+ $$ = function;
+ }
;
unary_expression
@@ -491,40 +382,14 @@ unary_expression
$$ = $1;
}
| INC_OP unary_expression {
- if (context->lValueErrorCheck(@1, "++", $2))
- context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPreIncrement, $2, @1);
- if ($$ == 0) {
- context->unaryOpError(@1, "++", $2->getCompleteString());
- context->recover();
- $$ = $2;
- }
+ $$ = context->addUnaryMathLValue(EOpPreIncrement, $2, @1);
}
| DEC_OP unary_expression {
- if (context->lValueErrorCheck(@1, "--", $2))
- context->recover();
- $$ = context->intermediate.addUnaryMath(EOpPreDecrement, $2, @1);
- if ($$ == 0) {
- context->unaryOpError(@1, "--", $2->getCompleteString());
- context->recover();
- $$ = $2;
- }
+ $$ = context->addUnaryMathLValue(EOpPreDecrement, $2, @1);
}
| unary_operator unary_expression {
if ($1.op != EOpNull) {
- $$ = context->intermediate.addUnaryMath($1.op, $2, @1);
- if ($$ == 0) {
- const char* errorOp = "";
- switch($1.op) {
- case EOpNegative: errorOp = "-"; break;
- case EOpPositive: errorOp = "+"; break;
- case EOpLogicalNot: errorOp = "!"; break;
- default: break;
- }
- context->unaryOpError(@1, errorOp, $2->getCompleteString());
- context->recover();
- $$ = $2;
- }
+ $$ = context->addUnaryMath($1.op, $2, @1);
} else
$$ = $2;
}
@@ -535,172 +400,117 @@ unary_operator
: PLUS { $$.op = EOpPositive; }
| DASH { $$.op = EOpNegative; }
| BANG { $$.op = EOpLogicalNot; }
+ | TILDE {
+ ES3_ONLY("~", @$, "bit-wise operator");
+ $$.op = EOpBitwiseNot;
+ }
;
// Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
multiplicative_expression
: unary_expression { $$ = $1; }
| multiplicative_expression STAR unary_expression {
- $$ = context->intermediate.addBinaryMath(EOpMul, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "*", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addBinaryMath(EOpMul, $1, $3, @2);
}
| multiplicative_expression SLASH unary_expression {
- $$ = context->intermediate.addBinaryMath(EOpDiv, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "/", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addBinaryMath(EOpDiv, $1, $3, @2);
+ }
+ | multiplicative_expression PERCENT unary_expression {
+ ES3_ONLY("%", @2, "integer modulus operator");
+ $$ = context->addBinaryMath(EOpIMod, $1, $3, @2);
}
;
additive_expression
: multiplicative_expression { $$ = $1; }
| additive_expression PLUS multiplicative_expression {
- $$ = context->intermediate.addBinaryMath(EOpAdd, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "+", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addBinaryMath(EOpAdd, $1, $3, @2);
}
| additive_expression DASH multiplicative_expression {
- $$ = context->intermediate.addBinaryMath(EOpSub, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "-", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addBinaryMath(EOpSub, $1, $3, @2);
}
;
shift_expression
: additive_expression { $$ = $1; }
+ | shift_expression LEFT_OP additive_expression {
+ ES3_ONLY("<<", @2, "bit-wise operator");
+ $$ = context->addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
+ }
+ | shift_expression RIGHT_OP additive_expression {
+ ES3_ONLY(">>", @2, "bit-wise operator");
+ $$ = context->addBinaryMath(EOpBitShiftRight, $1, $3, @2);
+ }
;
relational_expression
: shift_expression { $$ = $1; }
| relational_expression LEFT_ANGLE shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpLessThan, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "<", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpLessThan, $1, $3, @2);
}
| relational_expression RIGHT_ANGLE shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpGreaterThan, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, ">", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpGreaterThan, $1, $3, @2);
}
| relational_expression LE_OP shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpLessThanEqual, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "<=", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpLessThanEqual, $1, $3, @2);
}
| relational_expression GE_OP shift_expression {
- $$ = context->intermediate.addBinaryMath(EOpGreaterThanEqual, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, ">=", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpGreaterThanEqual, $1, $3, @2);
}
;
equality_expression
: relational_expression { $$ = $1; }
| equality_expression EQ_OP relational_expression {
- $$ = context->intermediate.addBinaryMath(EOpEqual, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "==", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpEqual, $1, $3, @2);
}
| equality_expression NE_OP relational_expression {
- $$ = context->intermediate.addBinaryMath(EOpNotEqual, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "!=", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpNotEqual, $1, $3, @2);
}
;
and_expression
: equality_expression { $$ = $1; }
+ | and_expression AMPERSAND equality_expression {
+ ES3_ONLY("&", @2, "bit-wise operator");
+ $$ = context->addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
+ }
;
exclusive_or_expression
: and_expression { $$ = $1; }
+ | exclusive_or_expression CARET and_expression {
+ ES3_ONLY("^", @2, "bit-wise operator");
+ $$ = context->addBinaryMath(EOpBitwiseXor, $1, $3, @2);
+ }
;
inclusive_or_expression
: exclusive_or_expression { $$ = $1; }
+ | inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
+ ES3_ONLY("|", @2, "bit-wise operator");
+ $$ = context->addBinaryMath(EOpBitwiseOr, $1, $3, @2);
+ }
;
logical_and_expression
: inclusive_or_expression { $$ = $1; }
| logical_and_expression AND_OP inclusive_or_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalAnd, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "&&", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpLogicalAnd, $1, $3, @2);
}
;
logical_xor_expression
: logical_and_expression { $$ = $1; }
| logical_xor_expression XOR_OP logical_and_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalXor, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "^^", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpLogicalXor, $1, $3, @2);
}
;
logical_or_expression
: logical_xor_expression { $$ = $1; }
| logical_or_expression OR_OP logical_xor_expression {
- $$ = context->intermediate.addBinaryMath(EOpLogicalOr, $1, $3, @2);
- if ($$ == 0) {
- context->binaryOpError(@2, "||", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- ConstantUnion *unionArray = new ConstantUnion[1];
- unionArray->setBConst(false);
- $$ = context->intermediate.addConstantUnion(unionArray, TType(EbtBool, EbpUndefined, EvqConst), @2);
- }
+ $$ = context->addBinaryMathBooleanResult(EOpLogicalOr, $1, $3, @2);
}
;
@@ -727,12 +537,7 @@ assignment_expression
| unary_expression assignment_operator assignment_expression {
if (context->lValueErrorCheck(@2, "assign", $1))
context->recover();
- $$ = context->intermediate.addAssign($2.op, $1, $3, @2);
- if ($$ == 0) {
- context->assignError(@2, "assign", $1->getCompleteString(), $3->getCompleteString());
- context->recover();
- $$ = $1;
- }
+ $$ = context->addAssign($2.op, $1, $3, @2);
}
;
@@ -740,8 +545,32 @@ assignment_operator
: EQUAL { $$.op = EOpAssign; }
| MUL_ASSIGN { $$.op = EOpMulAssign; }
| DIV_ASSIGN { $$.op = EOpDivAssign; }
+ | MOD_ASSIGN {
+ ES3_ONLY("%=", @$, "integer modulus operator");
+ $$.op = EOpIModAssign;
+ }
| ADD_ASSIGN { $$.op = EOpAddAssign; }
| SUB_ASSIGN { $$.op = EOpSubAssign; }
+ | LEFT_ASSIGN {
+ ES3_ONLY("<<=", @$, "bit-wise operator");
+ $$.op = EOpBitShiftLeftAssign;
+ }
+ | RIGHT_ASSIGN {
+ ES3_ONLY(">>=", @$, "bit-wise operator");
+ $$.op = EOpBitShiftRightAssign;
+ }
+ | AND_ASSIGN {
+ ES3_ONLY("&=", @$, "bit-wise operator");
+ $$.op = EOpBitwiseAndAssign;
+ }
+ | XOR_ASSIGN {
+ ES3_ONLY("^=", @$, "bit-wise operator");
+ $$.op = EOpBitwiseXorAssign;
+ }
+ | OR_ASSIGN {
+ ES3_ONLY("|=", @$, "bit-wise operator");
+ $$.op = EOpBitwiseOrAssign;
+ }
;
expression
@@ -877,7 +706,7 @@ function_prototype
{
// Insert the unmangled name to detect potential future redefinition as a variable.
TFunction *function = new TFunction(NewPoolTString($1->getName().c_str()), $1->getReturnType());
- context->symbolTable.getOuterLevel()->insert(function);
+ context->symbolTable.getOuterLevel()->insertUnmangled(function);
}
//
@@ -1599,12 +1428,14 @@ statement
| simple_statement { $$ = $1; }
;
-// Grammar Note: No labeled statements; 'goto' is not supported.
+// Grammar Note: Labeled statements for SWITCH only; 'goto' is not supported.
simple_statement
: declaration_statement { $$ = $1; }
| expression_statement { $$ = $1; }
| selection_statement { $$ = $1; }
+ | switch_statement { $$ = $1; }
+ | case_label { $$ = $1; }
| iteration_statement { $$ = $1; }
| jump_statement { $$ = $1; }
;
@@ -1677,7 +1508,21 @@ selection_rest_statement
}
;
-// Grammar Note: No 'switch'. Switch statements not supported.
+switch_statement
+ : SWITCH LEFT_PAREN expression RIGHT_PAREN { ++context->mSwitchNestingLevel; } compound_statement {
+ $$ = context->addSwitch($3, $6, @1);
+ --context->mSwitchNestingLevel;
+ }
+ ;
+
+case_label
+ : CASE constant_expression COLON {
+ $$ = context->addCase($2, @1);
+ }
+ | DEFAULT COLON {
+ $$ = context->addDefault(@1);
+ }
+ ;
condition
// In 1996 c++ draft, conditions can include single declarations
@@ -1703,22 +1548,22 @@ condition
;
iteration_statement
- : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
+ : WHILE LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } condition RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
$$ = context->intermediate.addLoop(ELoopWhile, 0, $4, 0, $6, @1);
- --context->loopNestingLevel;
+ --context->mLoopNestingLevel;
}
- | DO { ++context->loopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
+ | DO { ++context->mLoopNestingLevel; } statement_with_scope WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON {
if (context->boolErrorCheck(@8, $6))
context->recover();
$$ = context->intermediate.addLoop(ELoopDoWhile, 0, $6, 0, $3, @4);
- --context->loopNestingLevel;
+ --context->mLoopNestingLevel;
}
- | FOR LEFT_PAREN { context->symbolTable.push(); ++context->loopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
+ | FOR LEFT_PAREN { context->symbolTable.push(); ++context->mLoopNestingLevel; } for_init_statement for_rest_statement RIGHT_PAREN statement_no_new_scope {
context->symbolTable.pop();
$$ = context->intermediate.addLoop(ELoopFor, $4, reinterpret_cast<TIntermTyped*>($5.node1), reinterpret_cast<TIntermTyped*>($5.node2), $7, @1);
- --context->loopNestingLevel;
+ --context->mLoopNestingLevel;
}
;
@@ -1753,40 +1598,20 @@ for_rest_statement
jump_statement
: CONTINUE SEMICOLON {
- if (context->loopNestingLevel <= 0) {
- context->error(@1, "continue statement only allowed in loops", "");
- context->recover();
- }
- $$ = context->intermediate.addBranch(EOpContinue, @1);
+ $$ = context->addBranch(EOpContinue, @1);
}
| BREAK SEMICOLON {
- if (context->loopNestingLevel <= 0) {
- context->error(@1, "break statement only allowed in loops", "");
- context->recover();
- }
- $$ = context->intermediate.addBranch(EOpBreak, @1);
+ $$ = context->addBranch(EOpBreak, @1);
}
| RETURN SEMICOLON {
- $$ = context->intermediate.addBranch(EOpReturn, @1);
- if (context->currentFunctionType->getBasicType() != EbtVoid) {
- context->error(@1, "non-void function must return a value", "return");
- context->recover();
- }
+ $$ = context->addBranch(EOpReturn, @1);
}
| RETURN expression SEMICOLON {
- $$ = context->intermediate.addBranch(EOpReturn, $2, @1);
- context->functionReturnsValue = true;
- if (context->currentFunctionType->getBasicType() == EbtVoid) {
- context->error(@1, "void function cannot return a value", "return");
- context->recover();
- } else if (*(context->currentFunctionType) != $2->getType()) {
- context->error(@1, "function return is not matching type:", "return");
- context->recover();
- }
+ $$ = context->addBranch(EOpReturn, $2, @1);
}
| DISCARD SEMICOLON {
FRAG_ONLY("discard", @1);
- $$ = context->intermediate.addBranch(EOpKill, @1);
+ $$ = context->addBranch(EOpKill, @1);
}
;
@@ -1857,7 +1682,7 @@ function_definition
// Remember the return type for later checking for RETURN statements.
//
context->currentFunctionType = &(prevDec->getReturnType());
- context->functionReturnsValue = false;
+ context->mFunctionReturnsValue = false;
//
// Insert parameters into the symbol table.
@@ -1896,12 +1721,12 @@ function_definition
}
context->intermediate.setAggregateOperator(paramNodes, EOpParameters, @1);
$1.intermAggregate = paramNodes;
- context->loopNestingLevel = 0;
+ context->mLoopNestingLevel = 0;
}
compound_statement_no_new_scope {
//?? Check that all paths return a value if return type != void ?
// May be best done as post process phase on intermediate code
- if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->functionReturnsValue) {
+ if (context->currentFunctionType->getBasicType() != EbtVoid && ! context->mFunctionReturnsValue) {
context->error(@1, "function does not return a value:", "", $1.function->getName().c_str());
context->recover();
}
@@ -1923,5 +1748,5 @@ function_definition
%%
int glslang_parse(TParseContext* context) {
- return yyparse(context);
+ return yyparse(context, context->scanner);
}
diff --git a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
index 00780f0454..07c50f0ce5 100644
--- a/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/intermOut.cpp
@@ -131,6 +131,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
case EOpDivAssign:
out << "divide second child into first child";
break;
+ case EOpIModAssign:
+ out << "modulo second child into first child";
+ break;
+ case EOpBitShiftLeftAssign:
+ out << "bit-wise shift first child left by second child";
+ break;
+ case EOpBitShiftRightAssign:
+ out << "bit-wise shift first child right by second child";
+ break;
+ case EOpBitwiseAndAssign:
+ out << "bit-wise and second child into first child";
+ break;
+ case EOpBitwiseXorAssign:
+ out << "bit-wise xor second child into first child";
+ break;
+ case EOpBitwiseOrAssign:
+ out << "bit-wise or second child into first child";
+ break;
+
case EOpIndexDirect:
out << "direct index";
break;
@@ -159,6 +178,25 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
case EOpDiv:
out << "divide";
break;
+ case EOpIMod:
+ out << "modulo";
+ break;
+ case EOpBitShiftLeft:
+ out << "bit-wise shift left";
+ break;
+ case EOpBitShiftRight:
+ out << "bit-wise shift right";
+ break;
+ case EOpBitwiseAnd:
+ out << "bit-wise and";
+ break;
+ case EOpBitwiseXor:
+ out << "bit-wise xor";
+ break;
+ case EOpBitwiseOr:
+ out << "bit-wise or";
+ break;
+
case EOpEqual:
out << "Compare Equal";
break;
@@ -211,6 +249,36 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
out << "\n";
+ // Special handling for direct indexes. Because constant
+ // unions are not aware they are struct indexes, treat them
+ // here where we have that contextual knowledge.
+ if (node->getOp() == EOpIndexDirectStruct ||
+ node->getOp() == EOpIndexDirectInterfaceBlock)
+ {
+ mDepth++;
+ node->getLeft()->traverse(this);
+ mDepth--;
+
+ TIntermConstantUnion *intermConstantUnion = node->getRight()->getAsConstantUnion();
+ ASSERT(intermConstantUnion);
+
+ OutputTreeText(out, intermConstantUnion, mDepth + 1);
+
+ // The following code finds the field name from the constant union
+ const ConstantUnion *constantUnion = intermConstantUnion->getUnionArrayPointer();
+ const TStructure *structure = node->getLeft()->getType().getStruct();
+ const TInterfaceBlock *interfaceBlock = node->getLeft()->getType().getInterfaceBlock();
+ ASSERT(structure || interfaceBlock);
+
+ const TFieldList &fields = structure ? structure->fields() : interfaceBlock->fields();
+
+ const TField *field = fields[constantUnion->getIConst()];
+
+ out << constantUnion->getIConst() << " (field '" << field->name() << "')";
+
+ return false;
+ }
+
return true;
}
@@ -226,6 +294,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: out << "Positive sign"; break;
case EOpVectorLogicalNot:
case EOpLogicalNot: out << "Negate conditional"; break;
+ case EOpBitwiseNot: out << "bit-wise not"; break;
case EOpPostIncrement: out << "Post-Increment"; break;
case EOpPostDecrement: out << "Post-Decrement"; break;
@@ -241,6 +310,13 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpAcos: out << "arc cosine"; break;
case EOpAtan: out << "arc tangent"; break;
+ case EOpSinh: out << "hyperbolic sine"; break;
+ case EOpCosh: out << "hyperbolic cosine"; break;
+ case EOpTanh: out << "hyperbolic tangent"; break;
+ case EOpAsinh: out << "arc hyperbolic sine"; break;
+ case EOpAcosh: out << "arc hyperbolic cosine"; break;
+ case EOpAtanh: out << "arc hyperbolic tangent"; break;
+
case EOpExp: out << "exp"; break;
case EOpLog: out << "log"; break;
case EOpExp2: out << "exp2"; break;
@@ -251,8 +327,26 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpAbs: out << "Absolute value"; break;
case EOpSign: out << "Sign"; break;
case EOpFloor: out << "Floor"; break;
+ case EOpTrunc: out << "Truncate"; break;
+ case EOpRound: out << "Round"; break;
+ case EOpRoundEven: out << "Round half even"; break;
case EOpCeil: out << "Ceiling"; break;
case EOpFract: out << "Fraction"; break;
+ case EOpIsNan: out << "Is not a number"; break;
+ case EOpIsInf: out << "Is infinity"; break;
+
+ case EOpFloatBitsToInt: out << "float bits to int"; break;
+ case EOpFloatBitsToUint: out << "float bits to uint"; break;
+ case EOpIntBitsToFloat: out << "int bits to float"; break;
+ case EOpUintBitsToFloat: out << "uint bits to float"; break;
+
+ case EOpPackSnorm2x16: out << "pack Snorm 2x16"; break;
+ case EOpPackUnorm2x16: out << "pack Unorm 2x16"; break;
+ case EOpPackHalf2x16: out << "pack half 2x16"; break;
+
+ case EOpUnpackSnorm2x16: out << "unpack Snorm 2x16"; break;
+ case EOpUnpackUnorm2x16: out << "unpack Unorm 2x16"; break;
+ case EOpUnpackHalf2x16: out << "unpack half 2x16"; break;
case EOpLength: out << "length"; break;
case EOpNormalize: out << "normalize"; break;
@@ -260,6 +354,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
// case EOpDPdy: out << "dPdy"; break;
// case EOpFwidth: out << "fwidth"; break;
+ case EOpDeterminant: out << "determinant"; break;
+ case EOpTranspose: out << "transpose"; break;
+ case EOpInverse: out << "inverse"; break;
+
case EOpAny: out << "any"; break;
case EOpAll: out << "all"; break;
@@ -326,6 +424,7 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpVectorNotEqual: out << "NotEqual"; break;
case EOpMod: out << "mod"; break;
+ case EOpModf: out << "modf"; break;
case EOpPow: out << "pow"; break;
case EOpAtan: out << "arc tangent"; break;
@@ -345,6 +444,8 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpRefract: out << "refract"; break;
case EOpMul: out << "component-wise multiply"; break;
+ case EOpOuterProduct: out << "outer product"; break;
+
case EOpDeclaration: out << "Declaration: "; break;
case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
@@ -518,14 +619,13 @@ bool TOutputTraverser::visitBranch(Visit visit, TIntermBranch *node)
//
// This function is the one to call externally to start the traversal.
// Individual functions can be initialized to 0 to skip processing of that
-// type of node. It's children will still be processed.
+// type of node. Its children will still be processed.
//
-void TIntermediate::outputTree(TIntermNode *root)
+void TIntermediate::outputTree(TIntermNode *root, TInfoSinkBase &infoSink)
{
- if (root == NULL)
- return;
+ TOutputTraverser it(infoSink);
- TOutputTraverser it(mInfoSink.info);
+ ASSERT(root);
root->traverse(&it);
}
diff --git a/src/3rdparty/angle/src/compiler/translator/length_limits.h b/src/3rdparty/angle/src/compiler/translator/length_limits.h
index df70ee5d84..88634381fa 100644
--- a/src/3rdparty/angle/src/compiler/translator/length_limits.h
+++ b/src/3rdparty/angle/src/compiler/translator/length_limits.h
@@ -8,8 +8,8 @@
// length_limits.h
//
-#if !defined(__LENGTH_LIMITS_H)
-#define __LENGTH_LIMITS_H 1
+#ifndef COMPILER_TRANSLATOR_LENGTHLIMITS_H_
+#define COMPILER_TRANSLATOR_LENGTHLIMITS_H_
#include "GLSLANG/ShaderLang.h"
@@ -18,4 +18,4 @@
size_t GetGlobalMaxTokenSize(ShShaderSpec spec);
-#endif // !(defined(__LENGTH_LIMITS_H)
+#endif // COMPILER_TRANSLATOR_LENGTHLIMITS_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
index 80d5f7fa7f..b8c7e82956 100644
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
+++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictFragmentShaderTiming.h
@@ -4,35 +4,36 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
-#define COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
+#define COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/depgraph/DependencyGraph.h"
class TInfoSinkBase;
-class RestrictFragmentShaderTiming : TDependencyGraphTraverser {
-public:
- RestrictFragmentShaderTiming(TInfoSinkBase& sink);
- void enforceRestrictions(const TDependencyGraph& graph);
+class RestrictFragmentShaderTiming : TDependencyGraphTraverser
+{
+ public:
+ RestrictFragmentShaderTiming(TInfoSinkBase &sink);
+ void enforceRestrictions(const TDependencyGraph &graph);
int numErrors() const { return mNumErrors; }
- virtual void visitArgument(TGraphArgument* parameter);
- virtual void visitSelection(TGraphSelection* selection);
- virtual void visitLoop(TGraphLoop* loop);
- virtual void visitLogicalOp(TGraphLogicalOp* logicalOp);
+ void visitArgument(TGraphArgument *parameter) override;
+ void visitSelection(TGraphSelection *selection) override;
+ void visitLoop(TGraphLoop *loop) override;
+ void visitLogicalOp(TGraphLogicalOp *logicalOp) override;
-private:
- void beginError(const TIntermNode* node);
- void validateUserDefinedFunctionCallUsage(const TDependencyGraph& graph);
- bool isSamplingOp(const TIntermAggregate* intermFunctionCall) const;
+ private:
+ void beginError(const TIntermNode *node);
+ void validateUserDefinedFunctionCallUsage(const TDependencyGraph &graph);
+ bool isSamplingOp(const TIntermAggregate *intermFunctionCall) const;
- TInfoSinkBase& mSink;
+ TInfoSinkBase &mSink;
int mNumErrors;
typedef std::set<TString> StringSet;
StringSet mSamplingOps;
};
-#endif // COMPILER_TIMING_RESTRICT_FRAGMENT_SHADER_TIMING_H_
+#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTFRAGMENTSHADERTIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h
index a6263567b4..74bfd0b5c2 100644
--- a/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h
+++ b/src/3rdparty/angle/src/compiler/translator/timing/RestrictVertexShaderTiming.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
-#define COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+#ifndef COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
+#define COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/InfoSink.h"
@@ -28,4 +28,4 @@ private:
int mNumErrors;
};
-#endif // COMPILER_TIMING_RESTRICT_VERTEX_SHADER_TIMING_H_
+#endif // COMPILER_TRANSLATOR_TIMING_RESTRICTVERTEXSHADERTIMING_H_
diff --git a/src/3rdparty/angle/src/compiler/translator/util.cpp b/src/3rdparty/angle/src/compiler/translator/util.cpp
index 8cc06a658a..42a995ee6f 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/util.cpp
@@ -307,7 +307,7 @@ void GetVariableTraverser::setTypeSpecificInfo(
break;
case EvqVaryingIn:
case EvqVaryingOut:
- if (mSymbolTable.isVaryingInvariant(name))
+ if (mSymbolTable.isVaryingInvariant(std::string(name.c_str())))
{
variable->isInvariant = true;
}
diff --git a/src/3rdparty/angle/src/compiler/translator/util.h b/src/3rdparty/angle/src/compiler/translator/util.h
index fb5308759e..68bae66168 100644
--- a/src/3rdparty/angle/src/compiler/translator/util.h
+++ b/src/3rdparty/angle/src/compiler/translator/util.h
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#ifndef COMPILER_UTIL_H
-#define COMPILER_UTIL_H
+#ifndef COMPILER_TRANSLATOR_UTIL_H_
+#define COMPILER_TRANSLATOR_UTIL_H_
#include <stack>
@@ -37,7 +37,7 @@ bool IsVarying(TQualifier qualifier);
InterpolationType GetInterpolationType(TQualifier qualifier);
TString ArrayString(const TType &type);
-class GetVariableTraverser
+class GetVariableTraverser : angle::NonCopyable
{
public:
GetVariableTraverser(const TSymbolTable &symbolTable);
@@ -57,10 +57,8 @@ class GetVariableTraverser
const TType &type, const TString &name, VarT *variable) {}
const TSymbolTable &mSymbolTable;
-
- DISALLOW_COPY_AND_ASSIGN(GetVariableTraverser);
};
}
-#endif // COMPILER_UTIL_H
+#endif // COMPILER_TRANSLATOR_UTIL_H_
diff --git a/src/3rdparty/angle/src/id/commit.h b/src/3rdparty/angle/src/id/commit.h
new file mode 100644
index 0000000000..fd9a011d0c
--- /dev/null
+++ b/src/3rdparty/angle/src/id/commit.h
@@ -0,0 +1,3 @@
+#define ANGLE_COMMIT_HASH "99f075dade7c"
+#define ANGLE_COMMIT_HASH_SIZE 12
+#define ANGLE_COMMIT_DATE "2015-04-02 17:07:24 +0000"
diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp
index 28dd3d842e..651a012037 100644
--- a/src/3rdparty/angle/src/libEGL/AttributeMap.cpp
+++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "libEGL/AttributeMap.h"
+#include "libANGLE/AttributeMap.h"
namespace egl
{
@@ -15,9 +15,12 @@ AttributeMap::AttributeMap()
AttributeMap::AttributeMap(const EGLint *attributes)
{
- for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ if (attributes)
{
- insert(curAttrib[0], curAttrib[1]);
+ for (const EGLint *curAttrib = attributes; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ insert(curAttrib[0], curAttrib[1]);
+ }
}
}
@@ -37,4 +40,14 @@ EGLint AttributeMap::get(EGLint key, EGLint defaultValue) const
return (mAttributes.find(key) != mAttributes.end()) ? iter->second : defaultValue;
}
+AttributeMap::const_iterator AttributeMap::begin() const
+{
+ return mAttributes.begin();
+}
+
+AttributeMap::const_iterator AttributeMap::end() const
+{
+ return mAttributes.end();
+}
+
}
diff --git a/src/3rdparty/angle/src/libEGL/AttributeMap.h b/src/3rdparty/angle/src/libANGLE/AttributeMap.h
index f2f082fe21..72b6edc3c7 100644
--- a/src/3rdparty/angle/src/libEGL/AttributeMap.h
+++ b/src/3rdparty/angle/src/libANGLE/AttributeMap.h
@@ -4,8 +4,9 @@
// found in the LICENSE file.
//
-#ifndef LIBEGL_ATTRIBUTEMAP_H_
-#define LIBEGL_ATTRIBUTEMAP_H_
+#ifndef LIBANGLE_ATTRIBUTEMAP_H_
+#define LIBANGLE_ATTRIBUTEMAP_H_
+
#include <EGL/egl.h>
@@ -24,10 +25,15 @@ class AttributeMap
virtual bool contains(EGLint key) const;
virtual EGLint get(EGLint key, EGLint defaultValue) const;
+ typedef std::map<EGLint, EGLint>::const_iterator const_iterator;
+
+ const_iterator begin() const;
+ const_iterator end() const;
+
private:
std::map<EGLint, EGLint> mAttributes;
};
}
-#endif // LIBEGL_ATTRIBUTEMAP_H_
+#endif // LIBANGLE_ATTRIBUTEMAP_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h b/src/3rdparty/angle/src/libANGLE/BinaryStream.h
index 4f7f5f2c85..50392e1d3f 100644
--- a/src/3rdparty/angle/src/libGLESv2/BinaryStream.h
+++ b/src/3rdparty/angle/src/libANGLE/BinaryStream.h
@@ -6,8 +6,8 @@
// BinaryStream.h: Provides binary serialization of simple types.
-#ifndef LIBGLESV2_BINARYSTREAM_H_
-#define LIBGLESV2_BINARYSTREAM_H_
+#ifndef LIBANGLE_BINARYSTREAM_H_
+#define LIBANGLE_BINARYSTREAM_H_
#include "common/angleutils.h"
#include "common/mathutil.h"
@@ -17,10 +17,22 @@
#include <vector>
#include <stdint.h>
+template <typename T>
+void StaticAssertIsFundamental()
+{
+ // c++11 STL is not available on OSX or Android
+#if !defined(ANGLE_PLATFORM_APPLE) && !defined(ANGLE_PLATFORM_ANDROID)
+ static_assert(std::is_fundamental<T>::value, "T must be a fundamental type.");
+#else
+ union { T dummy; } dummy;
+ static_cast<void>(dummy);
+#endif
+}
+
namespace gl
{
-class BinaryInputStream
+class BinaryInputStream : angle::NonCopyable
{
public:
BinaryInputStream(const void *data, size_t length)
@@ -122,7 +134,6 @@ class BinaryInputStream
}
private:
- DISALLOW_COPY_AND_ASSIGN(BinaryInputStream);
bool mError;
size_t mOffset;
const uint8_t *mData;
@@ -131,7 +142,7 @@ class BinaryInputStream
template <typename T>
void read(T *v, size_t num)
{
- META_ASSERT(std::is_fundamental<T>::value);
+ StaticAssertIsFundamental<T>();
size_t length = num * sizeof(T);
@@ -153,7 +164,7 @@ class BinaryInputStream
};
-class BinaryOutputStream
+class BinaryOutputStream : angle::NonCopyable
{
public:
BinaryOutputStream()
@@ -191,13 +202,12 @@ class BinaryOutputStream
}
private:
- DISALLOW_COPY_AND_ASSIGN(BinaryOutputStream);
std::vector<char> mData;
template <typename T>
void write(const T *v, size_t num)
{
- META_ASSERT(std::is_fundamental<T>::value);
+ StaticAssertIsFundamental<T>();
const char *asBytes = reinterpret_cast<const char*>(v);
mData.insert(mData.end(), asBytes, asBytes + num * sizeof(T));
}
@@ -205,4 +215,4 @@ class BinaryOutputStream
};
}
-#endif // LIBGLESV2_BINARYSTREAM_H_
+#endif // LIBANGLE_BINARYSTREAM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp b/src/3rdparty/angle/src/libANGLE/Buffer.cpp
index 3b2a1a912a..f394a6b1d1 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Buffer.cpp
@@ -8,9 +8,9 @@
// index data. Implements GL buffer objects and related functionality.
// [OpenGL ES 2.0.24] section 2.9 page 21.
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/renderer/BufferImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/Renderer.h"
namespace gl
{
@@ -118,11 +118,4 @@ Error Buffer::unmap()
return error;
}
-void Buffer::markTransformFeedbackUsage()
-{
- // TODO: Only used by the DX11 backend. Refactor to a more appropriate place.
- mBuffer->markTransformFeedbackUsage();
- mIndexRangeCache.clear();
-}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Buffer.h b/src/3rdparty/angle/src/libANGLE/Buffer.h
index daa862ca0d..6793028e3b 100644
--- a/src/3rdparty/angle/src/libGLESv2/Buffer.h
+++ b/src/3rdparty/angle/src/libANGLE/Buffer.h
@@ -8,14 +8,14 @@
// index data. Implements GL buffer objects and related functionality.
// [OpenGL ES 2.0.24] section 2.9 page 21.
-#ifndef LIBGLESV2_BUFFER_H_
-#define LIBGLESV2_BUFFER_H_
+#ifndef LIBANGLE_BUFFER_H_
+#define LIBANGLE_BUFFER_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/renderer/IndexRangeCache.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/renderer/IndexRangeCache.h"
namespace rx
{
@@ -48,14 +48,10 @@ class Buffer : public RefCountObject
rx::BufferImpl *getImplementation() const { return mBuffer; }
- void markTransformFeedbackUsage();
-
rx::IndexRangeCache *getIndexRangeCache() { return &mIndexRangeCache; }
const rx::IndexRangeCache *getIndexRangeCache() const { return &mIndexRangeCache; }
private:
- DISALLOW_COPY_AND_ASSIGN(Buffer);
-
rx::BufferImpl *mBuffer;
GLenum mUsage;
@@ -71,4 +67,4 @@ class Buffer : public RefCountObject
}
-#endif // LIBGLESV2_BUFFER_H_
+#endif // LIBANGLE_BUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.cpp b/src/3rdparty/angle/src/libANGLE/Caps.cpp
index 983800c0e6..086d0a02a2 100644
--- a/src/3rdparty/angle/src/libGLESv2/Caps.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Caps.cpp
@@ -4,7 +4,7 @@
// found in the LICENSE file.
//
-#include "libGLESv2/Caps.h"
+#include "libANGLE/Caps.h"
#include "common/debug.h"
#include "common/angleutils.h"
@@ -13,6 +13,14 @@
#include <algorithm>
#include <sstream>
+static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector)
+{
+ if (supported)
+ {
+ extensionVector->push_back(extension);
+ }
+}
+
namespace gl
{
@@ -119,6 +127,9 @@ Extensions::Extensions()
packReverseRowOrder(false),
standardDerivatives(false),
shaderTextureLOD(false),
+ shaderFramebufferFetch(false),
+ ARMshaderFramebufferFetch(false),
+ NVshaderFramebufferFetch(false),
fragDepth(false),
textureUsage(false),
translatedShaderSource(false),
@@ -126,14 +137,6 @@ Extensions::Extensions()
{
}
-static void InsertExtensionString(const std::string &extension, bool supported, std::vector<std::string> *extensionVector)
-{
- if (supported)
- {
- extensionVector->push_back(extension);
- }
-}
-
std::vector<std::string> Extensions::getStrings() const
{
std::vector<std::string> extensionStrings;
@@ -173,6 +176,9 @@ std::vector<std::string> Extensions::getStrings() const
InsertExtensionString("GL_ANGLE_pack_reverse_row_order", packReverseRowOrder, &extensionStrings);
InsertExtensionString("GL_OES_standard_derivatives", standardDerivatives, &extensionStrings);
InsertExtensionString("GL_EXT_shader_texture_lod", shaderTextureLOD, &extensionStrings);
+ InsertExtensionString("GL_NV_shader_framebuffer_fetch", NVshaderFramebufferFetch, &extensionStrings);
+ InsertExtensionString("GL_ARM_shader_framebuffer_fetch", ARMshaderFramebufferFetch,&extensionStrings);
+ InsertExtensionString("GL_EXT_shader_framebuffer_fetch", shaderFramebufferFetch, &extensionStrings);
InsertExtensionString("GL_EXT_frag_depth", fragDepth, &extensionStrings);
InsertExtensionString("GL_ANGLE_texture_usage", textureUsage, &extensionStrings);
InsertExtensionString("GL_ANGLE_translated_shader_source", translatedShaderSource, &extensionStrings);
@@ -371,6 +377,41 @@ void Extensions::setTextureExtensionSupport(const TextureCapsMap &textureCaps)
colorBufferFloat = DetermineColorBufferFloatSupport(textureCaps);
}
+TypePrecision::TypePrecision()
+{
+ range[0] = 0;
+ range[1] = 0;
+ precision = 0;
+}
+
+void TypePrecision::setIEEEFloat()
+{
+ range[0] = 127;
+ range[1] = 127;
+ precision = 23;
+}
+
+void TypePrecision::setTwosComplementInt(unsigned int bits)
+{
+ range[0] = GLint(bits) - 1;
+ range[1] = GLint(bits) - 2;
+ precision = 0;
+}
+
+void TypePrecision::setSimulatedInt(unsigned int r)
+{
+ range[0] = GLint(r);
+ range[1] = GLint(r);
+ precision = 0;
+}
+
+void TypePrecision::get(GLint *returnRange, GLint *returnPrecision) const
+{
+ returnRange[0] = range[0];
+ returnRange[1] = range[1];
+ *returnPrecision = precision;
+}
+
Caps::Caps()
: maxElementIndex(0),
max3DTextureSize(0),
@@ -423,3 +464,64 @@ Caps::Caps()
}
}
+
+namespace egl
+{
+
+Caps::Caps()
+ : textureNPOT(false)
+{
+}
+
+DisplayExtensions::DisplayExtensions()
+ : createContextRobustness(false),
+ d3dShareHandleClientBuffer(false),
+ surfaceD3DTexture2DShareHandle(false),
+ querySurfacePointer(false),
+ windowFixedSize(false),
+ postSubBuffer(false),
+ createContext(false)
+{
+}
+
+std::vector<std::string> DisplayExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_EXT_create_context_robustness", createContextRobustness, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_d3d_share_handle_client_buffer", d3dShareHandleClientBuffer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_surface_d3d_texture_2d_share_handle", surfaceD3DTexture2DShareHandle, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_query_surface_pointer", querySurfacePointer, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_window_fixed_size", windowFixedSize, &extensionStrings);
+ InsertExtensionString("EGL_NV_post_sub_buffer", postSubBuffer, &extensionStrings);
+ InsertExtensionString("EGL_KHR_create_context", createContext, &extensionStrings);
+
+ return extensionStrings;
+}
+
+
+ClientExtensions::ClientExtensions()
+ : clientExtensions(false),
+ platformBase(false),
+ platformANGLE(false),
+ platformANGLED3D(false),
+ platformANGLEOpenGL(false)
+{
+}
+
+std::vector<std::string> ClientExtensions::getStrings() const
+{
+ std::vector<std::string> extensionStrings;
+
+ // | Extension name | Supported flag | Output vector |
+ InsertExtensionString("EGL_EXT_client_extensions", clientExtensions, &extensionStrings);
+ InsertExtensionString("EGL_EXT_platform_base", platformBase, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle", platformANGLE, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_d3d", platformANGLED3D, &extensionStrings);
+ InsertExtensionString("EGL_ANGLE_platform_angle_opengl", platformANGLEOpenGL, &extensionStrings);
+
+ return extensionStrings;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Caps.h b/src/3rdparty/angle/src/libANGLE/Caps.h
index a00e554176..37a634226a 100644
--- a/src/3rdparty/angle/src/libGLESv2/Caps.h
+++ b/src/3rdparty/angle/src/libANGLE/Caps.h
@@ -1,18 +1,19 @@
-#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.
//
+#ifndef LIBANGLE_CAPS_H_
+#define LIBANGLE_CAPS_H_
+
#include "angle_gl.h"
+#include "libANGLE/angletypes.h"
+#include <map>
#include <set>
-#include <unordered_map>
-#include <vector>
#include <string>
+#include <vector>
namespace gl
{
@@ -45,7 +46,7 @@ struct TextureCaps
class TextureCapsMap
{
public:
- typedef std::unordered_map<GLenum, TextureCaps>::const_iterator const_iterator;
+ typedef std::map<GLenum, TextureCaps>::const_iterator const_iterator;
void insert(GLenum internalFormat, const TextureCaps &caps);
void remove(GLenum internalFormat);
@@ -58,7 +59,7 @@ class TextureCapsMap
size_t size() const;
private:
- typedef std::unordered_map<GLenum, TextureCaps> InternalFormatToCapsMap;
+ typedef std::map<GLenum, TextureCaps> InternalFormatToCapsMap;
InternalFormatToCapsMap mCapsMap;
};
@@ -190,6 +191,15 @@ struct Extensions
// GL_EXT_shader_texture_lod
bool shaderTextureLOD;
+ // GL_EXT_shader_framebuffer_fetch
+ bool shaderFramebufferFetch;
+
+ // GL_ARM_shader_framebuffer_fetch
+ bool ARMshaderFramebufferFetch;
+
+ // GL_NV_shader_framebuffer_fetch
+ bool NVshaderFramebufferFetch;
+
// GL_EXT_frag_depth
bool fragDepth;
@@ -205,6 +215,20 @@ struct Extensions
bool colorBufferFloat;
};
+struct TypePrecision
+{
+ TypePrecision();
+
+ void setIEEEFloat();
+ void setTwosComplementInt(unsigned int bits);
+ void setSimulatedInt(unsigned int range);
+
+ void get(GLint *returnRange, GLint *returnPrecision) const;
+
+ GLint range[2];
+ GLint precision;
+};
+
struct Caps
{
Caps();
@@ -232,6 +256,18 @@ struct Caps
std::vector<GLenum> compressedTextureFormats;
std::vector<GLenum> programBinaryFormats;
std::vector<GLenum> shaderBinaryFormats;
+ TypePrecision vertexHighpFloat;
+ TypePrecision vertexMediumpFloat;
+ TypePrecision vertexLowpFloat;
+ TypePrecision vertexHighpInt;
+ TypePrecision vertexMediumpInt;
+ TypePrecision vertexLowpInt;
+ TypePrecision fragmentHighpFloat;
+ TypePrecision fragmentMediumpFloat;
+ TypePrecision fragmentLowpFloat;
+ TypePrecision fragmentHighpInt;
+ TypePrecision fragmentMediumpInt;
+ TypePrecision fragmentLowpInt;
GLuint64 maxServerWaitTimeout;
// Table 6.31, implementation dependent vertex shader limits
@@ -270,4 +306,69 @@ struct Caps
}
-#endif // LIBGLESV2_CAPS_H
+namespace egl
+{
+
+struct Caps
+{
+ Caps();
+
+ // Support for NPOT surfaces
+ bool textureNPOT;
+};
+
+struct DisplayExtensions
+{
+ DisplayExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_create_context_robustness
+ bool createContextRobustness;
+
+ // EGL_ANGLE_d3d_share_handle_client_buffer
+ bool d3dShareHandleClientBuffer;
+
+ // EGL_ANGLE_surface_d3d_texture_2d_share_handle
+ bool surfaceD3DTexture2DShareHandle;
+
+ // EGL_ANGLE_query_surface_pointer
+ bool querySurfacePointer;
+
+ // EGL_ANGLE_window_fixed_size
+ bool windowFixedSize;
+
+ // EGL_NV_post_sub_buffer
+ bool postSubBuffer;
+
+ // EGL_KHR_create_context
+ bool createContext;
+};
+
+struct ClientExtensions
+{
+ ClientExtensions();
+
+ // Generate a vector of supported extension strings
+ std::vector<std::string> getStrings() const;
+
+ // EGL_EXT_client_extensions
+ bool clientExtensions;
+
+ // EGL_EXT_platform_base
+ bool platformBase;
+
+ // EGL_ANGLE_platform_angle
+ bool platformANGLE;
+
+ // EGL_ANGLE_platform_angle_d3d
+ bool platformANGLED3D;
+
+ // EGL_ANGLE_platform_angle_opengl
+ bool platformANGLEOpenGL;
+};
+
+}
+
+#endif // LIBANGLE_CAPS_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.cpp b/src/3rdparty/angle/src/libANGLE/Compiler.cpp
new file mode 100644
index 0000000000..7d0efea220
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Compiler.cpp
@@ -0,0 +1,38 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.cpp: implements the gl::Compiler class.
+
+#include "libANGLE/Compiler.h"
+#include "libANGLE/renderer/CompilerImpl.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+Compiler::Compiler(rx::CompilerImpl *impl)
+ : mCompiler(impl)
+{
+ ASSERT(mCompiler);
+}
+
+Compiler::~Compiler()
+{
+ SafeDelete(mCompiler);
+}
+
+Error Compiler::release()
+{
+ return mCompiler->release();
+}
+
+rx::CompilerImpl *Compiler::getImplementation()
+{
+ return mCompiler;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Compiler.h b/src/3rdparty/angle/src/libANGLE/Compiler.h
new file mode 100644
index 0000000000..05de15ec97
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Compiler.h
@@ -0,0 +1,39 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Compiler.h: Defines the gl::Compiler class, abstracting the ESSL compiler
+// that a GL context holds.
+
+#ifndef LIBANGLE_COMPILER_H_
+#define LIBANGLE_COMPILER_H_
+
+#include "libANGLE/Error.h"
+
+namespace rx
+{
+class CompilerImpl;
+}
+
+namespace gl
+{
+
+class Compiler final
+{
+ public:
+ explicit Compiler(rx::CompilerImpl *impl);
+ ~Compiler();
+
+ Error release();
+
+ rx::CompilerImpl *getImplementation();
+
+ private:
+ rx::CompilerImpl *mCompiler;
+};
+
+}
+
+#endif // LIBANGLE_COMPILER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Config.cpp b/src/3rdparty/angle/src/libANGLE/Config.cpp
new file mode 100644
index 0000000000..1b1fc50cb3
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Config.cpp
@@ -0,0 +1,275 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.cpp: Implements the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#include "libANGLE/Config.h"
+#include "libANGLE/AttributeMap.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "angle_gl.h"
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+Config::Config()
+ : renderTargetFormat(GL_NONE),
+ depthStencilFormat(GL_NONE),
+ bufferSize(0),
+ redSize(0),
+ greenSize(0),
+ blueSize(0),
+ luminanceSize(0),
+ alphaSize(0),
+ alphaMaskSize(0),
+ bindToTextureRGB(EGL_FALSE),
+ bindToTextureRGBA(EGL_FALSE),
+ colorBufferType(EGL_NONE),
+ configCaveat(EGL_NONE),
+ configID(0),
+ conformant(0),
+ depthSize(0),
+ level(0),
+ matchNativePixmap(EGL_FALSE),
+ maxPBufferWidth(0),
+ maxPBufferHeight(0),
+ maxPBufferPixels(0),
+ maxSwapInterval(0),
+ minSwapInterval(0),
+ nativeRenderable(EGL_FALSE),
+ nativeVisualID(0),
+ nativeVisualType(0),
+ renderableType(0),
+ sampleBuffers(0),
+ samples(0),
+ stencilSize(0),
+ surfaceType(0),
+ transparentType(EGL_NONE),
+ transparentRedValue(0),
+ transparentGreenValue(0),
+ transparentBlueValue(0)
+{
+}
+
+EGLint ConfigSet::add(const Config &config)
+{
+ // Set the config's ID to a small number that starts at 1 ([EGL 1.5] section 3.4)
+ EGLint id = mConfigs.size() + 1;
+
+ Config copyConfig(config);
+ copyConfig.configID = id;
+ mConfigs.insert(std::make_pair(id, copyConfig));
+
+ return id;
+}
+
+const Config &ConfigSet::get(EGLint id) const
+{
+ ASSERT(mConfigs.find(id) != mConfigs.end());
+ return mConfigs.find(id)->second;
+}
+
+void ConfigSet::clear()
+{
+ mConfigs.clear();
+}
+
+size_t ConfigSet::size() const
+{
+ return mConfigs.size();
+}
+
+bool ConfigSet::contains(const Config *config) const
+{
+ for (auto i = mConfigs.begin(); i != mConfigs.end(); i++)
+ {
+ const Config &item = i->second;
+ if (config == &item)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+// Function object used by STL sorting routines for ordering Configs according to [EGL 1.5] section 3.4.1.2 page 28.
+class ConfigSorter
+{
+ public:
+ explicit ConfigSorter(const AttributeMap &attributeMap)
+ : mWantRed(false),
+ mWantGreen(false),
+ mWantBlue(false),
+ mWantAlpha(false),
+ mWantLuminance(false)
+ {
+ scanForWantedComponents(attributeMap);
+ }
+
+ bool operator()(const Config *x, const Config *y) const
+ {
+ return (*this)(*x, *y);
+ }
+
+ bool operator()(const Config &x, const Config &y) const
+ {
+ #define SORT(attribute) \
+ if (x.attribute != y.attribute) \
+ { \
+ return x.attribute < y.attribute; \
+ }
+
+ static_assert(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG, "Unexpected EGL enum value.");
+ SORT(configCaveat);
+
+ static_assert(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER, "Unexpected EGL enum value.");
+ SORT(colorBufferType);
+
+ // By larger total number of color bits, only considering those that are requested to be > 0.
+ EGLint xComponentsSize = wantedComponentsSize(x);
+ EGLint yComponentsSize = wantedComponentsSize(y);
+ if (xComponentsSize != yComponentsSize)
+ {
+ return xComponentsSize > yComponentsSize;
+ }
+
+ SORT(bufferSize);
+ SORT(sampleBuffers);
+ SORT(samples);
+ SORT(depthSize);
+ SORT(stencilSize);
+ SORT(alphaMaskSize);
+ SORT(nativeVisualType);
+ SORT(configID);
+
+ #undef SORT
+
+ return false;
+ }
+
+ private:
+ void scanForWantedComponents(const AttributeMap &attributeMap)
+ {
+ // [EGL 1.5] section 3.4.1.2 page 30
+ // Sorting rule #3: by larger total number of color bits, not considering
+ // components that are 0 or don't-care.
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLint attributeKey = attribIter->first;
+ EGLint attributeValue = attribIter->second;
+ if (attributeKey != 0 && attributeValue != EGL_DONT_CARE)
+ {
+ switch (attributeKey)
+ {
+ case EGL_RED_SIZE: mWantRed = true; break;
+ case EGL_GREEN_SIZE: mWantGreen = true; break;
+ case EGL_BLUE_SIZE: mWantBlue = true; break;
+ case EGL_ALPHA_SIZE: mWantAlpha = true; break;
+ case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
+ }
+ }
+ }
+ }
+
+ EGLint wantedComponentsSize(const Config &config) const
+ {
+ EGLint total = 0;
+
+ if (mWantRed) total += config.redSize;
+ if (mWantGreen) total += config.greenSize;
+ if (mWantBlue) total += config.blueSize;
+ if (mWantAlpha) total += config.alphaSize;
+ if (mWantLuminance) total += config.luminanceSize;
+
+ return total;
+ }
+
+ bool mWantRed;
+ bool mWantGreen;
+ bool mWantBlue;
+ bool mWantAlpha;
+ bool mWantLuminance;
+};
+
+std::vector<const Config*> ConfigSet::filter(const AttributeMap &attributeMap) const
+{
+ std::vector<const Config*> result;
+ result.reserve(mConfigs.size());
+
+ for (auto configIter = mConfigs.begin(); configIter != mConfigs.end(); configIter++)
+ {
+ const Config &config = configIter->second;
+ bool match = true;
+
+ for (auto attribIter = attributeMap.begin(); attribIter != attributeMap.end(); attribIter++)
+ {
+ EGLint attributeKey = attribIter->first;
+ EGLint attributeValue = attribIter->second;
+
+ switch (attributeKey)
+ {
+ case EGL_BUFFER_SIZE: match = config.bufferSize >= attributeValue; break;
+ case EGL_ALPHA_SIZE: match = config.alphaSize >= attributeValue; break;
+ case EGL_BLUE_SIZE: match = config.blueSize >= attributeValue; break;
+ case EGL_GREEN_SIZE: match = config.greenSize >= attributeValue; break;
+ case EGL_RED_SIZE: match = config.redSize >= attributeValue; break;
+ case EGL_DEPTH_SIZE: match = config.depthSize >= attributeValue; break;
+ case EGL_STENCIL_SIZE: match = config.stencilSize >= attributeValue; break;
+ case EGL_CONFIG_CAVEAT: match = config.configCaveat == (EGLenum)attributeValue; break;
+ case EGL_CONFIG_ID: match = config.configID == attributeValue; break;
+ case EGL_LEVEL: match = config.level >= attributeValue; break;
+ case EGL_NATIVE_RENDERABLE: match = config.nativeRenderable == (EGLBoolean)attributeValue; break;
+ case EGL_NATIVE_VISUAL_TYPE: match = config.nativeVisualType == attributeValue; break;
+ case EGL_SAMPLES: match = config.samples >= attributeValue; break;
+ case EGL_SAMPLE_BUFFERS: match = config.sampleBuffers >= attributeValue; break;
+ case EGL_SURFACE_TYPE: match = (config.surfaceType & attributeValue) == attributeValue; break;
+ case EGL_TRANSPARENT_TYPE: match = config.transparentType == (EGLenum)attributeValue; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: match = config.transparentBlueValue == attributeValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: match = config.transparentGreenValue == attributeValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: match = config.transparentRedValue == attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: match = config.bindToTextureRGB == (EGLBoolean)attributeValue; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: match = config.bindToTextureRGBA == (EGLBoolean)attributeValue; break;
+ case EGL_MIN_SWAP_INTERVAL: match = config.minSwapInterval == attributeValue; break;
+ case EGL_MAX_SWAP_INTERVAL: match = config.maxSwapInterval == attributeValue; break;
+ case EGL_LUMINANCE_SIZE: match = config.luminanceSize >= attributeValue; break;
+ case EGL_ALPHA_MASK_SIZE: match = config.alphaMaskSize >= attributeValue; break;
+ case EGL_COLOR_BUFFER_TYPE: match = config.colorBufferType == (EGLenum)attributeValue; break;
+ case EGL_RENDERABLE_TYPE: match = (config.renderableType & attributeValue) == attributeValue; break;
+ case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: match = (config.conformant & attributeValue) == attributeValue; break;
+ case EGL_MAX_PBUFFER_WIDTH: match = config.maxPBufferWidth >= attributeValue; break;
+ case EGL_MAX_PBUFFER_HEIGHT: match = config.maxPBufferHeight >= attributeValue; break;
+ case EGL_MAX_PBUFFER_PIXELS: match = config.maxPBufferPixels >= attributeValue; break;
+ default: UNREACHABLE();
+ }
+
+ if (!match)
+ {
+ break;
+ }
+ }
+
+ if (match)
+ {
+ result.push_back(&config);
+ }
+ }
+
+ // Sort the result
+ std::sort(result.begin(), result.end(), ConfigSorter(attributeMap));
+
+ return result;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Config.h b/src/3rdparty/angle/src/libANGLE/Config.h
new file mode 100644
index 0000000000..aed8aedb1d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Config.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Config.h: Defines the egl::Config class, describing the format, type
+// and size for an egl::Surface. Implements EGLConfig and related functionality.
+// [EGL 1.5] section 3.4 page 19.
+
+#ifndef INCLUDE_CONFIG_H_
+#define INCLUDE_CONFIG_H_
+
+#include "libANGLE/AttributeMap.h"
+
+#include "common/angleutils.h"
+
+#include <EGL/egl.h>
+#include <GLES2/gl2.h>
+
+#include <map>
+#include <vector>
+
+namespace egl
+{
+
+struct Config
+{
+ Config();
+
+ GLenum renderTargetFormat; // TODO(geofflang): remove this
+ GLenum depthStencilFormat; // TODO(geofflang): remove this
+
+ EGLint bufferSize; // Depth of the color buffer
+ EGLint redSize; // Bits of Red in the color buffer
+ EGLint greenSize; // Bits of Green in the color buffer
+ EGLint blueSize; // Bits of Blue in the color buffer
+ EGLint luminanceSize; // Bits of Luminance in the color buffer
+ EGLint alphaSize; // Bits of Alpha in the color buffer
+ EGLint alphaMaskSize; // Bits of Alpha Mask in the mask buffer
+ EGLBoolean bindToTextureRGB; // True if bindable to RGB textures.
+ EGLBoolean bindToTextureRGBA; // True if bindable to RGBA textures.
+ EGLenum colorBufferType; // Color buffer type
+ EGLenum configCaveat; // Any caveats for the configuration
+ EGLint configID; // Unique EGLConfig identifier
+ EGLint conformant; // Whether contexts created with this config are conformant
+ EGLint depthSize; // Bits of Z in the depth buffer
+ EGLint level; // Frame buffer level
+ EGLBoolean matchNativePixmap; // Match the native pixmap format
+ EGLint maxPBufferWidth; // Maximum width of pbuffer
+ EGLint maxPBufferHeight; // Maximum height of pbuffer
+ EGLint maxPBufferPixels; // Maximum size of pbuffer
+ EGLint maxSwapInterval; // Maximum swap interval
+ EGLint minSwapInterval; // Minimum swap interval
+ EGLBoolean nativeRenderable; // EGL_TRUE if native rendering APIs can render to surface
+ EGLint nativeVisualID; // Handle of corresponding native visual
+ EGLint nativeVisualType; // Native visual type of the associated visual
+ EGLint renderableType; // Which client rendering APIs are supported.
+ EGLint sampleBuffers; // Number of multisample buffers
+ EGLint samples; // Number of samples per pixel
+ EGLint stencilSize; // Bits of Stencil in the stencil buffer
+ EGLint surfaceType; // Which types of EGL surfaces are supported.
+ EGLenum transparentType; // Type of transparency supported
+ EGLint transparentRedValue; // Transparent red value
+ EGLint transparentGreenValue; // Transparent green value
+ EGLint transparentBlueValue; // Transparent blue value
+};
+
+class ConfigSet
+{
+ public:
+ EGLint add(const Config &config);
+ const Config &get(EGLint id) const;
+
+ void clear();
+
+ size_t size() const;
+
+ bool contains(const Config *config) const;
+
+ // Filter configurations based on the table in [EGL 1.5] section 3.4.1.2 page 29
+ std::vector<const Config*> filter(const AttributeMap &attributeMap) const;
+
+ private:
+ typedef std::map<EGLint, const Config> ConfigMap;
+ ConfigMap mConfigs;
+};
+
+}
+
+#endif // INCLUDE_CONFIG_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/constants.h b/src/3rdparty/angle/src/libANGLE/Constants.h
index 69c4823fb2..dc8f9555b8 100644
--- a/src/3rdparty/angle/src/libGLESv2/constants.h
+++ b/src/3rdparty/angle/src/libANGLE/Constants.h
@@ -6,8 +6,8 @@
// Contants.h: Defines some implementation specific and gl constants
-#ifndef LIBGLESV2_CONSTANTS_H_
-#define LIBGLESV2_CONSTANTS_H_
+#ifndef LIBANGLE_CONSTANTS_H_
+#define LIBANGLE_CONSTANTS_H_
namespace gl
{
@@ -41,4 +41,4 @@ enum
}
-#endif // LIBGLESV2_CONSTANTS_H_
+#endif // LIBANGLE_CONSTANTS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp
index 3772da6f42..1da5fdae95 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Context.cpp
@@ -7,37 +7,36 @@
// Context.cpp: Implements the gl::Context class, managing all GL state and performing
// rendering operations. It is the GLES2 specific implementation of EGLContext.
-#include "libGLESv2/Context.h"
+#include "libANGLE/Context.h"
-#include "common/utilities.h"
-#include "common/platform.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/Sampler.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/TransformFeedback.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/validationES.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-#include "libEGL/Surface.h"
-
-#include <sstream>
#include <iterator>
+#include <sstream>
+
+#include "common/platform.h"
+#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/renderer/Renderer.h"
namespace gl
{
-Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
+Context::Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
: mRenderer(renderer)
{
ASSERT(robustAccess == false); // Unimplemented
@@ -47,6 +46,10 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r
mClientVersion = clientVersion;
+ mConfigID = config->configID;
+ mClientType = EGL_OPENGL_ES_API;
+ mRenderBuffer = EGL_NONE;
+
mFenceNVHandleAllocator.setBaseHandle(0);
if (shareContext != NULL)
@@ -65,19 +68,19 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r
// In order that access to these initial textures not be lost, they are treated as texture
// objects all of whose names are 0.
- Texture2D *zeroTexture2D = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), 0);
+ Texture *zeroTexture2D = new Texture(mRenderer->createTexture(GL_TEXTURE_2D), 0, GL_TEXTURE_2D);
mZeroTextures[GL_TEXTURE_2D].set(zeroTexture2D);
- TextureCubeMap *zeroTextureCube = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0);
+ Texture *zeroTextureCube = new Texture(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), 0, GL_TEXTURE_CUBE_MAP);
mZeroTextures[GL_TEXTURE_CUBE_MAP].set(zeroTextureCube);
if (mClientVersion >= 3)
{
// TODO: These could also be enabled via extension
- Texture3D *zeroTexture3D = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), 0);
+ Texture *zeroTexture3D = new Texture(mRenderer->createTexture(GL_TEXTURE_3D), 0, GL_TEXTURE_3D);
mZeroTextures[GL_TEXTURE_3D].set(zeroTexture3D);
- Texture2DArray *zeroTexture2DArray = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0);
+ Texture *zeroTexture2DArray = new Texture(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), 0, GL_TEXTURE_2D_ARRAY);
mZeroTextures[GL_TEXTURE_2D_ARRAY].set(zeroTexture2DArray);
}
@@ -120,25 +123,18 @@ Context::Context(int clientVersion, const Context *shareContext, rx::Renderer *r
mResetStatus = GL_NO_ERROR;
mResetStrategy = (notifyResets ? GL_LOSE_CONTEXT_ON_RESET_EXT : GL_NO_RESET_NOTIFICATION_EXT);
mRobustAccess = robustAccess;
+
+ mCompiler = new Compiler(mRenderer->createCompiler(getData()));
}
Context::~Context()
{
- GLuint currentProgram = mState.getCurrentProgramId();
- if (currentProgram != 0)
- {
- Program *programObject = mResourceManager->getProgram(currentProgram);
- if (programObject)
- {
- programObject->release();
- }
- currentProgram = 0;
- }
- mState.setCurrentProgram(0, NULL);
+ mState.reset();
while (!mFramebufferMap.empty())
{
- deleteFramebuffer(mFramebufferMap.begin()->first);
+ // Delete the framebuffer in reverse order to destroy the framebuffer zero last.
+ deleteFramebuffer(mFramebufferMap.rbegin()->first);
}
while (!mFenceNVMap.empty())
@@ -162,9 +158,9 @@ Context::~Context()
deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
}
- for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
+ for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it)
{
- i->second.set(NULL);
+ it->second.set(NULL);
}
mZeroTextures.clear();
@@ -172,6 +168,8 @@ Context::~Context()
{
mResourceManager->release();
}
+
+ SafeDelete(mCompiler);
}
void Context::makeCurrent(egl::Surface *surface)
@@ -187,14 +185,12 @@ void Context::makeCurrent(egl::Surface *surface)
mHasBeenCurrent = true;
}
- // Wrap the existing swapchain resources into GL objects and assign them to the '0' names
- rx::SwapChain *swapchain = surface->getSwapChain();
-
- rx::RenderbufferImpl *colorbufferZero = mRenderer->createRenderbuffer(swapchain, false);
- rx::RenderbufferImpl *depthStencilbufferZero = mRenderer->createRenderbuffer(swapchain, true);
- Framebuffer *framebufferZero = new DefaultFramebuffer(colorbufferZero, depthStencilbufferZero);
+ // TODO(jmadill): do not allocate new pointers here
+ Framebuffer *framebufferZero = new DefaultFramebuffer(mCaps, mRenderer, surface);
setFramebufferZero(framebufferZero);
+
+ mRenderBuffer = surface->getRenderBuffer();
}
// NOTE: this function should not assume that this context is current!
@@ -239,7 +235,7 @@ GLsync Context::createFenceSync()
{
GLuint handle = mResourceManager->createFenceSync();
- return reinterpret_cast<GLsync>(handle);
+ return reinterpret_cast<GLsync>(static_cast<uintptr_t>(handle));
}
GLuint Context::createVertexArray()
@@ -348,7 +344,7 @@ void Context::deleteFenceSync(GLsync fenceSync)
void Context::deleteVertexArray(GLuint vertexArray)
{
- VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray);
+ auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
if (vertexArrayObject != mVertexArrayMap.end())
{
@@ -372,7 +368,7 @@ void Context::deleteSampler(GLuint sampler)
void Context::deleteTransformFeedback(GLuint transformFeedback)
{
- TransformFeedbackMap::const_iterator iter = mTransformFeedbackMap.find(transformFeedback);
+ auto iter = mTransformFeedbackMap.find(transformFeedback);
if (iter != mTransformFeedbackMap.end())
{
detachTransformFeedback(transformFeedback);
@@ -454,7 +450,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const
VertexArray *Context::getVertexArray(GLuint handle) const
{
- VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle);
+ auto vertexArray = mVertexArrayMap.find(handle);
if (vertexArray == mVertexArrayMap.end())
{
@@ -526,7 +522,7 @@ void Context::bindReadFramebuffer(GLuint framebuffer)
{
if (!getFramebuffer(framebuffer))
{
- mFramebufferMap[framebuffer] = new Framebuffer(framebuffer);
+ mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer);
}
mState.setReadFramebufferBinding(getFramebuffer(framebuffer));
@@ -536,7 +532,7 @@ void Context::bindDrawFramebuffer(GLuint framebuffer)
{
if (!getFramebuffer(framebuffer))
{
- mFramebufferMap[framebuffer] = new Framebuffer(framebuffer);
+ mFramebufferMap[framebuffer] = new Framebuffer(mCaps, mRenderer, framebuffer);
}
mState.setDrawFramebufferBinding(getFramebuffer(framebuffer));
@@ -626,58 +622,7 @@ void Context::bindPixelUnpackBuffer(GLuint buffer)
void Context::useProgram(GLuint program)
{
- GLuint priorProgramId = mState.getCurrentProgramId();
- Program *priorProgram = mResourceManager->getProgram(priorProgramId);
-
- if (priorProgramId != program)
- {
- mState.setCurrentProgram(program, mResourceManager->getProgram(program));
-
- if (priorProgram)
- {
- priorProgram->release();
- }
- }
-}
-
-Error Context::linkProgram(GLuint program)
-{
- Program *programObject = mResourceManager->getProgram(program);
-
- Error error = programObject->link(getData());
- if (error.isError())
- {
- return error;
- }
-
- // if the current program was relinked successfully we
- // need to install the new executables
- if (programObject->isLinked() && program == mState.getCurrentProgramId())
- {
- mState.setCurrentProgramBinary(programObject->getProgramBinary());
- }
-
- return Error(GL_NO_ERROR);
-}
-
-Error Context::setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
-{
- Program *programObject = mResourceManager->getProgram(program);
-
- Error error = programObject->setProgramBinary(binaryFormat, binary, length);
- if (error.isError())
- {
- return error;
- }
-
- // if the current program was reloaded successfully we
- // need to install the new executables
- if (programObject->isLinked() && program == mState.getCurrentProgramId())
- {
- mState.setCurrentProgramBinary(programObject->getProgramBinary());
- }
-
- return Error(GL_NO_ERROR);
+ mState.setProgram(getProgram(program));
}
void Context::bindTransformFeedback(GLuint transformFeedback)
@@ -784,44 +729,19 @@ Query *Context::getQuery(unsigned int handle, bool create, GLenum type)
Texture *Context::getTargetTexture(GLenum target) const
{
- if (!ValidTextureTarget(this, target))
- {
- return NULL;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D: return getTexture2D();
- case GL_TEXTURE_CUBE_MAP: return getTextureCubeMap();
- case GL_TEXTURE_3D: return getTexture3D();
- case GL_TEXTURE_2D_ARRAY: return getTexture2DArray();
- default: return NULL;
- }
-}
-
-Texture2D *Context::getTexture2D() const
-{
- return static_cast<Texture2D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D));
-}
+ ASSERT(ValidTextureTarget(this, target));
-TextureCubeMap *Context::getTextureCubeMap() const
-{
- return static_cast<TextureCubeMap*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_CUBE_MAP));
+ return getSamplerTexture(mState.getActiveSampler(), target);
}
-Texture3D *Context::getTexture3D() const
+Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
{
- return static_cast<Texture3D*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_3D));
+ return mState.getSamplerTexture(sampler, type);
}
-Texture2DArray *Context::getTexture2DArray() const
+Compiler *Context::getCompiler() const
{
- return static_cast<Texture2DArray*>(getSamplerTexture(mState.getActiveSampler(), GL_TEXTURE_2D_ARRAY));
-}
-
-Texture *Context::getSamplerTexture(unsigned int sampler, GLenum type) const
-{
- return mState.getSamplerTexture(sampler, type);
+ return mCompiler;
}
void Context::getBooleanv(GLenum pname, GLboolean *params)
@@ -900,17 +820,6 @@ void Context::getIntegerv(GLenum pname, GLint *params)
case GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS: *params = mCaps.maxTransformFeedbackSeparateComponents; break;
case GL_NUM_COMPRESSED_TEXTURE_FORMATS: *params = mCaps.compressedTextureFormats.size(); break;
case GL_MAX_SAMPLES_ANGLE: *params = mExtensions.maxSamples; break;
- case GL_IMPLEMENTATION_COLOR_READ_TYPE:
- case GL_IMPLEMENTATION_COLOR_READ_FORMAT:
- {
- GLenum internalFormat, format, type;
- getCurrentReadFormatType(&internalFormat, &format, &type);
- if (pname == GL_IMPLEMENTATION_COLOR_READ_FORMAT)
- *params = format;
- else
- *params = type;
- }
- break;
case GL_MAX_VIEWPORT_DIMS:
{
params[0] = mCaps.maxViewportWidth;
@@ -1025,6 +934,7 @@ bool Context::getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *nu
*numParams = mCaps.shaderBinaryFormats.size();
}
return true;
+
case GL_MAX_VERTEX_ATTRIBS:
case GL_MAX_VERTEX_UNIFORM_VECTORS:
case GL_MAX_VARYING_VECTORS:
@@ -1286,62 +1196,6 @@ bool Context::getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned
return false;
}
-Error Context::clear(GLbitfield mask)
-{
- if (mState.isRasterizerDiscardEnabled())
- {
- return Error(GL_NO_ERROR);
- }
-
- return mRenderer->clear(getData(), mask);
-}
-
-Error Context::clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values)
-{
- if (mState.isRasterizerDiscardEnabled())
- {
- return Error(GL_NO_ERROR);
- }
-
- return mRenderer->clearBufferfv(getData(), buffer, drawbuffer, values);
-}
-
-Error Context::clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values)
-{
- if (mState.isRasterizerDiscardEnabled())
- {
- return Error(GL_NO_ERROR);
- }
-
- return mRenderer->clearBufferuiv(getData(), buffer, drawbuffer, values);
-}
-
-Error Context::clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values)
-{
- if (mState.isRasterizerDiscardEnabled())
- {
- return Error(GL_NO_ERROR);
- }
-
- return mRenderer->clearBufferiv(getData(), buffer, drawbuffer, values);
-}
-
-Error Context::clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
-{
- if (mState.isRasterizerDiscardEnabled())
- {
- return Error(GL_NO_ERROR);
- }
-
- return mRenderer->clearBufferfi(getData(), buffer, drawbuffer, depth, stencil);
-}
-
-Error Context::readPixels(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
-{
- return mRenderer->readPixels(getData(), x, y, width, height, format, type, bufSize, pixels);
-}
-
Error Context::drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
return mRenderer->drawArrays(getData(), mode, first, count, instances);
@@ -1354,10 +1208,14 @@ Error Context::drawElements(GLenum mode, GLsizei count, GLenum type,
return mRenderer->drawElements(getData(), mode, count, type, indices, instances, indexRange);
}
-// Implements glFlush when block is false, glFinish when block is true
-Error Context::sync(bool block)
+Error Context::flush()
{
- return mRenderer->sync(block);
+ return mRenderer->flush();
+}
+
+Error Context::finish()
+{
+ return mRenderer->finish();
}
void Context::recordError(const Error &error)
@@ -1391,7 +1249,10 @@ GLenum Context::getResetStatus()
{
// mResetStatus will be set by the markContextLost callback
// in the case a notification is sent
- mRenderer->testDeviceLost(true);
+ if (mRenderer->testDeviceLost())
+ {
+ mRenderer->notifyDeviceLost();
+ }
}
GLenum status = mResetStatus;
@@ -1419,6 +1280,21 @@ int Context::getClientVersion() const
return mClientVersion;
}
+EGLint Context::getConfigID() const
+{
+ return mConfigID;
+}
+
+EGLenum Context::getClientType() const
+{
+ return mClientType;
+}
+
+EGLenum Context::getRenderBuffer() const
+{
+ return mRenderBuffer;
+}
+
const Caps &Context::getCaps() const
{
return mCaps;
@@ -1434,22 +1310,6 @@ const Extensions &Context::getExtensions() const
return mExtensions;
}
-void Context::getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type)
-{
- Framebuffer *framebuffer = mState.getReadFramebuffer();
- ASSERT(framebuffer && framebuffer->completeness(getData()) == GL_FRAMEBUFFER_COMPLETE);
-
- FramebufferAttachment *attachment = framebuffer->getReadColorbuffer();
- ASSERT(attachment);
-
- GLenum actualFormat = attachment->getActualFormat();
- const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualFormat);
-
- *internalFormat = actualFormat;
- *format = actualFormatInfo.format;
- *type = actualFormatInfo.type;
-}
-
void Context::detachTexture(GLuint texture)
{
// Simple pass-through to State's detachTexture method, as textures do not require
@@ -1487,12 +1347,12 @@ void Context::detachFramebuffer(GLuint framebuffer)
// If a framebuffer that is currently bound to the target FRAMEBUFFER is deleted, it is as though
// BindFramebuffer had been executed with the target of FRAMEBUFFER and framebuffer of zero.
- if (mState.removeReadFramebufferBinding(framebuffer))
+ if (mState.removeReadFramebufferBinding(framebuffer) && framebuffer != 0)
{
bindReadFramebuffer(0);
}
- if (mState.removeDrawFramebufferBinding(framebuffer))
+ if (mState.removeDrawFramebufferBinding(framebuffer) && framebuffer != 0)
{
bindDrawFramebuffer(0);
}
@@ -1660,19 +1520,6 @@ size_t Context::getExtensionStringCount() const
return mExtensionStrings.size();
}
-Error Context::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- return mRenderer->blitFramebuffer(getData(), srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter);
-}
-
-void Context::releaseShaderCompiler()
-{
- mRenderer->releaseShaderCompiler();
-}
-
void Context::initCaps(GLuint clientVersion)
{
mCaps = mRenderer->getRendererCaps();
@@ -1738,32 +1585,3 @@ Data Context::getData() const
}
}
-
-extern "C"
-{
-gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess)
-{
- return new gl::Context(clientVersion, shareContext, renderer, notifyResets, robustAccess);
-}
-
-void glDestroyContext(gl::Context *context)
-{
- delete context;
-
- if (context == gl::getContext())
- {
- gl::makeCurrent(NULL, NULL, NULL);
- }
-}
-
-void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface)
-{
- gl::makeCurrent(context, display, surface);
-}
-
-gl::Context *glGetCurrentContext()
-{
- return gl::getContext();
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libANGLE/Context.h
index 0699592d91..eeada43355 100644
--- a/src/3rdparty/angle/src/libGLESv2/Context.h
+++ b/src/3rdparty/angle/src/libANGLE/Context.h
@@ -7,26 +7,24 @@
// Context.h: Defines the gl::Context class, managing all GL state and performing
// rendering operations. It is the GLES2 specific implementation of EGLContext.
-#ifndef LIBGLESV2_CONTEXT_H_
-#define LIBGLESV2_CONTEXT_H_
+#ifndef LIBANGLE_CONTEXT_H_
+#define LIBANGLE_CONTEXT_H_
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/Data.h"
-#include "libGLESv2/Error.h"
-#include "libGLESv2/HandleAllocator.h"
-#include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/HandleAllocator.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/angletypes.h"
#include "angle_gl.h"
#include <string>
#include <set>
#include <map>
-#include <unordered_map>
-#include <array>
namespace rx
{
@@ -36,18 +34,15 @@ class Renderer;
namespace egl
{
class Surface;
+struct Config;
}
namespace gl
{
+class Compiler;
class Shader;
class Program;
-class ProgramBinary;
class Texture;
-class Texture2D;
-class TextureCubeMap;
-class Texture3D;
-class Texture2DArray;
class Framebuffer;
class Renderbuffer;
class FenceNV;
@@ -60,10 +55,10 @@ class VertexArray;
class Sampler;
class TransformFeedback;
-class Context
+class Context final : angle::NonCopyable
{
public:
- Context(int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
+ Context(const egl::Config *config, int clientVersion, const Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
virtual ~Context();
@@ -125,8 +120,6 @@ class Context
void bindPixelPackBuffer(GLuint buffer);
void bindPixelUnpackBuffer(GLuint buffer);
void useProgram(GLuint program);
- Error linkProgram(GLuint program);
- Error setProgramBinary(GLuint program, GLenum binaryFormat, const void *binary, GLint length);
void bindTransformFeedback(GLuint transformFeedback);
Error beginQuery(GLenum target, GLuint query);
@@ -155,13 +148,10 @@ class Context
TransformFeedback *getTransformFeedback(GLuint handle) const;
Texture *getTargetTexture(GLenum target) const;
- Texture2D *getTexture2D() const;
- TextureCubeMap *getTextureCubeMap() const;
- Texture3D *getTexture3D() const;
- Texture2DArray *getTexture2DArray() const;
-
Texture *getSamplerTexture(unsigned int sampler, GLenum type) const;
+ Compiler *getCompiler() const;
+
bool isSampler(GLuint samplerName) const;
void getBooleanv(GLenum pname, GLboolean *params);
@@ -175,18 +165,12 @@ class Context
bool getQueryParameterInfo(GLenum pname, GLenum *type, unsigned int *numParams);
bool getIndexedQueryParameterInfo(GLenum target, GLenum *type, unsigned int *numParams);
- Error clear(GLbitfield mask);
- Error clearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat *values);
- Error clearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint *values);
- Error clearBufferiv(GLenum buffer, GLint drawbuffer, const GLint *values);
- Error clearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
-
- Error readPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei *bufSize, void* pixels);
Error drawArrays(GLenum mode, GLint first, GLsizei count, GLsizei instances);
Error drawElements(GLenum mode, GLsizei count, GLenum type,
const GLvoid *indices, GLsizei instances,
const rx::RangeUI &indexRange);
- Error sync(bool block); // flush/finish
+ Error flush();
+ Error finish();
void recordError(const Error &error);
@@ -196,6 +180,10 @@ class Context
virtual int getClientVersion() const;
+ EGLint getConfigID() const;
+ EGLenum getClientType() const;
+ EGLenum getRenderBuffer() const;
+
const Caps &getCaps() const;
const TextureCapsMap &getTextureCaps() const;
const Extensions &getExtensions() const;
@@ -206,11 +194,6 @@ class Context
const std::string &getExtensionString(size_t idx) const;
size_t getExtensionStringCount() const;
- void getCurrentReadFormatType(GLenum *internalFormat, GLenum *format, GLenum *type);
-
- Error blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter);
-
rx::Renderer *getRenderer() { return mRenderer; }
State &getState() { return mState; }
@@ -218,11 +201,7 @@ class Context
Data getData() const;
- void releaseShaderCompiler();
-
private:
- DISALLOW_COPY_AND_ASSIGN(Context);
-
void detachBuffer(GLuint buffer);
void detachTexture(GLuint texture);
void detachFramebuffer(GLuint framebuffer);
@@ -241,31 +220,38 @@ class Context
TextureCapsMap mTextureCaps;
Extensions mExtensions;
+ // Shader compiler
+ Compiler *mCompiler;
+
rx::Renderer *const mRenderer;
State mState;
int mClientVersion;
+ EGLint mConfigID;
+ EGLenum mClientType;
+ EGLenum mRenderBuffer;
+
TextureMap mZeroTextures;
- typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap;
+ typedef std::map<GLuint, Framebuffer*> FramebufferMap;
FramebufferMap mFramebufferMap;
HandleAllocator mFramebufferHandleAllocator;
- typedef std::unordered_map<GLuint, FenceNV*> FenceNVMap;
+ typedef std::map<GLuint, FenceNV*> FenceNVMap;
FenceNVMap mFenceNVMap;
HandleAllocator mFenceNVHandleAllocator;
- typedef std::unordered_map<GLuint, Query*> QueryMap;
+ typedef std::map<GLuint, Query*> QueryMap;
QueryMap mQueryMap;
HandleAllocator mQueryHandleAllocator;
- typedef std::unordered_map<GLuint, VertexArray*> VertexArrayMap;
+ typedef std::map<GLuint, VertexArray*> VertexArrayMap;
VertexArrayMap mVertexArrayMap;
HandleAllocator mVertexArrayHandleAllocator;
BindingPointer<TransformFeedback> mTransformFeedbackZero;
- typedef std::unordered_map<GLuint, TransformFeedback*> TransformFeedbackMap;
+ typedef std::map<GLuint, TransformFeedback*> TransformFeedbackMap;
TransformFeedbackMap mTransformFeedbackMap;
HandleAllocator mTransformFeedbackAllocator;
@@ -288,4 +274,4 @@ class Context
};
}
-#endif // INCLUDE_CONTEXT_H_
+#endif // LIBANGLE_CONTEXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Data.cpp b/src/3rdparty/angle/src/libANGLE/Data.cpp
index 3ddf591d77..7832e21b23 100644
--- a/src/3rdparty/angle/src/libGLESv2/Data.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Data.cpp
@@ -6,8 +6,8 @@
// Data.cpp: Container class for all GL relevant state, caps and objects
-#include "libGLESv2/Data.h"
-#include "libGLESv2/ResourceManager.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/ResourceManager.h"
namespace gl
{
diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libANGLE/Data.h
index 9234403e13..7eb6827dfc 100644
--- a/src/3rdparty/angle/src/libGLESv2/Data.h
+++ b/src/3rdparty/angle/src/libANGLE/Data.h
@@ -6,15 +6,15 @@
// Data.h: Container class for all GL relevant state, caps and objects
-#ifndef LIBGLESV2_DATA_H_
-#define LIBGLESV2_DATA_H_
+#ifndef LIBANGLE_DATA_H_
+#define LIBANGLE_DATA_H_
-#include "libGLESv2/State.h"
+#include "libANGLE/State.h"
namespace gl
{
-struct Data
+struct Data final
{
public:
Data(GLint clientVersion, const State &state, const Caps &caps,
@@ -35,4 +35,4 @@ struct Data
}
-#endif // LIBGLESV2_DATA_H_
+#endif // LIBANGLE_DATA_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
new file mode 100644
index 0000000000..1f54f82dea
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
@@ -0,0 +1,675 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.cpp: Implements the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#include "libANGLE/Display.h"
+
+#include <algorithm>
+#include <iterator>
+#include <map>
+#include <sstream>
+#include <vector>
+
+#include <platform/Platform.h>
+#include <EGL/eglext.h>
+
+#include "common/debug.h"
+#include "common/mathutil.h"
+#include "common/platform.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+# include "libANGLE/renderer/d3d/DisplayD3D.h"
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+# if defined(ANGLE_PLATFORM_WINDOWS)
+# include "libANGLE/renderer/gl/wgl/DisplayWGL.h"
+# else
+# error Unsupported OpenGL platform.
+# endif
+#endif
+
+namespace egl
+{
+
+namespace
+{
+
+class DefaultPlatform : public angle::Platform
+{
+public:
+ DefaultPlatform() {}
+ ~DefaultPlatform() override {}
+};
+
+DefaultPlatform *defaultPlatform = nullptr;
+
+void InitDefaultPlatformImpl()
+{
+ if (ANGLEPlatformCurrent() == nullptr)
+ {
+ if (defaultPlatform == nullptr)
+ {
+ defaultPlatform = new DefaultPlatform();
+ }
+
+ ANGLEPlatformInitialize(defaultPlatform);
+ }
+}
+
+void DeinitDefaultPlatformImpl()
+{
+ if (defaultPlatform != nullptr)
+ {
+ if (ANGLEPlatformCurrent() == defaultPlatform)
+ {
+ ANGLEPlatformShutdown();
+ }
+
+ SafeDelete(defaultPlatform);
+ }
+}
+
+typedef std::map<EGLNativeWindowType, Surface*> WindowSurfaceMap;
+// Get a map of all EGL window surfaces to validate that no window has more than one EGL surface
+// associated with it.
+static WindowSurfaceMap *GetWindowSurfaces()
+{
+ static WindowSurfaceMap windowSurfaces;
+ return &windowSurfaces;
+}
+
+typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
+static DisplayMap *GetDisplayMap()
+{
+ static DisplayMap displays;
+ return &displays;
+}
+
+rx::DisplayImpl *CreateDisplayImpl(const AttributeMap &attribMap)
+{
+ rx::DisplayImpl *impl = nullptr;
+ EGLint displayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+ switch (displayType)
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ // Default to D3D displays
+ impl = new rx::DisplayD3D();
+#else
+ // No display available
+ UNREACHABLE();
+#endif
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ impl = new rx::DisplayD3D();
+#else
+ // A D3D display was requested on a platform that doesn't support it
+ UNREACHABLE();
+#endif
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+#if defined(ANGLE_ENABLE_OPENGL)
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ impl = new rx::DisplayWGL();
+#else
+#error Unsupported OpenGL platform.
+#endif
+#else
+ UNREACHABLE();
+#endif
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ ASSERT(impl != nullptr);
+ return impl;
+}
+
+}
+
+Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
+{
+ // Initialize the global platform if not already
+ InitDefaultPlatformImpl();
+
+ Display *display = NULL;
+
+ DisplayMap *displays = GetDisplayMap();
+ DisplayMap::const_iterator iter = displays->find(displayId);
+ if (iter != displays->end())
+ {
+ display = iter->second;
+ }
+
+ if (display == nullptr)
+ {
+ // Validate the native display
+ if (!Display::isValidNativeDisplay(displayId))
+ {
+ return NULL;
+ }
+
+ display = new Display(displayId);
+ displays->insert(std::make_pair(displayId, display));
+ }
+
+ // Apply new attributes if the display is not initialized yet.
+ if (!display->isInitialized())
+ {
+ rx::DisplayImpl* impl = CreateDisplayImpl(attribMap);
+ display->setAttributes(impl, attribMap);
+ }
+
+ return display;
+}
+
+Display::Display(EGLNativeDisplayType displayId)
+ : mImplementation(nullptr),
+ mDisplayId(displayId),
+ mAttributeMap(),
+ mConfigSet(),
+ mContextSet(),
+ mInitialized(false),
+ mCaps(),
+ mDisplayExtensions(),
+ mDisplayExtensionString(),
+ mVendorString()
+{
+}
+
+Display::~Display()
+{
+ terminate();
+
+ DisplayMap *displays = GetDisplayMap();
+ DisplayMap::iterator iter = displays->find(mDisplayId);
+ if (iter != displays->end())
+ {
+ displays->erase(iter);
+ }
+
+ SafeDelete(mImplementation);
+}
+
+void Display::setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap)
+{
+ ASSERT(!mInitialized);
+
+ ASSERT(impl != nullptr);
+ SafeDelete(mImplementation);
+ mImplementation = impl;
+
+ mAttributeMap = attribMap;
+}
+
+Error Display::initialize()
+{
+ ASSERT(mImplementation != nullptr);
+
+ if (isInitialized())
+ {
+ return Error(EGL_SUCCESS);
+ }
+
+ Error error = mImplementation->initialize(this);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mCaps = mImplementation->getCaps();
+
+ mConfigSet = mImplementation->generateConfigs();
+ if (mConfigSet.size() == 0)
+ {
+ mImplementation->terminate();
+ return Error(EGL_NOT_INITIALIZED);
+ }
+
+ initDisplayExtensions();
+ initVendorString();
+
+ mInitialized = true;
+ return Error(EGL_SUCCESS);
+}
+
+void Display::terminate()
+{
+ makeCurrent(nullptr, nullptr, nullptr);
+
+ while (!mContextSet.empty())
+ {
+ destroyContext(*mContextSet.begin());
+ }
+
+ mConfigSet.clear();
+
+ mImplementation->terminate();
+ mInitialized = false;
+
+ // De-init default platform
+ DeinitDefaultPlatformImpl();
+}
+
+std::vector<const Config*> Display::getConfigs(const egl::AttributeMap &attribs) const
+{
+ return mConfigSet.filter(attribs);
+}
+
+bool Display::getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value)
+{
+ switch (attribute)
+ {
+ case EGL_BUFFER_SIZE: *value = configuration->bufferSize; break;
+ case EGL_ALPHA_SIZE: *value = configuration->alphaSize; break;
+ case EGL_BLUE_SIZE: *value = configuration->blueSize; break;
+ case EGL_GREEN_SIZE: *value = configuration->greenSize; break;
+ case EGL_RED_SIZE: *value = configuration->redSize; break;
+ case EGL_DEPTH_SIZE: *value = configuration->depthSize; break;
+ case EGL_STENCIL_SIZE: *value = configuration->stencilSize; break;
+ case EGL_CONFIG_CAVEAT: *value = configuration->configCaveat; break;
+ case EGL_CONFIG_ID: *value = configuration->configID; break;
+ case EGL_LEVEL: *value = configuration->level; break;
+ case EGL_NATIVE_RENDERABLE: *value = configuration->nativeRenderable; break;
+ case EGL_NATIVE_VISUAL_TYPE: *value = configuration->nativeVisualType; break;
+ case EGL_SAMPLES: *value = configuration->samples; break;
+ case EGL_SAMPLE_BUFFERS: *value = configuration->sampleBuffers; break;
+ case EGL_SURFACE_TYPE: *value = configuration->surfaceType; break;
+ case EGL_TRANSPARENT_TYPE: *value = configuration->transparentType; break;
+ case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->transparentBlueValue; break;
+ case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->transparentGreenValue; break;
+ case EGL_TRANSPARENT_RED_VALUE: *value = configuration->transparentRedValue; break;
+ case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->bindToTextureRGB; break;
+ case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->bindToTextureRGBA; break;
+ case EGL_MIN_SWAP_INTERVAL: *value = configuration->minSwapInterval; break;
+ case EGL_MAX_SWAP_INTERVAL: *value = configuration->maxSwapInterval; break;
+ case EGL_LUMINANCE_SIZE: *value = configuration->luminanceSize; break;
+ case EGL_ALPHA_MASK_SIZE: *value = configuration->alphaMaskSize; break;
+ case EGL_COLOR_BUFFER_TYPE: *value = configuration->colorBufferType; break;
+ case EGL_RENDERABLE_TYPE: *value = configuration->renderableType; break;
+ case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
+ case EGL_CONFORMANT: *value = configuration->conformant; break;
+ case EGL_MAX_PBUFFER_WIDTH: *value = configuration->maxPBufferWidth; break;
+ case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->maxPBufferHeight; break;
+ case EGL_MAX_PBUFFER_PIXELS: *value = configuration->maxPBufferPixels; break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+Error Display::createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ if (mImplementation->testDeviceLost())
+ {
+ Error error = restoreLostDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ rx::SurfaceImpl *surfaceImpl = nullptr;
+ Error error = mImplementation->createWindowSurface(configuration, window, attribs, &surfaceImpl);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(surfaceImpl != nullptr);
+ Surface *surface = new Surface(surfaceImpl, EGL_WINDOW_BIT, configuration, attribs);
+ mImplementation->getSurfaceSet().insert(surface);
+
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces && windowSurfaces->find(window) == windowSurfaces->end());
+ windowSurfaces->insert(std::make_pair(window, surface));
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface;
+ return Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ Error error = restoreLostDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ rx::SurfaceImpl *surfaceImpl = nullptr;
+ Error error = mImplementation->createPbufferSurface(configuration, attribs, &surfaceImpl);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(surfaceImpl != nullptr);
+ Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs);
+ mImplementation->getSurfaceSet().insert(surface);
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface;
+ return Error(EGL_SUCCESS);
+}
+
+Error Display::createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle,
+ const AttributeMap &attribs, Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ Error error = restoreLostDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ rx::SurfaceImpl *surfaceImpl = nullptr;
+ Error error = mImplementation->createPbufferFromClientBuffer(configuration, shareHandle, attribs, &surfaceImpl);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(surfaceImpl != nullptr);
+ Surface *surface = new Surface(surfaceImpl, EGL_PBUFFER_BIT, configuration, attribs);
+ mImplementation->getSurfaceSet().insert(surface);
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface;
+ return Error(EGL_SUCCESS);
+}
+
+Error Display::createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+ Surface **outSurface)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ Error error = restoreLostDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ rx::SurfaceImpl *surfaceImpl = nullptr;
+ Error error = mImplementation->createPixmapSurface(configuration, nativePixmap, attribs, &surfaceImpl);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(surfaceImpl != nullptr);
+ Surface *surface = new Surface(surfaceImpl, EGL_PIXMAP_BIT, configuration, attribs);
+ mImplementation->getSurfaceSet().insert(surface);
+
+ ASSERT(outSurface != nullptr);
+ *outSurface = surface;
+ return Error(EGL_SUCCESS);
+}
+
+Error Display::createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+ gl::Context **outContext)
+{
+ ASSERT(isInitialized());
+
+ if (mImplementation->testDeviceLost())
+ {
+ Error error = restoreLostDevice();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ gl::Context *context = nullptr;
+ Error error = mImplementation->createContext(configuration, shareContext, attribs, &context);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(context != nullptr);
+ mContextSet.insert(context);
+
+ ASSERT(outContext != nullptr);
+ *outContext = context;
+ return Error(EGL_SUCCESS);
+}
+
+Error Display::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+ Error error = mImplementation->makeCurrent(drawSurface, readSurface, context);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (context && drawSurface)
+ {
+ context->makeCurrent(drawSurface);
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+Error Display::restoreLostDevice()
+{
+ for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
+ {
+ if ((*ctx)->isResetNotificationEnabled())
+ {
+ // If reset notifications have been requested, application must delete all contexts first
+ return Error(EGL_CONTEXT_LOST);
+ }
+ }
+
+ return mImplementation->restoreLostDevice();
+}
+
+void Display::destroySurface(Surface *surface)
+{
+ if (surface->getType() == EGL_WINDOW_BIT)
+ {
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces);
+
+ bool surfaceRemoved = false;
+ for (WindowSurfaceMap::iterator iter = windowSurfaces->begin(); iter != windowSurfaces->end(); iter++)
+ {
+ if (iter->second == surface)
+ {
+ windowSurfaces->erase(iter);
+ surfaceRemoved = true;
+ break;
+ }
+ }
+
+ ASSERT(surfaceRemoved);
+ }
+
+ mImplementation->destroySurface(surface);
+}
+
+void Display::destroyContext(gl::Context *context)
+{
+ mContextSet.erase(context);
+ SafeDelete(context);
+}
+
+bool Display::isDeviceLost() const
+{
+ ASSERT(isInitialized());
+ return mImplementation->isDeviceLost();
+}
+
+bool Display::testDeviceLost()
+{
+ ASSERT(isInitialized());
+ return mImplementation->testDeviceLost();
+}
+
+void Display::notifyDeviceLost()
+{
+ for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
+ {
+ (*context)->markContextLost();
+ }
+}
+
+const Caps &Display::getCaps() const
+{
+ return mCaps;
+}
+
+bool Display::isInitialized() const
+{
+ return mInitialized;
+}
+
+bool Display::isValidConfig(const Config *config) const
+{
+ return mConfigSet.contains(config);
+}
+
+bool Display::isValidContext(gl::Context *context) const
+{
+ return mContextSet.find(context) != mContextSet.end();
+}
+
+bool Display::isValidSurface(Surface *surface) const
+{
+ return mImplementation->getSurfaceSet().find(surface) != mImplementation->getSurfaceSet().end();
+}
+
+bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
+{
+ WindowSurfaceMap *windowSurfaces = GetWindowSurfaces();
+ ASSERT(windowSurfaces);
+
+ return windowSurfaces->find(window) != windowSurfaces->end();
+}
+
+static ClientExtensions GenerateClientExtensions()
+{
+ ClientExtensions extensions;
+
+ extensions.clientExtensions = true;
+ extensions.platformBase = true;
+ extensions.platformANGLE = true;
+
+#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
+ extensions.platformANGLED3D = true;
+#endif
+
+#if defined(ANGLE_ENABLE_OPENGL)
+ extensions.platformANGLEOpenGL = true;
+#endif
+
+ return extensions;
+}
+
+template <typename T>
+static std::string GenerateExtensionsString(const T &extensions)
+{
+ std::vector<std::string> extensionsVector = extensions.getStrings();
+
+ std::ostringstream stream;
+ std::copy(extensionsVector.begin(), extensionsVector.end(), std::ostream_iterator<std::string>(stream, " "));
+ return stream.str();
+}
+
+const ClientExtensions &Display::getClientExtensions()
+{
+ static const ClientExtensions clientExtensions = GenerateClientExtensions();
+ return clientExtensions;
+}
+
+const std::string &Display::getClientExtensionString()
+{
+ static const std::string clientExtensionsString = GenerateExtensionsString(getClientExtensions());
+ return clientExtensionsString;
+}
+
+void Display::initDisplayExtensions()
+{
+ mDisplayExtensions = mImplementation->getExtensions();
+ mDisplayExtensionString = GenerateExtensionsString(mDisplayExtensions);
+}
+
+bool Display::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return mImplementation->isValidNativeWindow(window);
+}
+
+bool Display::isValidNativeDisplay(EGLNativeDisplayType display)
+{
+ // TODO(jmadill): handle this properly
+ if (display == EGL_DEFAULT_DISPLAY)
+ {
+ return true;
+ }
+
+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ if (display == EGL_SOFTWARE_DISPLAY_ANGLE ||
+ display == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ display == EGL_D3D11_ONLY_DISPLAY_ANGLE)
+ {
+ return true;
+ }
+ return (WindowFromDC(display) != NULL);
+#else
+ return true;
+#endif
+}
+
+void Display::initVendorString()
+{
+ mVendorString = mImplementation->getVendorString();
+}
+
+const DisplayExtensions &Display::getExtensions() const
+{
+ return mDisplayExtensions;
+}
+
+const std::string &Display::getExtensionString() const
+{
+ return mDisplayExtensionString;
+}
+
+const std::string &Display::getVendorString() const
+{
+ return mVendorString;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
new file mode 100644
index 0000000000..5ab3f9c0e9
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Display.h
@@ -0,0 +1,124 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Display.h: Defines the egl::Display class, representing the abstract
+// display on which graphics are drawn. Implements EGLDisplay.
+// [EGL 1.4] section 2.1.2 page 3.
+
+#ifndef LIBANGLE_DISPLAY_H_
+#define LIBANGLE_DISPLAY_H_
+
+#include <set>
+#include <vector>
+
+#include "libANGLE/Error.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/AttributeMap.h"
+
+namespace gl
+{
+class Context;
+}
+
+namespace rx
+{
+class DisplayImpl;
+}
+
+namespace egl
+{
+class Surface;
+
+class Display final : angle::NonCopyable
+{
+ public:
+ ~Display();
+
+ Error initialize();
+ void terminate();
+
+ static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
+
+ static const ClientExtensions &getClientExtensions();
+ static const std::string &getClientExtensionString();
+
+ std::vector<const Config*> getConfigs(const egl::AttributeMap &attribs) const;
+ bool getConfigAttrib(const Config *configuration, EGLint attribute, EGLint *value);
+
+ Error createWindowSurface(const Config *configuration, EGLNativeWindowType window, const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPbufferSurface(const Config *configuration, const AttributeMap &attribs, Surface **outSurface);
+ Error createPbufferFromClientBuffer(const Config *configuration, EGLClientBuffer shareHandle, const AttributeMap &attribs,
+ Surface **outSurface);
+ Error createPixmapSurface(const Config *configuration, NativePixmapType nativePixmap, const AttributeMap &attribs,
+ Surface **outSurface);
+
+ Error createContext(const Config *configuration, gl::Context *shareContext, const AttributeMap &attribs,
+ gl::Context **outContext);
+
+ Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context);
+
+ void destroySurface(egl::Surface *surface);
+ void destroyContext(gl::Context *context);
+
+ bool isInitialized() const;
+ bool isValidConfig(const Config *config) const;
+ bool isValidContext(gl::Context *context) const;
+ bool isValidSurface(egl::Surface *surface) const;
+ bool isValidNativeWindow(EGLNativeWindowType window) const;
+
+ static bool isValidNativeDisplay(EGLNativeDisplayType display);
+ static bool hasExistingWindowSurface(EGLNativeWindowType window);
+
+ bool isDeviceLost() const;
+ bool testDeviceLost();
+ void notifyDeviceLost();
+
+ const Caps &getCaps() const;
+
+ const DisplayExtensions &getExtensions() const;
+ const std::string &getExtensionString() const;
+ const std::string &getVendorString() const;
+
+ const AttributeMap &getAttributeMap() const { return mAttributeMap; }
+ EGLNativeDisplayType getNativeDisplayId() const { return mDisplayId; }
+
+ rx::DisplayImpl *getImplementation() { return mImplementation; }
+
+ private:
+ Display(EGLNativeDisplayType displayId);
+
+ void setAttributes(rx::DisplayImpl *impl, const AttributeMap &attribMap);
+
+ Error restoreLostDevice();
+
+ void initDisplayExtensions();
+ void initVendorString();
+
+ rx::DisplayImpl *mImplementation;
+
+ EGLNativeDisplayType mDisplayId;
+ AttributeMap mAttributeMap;
+
+ ConfigSet mConfigSet;
+
+ typedef std::set<gl::Context*> ContextSet;
+ ContextSet mContextSet;
+
+ bool mInitialized;
+
+ Caps mCaps;
+
+ DisplayExtensions mDisplayExtensions;
+ std::string mDisplayExtensionString;
+
+ std::string mVendorString;
+};
+
+}
+
+#endif // LIBANGLE_DISPLAY_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Error.cpp b/src/3rdparty/angle/src/libANGLE/Error.cpp
new file mode 100644
index 0000000000..e17f26bec4
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Error.cpp
@@ -0,0 +1,86 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Error.cpp: Implements the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode, const char *msg, ...)
+ : mCode(errorCode),
+ mMessage(nullptr)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+void Error::createMessageString() const
+{
+ if (mMessage == nullptr)
+ {
+ mMessage = new std::string();
+ }
+}
+
+const std::string &Error::getMessage() const
+{
+ createMessageString();
+ return *mMessage;
+}
+
+}
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode, const char *msg, ...)
+ : mCode(errorCode),
+ mID(0),
+ mMessage(nullptr)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+
+Error::Error(EGLint errorCode, EGLint id, const char *msg, ...)
+ : mCode(errorCode),
+ mID(id),
+ mMessage(nullptr)
+{
+ va_list vararg;
+ va_start(vararg, msg);
+ createMessageString();
+ *mMessage = FormatString(msg, vararg);
+ va_end(vararg);
+}
+void Error::createMessageString() const
+{
+ if (mMessage == nullptr)
+ {
+ mMessage = new std::string();
+ }
+}
+
+const std::string &Error::getMessage() const
+{
+ createMessageString();
+ return *mMessage;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h
new file mode 100644
index 0000000000..896b777567
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Error.h
@@ -0,0 +1,83 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.h: Defines the egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#ifndef LIBANGLE_ERROR_H_
+#define LIBANGLE_ERROR_H_
+
+#include "angle_gl.h"
+#include "common/platform.h"
+#include <EGL/egl.h>
+
+#include <string>
+
+namespace gl
+{
+
+class Error final
+{
+ public:
+ explicit inline Error(GLenum errorCode);
+ Error(GLenum errorCode, const char *msg, ...);
+ inline Error(const Error &other);
+ inline Error(Error &&other);
+
+ inline ~Error();
+
+ inline Error &operator=(const Error &other);
+ inline Error &operator=(Error &&other);
+
+ inline GLenum getCode() const;
+ inline bool isError() const;
+
+ const std::string &getMessage() const;
+
+ private:
+ void createMessageString() const;
+
+ GLenum mCode;
+ mutable std::string *mMessage;
+};
+
+}
+
+namespace egl
+{
+
+class Error final
+{
+ public:
+ explicit inline Error(EGLint errorCode);
+ Error(EGLint errorCode, const char *msg, ...);
+ Error(EGLint errorCode, EGLint id, const char *msg, ...);
+ inline Error(const Error &other);
+ inline Error(Error &&other);
+
+ inline ~Error();
+
+ inline Error &operator=(const Error &other);
+ inline Error &operator=(Error &&other);
+
+ inline EGLint getCode() const;
+ inline EGLint getID() const;
+ inline bool isError() const;
+
+ const std::string &getMessage() const;
+
+ private:
+ void createMessageString() const;
+
+ EGLint mCode;
+ EGLint mID;
+ mutable std::string *mMessage;
+};
+
+}
+
+#include "Error.inl"
+
+#endif // LIBANGLE_ERROR_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Error.inl b/src/3rdparty/angle/src/libANGLE/Error.inl
new file mode 100644
index 0000000000..32e8f05828
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Error.inl
@@ -0,0 +1,163 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Error.inl: Inline definitions of egl::Error and gl::Error classes which encapsulate API errors
+// and optional error messages.
+
+#include "common/angleutils.h"
+
+#include <cstdarg>
+
+namespace gl
+{
+
+Error::Error(GLenum errorCode)
+ : mCode(errorCode),
+ mMessage(nullptr)
+{
+}
+
+Error::Error(const Error &other)
+ : mCode(other.mCode),
+ mMessage(nullptr)
+{
+ if (other.mMessage != nullptr)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+}
+
+Error::Error(Error &&other)
+ : mCode(other.mCode),
+ mMessage(other.mMessage)
+{
+ other.mMessage = nullptr;
+}
+
+Error::~Error()
+{
+ SafeDelete(mMessage);
+}
+
+Error &Error::operator=(const Error &other)
+{
+ mCode = other.mCode;
+
+ if (other.mMessage != nullptr)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+ else
+ {
+ SafeDelete(mMessage);
+ }
+
+ return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+ mCode = other.mCode;
+ mMessage = other.mMessage;
+
+ other.mMessage = nullptr;
+
+ return *this;
+}
+
+GLenum Error::getCode() const
+{
+ return mCode;
+}
+
+bool Error::isError() const
+{
+ return (mCode != GL_NO_ERROR);
+}
+
+}
+
+namespace egl
+{
+
+Error::Error(EGLint errorCode)
+ : mCode(errorCode),
+ mID(0),
+ mMessage(nullptr)
+{
+}
+
+Error::Error(const Error &other)
+ : mCode(other.mCode),
+ mID(other.mID),
+ mMessage(nullptr)
+{
+ if (other.mMessage != nullptr)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+}
+
+Error::Error(Error &&other)
+ : mCode(other.mCode),
+ mID(other.mID),
+ mMessage(other.mMessage)
+{
+ other.mMessage = nullptr;
+}
+
+Error::~Error()
+{
+ SafeDelete(mMessage);
+}
+
+Error &Error::operator=(const Error &other)
+{
+ mCode = other.mCode;
+ mID = other.mID;
+
+ if (other.mMessage != nullptr)
+ {
+ createMessageString();
+ *mMessage = *(other.mMessage);
+ }
+ else
+ {
+ SafeDelete(mMessage);
+ }
+
+ return *this;
+}
+
+Error &Error::operator=(Error &&other)
+{
+ mCode = other.mCode;
+ mID = other.mID;
+ mMessage = other.mMessage;
+
+ other.mMessage = nullptr;
+
+ return *this;
+}
+
+EGLint Error::getCode() const
+{
+ return mCode;
+}
+
+EGLint Error::getID() const
+{
+ return mID;
+}
+
+bool Error::isError() const
+{
+ return (mCode != EGL_SUCCESS);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.cpp b/src/3rdparty/angle/src/libANGLE/Fence.cpp
index 966a327de5..8ab4cc9daa 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Fence.cpp
@@ -7,10 +7,11 @@
// Fence.cpp: Implements the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/renderer/FenceImpl.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/Fence.h"
+
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
+#include "libANGLE/renderer/Renderer.h"
#include "common/utilities.h"
#include "angle_gl.h"
diff --git a/src/3rdparty/angle/src/libGLESv2/Fence.h b/src/3rdparty/angle/src/libANGLE/Fence.h
index fd565e96a6..bcd66b6831 100644
--- a/src/3rdparty/angle/src/libGLESv2/Fence.h
+++ b/src/3rdparty/angle/src/libANGLE/Fence.h
@@ -7,13 +7,13 @@
// Fence.h: Defines the gl::FenceNV and gl::FenceSync classes, which support the GL_NV_fence
// extension and GLES3 sync objects.
-#ifndef LIBGLESV2_FENCE_H_
-#define LIBGLESV2_FENCE_H_
+#ifndef LIBANGLE_FENCE_H_
+#define LIBANGLE_FENCE_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
namespace rx
{
@@ -24,7 +24,7 @@ class FenceSyncImpl;
namespace gl
{
-class FenceNV
+class FenceNV final : angle::NonCopyable
{
public:
explicit FenceNV(rx::FenceNVImpl *impl);
@@ -36,11 +36,9 @@ class FenceNV
Error finishFence();
GLboolean getStatus() const { return mStatus; }
- GLuint getCondition() const { return mCondition; }
+ GLenum getCondition() const { return mCondition; }
private:
- DISALLOW_COPY_AND_ASSIGN(FenceNV);
-
rx::FenceNVImpl *mFence;
bool mIsSet;
@@ -49,7 +47,7 @@ class FenceNV
GLenum mCondition;
};
-class FenceSync : public RefCountObject
+class FenceSync final : public RefCountObject
{
public:
explicit FenceSync(rx::FenceSyncImpl *impl, GLuint id);
@@ -60,11 +58,9 @@ class FenceSync : public RefCountObject
Error serverWait(GLbitfield flags, GLuint64 timeout);
Error getStatus(GLint *outResult) const;
- GLuint getCondition() const { return mCondition; }
+ GLenum getCondition() const { return mCondition; }
private:
- DISALLOW_COPY_AND_ASSIGN(FenceSync);
-
rx::FenceSyncImpl *mFence;
GLenum mCondition;
@@ -72,4 +68,4 @@ class FenceSync : public RefCountObject
}
-#endif // LIBGLESV2_FENCE_H_
+#endif // LIBANGLE_FENCE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp
index 5bf7b3fce8..5bf7b3fce8 100644
--- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Float16ToFloat32.cpp
diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
new file mode 100644
index 0000000000..b1dd4a1b0f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
@@ -0,0 +1,658 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#include "libANGLE/Framebuffer.h"
+
+#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+#include "libANGLE/renderer/Workarounds.h"
+
+namespace gl
+{
+
+namespace
+{
+void DeleteMatchingAttachment(FramebufferAttachment *&attachment, GLenum matchType, GLuint matchId)
+{
+ if (attachment && attachment->type() == matchType && attachment->id() == matchId)
+ {
+ SafeDelete(attachment);
+ }
+}
+}
+
+Framebuffer::Data::Data(const Caps &caps)
+ : mColorAttachments(caps.maxColorAttachments, nullptr),
+ mDepthAttachment(nullptr),
+ mStencilAttachment(nullptr),
+ mDrawBufferStates(caps.maxDrawBuffers, GL_NONE),
+ mReadBufferState(GL_COLOR_ATTACHMENT0_EXT)
+{
+ mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
+}
+
+Framebuffer::Data::~Data()
+{
+ for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it)
+ {
+ SafeDelete(*it);
+ }
+ SafeDelete(mDepthAttachment);
+ SafeDelete(mStencilAttachment);
+}
+
+FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
+{
+ ASSERT(mReadBufferState == GL_BACK || (mReadBufferState >= GL_COLOR_ATTACHMENT0 && mReadBufferState <= GL_COLOR_ATTACHMENT15));
+ size_t readIndex = (mReadBufferState == GL_BACK ? 0 : static_cast<size_t>(mReadBufferState - GL_COLOR_ATTACHMENT0));
+ ASSERT(readIndex < mColorAttachments.size());
+ return mColorAttachments[readIndex];
+}
+
+FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
+{
+ for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it)
+ {
+ if (*it != nullptr)
+ {
+ return *it;
+ }
+ }
+
+ return nullptr;
+}
+
+FramebufferAttachment *Framebuffer::Data::getDepthOrStencilAttachment() const
+{
+ return (mDepthAttachment != nullptr ? mDepthAttachment : mStencilAttachment);
+}
+
+Framebuffer::Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id)
+ : mData(caps),
+ mImpl(nullptr),
+ mId(id)
+{
+ if (mId == 0)
+ {
+ mImpl = factory->createDefaultFramebuffer(mData);
+ }
+ else
+ {
+ mImpl = factory->createFramebuffer(mData);
+ }
+ ASSERT(mImpl != nullptr);
+}
+
+Framebuffer::~Framebuffer()
+{
+ SafeDelete(mImpl);
+}
+
+void Framebuffer::detachTexture(GLuint textureId)
+{
+ detachResourceById(GL_TEXTURE, textureId);
+}
+
+void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
+{
+ detachResourceById(GL_RENDERBUFFER, renderbufferId);
+}
+
+void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
+{
+ for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it)
+ {
+ DeleteMatchingAttachment(*it, resourceType, resourceId);
+ }
+
+ DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId);
+ DeleteMatchingAttachment(mData.mStencilAttachment, resourceType, resourceId);
+}
+
+FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
+{
+ ASSERT(colorAttachment < mData.mColorAttachments.size());
+ return mData.mColorAttachments[colorAttachment];
+}
+
+FramebufferAttachment *Framebuffer::getDepthbuffer() const
+{
+ return mData.mDepthAttachment;
+}
+
+FramebufferAttachment *Framebuffer::getStencilbuffer() const
+{
+ return mData.mStencilAttachment;
+}
+
+FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
+{
+ return (hasValidDepthStencil() ? mData.mDepthAttachment : NULL);
+}
+
+FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
+{
+ return mData.getDepthOrStencilAttachment();
+}
+
+FramebufferAttachment *Framebuffer::getReadColorbuffer() const
+{
+ return mData.getReadAttachment();
+}
+
+GLenum Framebuffer::getReadColorbufferType() const
+{
+ FramebufferAttachment *readAttachment = mData.getReadAttachment();
+ return (readAttachment ? readAttachment->type() : GL_NONE);
+}
+
+FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
+{
+ return mData.getFirstColorAttachment();
+}
+
+FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
+ {
+ return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_COLOR:
+ case GL_BACK:
+ return getColorbuffer(0);
+ case GL_DEPTH:
+ case GL_DEPTH_ATTACHMENT:
+ return getDepthbuffer();
+ case GL_STENCIL:
+ case GL_STENCIL_ATTACHMENT:
+ return getStencilbuffer();
+ case GL_DEPTH_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ return getDepthStencilBuffer();
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+ }
+}
+
+GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
+{
+ ASSERT(colorAttachment < mData.mDrawBufferStates.size());
+ return mData.mDrawBufferStates[colorAttachment];
+}
+
+void Framebuffer::setDrawBuffers(size_t count, const GLenum *buffers)
+{
+ auto &drawStates = mData.mDrawBufferStates;
+
+ ASSERT(count <= drawStates.size());
+ std::copy(buffers, buffers + count, drawStates.begin());
+ std::fill(drawStates.begin() + count, drawStates.end(), GL_NONE);
+ mImpl->setDrawBuffers(count, buffers);
+}
+
+GLenum Framebuffer::getReadBufferState() const
+{
+ return mData.mReadBufferState;
+}
+
+void Framebuffer::setReadBuffer(GLenum buffer)
+{
+ ASSERT(buffer == GL_BACK || buffer == GL_NONE ||
+ (buffer >= GL_COLOR_ATTACHMENT0 &&
+ (buffer - GL_COLOR_ATTACHMENT0) < mData.mColorAttachments.size()));
+ mData.mReadBufferState = buffer;
+ mImpl->setReadBuffer(buffer);
+}
+
+bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
+{
+ ASSERT(colorAttachment < mData.mColorAttachments.size());
+ return (mData.mColorAttachments[colorAttachment] &&
+ mData.mDrawBufferStates[colorAttachment] != GL_NONE);
+}
+
+bool Framebuffer::hasEnabledColorAttachment() const
+{
+ for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
+ {
+ if (isEnabledColorAttachment(colorAttachment))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool Framebuffer::hasStencil() const
+{
+ return (mData.mStencilAttachment && mData.mStencilAttachment->getStencilSize() > 0);
+}
+
+bool Framebuffer::usingExtendedDrawBuffers() const
+{
+ for (size_t colorAttachment = 1; colorAttachment < mData.mColorAttachments.size(); ++colorAttachment)
+ {
+ if (isEnabledColorAttachment(colorAttachment))
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+GLenum Framebuffer::checkStatus(const gl::Data &data) const
+{
+ // The default framebuffer *must* always be complete, though it may not be
+ // subject to the same rules as application FBOs. ie, it could have 0x0 size.
+ if (mId == 0)
+ {
+ return GL_FRAMEBUFFER_COMPLETE;
+ }
+
+ int width = 0;
+ int height = 0;
+ unsigned int colorbufferSize = 0;
+ int samples = -1;
+ bool missingAttachment = true;
+
+ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
+ const auto &colorAttachment = *it;
+ if (colorAttachment != nullptr)
+ {
+ if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ GLenum internalformat = colorAttachment->getInternalFormat();
+ const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (colorAttachment->type() == GL_TEXTURE)
+ {
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (colorAttachment->type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (!missingAttachment)
+ {
+ // all color attachments must have the same width and height
+ if (colorAttachment->getWidth() != width || colorAttachment->getHeight() != height)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+
+ // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
+ // all color attachments have the same number of samples for the FBO to be complete.
+ if (colorAttachment->getSamples() != samples)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
+ }
+
+ // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
+ // in GLES 3.0, there is no such restriction
+ if (data.clientVersion < 3)
+ {
+ if (formatInfo.pixelBytes != colorbufferSize)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+ else
+ {
+ width = colorAttachment->getWidth();
+ height = colorAttachment->getHeight();
+ samples = colorAttachment->getSamples();
+ colorbufferSize = formatInfo.pixelBytes;
+ missingAttachment = false;
+ }
+ }
+ }
+
+ const FramebufferAttachment *depthAttachment = mData.mDepthAttachment;
+ if (depthAttachment != nullptr)
+ {
+ if (depthAttachment->getWidth() == 0 || depthAttachment->getHeight() == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ GLenum internalformat = depthAttachment->getInternalFormat();
+ const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (depthAttachment->type() == GL_TEXTURE)
+ {
+ // depth texture attachments require OES/ANGLE_depth_texture
+ if (!data.extensions->depthTextures)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ if (formatInfo.depthBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (depthAttachment->type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || formatInfo.depthBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (missingAttachment)
+ {
+ width = depthAttachment->getWidth();
+ height = depthAttachment->getHeight();
+ samples = depthAttachment->getSamples();
+ missingAttachment = false;
+ }
+ else if (width != depthAttachment->getWidth() || height != depthAttachment->getHeight())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+ else if (samples != depthAttachment->getSamples())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+ }
+
+ const FramebufferAttachment *stencilAttachment = mData.mStencilAttachment;
+ if (stencilAttachment)
+ {
+ if (stencilAttachment->getWidth() == 0 || stencilAttachment->getHeight() == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ GLenum internalformat = stencilAttachment->getInternalFormat();
+ const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (stencilAttachment->type() == GL_TEXTURE)
+ {
+ // texture stencil attachments come along as part
+ // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
+ if (!data.extensions->depthTextures)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+
+ if (!formatCaps.renderable)
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ if (formatInfo.stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+ else if (stencilAttachment->type() == GL_RENDERBUFFER)
+ {
+ if (!formatCaps.renderable || formatInfo.stencilBits == 0)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
+ }
+ }
+
+ if (missingAttachment)
+ {
+ width = stencilAttachment->getWidth();
+ height = stencilAttachment->getHeight();
+ samples = stencilAttachment->getSamples();
+ missingAttachment = false;
+ }
+ else if (width != stencilAttachment->getWidth() || height != stencilAttachment->getHeight())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
+ }
+ else if (samples != stencilAttachment->getSamples())
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
+ }
+ }
+
+ // if we have both a depth and stencil buffer, they must refer to the same object
+ // since we only support packed_depth_stencil and not separate depth and stencil
+ if (depthAttachment && stencilAttachment && !hasValidDepthStencil())
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+
+ // we need to have at least one attachment to be complete
+ if (missingAttachment)
+ {
+ return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
+ }
+
+ return mImpl->checkStatus();
+}
+
+Error Framebuffer::invalidate(size_t count, const GLenum *attachments)
+{
+ return mImpl->invalidate(count, attachments);
+}
+
+Error Framebuffer::invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area)
+{
+ return mImpl->invalidateSub(count, attachments, area);
+}
+
+Error Framebuffer::clear(const gl::Data &data, GLbitfield mask)
+{
+ return mImpl->clear(data, mask);
+}
+
+Error Framebuffer::clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+ return mImpl->clearBufferfv(state, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+ return mImpl->clearBufferuiv(state, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+ return mImpl->clearBufferiv(state, buffer, drawbuffer, values);
+}
+
+Error Framebuffer::clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ return mImpl->clearBufferfi(state, buffer, drawbuffer, depth, stencil);
+}
+
+GLenum Framebuffer::getImplementationColorReadFormat() const
+{
+ return mImpl->getImplementationColorReadFormat();
+}
+
+GLenum Framebuffer::getImplementationColorReadType() const
+{
+ return mImpl->getImplementationColorReadType();
+}
+
+Error Framebuffer::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
+{
+ return mImpl->readPixels(state, area, format, type, pixels);
+}
+
+Error Framebuffer::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
+{
+ return mImpl->blit(state, sourceArea, destArea, mask, filter, sourceFramebuffer);
+}
+
+int Framebuffer::getSamples(const gl::Data &data) const
+{
+ if (checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
+ {
+ // for a complete framebuffer, all attachments must have the same sample count
+ // in this case return the first nonzero sample size
+ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
+ if (*it != nullptr)
+ {
+ return (*it)->getSamples();
+ }
+ }
+ }
+
+ return 0;
+}
+
+bool Framebuffer::hasValidDepthStencil() const
+{
+ // A valid depth-stencil attachment has the same resource bound to both the
+ // depth and stencil attachment points.
+ return (mData.mDepthAttachment && mData.mStencilAttachment &&
+ mData.mDepthAttachment->type() == mData.mStencilAttachment->type() &&
+ mData.mDepthAttachment->id() == mData.mStencilAttachment->id());
+}
+
+void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
+{
+ setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex));
+}
+
+void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
+{
+ setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer));
+}
+
+void Framebuffer::setNULLAttachment(GLenum attachment)
+{
+ setAttachment(attachment, NULL);
+}
+
+void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
+{
+ if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + mData.mColorAttachments.size()))
+ {
+ size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
+ SafeDelete(mData.mColorAttachments[colorAttachment]);
+ mData.mColorAttachments[colorAttachment] = attachmentObj;
+ mImpl->setColorAttachment(colorAttachment, attachmentObj);
+ }
+ else if (attachment == GL_BACK)
+ {
+ SafeDelete(mData.mColorAttachments[0]);
+ mData.mColorAttachments[0] = attachmentObj;
+ mImpl->setColorAttachment(0, attachmentObj);
+ }
+ else if (attachment == GL_DEPTH_ATTACHMENT || attachment == GL_DEPTH)
+ {
+ SafeDelete(mData.mDepthAttachment);
+ mData.mDepthAttachment = attachmentObj;
+ mImpl->setDepthAttachment(attachmentObj);
+ }
+ else if (attachment == GL_STENCIL_ATTACHMENT || attachment == GL_STENCIL)
+ {
+ SafeDelete(mData.mStencilAttachment);
+ mData.mStencilAttachment = attachmentObj;
+ mImpl->setStencilAttachment(attachmentObj);
+ }
+ else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT || attachment == GL_DEPTH_STENCIL)
+ {
+ SafeDelete(mData.mDepthAttachment);
+ SafeDelete(mData.mStencilAttachment);
+
+ // ensure this is a legitimate depth+stencil format
+ if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
+ {
+ mData.mDepthAttachment = attachmentObj;
+ mImpl->setDepthAttachment(attachmentObj);
+
+ // Make a new attachment object to ensure we do not double-delete
+ // See angle issue 686
+ if (attachmentObj->type() == GL_TEXTURE)
+ {
+ mData.mStencilAttachment = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(),
+ *attachmentObj->getTextureImageIndex());
+ mImpl->setStencilAttachment(mData.mStencilAttachment);
+ }
+ else if (attachmentObj->type() == GL_RENDERBUFFER)
+ {
+ mData.mStencilAttachment = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer());
+ mImpl->setStencilAttachment(mData.mStencilAttachment);
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+}
+
+DefaultFramebuffer::DefaultFramebuffer(const Caps &caps, rx::ImplFactory *factory, egl::Surface *surface)
+ : Framebuffer(caps, factory, 0)
+{
+ const egl::Config *config = surface->getConfig();
+
+ setAttachment(GL_BACK, new DefaultAttachment(GL_BACK, surface));
+
+ if (config->depthSize > 0)
+ {
+ setAttachment(GL_DEPTH, new DefaultAttachment(GL_DEPTH, surface));
+ }
+ if (config->stencilSize > 0)
+ {
+ setAttachment(GL_STENCIL, new DefaultAttachment(GL_STENCIL, surface));
+ }
+
+ GLenum drawBufferState = GL_BACK;
+ setDrawBuffers(1, &drawBufferState);
+
+ setReadBuffer(GL_BACK);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.h b/src/3rdparty/angle/src/libANGLE/Framebuffer.h
new file mode 100644
index 0000000000..8b24cf984e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.h
@@ -0,0 +1,144 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
+// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
+
+#ifndef LIBANGLE_FRAMEBUFFER_H_
+#define LIBANGLE_FRAMEBUFFER_H_
+
+#include <vector>
+
+#include "common/angleutils.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace rx
+{
+class ImplFactory;
+class FramebufferImpl;
+class RenderbufferImpl;
+struct Workarounds;
+}
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+class FramebufferAttachment;
+class Renderbuffer;
+class State;
+class Texture;
+class TextureCapsMap;
+struct Caps;
+struct Data;
+struct Extensions;
+struct ImageIndex;
+struct Rectangle;
+
+typedef std::vector<FramebufferAttachment *> AttachmentList;
+
+class Framebuffer
+{
+ public:
+
+ class Data final : angle::NonCopyable
+ {
+ public:
+ explicit Data(const Caps &caps);
+ ~Data();
+
+ FramebufferAttachment *getReadAttachment() const;
+ FramebufferAttachment *getFirstColorAttachment() const;
+ FramebufferAttachment *getDepthOrStencilAttachment() const;
+
+ AttachmentList mColorAttachments;
+ FramebufferAttachment *mDepthAttachment;
+ FramebufferAttachment *mStencilAttachment;
+
+ std::vector<GLenum> mDrawBufferStates;
+ GLenum mReadBufferState;
+ };
+
+ Framebuffer(const Caps &caps, rx::ImplFactory *factory, GLuint id);
+ virtual ~Framebuffer();
+
+ const rx::FramebufferImpl *getImplementation() const { return mImpl; }
+ rx::FramebufferImpl *getImplementation() { return mImpl; }
+
+ GLuint id() const { return mId; }
+
+ void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex);
+ void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer);
+ void setNULLAttachment(GLenum attachment);
+
+ void detachTexture(GLuint texture);
+ void detachRenderbuffer(GLuint renderbuffer);
+
+ FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const;
+ FramebufferAttachment *getDepthbuffer() const;
+ FramebufferAttachment *getStencilbuffer() const;
+ FramebufferAttachment *getDepthStencilBuffer() const;
+ FramebufferAttachment *getDepthOrStencilbuffer() const;
+ FramebufferAttachment *getReadColorbuffer() const;
+ GLenum getReadColorbufferType() const;
+ FramebufferAttachment *getFirstColorbuffer() const;
+
+ FramebufferAttachment *getAttachment(GLenum attachment) const;
+
+ GLenum getDrawBufferState(unsigned int colorAttachment) const;
+ void setDrawBuffers(size_t count, const GLenum *buffers);
+
+ GLenum getReadBufferState() const;
+ void setReadBuffer(GLenum buffer);
+
+ bool isEnabledColorAttachment(unsigned int colorAttachment) const;
+ bool hasEnabledColorAttachment() const;
+ bool hasStencil() const;
+ int getSamples(const gl::Data &data) const;
+ bool usingExtendedDrawBuffers() const;
+
+ GLenum checkStatus(const gl::Data &data) const;
+ bool hasValidDepthStencil() const;
+
+ Error invalidate(size_t count, const GLenum *attachments);
+ Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area);
+
+ Error clear(const gl::Data &data, GLbitfield mask);
+ Error clearBufferfv(const State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values);
+ Error clearBufferuiv(const State &state, GLenum buffer, GLint drawbuffer, const GLuint *values);
+ Error clearBufferiv(const State &state, GLenum buffer, GLint drawbuffer, const GLint *values);
+ Error clearBufferfi(const State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+
+ GLenum getImplementationColorReadFormat() const;
+ GLenum getImplementationColorReadType() const;
+ Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const;
+
+ Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer);
+
+ protected:
+ void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj);
+ void detachResourceById(GLenum resourceType, GLuint resourceId);
+
+ Data mData;
+ rx::FramebufferImpl *mImpl;
+ GLuint mId;
+};
+
+class DefaultFramebuffer : public Framebuffer
+{
+ public:
+ DefaultFramebuffer(const gl::Caps &caps, rx::ImplFactory *factory, egl::Surface *surface);
+};
+
+}
+
+#endif // LIBANGLE_FRAMEBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp
index 894884a6d8..e56fc750ad 100644
--- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.cpp
+++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.cpp
@@ -7,15 +7,15 @@
// FramebufferAttachment.cpp: the gl::FramebufferAttachment class and its derived classes
// objects and related functionality. [OpenGL ES 2.0.24] section 4.4.3 page 108.
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "common/utilities.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
namespace gl
{
@@ -33,47 +33,42 @@ FramebufferAttachment::~FramebufferAttachment()
GLuint FramebufferAttachment::getRedSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).redBits > 0) ? GetInternalFormatInfo(getActualFormat()).redBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).redBits;
}
GLuint FramebufferAttachment::getGreenSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).greenBits > 0) ? GetInternalFormatInfo(getActualFormat()).greenBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).greenBits;
}
GLuint FramebufferAttachment::getBlueSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).blueBits > 0) ? GetInternalFormatInfo(getActualFormat()).blueBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).blueBits;
}
GLuint FramebufferAttachment::getAlphaSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).alphaBits > 0) ? GetInternalFormatInfo(getActualFormat()).alphaBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).alphaBits;
}
GLuint FramebufferAttachment::getDepthSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).depthBits > 0) ? GetInternalFormatInfo(getActualFormat()).depthBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).depthBits;
}
GLuint FramebufferAttachment::getStencilSize() const
{
- return (GetInternalFormatInfo(getInternalFormat()).stencilBits > 0) ? GetInternalFormatInfo(getActualFormat()).stencilBits : 0;
+ return GetInternalFormatInfo(getInternalFormat()).stencilBits;
}
GLenum FramebufferAttachment::getComponentType() const
{
- return GetInternalFormatInfo(getActualFormat()).componentType;
+ return GetInternalFormatInfo(getInternalFormat()).componentType;
}
GLenum FramebufferAttachment::getColorEncoding() const
{
- return GetInternalFormatInfo(getActualFormat()).colorEncoding;
-}
-
-bool FramebufferAttachment::isTexture() const
-{
- return (type() != GL_RENDERBUFFER);
+ return GetInternalFormatInfo(getInternalFormat()).colorEncoding;
}
///// TextureAttachment Implementation ////////
@@ -102,27 +97,22 @@ GLuint TextureAttachment::id() const
GLsizei TextureAttachment::getWidth() const
{
- return mTexture->getWidth(mIndex);
+ return mTexture->getWidth(mIndex.type, mIndex.mipIndex);
}
GLsizei TextureAttachment::getHeight() const
{
- return mTexture->getHeight(mIndex);
+ return mTexture->getHeight(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::getInternalFormat() const
{
- return mTexture->getInternalFormat(mIndex);
-}
-
-GLenum TextureAttachment::getActualFormat() const
-{
- return mTexture->getActualFormat(mIndex);
+ return mTexture->getInternalFormat(mIndex.type, mIndex.mipIndex);
}
GLenum TextureAttachment::type() const
{
- return mIndex.type;
+ return GL_TEXTURE;
}
GLint TextureAttachment::mipLevel() const
@@ -130,12 +120,17 @@ GLint TextureAttachment::mipLevel() const
return mIndex.mipIndex;
}
+GLenum TextureAttachment::cubeMapFace() const
+{
+ return IsCubeMapTextureTarget(mIndex.type) ? mIndex.type : GL_NONE;
+}
+
GLint TextureAttachment::layer() const
{
return mIndex.layerIndex;
}
-Texture *TextureAttachment::getTexture()
+Texture *TextureAttachment::getTexture() const
{
return mTexture.get();
}
@@ -145,7 +140,7 @@ const ImageIndex *TextureAttachment::getTextureImageIndex() const
return &mIndex;
}
-Renderbuffer *TextureAttachment::getRenderbuffer()
+Renderbuffer *TextureAttachment::getRenderbuffer() const
{
UNREACHABLE();
return NULL;
@@ -180,11 +175,6 @@ GLenum RenderbufferAttachment::getInternalFormat() const
return mRenderbuffer->getInternalFormat();
}
-GLenum RenderbufferAttachment::getActualFormat() const
-{
- return mRenderbuffer->getActualFormat();
-}
-
GLsizei RenderbufferAttachment::getSamples() const
{
return mRenderbuffer->getSamples();
@@ -205,12 +195,17 @@ GLint RenderbufferAttachment::mipLevel() const
return 0;
}
+GLenum RenderbufferAttachment::cubeMapFace() const
+{
+ return GL_NONE;
+}
+
GLint RenderbufferAttachment::layer() const
{
return 0;
}
-Texture *RenderbufferAttachment::getTexture()
+Texture *RenderbufferAttachment::getTexture() const
{
UNREACHABLE();
return NULL;
@@ -222,9 +217,86 @@ const ImageIndex *RenderbufferAttachment::getTextureImageIndex() const
return NULL;
}
-Renderbuffer *RenderbufferAttachment::getRenderbuffer()
+Renderbuffer *RenderbufferAttachment::getRenderbuffer() const
{
return mRenderbuffer.get();
}
+
+DefaultAttachment::DefaultAttachment(GLenum binding, egl::Surface *surface)
+ : FramebufferAttachment(binding)
+{
+ mSurface.set(surface);
+}
+
+DefaultAttachment::~DefaultAttachment()
+{
+ mSurface.set(nullptr);
+}
+
+GLsizei DefaultAttachment::getWidth() const
+{
+ return mSurface->getWidth();
+}
+
+GLsizei DefaultAttachment::getHeight() const
+{
+ return mSurface->getHeight();
+}
+
+GLenum DefaultAttachment::getInternalFormat() const
+{
+ const egl::Config *config = mSurface->getConfig();
+ return (getBinding() == GL_BACK ? config->renderTargetFormat : config->depthStencilFormat);
+}
+
+GLsizei DefaultAttachment::getSamples() const
+{
+ const egl::Config *config = mSurface->getConfig();
+ return config->samples;
+}
+
+GLuint DefaultAttachment::id() const
+{
+ return 0;
+}
+
+GLenum DefaultAttachment::type() const
+{
+ return GL_FRAMEBUFFER_DEFAULT;
+}
+
+GLint DefaultAttachment::mipLevel() const
+{
+ return 0;
+}
+
+GLenum DefaultAttachment::cubeMapFace() const
+{
+ return GL_NONE;
+}
+
+GLint DefaultAttachment::layer() const
+{
+ return 0;
+}
+
+Texture *DefaultAttachment::getTexture() const
+{
+ UNREACHABLE();
+ return NULL;
+}
+
+const ImageIndex *DefaultAttachment::getTextureImageIndex() const
+{
+ UNREACHABLE();
+ return NULL;
+}
+
+Renderbuffer *DefaultAttachment::getRenderbuffer() const
+{
+ UNREACHABLE();
+ return NULL;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h
index 8d2dafa7ee..0662130931 100644
--- a/src/3rdparty/angle/src/libGLESv2/FramebufferAttachment.h
+++ b/src/3rdparty/angle/src/libANGLE/FramebufferAttachment.h
@@ -7,12 +7,13 @@
// 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_
+#ifndef LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+#define LIBANGLE_FRAMEBUFFERATTACHMENT_H_
+
+#include "libANGLE/Texture.h"
+#include "libANGLE/RefCountObject.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "Texture.h"
#include "angle_gl.h"
@@ -26,7 +27,7 @@ class Renderbuffer;
// Note: Our old naming scheme used the term "Renderbuffer" for both GL renderbuffers and for
// framebuffer attachments, which confused their usage.
-class FramebufferAttachment
+class FramebufferAttachment : angle::NonCopyable
{
public:
explicit FramebufferAttachment(GLenum binding);
@@ -41,10 +42,9 @@ class FramebufferAttachment
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; }
+ bool isTextureWithId(GLuint textureId) const { return type() == GL_TEXTURE && id() == textureId; }
+ bool isRenderbufferWithId(GLuint renderbufferId) const { return type() == GL_RENDERBUFFER && id() == renderbufferId; }
GLenum getBinding() const { return mBinding; }
@@ -52,21 +52,19 @@ class FramebufferAttachment
virtual GLsizei getWidth() const = 0;
virtual GLsizei getHeight() const = 0;
virtual GLenum getInternalFormat() const = 0;
- virtual GLenum getActualFormat() const = 0;
virtual GLsizei getSamples() const = 0;
virtual GLuint id() const = 0;
virtual GLenum type() const = 0;
virtual GLint mipLevel() const = 0;
+ virtual GLenum cubeMapFace() const = 0;
virtual GLint layer() const = 0;
- virtual Texture *getTexture() = 0;
+ virtual Texture *getTexture() const = 0;
virtual const ImageIndex *getTextureImageIndex() const = 0;
- virtual Renderbuffer *getRenderbuffer() = 0;
+ virtual Renderbuffer *getRenderbuffer() const = 0;
private:
- DISALLOW_COPY_AND_ASSIGN(FramebufferAttachment);
-
GLenum mBinding;
};
@@ -82,19 +80,17 @@ class TextureAttachment : public FramebufferAttachment
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
- virtual GLenum getActualFormat() const;
virtual GLenum type() const;
virtual GLint mipLevel() const;
+ virtual GLenum cubeMapFace() const;
virtual GLint layer() const;
- virtual Texture *getTexture();
+ virtual Texture *getTexture() const;
virtual const ImageIndex *getTextureImageIndex() const;
- virtual Renderbuffer *getRenderbuffer();
+ virtual Renderbuffer *getRenderbuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureAttachment);
-
BindingPointer<Texture> mTexture;
ImageIndex mIndex;
};
@@ -109,24 +105,50 @@ class RenderbufferAttachment : public FramebufferAttachment
virtual GLsizei getWidth() const;
virtual GLsizei getHeight() const;
virtual GLenum getInternalFormat() const;
- virtual GLenum getActualFormat() const;
virtual GLsizei getSamples() const;
virtual GLuint id() const;
virtual GLenum type() const;
virtual GLint mipLevel() const;
+ virtual GLenum cubeMapFace() const;
virtual GLint layer() const;
- virtual Texture *getTexture();
+ virtual Texture *getTexture() const;
virtual const ImageIndex *getTextureImageIndex() const;
- virtual Renderbuffer *getRenderbuffer();
+ virtual Renderbuffer *getRenderbuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferAttachment);
-
BindingPointer<Renderbuffer> mRenderbuffer;
};
+class DefaultAttachment : public FramebufferAttachment
+{
+ public:
+ DefaultAttachment(GLenum binding, egl::Surface *surface);
+
+ virtual ~DefaultAttachment();
+
+ virtual GLsizei getWidth() const;
+ virtual GLsizei getHeight() const;
+ virtual GLenum getInternalFormat() const;
+ virtual GLsizei getSamples() const;
+
+ virtual GLuint id() const;
+ virtual GLenum type() const;
+ virtual GLint mipLevel() const;
+ virtual GLenum cubeMapFace() const;
+ virtual GLint layer() const;
+
+ virtual Texture *getTexture() const;
+ virtual const ImageIndex *getTextureImageIndex() const;
+ virtual Renderbuffer *getRenderbuffer() const;
+
+ const egl::Surface *getSurface() const { return mSurface.get(); }
+
+ private:
+ BindingPointer<egl::Surface> mSurface;
+};
+
}
-#endif // LIBGLESV2_FRAMEBUFFERATTACHMENT_H_
+#endif // LIBANGLE_FRAMEBUFFERATTACHMENT_H_
diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
new file mode 100644
index 0000000000..59d3966758
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.cpp
@@ -0,0 +1,133 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
+// to allocate GL handles.
+
+#include "libANGLE/HandleAllocator.h"
+
+#include <algorithm>
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+struct HandleAllocator::HandleRangeComparator
+{
+ bool operator()(const HandleRange &range, GLuint handle) const
+ {
+ return (handle < range.begin);
+ }
+};
+
+HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
+{
+ mUnallocatedList.push_back(HandleRange(1, std::numeric_limits<GLuint>::max() - 1));
+}
+
+HandleAllocator::HandleAllocator(GLuint maximumHandleValue) : mBaseValue(1), mNextValue(1)
+{
+ mUnallocatedList.push_back(HandleRange(1, maximumHandleValue));
+}
+
+HandleAllocator::~HandleAllocator()
+{
+}
+
+void HandleAllocator::setBaseHandle(GLuint value)
+{
+ ASSERT(mBaseValue == mNextValue);
+ mBaseValue = value;
+ mNextValue = value;
+}
+
+GLuint HandleAllocator::allocate()
+{
+ ASSERT(!mUnallocatedList.empty() || !mReleasedList.empty());
+
+ // Allocate from released list, constant time.
+ if (!mReleasedList.empty())
+ {
+ GLuint reusedHandle = mReleasedList.back();
+ mReleasedList.pop_back();
+ return reusedHandle;
+ }
+
+ // Allocate from unallocated list, constant time.
+ auto listIt = mUnallocatedList.begin();
+
+ GLuint freeListHandle = listIt->begin;
+ ASSERT(freeListHandle > 0);
+
+ listIt->begin++;
+ if (listIt->begin == listIt->end)
+ {
+ mUnallocatedList.erase(listIt);
+ }
+
+ return freeListHandle;
+}
+
+void HandleAllocator::release(GLuint handle)
+{
+ // Add to released list, constant time.
+ mReleasedList.push_back(handle);
+}
+
+void HandleAllocator::reserve(GLuint handle)
+{
+ // Clear from released list -- might be a slow operation.
+ if (!mReleasedList.empty())
+ {
+ auto releasedIt = std::find(mReleasedList.begin(), mReleasedList.end(), handle);
+ if (releasedIt != mReleasedList.end())
+ {
+ mReleasedList.erase(releasedIt);
+ return;
+ }
+ }
+
+ // Not in released list, reserve in the unallocated list.
+ auto boundIt = std::lower_bound(mUnallocatedList.begin(), mUnallocatedList.end(), handle, HandleRangeComparator());
+
+ ASSERT(boundIt != mUnallocatedList.end());
+
+ GLuint begin = boundIt->begin;
+ GLuint end = boundIt->end;
+
+ if (handle == begin || handle == end)
+ {
+ if (begin + 1 == end)
+ {
+ mUnallocatedList.erase(boundIt);
+ }
+ else if (handle == begin)
+ {
+ boundIt->begin++;
+ }
+ else
+ {
+ ASSERT(handle == end);
+ boundIt->end--;
+ }
+ return;
+ }
+
+ // need to split the range
+ auto placementIt = mUnallocatedList.erase(boundIt);
+
+ if (begin != handle)
+ {
+ placementIt = mUnallocatedList.insert(placementIt, HandleRange(begin, handle));
+ }
+ if (handle + 1 != end)
+ {
+ mUnallocatedList.insert(placementIt, HandleRange(handle + 1, end));
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/HandleAllocator.h b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h
new file mode 100644
index 0000000000..c22f2ba61a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/HandleAllocator.h
@@ -0,0 +1,63 @@
+//
+// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
+// allocate GL handles.
+
+#ifndef LIBANGLE_HANDLEALLOCATOR_H_
+#define LIBANGLE_HANDLEALLOCATOR_H_
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+#include <stack>
+
+namespace gl
+{
+
+class HandleAllocator final : angle::NonCopyable
+{
+ public:
+ // Maximum handle = MAX_UINT-1
+ HandleAllocator();
+ // Specify maximum handle value
+ HandleAllocator(GLuint maximumHandleValue);
+
+ ~HandleAllocator();
+
+ void setBaseHandle(GLuint value);
+
+ GLuint allocate();
+ void release(GLuint handle);
+ void reserve(GLuint handle);
+
+ private:
+ GLuint mBaseValue;
+ GLuint mNextValue;
+ typedef std::vector<GLuint> HandleList;
+ HandleList mFreeValues;
+
+ struct HandleRange
+ {
+ HandleRange(GLuint beginIn, GLuint endIn) : begin(beginIn), end(endIn) {}
+
+ GLuint begin;
+ GLuint end;
+ };
+
+ struct HandleRangeComparator;
+
+ // The freelist consists of never-allocated handles, stored
+ // as ranges, and handles that were previously allocated and
+ // released, stored in a stack.
+ std::vector<HandleRange> mUnallocatedList;
+ std::vector<GLuint> mReleasedList;
+};
+
+}
+
+#endif // LIBANGLE_HANDLEALLOCATOR_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp
index b45cd9c169..ac7302d121 100644
--- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.cpp
+++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.cpp
@@ -6,8 +6,8 @@
// ImageIndex.cpp: Implementation for ImageIndex methods.
-#include "libGLESv2/ImageIndex.h"
-#include "libGLESv2/Texture.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/Constants.h"
#include "common/utilities.h"
namespace gl
@@ -34,8 +34,8 @@ ImageIndex ImageIndex::Make2D(GLint mipIndex)
ImageIndex ImageIndex::MakeCube(GLenum target, GLint mipIndex)
{
- ASSERT(gl::IsCubemapTextureTarget(target));
- return ImageIndex(target, mipIndex, TextureCubeMap::targetToLayerIndex(target));
+ ASSERT(gl::IsCubeMapTextureTarget(target));
+ return ImageIndex(target, mipIndex, CubeMapTextureTargetToLayerIndex(target));
}
ImageIndex ImageIndex::Make2DArray(GLint mipIndex, GLint layerIndex)
@@ -48,11 +48,33 @@ ImageIndex ImageIndex::Make3D(GLint mipIndex, GLint layerIndex)
return ImageIndex(GL_TEXTURE_3D, mipIndex, layerIndex);
}
+ImageIndex ImageIndex::MakeGeneric(GLenum target, GLint mipIndex)
+{
+ GLint layerIndex = IsCubeMapTextureTarget(target) ? CubeMapTextureTargetToLayerIndex(target) : ENTIRE_LEVEL;
+ return ImageIndex(target, mipIndex, layerIndex);
+}
+
ImageIndex ImageIndex::MakeInvalid()
{
return ImageIndex(GL_NONE, -1, -1);
}
+bool ImageIndex::operator<(const ImageIndex &other) const
+{
+ if (type != other.type)
+ {
+ return type < other.type;
+ }
+ else if (mipIndex != other.mipIndex)
+ {
+ return mipIndex < other.mipIndex;
+ }
+ else
+ {
+ return layerIndex < other.layerIndex;
+ }
+}
+
ImageIndex::ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn)
: type(typeIn),
mipIndex(mipIndexIn),
@@ -134,7 +156,7 @@ ImageIndex ImageIndexIterator::current() const
if (mType == GL_TEXTURE_CUBE_MAP)
{
- value.type = TextureCubeMap::layerIndexToTarget(mCurrentLayer);
+ value.type = LayerIndexToCubeMapTextureTarget(mCurrentLayer);
}
return value;
diff --git a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h b/src/3rdparty/angle/src/libANGLE/ImageIndex.h
index 8bb14fd555..820c650f20 100644
--- a/src/3rdparty/angle/src/libGLESv2/ImageIndex.h
+++ b/src/3rdparty/angle/src/libANGLE/ImageIndex.h
@@ -6,22 +6,24 @@
// ImageIndex.h: A helper struct for indexing into an Image array
-#ifndef LIBGLESV2_IMAGE_INDEX_H_
-#define LIBGLESV2_IMAGE_INDEX_H_
+#ifndef LIBANGLE_IMAGE_INDEX_H_
+#define LIBANGLE_IMAGE_INDEX_H_
-#include "angle_gl.h"
#include "common/mathutil.h"
+#include "angle_gl.h"
+
namespace gl
{
+class ImageIndexIterator;
+
struct ImageIndex
{
GLenum type;
GLint mipIndex;
GLint layerIndex;
- ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
ImageIndex(const ImageIndex &other);
ImageIndex &operator=(const ImageIndex &other);
@@ -31,9 +33,18 @@ struct ImageIndex
static ImageIndex MakeCube(GLenum target, GLint mipIndex);
static ImageIndex Make2DArray(GLint mipIndex, GLint layerIndex);
static ImageIndex Make3D(GLint mipIndex, GLint layerIndex = ENTIRE_LEVEL);
+ static ImageIndex MakeGeneric(GLenum target, GLint mipIndex);
+
static ImageIndex MakeInvalid();
static const GLint ENTIRE_LEVEL = static_cast<GLint>(-1);
+
+ bool operator<(const ImageIndex &other) const;
+
+ private:
+ friend class ImageIndexIterator;
+
+ ImageIndex(GLenum typeIn, GLint mipIndexIn, GLint layerIndexIn);
};
class ImageIndexIterator
@@ -65,4 +76,4 @@ class ImageIndexIterator
}
-#endif // LIBGLESV2_IMAGE_INDEX_H_
+#endif // LIBANGLE_IMAGE_INDEX_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Platform.cpp b/src/3rdparty/angle/src/libANGLE/Platform.cpp
new file mode 100644
index 0000000000..ab75bbba5a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Platform.cpp
@@ -0,0 +1,35 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Platform.cpp: Implementation methods for angle::Platform.
+
+#include <platform/Platform.h>
+
+#include "common/debug.h"
+
+namespace
+{
+angle::Platform *currentPlatform = nullptr;
+}
+
+// static
+ANGLE_EXPORT angle::Platform *ANGLEPlatformCurrent()
+{
+ return currentPlatform;
+}
+
+// static
+ANGLE_EXPORT void ANGLEPlatformInitialize(angle::Platform *platformImpl)
+{
+ ASSERT(platformImpl != nullptr);
+ currentPlatform = platformImpl;
+}
+
+// static
+ANGLE_EXPORT void ANGLEPlatformShutdown()
+{
+ currentPlatform = nullptr;
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libANGLE/Program.cpp
index 6d64b38b56..daf0a403f0 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Program.cpp
@@ -7,30 +7,24 @@
// Program.cpp: Implements the gl::Program class. Implements GL program objects
// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-#include "libGLESv2/BinaryStream.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/ShaderExecutable.h"
+#include "libANGLE/Program.h"
+
+#include <algorithm>
#include "common/debug.h"
-#include "common/version.h"
-#include "common/utilities.h"
#include "common/platform.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/renderer/ProgramImpl.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/Buffer.h"
-#include "common/blocklayout.h"
-#include "common/features.h"
+#include "common/utilities.h"
+#include "common/version.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/ProgramImpl.h"
namespace gl
{
+const char * const g_fakepath = "C:\\fakepath";
namespace
{
@@ -53,353 +47,403 @@ unsigned int ParseAndStripArrayIndex(std::string* name)
}
-VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
- : name(name), element(element), index(index)
+AttributeBindings::AttributeBindings()
{
}
-LinkedVarying::LinkedVarying()
+AttributeBindings::~AttributeBindings()
{
}
-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)
+InfoLog::InfoLog() : mInfoLog(NULL)
{
}
-LinkResult::LinkResult(bool linkSuccess, const Error &error)
- : linkSuccess(linkSuccess),
- error(error)
+InfoLog::~InfoLog()
{
+ delete[] mInfoLog;
}
-unsigned int ProgramBinary::mCurrentSerial = 1;
-ProgramBinary::ProgramBinary(rx::ProgramImpl *impl)
- : RefCountObject(0),
- mProgram(impl),
- mValidated(false),
- mSerial(issueSerial())
+int InfoLog::getLength() const
{
- ASSERT(impl);
-
- for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+ if (!mInfoLog)
{
- mSemanticIndex[index] = -1;
+ return 0;
+ }
+ else
+ {
+ return strlen(mInfoLog) + 1;
}
}
-ProgramBinary::~ProgramBinary()
+void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
{
- reset();
- SafeDelete(mProgram);
-}
+ int index = 0;
-unsigned int ProgramBinary::getSerial() const
-{
- return mSerial;
-}
+ if (bufSize > 0)
+ {
+ if (mInfoLog)
+ {
+ index = std::min(bufSize - 1, (int)strlen(mInfoLog));
+ memcpy(infoLog, mInfoLog, index);
+ }
-unsigned int ProgramBinary::issueSerial()
-{
- return mCurrentSerial++;
+ infoLog[index] = '\0';
+ }
+
+ if (length)
+ {
+ *length = index;
+ }
}
-GLuint ProgramBinary::getAttributeLocation(const char *name)
+// append a santized message to the program info log.
+// The D3D compiler includes a fake file path in some of the warning or error
+// messages, so lets remove all occurrences of this fake file path from the log.
+void InfoLog::appendSanitized(const char *message)
{
- if (name)
+ std::string msg(message);
+
+ size_t found;
+ do
{
- for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
+ found = msg.find(g_fakepath);
+ if (found != std::string::npos)
{
- if (mLinkedAttribute[index].name == std::string(name))
- {
- return index;
- }
+ msg.erase(found, strlen(g_fakepath));
}
}
+ while (found != std::string::npos);
- return -1;
+ append("%s", msg.c_str());
}
-int ProgramBinary::getSemanticIndex(int attributeIndex)
+void InfoLog::append(const char *format, ...)
{
- ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
+ if (!format)
+ {
+ return;
+ }
- return mSemanticIndex[attributeIndex];
-}
+ va_list vararg;
+ va_start(vararg, format);
+ size_t infoLength = vsnprintf(NULL, 0, format, vararg);
+ va_end(vararg);
-// Returns one more than the highest sampler index used.
-GLint ProgramBinary::getUsedSamplerRange(SamplerType type)
-{
- return mProgram->getUsedSamplerRange(type);
-}
+ char *logPointer = NULL;
-bool ProgramBinary::usesPointSize() const
-{
- return mProgram->usesPointSize();
+ if (!mInfoLog)
+ {
+ mInfoLog = new char[infoLength + 2];
+ logPointer = mInfoLog;
+ }
+ else
+ {
+ size_t currentlogLength = strlen(mInfoLog);
+ char *newLog = new char[currentlogLength + infoLength + 2];
+ strcpy(newLog, mInfoLog);
+
+ delete[] mInfoLog;
+ mInfoLog = newLog;
+
+ logPointer = mInfoLog + currentlogLength;
+ }
+
+ va_start(vararg, format);
+ vsnprintf(logPointer, infoLength, format, vararg);
+ va_end(vararg);
+
+ logPointer[infoLength] = 0;
+ strcpy(logPointer + infoLength, "\n");
}
-GLint ProgramBinary::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
+void InfoLog::reset()
{
- return mProgram->getSamplerMapping(type, samplerIndex, caps);
+ if (mInfoLog)
+ {
+ delete [] mInfoLog;
+ mInfoLog = NULL;
+ }
}
-GLenum ProgramBinary::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
+VariableLocation::VariableLocation()
+ : name(), element(0), index(0)
{
- return mProgram->getSamplerTextureType(type, samplerIndex);
}
-GLint ProgramBinary::getUniformLocation(std::string name)
+VariableLocation::VariableLocation(const std::string &name, unsigned int element, unsigned int index)
+ : name(name), element(element), index(index)
{
- return mProgram->getUniformLocation(name);
}
-GLuint ProgramBinary::getUniformIndex(std::string name)
+LinkedVarying::LinkedVarying()
{
- return mProgram->getUniformIndex(name);
}
-GLuint ProgramBinary::getUniformBlockIndex(std::string name)
+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)
{
- return mProgram->getUniformBlockIndex(name);
}
-UniformBlock *ProgramBinary::getUniformBlockByIndex(GLuint blockIndex)
+Program::Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle)
+ : mProgram(impl),
+ mValidated(false),
+ mTransformFeedbackVaryings(),
+ mTransformFeedbackBufferMode(GL_NONE),
+ mFragmentShader(NULL),
+ mVertexShader(NULL),
+ mLinked(false),
+ mDeleteStatus(false),
+ mRefCount(0),
+ mResourceManager(manager),
+ mHandle(handle)
{
- return mProgram->getUniformBlockByIndex(blockIndex);
+ ASSERT(mProgram);
+
+ resetUniformBlockBindings();
+ unlink();
}
-GLint ProgramBinary::getFragDataLocation(const char *name) const
+Program::~Program()
{
- std::string baseName(name);
- unsigned int arrayIndex;
- arrayIndex = ParseAndStripArrayIndex(&baseName);
+ unlink(true);
- for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
+ if (mVertexShader != NULL)
{
- const VariableLocation &outputVariable = locationIt->second;
-
- if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
- {
- return static_cast<GLint>(locationIt->first);
- }
+ mVertexShader->release();
}
- return -1;
-}
-
-size_t ProgramBinary::getTransformFeedbackVaryingCount() const
-{
- return mProgram->getTransformFeedbackLinkedVaryings().size();
-}
+ if (mFragmentShader != NULL)
+ {
+ mFragmentShader->release();
+ }
-const LinkedVarying &ProgramBinary::getTransformFeedbackVarying(size_t idx) const
-{
- return mProgram->getTransformFeedbackLinkedVaryings()[idx];
+ SafeDelete(mProgram);
}
-GLenum ProgramBinary::getTransformFeedbackBufferMode() const
+bool Program::attachShader(Shader *shader)
{
- return mProgram->getTransformFeedbackBufferMode();
-}
-
-void ProgramBinary::setUniform1fv(GLint location, GLsizei count, const GLfloat *v) {
- mProgram->setUniform1fv(location, count, v);
-}
-
-void ProgramBinary::setUniform2fv(GLint location, GLsizei count, const GLfloat *v) {
- mProgram->setUniform2fv(location, count, v);
-}
-
-void ProgramBinary::setUniform3fv(GLint location, GLsizei count, const GLfloat *v) {
- mProgram->setUniform3fv(location, count, v);
-}
+ if (shader->getType() == GL_VERTEX_SHADER)
+ {
+ if (mVertexShader)
+ {
+ return false;
+ }
-void ProgramBinary::setUniform4fv(GLint location, GLsizei count, const GLfloat *v) {
- mProgram->setUniform4fv(location, count, v);
-}
+ mVertexShader = shader;
+ mVertexShader->addRef();
+ }
+ else if (shader->getType() == GL_FRAGMENT_SHADER)
+ {
+ if (mFragmentShader)
+ {
+ return false;
+ }
-void ProgramBinary::setUniform1iv(GLint location, GLsizei count, const GLint *v) {
- mProgram->setUniform1iv(location, count, v);
-}
+ mFragmentShader = shader;
+ mFragmentShader->addRef();
+ }
+ else UNREACHABLE();
-void ProgramBinary::setUniform2iv(GLint location, GLsizei count, const GLint *v) {
- mProgram->setUniform2iv(location, count, v);
+ return true;
}
-void ProgramBinary::setUniform3iv(GLint location, GLsizei count, const GLint *v) {
- mProgram->setUniform3iv(location, count, v);
-}
+bool Program::detachShader(Shader *shader)
+{
+ if (shader->getType() == GL_VERTEX_SHADER)
+ {
+ if (mVertexShader != shader)
+ {
+ return false;
+ }
-void ProgramBinary::setUniform4iv(GLint location, GLsizei count, const GLint *v) {
- mProgram->setUniform4iv(location, count, v);
-}
+ mVertexShader->release();
+ mVertexShader = NULL;
+ }
+ else if (shader->getType() == GL_FRAGMENT_SHADER)
+ {
+ if (mFragmentShader != shader)
+ {
+ return false;
+ }
-void ProgramBinary::setUniform1uiv(GLint location, GLsizei count, const GLuint *v) {
- mProgram->setUniform1uiv(location, count, v);
-}
+ mFragmentShader->release();
+ mFragmentShader = NULL;
+ }
+ else UNREACHABLE();
-void ProgramBinary::setUniform2uiv(GLint location, GLsizei count, const GLuint *v) {
- mProgram->setUniform2uiv(location, count, v);
+ return true;
}
-void ProgramBinary::setUniform3uiv(GLint location, GLsizei count, const GLuint *v) {
- mProgram->setUniform3uiv(location, count, v);
+int Program::getAttachedShadersCount() const
+{
+ return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
}
-void ProgramBinary::setUniform4uiv(GLint location, GLsizei count, const GLuint *v) {
- mProgram->setUniform4uiv(location, count, v);
-}
+void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
+{
+ if (index < MAX_VERTEX_ATTRIBS)
+ {
+ for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAttributeBinding[i].erase(name);
+ }
-void ProgramBinary::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix2fv(location, count, transpose, v);
+ mAttributeBinding[index].insert(name);
+ }
}
-void ProgramBinary::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix3fv(location, count, transpose, v);
+void Program::bindAttributeLocation(GLuint index, const char *name)
+{
+ mAttributeBindings.bindAttributeLocation(index, name);
}
-void ProgramBinary::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix4fv(location, count, transpose, v);
-}
+// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
+// compiling them into binaries, determining the attribute mappings, and collecting
+// a list of uniforms
+Error Program::link(const Data &data)
+{
+ unlink(false);
-void ProgramBinary::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
-}
+ mInfoLog.reset();
+ resetUniformBlockBindings();
-void ProgramBinary::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
-}
+ if (!mFragmentShader || !mFragmentShader->isCompiled())
+ {
+ return Error(GL_NO_ERROR);
+ }
+ ASSERT(mFragmentShader->getType() == GL_FRAGMENT_SHADER);
-void ProgramBinary::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
-}
+ if (!mVertexShader || !mVertexShader->isCompiled())
+ {
+ return Error(GL_NO_ERROR);
+ }
+ ASSERT(mVertexShader->getType() == GL_VERTEX_SHADER);
-void ProgramBinary::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
-}
+ if (!linkAttributes(mInfoLog, mAttributeBindings, mVertexShader))
+ {
+ return Error(GL_NO_ERROR);
+ }
-void ProgramBinary::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
-}
+ int registers;
+ std::vector<LinkedVarying> linkedVaryings;
+ rx::LinkResult result = mProgram->link(data, mInfoLog, mFragmentShader, mVertexShader, mTransformFeedbackVaryings, mTransformFeedbackBufferMode,
+ &registers, &linkedVaryings, &mOutputVariables);
+ if (result.error.isError() || !result.linkSuccess)
+ {
+ return result.error;
+ }
-void ProgramBinary::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v) {
- mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
-}
+ if (!mProgram->linkUniforms(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps))
+ {
+ return Error(GL_NO_ERROR);
+ }
-void ProgramBinary::getUniformfv(GLint location, GLfloat *v) {
- mProgram->getUniformfv(location, v);
-}
+ if (!linkUniformBlocks(mInfoLog, *mVertexShader, *mFragmentShader, *data.caps))
+ {
+ return Error(GL_NO_ERROR);
+ }
-void ProgramBinary::getUniformiv(GLint location, GLint *v) {
- mProgram->getUniformiv(location, v);
-}
+ if (!gatherTransformFeedbackLinkedVaryings(mInfoLog, linkedVaryings, mTransformFeedbackVaryings,
+ mTransformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps))
+ {
+ return Error(GL_NO_ERROR);
+ }
-void ProgramBinary::getUniformuiv(GLint location, GLuint *v) {
- mProgram->getUniformuiv(location, v);
-}
+ // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
+ // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
+ result = mProgram->compileProgramExecutables(mInfoLog, mFragmentShader, mVertexShader, registers);
+ if (result.error.isError() || !result.linkSuccess)
+ {
+ mInfoLog.append("Failed to create D3D shaders.");
+ unlink(false);
+ return result.error;
+ }
-void ProgramBinary::updateSamplerMapping()
-{
- return mProgram->updateSamplerMapping();
+ mLinked = true;
+ return gl::Error(GL_NO_ERROR);
}
-// Applies all the uniforms set for this program object to the renderer
-Error ProgramBinary::applyUniforms()
+int AttributeBindings::getAttributeBinding(const std::string &name) const
{
- return mProgram->applyUniforms();
-}
+ for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
+ {
+ if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
+ {
+ return location;
+ }
+ }
-Error ProgramBinary::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const Caps &caps)
-{
- return mProgram->applyUniformBuffers(boundBuffers, caps);
+ return -1;
}
-bool ProgramBinary::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
+// Returns the program object to an unlinked state, before re-linking, or at destruction
+void Program::unlink(bool destroy)
{
- std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
- std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
-
- for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
+ if (destroy) // Object being destructed
{
- PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
- bool matched = false;
-
- // Built-in varyings obey special rules
- if (input->isBuiltIn())
+ if (mFragmentShader)
{
- continue;
+ mFragmentShader->release();
+ mFragmentShader = NULL;
}
- for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
+ if (mVertexShader)
{
- PackedVarying *output = &vertexVaryings[vertVaryingIndex];
- if (output->name == input->name)
- {
- if (!linkValidateVaryings(infoLog, output->name, *input, *output))
- {
- return false;
- }
+ mVertexShader->release();
+ mVertexShader = NULL;
+ }
+ }
- output->registerIndex = input->registerIndex;
- output->columnIndex = input->columnIndex;
+ std::fill(mLinkedAttribute, mLinkedAttribute + ArraySize(mLinkedAttribute), sh::Attribute());
+ mOutputVariables.clear();
- matched = true;
- break;
- }
- }
+ mProgram->reset();
- // We permit unmatched, unreferenced varyings
- if (!matched && input->staticUse)
- {
- infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
- return false;
- }
- }
+ mValidated = false;
- return true;
+ mLinked = false;
}
-LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length)
+bool Program::isLinked()
{
-#if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_DISABLED
- return LinkResult(false, Error(GL_NO_ERROR));
+ return mLinked;
+}
+
+Error Program::loadBinary(GLenum binaryFormat, const void *binary, GLsizei length)
+{
+ unlink(false);
+
+#if ANGLE_PROGRAM_BINARY_LOAD != ANGLE_ENABLED
+ return Error(GL_NO_ERROR);
#else
ASSERT(binaryFormat == mProgram->getBinaryFormat());
- reset();
-
BinaryInputStream stream(binary, length);
GLenum format = stream.readInt<GLenum>();
if (format != mProgram->getBinaryFormat())
{
- infoLog.append("Invalid program binary format.");
- return LinkResult(false, Error(GL_NO_ERROR));
+ mInfoLog.append("Invalid program binary format.");
+ return Error(GL_NO_ERROR);
}
int majorVersion = stream.readInt<int>();
int minorVersion = stream.readInt<int>();
if (majorVersion != ANGLE_MAJOR_VERSION || minorVersion != ANGLE_MINOR_VERSION)
{
- infoLog.append("Invalid program binary version.");
- return LinkResult(false, Error(GL_NO_ERROR));
+ mInfoLog.append("Invalid program binary version.");
+ return Error(GL_NO_ERROR);
}
unsigned char commitString[ANGLE_COMMIT_HASH_SIZE];
stream.readBytes(commitString, ANGLE_COMMIT_HASH_SIZE);
if (memcmp(commitString, ANGLE_COMMIT_HASH, sizeof(unsigned char) * ANGLE_COMMIT_HASH_SIZE) != 0)
{
- infoLog.append("Invalid program binary version.");
- return LinkResult(false, Error(GL_NO_ERROR));
- }
-
- int compileFlags = stream.readInt<int>();
- if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
- {
- infoLog.append("Mismatched compilation flags.");
- return LinkResult(false, Error(GL_NO_ERROR));
+ mInfoLog.append("Invalid program binary version.");
+ return Error(GL_NO_ERROR);
}
for (int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
@@ -408,22 +452,21 @@ LinkResult ProgramBinary::load(InfoLog &infoLog, GLenum binaryFormat, const void
stream.readString(&mLinkedAttribute[i].name);
stream.readInt(&mProgram->getShaderAttributes()[i].type);
stream.readString(&mProgram->getShaderAttributes()[i].name);
- stream.readInt(&mSemanticIndex[i]);
+ stream.readInt(&mProgram->getSemanticIndexes()[i]);
}
- initAttributesByLayout();
-
- LinkResult result = mProgram->load(infoLog, &stream);
+ rx::LinkResult result = mProgram->load(mInfoLog, &stream);
if (result.error.isError() || !result.linkSuccess)
{
- return result;
+ return result.error;
}
- return LinkResult(true, Error(GL_NO_ERROR));
+ mLinked = true;
+ return Error(GL_NO_ERROR);
#endif // #if ANGLE_PROGRAM_BINARY_LOAD == ANGLE_ENABLED
}
-Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length)
+Error Program::saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const
{
if (binaryFormat)
{
@@ -436,7 +479,6 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
stream.writeInt(ANGLE_MAJOR_VERSION);
stream.writeInt(ANGLE_MINOR_VERSION);
stream.writeBytes(reinterpret_cast<const unsigned char*>(ANGLE_COMMIT_HASH), ANGLE_COMMIT_HASH_SIZE);
- stream.writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
for (unsigned int i = 0; i < MAX_VERTEX_ATTRIBS; ++i)
{
@@ -444,10 +486,14 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
stream.writeString(mLinkedAttribute[i].name);
stream.writeInt(mProgram->getShaderAttributes()[i].type);
stream.writeString(mProgram->getShaderAttributes()[i].name);
- stream.writeInt(mSemanticIndex[i]);
+ stream.writeInt(mProgram->getSemanticIndexes()[i]);
}
- mProgram->save(&stream);
+ gl::Error error = mProgram->save(&stream);
+ if (error.isError())
+ {
+ return error;
+ }
GLsizei streamLength = stream.length();
const void *streamData = stream.data();
@@ -467,7 +513,7 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
if (binary)
{
- char *ptr = (char*) binary;
+ char *ptr = reinterpret_cast<char*>(binary);
memcpy(ptr, streamData, streamLength);
ptr += streamLength;
@@ -483,10 +529,10 @@ Error ProgramBinary::save(GLenum *binaryFormat, void *binary, GLsizei bufSize, G
return Error(GL_NO_ERROR);
}
-GLint ProgramBinary::getLength()
+GLint Program::getBinaryLength() const
{
GLint length;
- Error error = save(NULL, NULL, INT_MAX, &length);
+ Error error = saveBinary(NULL, NULL, std::numeric_limits<GLint>::max(), &length);
if (error.isError())
{
return 0;
@@ -495,169 +541,742 @@ GLint ProgramBinary::getLength()
return length;
}
-LinkResult ProgramBinary::link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
- Shader *fragmentShader, Shader *vertexShader,
- const std::vector<std::string> &transformFeedbackVaryings,
- GLenum transformFeedbackBufferMode)
+void Program::release()
{
- if (!fragmentShader || !fragmentShader->isCompiled())
+ mRefCount--;
+
+ if (mRefCount == 0 && mDeleteStatus)
{
- return LinkResult(false, Error(GL_NO_ERROR));
+ mResourceManager->deleteProgram(mHandle);
}
- ASSERT(fragmentShader->getType() == GL_FRAGMENT_SHADER);
+}
+
+void Program::addRef()
+{
+ mRefCount++;
+}
- if (!vertexShader || !vertexShader->isCompiled())
+unsigned int Program::getRefCount() const
+{
+ return mRefCount;
+}
+
+int Program::getInfoLogLength() const
+{
+ return mInfoLog.getLength();
+}
+
+void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
+{
+ return mInfoLog.getLog(bufSize, length, infoLog);
+}
+
+void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
+{
+ int total = 0;
+
+ if (mVertexShader)
{
- return LinkResult(false, Error(GL_NO_ERROR));
- }
- ASSERT(vertexShader->getType() == GL_VERTEX_SHADER);
+ if (total < maxCount)
+ {
+ shaders[total] = mVertexShader->getHandle();
+ }
- reset();
+ total++;
+ }
- int registers;
- std::vector<LinkedVarying> linkedVaryings;
- LinkResult result = mProgram->link(data, infoLog, fragmentShader, vertexShader, transformFeedbackVaryings, transformFeedbackBufferMode,
- &registers, &linkedVaryings, &mOutputVariables);
- if (result.error.isError() || !result.linkSuccess)
+ if (mFragmentShader)
{
- return result;
+ if (total < maxCount)
+ {
+ shaders[total] = mFragmentShader->getHandle();
+ }
+
+ total++;
}
- if (!linkAttributes(infoLog, attributeBindings, vertexShader))
+ if (count)
{
- return LinkResult(false, Error(GL_NO_ERROR));
+ *count = total;
}
+}
- if (!mProgram->linkUniforms(infoLog, *vertexShader, *fragmentShader, *data.caps))
+GLuint Program::getAttributeLocation(const std::string &name)
+{
+ for (int index = 0; index < MAX_VERTEX_ATTRIBS; index++)
{
- return LinkResult(false, Error(GL_NO_ERROR));
+ if (mLinkedAttribute[index].name == name)
+ {
+ return index;
+ }
}
- if (!linkUniformBlocks(infoLog, *vertexShader, *fragmentShader, *data.caps))
+ return static_cast<GLuint>(-1);
+}
+
+int Program::getSemanticIndex(int attributeIndex)
+{
+ ASSERT(attributeIndex >= 0 && attributeIndex < MAX_VERTEX_ATTRIBS);
+
+ return mProgram->getSemanticIndexes()[attributeIndex];
+}
+
+void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ if (mLinked)
{
- return LinkResult(false, Error(GL_NO_ERROR));
+ // Skip over inactive attributes
+ unsigned int activeAttribute = 0;
+ unsigned int attribute;
+ for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
+ {
+ if (mLinkedAttribute[attribute].name.empty())
+ {
+ continue;
+ }
+
+ if (activeAttribute == index)
+ {
+ break;
+ }
+
+ activeAttribute++;
+ }
+
+ if (bufsize > 0)
+ {
+ const char *string = mLinkedAttribute[attribute].name.c_str();
+
+ strncpy(name, string, bufsize);
+ name[bufsize - 1] = '\0';
+
+ if (length)
+ {
+ *length = strlen(name);
+ }
+ }
+
+ *size = 1; // Always a single 'type' instance
+
+ *type = mLinkedAttribute[attribute].type;
+ }
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
+
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *type = GL_NONE;
+ *size = 1;
}
+}
- if (!gatherTransformFeedbackLinkedVaryings(infoLog, linkedVaryings, transformFeedbackVaryings,
- transformFeedbackBufferMode, &mProgram->getTransformFeedbackLinkedVaryings(), *data.caps))
+GLint Program::getActiveAttributeCount()
+{
+ int count = 0;
+
+ if (mLinked)
{
- return LinkResult(false, Error(GL_NO_ERROR));
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ if (!mLinkedAttribute[attributeIndex].name.empty())
+ {
+ count++;
+ }
+ }
}
- // TODO: The concept of "executables" is D3D only, and as such this belongs in ProgramD3D. It must be called,
- // however, last in this function, so it can't simply be moved to ProgramD3D::link without further shuffling.
- result = mProgram->compileProgramExecutables(infoLog, fragmentShader, vertexShader, registers);
- if (result.error.isError() || !result.linkSuccess)
+ return count;
+}
+
+GLint Program::getActiveAttributeMaxLength()
+{
+ int maxLength = 0;
+
+ if (mLinked)
{
- infoLog.append("Failed to create D3D shaders.");
- reset();
- return result;
+ for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ if (!mLinkedAttribute[attributeIndex].name.empty())
+ {
+ maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
+ }
+ }
}
- return LinkResult(true, Error(GL_NO_ERROR));
+ return maxLength;
}
-bool ProgramBinary::linkUniformBlocks(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
- const gl::Caps &caps)
+// Returns one more than the highest sampler index used.
+GLint Program::getUsedSamplerRange(SamplerType type)
{
- const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
- const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+ return mProgram->getUsedSamplerRange(type);
+}
- // Check that interface blocks defined in the vertex and fragment shaders are identical
- typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
- UniformBlockMap linkedUniformBlocks;
+bool Program::usesPointSize() const
+{
+ return mProgram->usesPointSize();
+}
- for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
+GLint Program::getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps)
+{
+ return mProgram->getSamplerMapping(type, samplerIndex, caps);
+}
+
+GLenum Program::getSamplerTextureType(SamplerType type, unsigned int samplerIndex)
+{
+ return mProgram->getSamplerTextureType(type, samplerIndex);
+}
+
+GLint Program::getFragDataLocation(const std::string &name) const
+{
+ std::string baseName(name);
+ unsigned int arrayIndex = ParseAndStripArrayIndex(&baseName);
+ for (auto locationIt = mOutputVariables.begin(); locationIt != mOutputVariables.end(); locationIt++)
{
- const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
- linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+ const VariableLocation &outputVariable = locationIt->second;
+ if (outputVariable.name == baseName && (arrayIndex == GL_INVALID_INDEX || arrayIndex == outputVariable.element))
+ {
+ return static_cast<GLint>(locationIt->first);
+ }
}
+ return -1;
+}
- for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ if (mLinked)
{
- const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
- UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
- if (entry != linkedUniformBlocks.end())
+ ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount()
+ LinkedUniform *uniform = mProgram->getUniforms()[index];
+
+ if (bufsize > 0)
{
- const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
- if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+ std::string string = uniform->name;
+ if (uniform->isArray())
{
- return false;
+ string += "[0]";
+ }
+
+ strncpy(name, string.c_str(), bufsize);
+ name[bufsize - 1] = '\0';
+
+ if (length)
+ {
+ *length = strlen(name);
}
}
+
+ *size = uniform->elementCount();
+ *type = uniform->type;
}
+ else
+ {
+ if (bufsize > 0)
+ {
+ name[0] = '\0';
+ }
- for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
+ if (length)
+ {
+ *length = 0;
+ }
+
+ *size = 0;
+ *type = GL_NONE;
+ }
+}
+
+GLint Program::getActiveUniformCount()
+{
+ if (mLinked)
{
- const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
+ return mProgram->getUniforms().size();
+ }
+ else
+ {
+ return 0;
+ }
+}
- // Note: shared and std140 layouts are always considered active
- if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+GLint Program::getActiveUniformMaxLength()
+{
+ int maxLength = 0;
+
+ if (mLinked)
+ {
+ unsigned int numUniforms = mProgram->getUniforms().size();
+ for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
{
- if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+ if (!mProgram->getUniforms()[uniformIndex]->name.empty())
{
- return false;
+ int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
+ if (mProgram->getUniforms()[uniformIndex]->isArray())
+ {
+ length += 3; // Counting in "[0]".
+ }
+ maxLength = std::max(length, maxLength);
}
}
}
- for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+ return maxLength;
+}
+
+GLint Program::getActiveUniformi(GLuint index, GLenum pname) const
+{
+ const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
+ switch (pname)
{
- const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
+ case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
+ case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
+ case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(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<GLint>(uniform.blockInfo.isRowMajorMatrix);
+ default:
+ UNREACHABLE();
+ break;
+ }
+ return 0;
+}
- // Note: shared and std140 layouts are always considered active
- if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+bool Program::isValidUniformLocation(GLint location) const
+{
+ ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size()));
+ return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size()));
+}
+
+LinkedUniform *Program::getUniformByLocation(GLint location) const
+{
+ return mProgram->getUniformByLocation(location);
+}
+
+LinkedUniform *Program::getUniformByName(const std::string &name) const
+{
+ return mProgram->getUniformByName(name);
+}
+
+GLint Program::getUniformLocation(const std::string &name)
+{
+ return mProgram->getUniformLocation(name);
+}
+
+GLuint Program::getUniformIndex(const std::string &name)
+{
+ return mProgram->getUniformIndex(name);
+}
+
+void Program::setUniform1fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mProgram->setUniform1fv(location, count, v);
+}
+
+void Program::setUniform2fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mProgram->setUniform2fv(location, count, v);
+}
+
+void Program::setUniform3fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mProgram->setUniform3fv(location, count, v);
+}
+
+void Program::setUniform4fv(GLint location, GLsizei count, const GLfloat *v)
+{
+ mProgram->setUniform4fv(location, count, v);
+}
+
+void Program::setUniform1iv(GLint location, GLsizei count, const GLint *v)
+{
+ mProgram->setUniform1iv(location, count, v);
+}
+
+void Program::setUniform2iv(GLint location, GLsizei count, const GLint *v)
+{
+ mProgram->setUniform2iv(location, count, v);
+}
+
+void Program::setUniform3iv(GLint location, GLsizei count, const GLint *v)
+{
+ mProgram->setUniform3iv(location, count, v);
+}
+
+void Program::setUniform4iv(GLint location, GLsizei count, const GLint *v)
+{
+ mProgram->setUniform4iv(location, count, v);
+}
+
+void Program::setUniform1uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mProgram->setUniform1uiv(location, count, v);
+}
+
+void Program::setUniform2uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mProgram->setUniform2uiv(location, count, v);
+}
+
+void Program::setUniform3uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mProgram->setUniform3uiv(location, count, v);
+}
+
+void Program::setUniform4uiv(GLint location, GLsizei count, const GLuint *v)
+{
+ mProgram->setUniform4uiv(location, count, v);
+}
+
+void Program::setUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix2fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix3fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix4fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix2x3fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix2x4fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix3x2fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix3x4fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix4x2fv(location, count, transpose, v);
+}
+
+void Program::setUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat *v)
+{
+ mProgram->setUniformMatrix4x3fv(location, count, transpose, v);
+}
+
+void Program::getUniformfv(GLint location, GLfloat *v)
+{
+ mProgram->getUniformfv(location, v);
+}
+
+void Program::getUniformiv(GLint location, GLint *v)
+{
+ mProgram->getUniformiv(location, v);
+}
+
+void Program::getUniformuiv(GLint location, GLuint *v)
+{
+ mProgram->getUniformuiv(location, v);
+}
+
+// Applies all the uniforms set for this program object to the renderer
+Error Program::applyUniforms()
+{
+ return mProgram->applyUniforms();
+}
+
+Error Program::applyUniformBuffers(const gl::Data &data)
+{
+ return mProgram->applyUniformBuffers(data, mUniformBlockBindings);
+}
+
+void Program::flagForDeletion()
+{
+ mDeleteStatus = true;
+}
+
+bool Program::isFlaggedForDeletion() const
+{
+ return mDeleteStatus;
+}
+
+void Program::validate(const Caps &caps)
+{
+ mInfoLog.reset();
+ mValidated = false;
+
+ if (mLinked)
+ {
+ applyUniforms();
+ mValidated = mProgram->validateSamplers(&mInfoLog, caps);
+ }
+ else
+ {
+ mInfoLog.append("Program has not been successfully linked.");
+ }
+}
+
+bool Program::validateSamplers(InfoLog *infoLog, const Caps &caps)
+{
+ return mProgram->validateSamplers(infoLog, caps);
+}
+
+bool Program::isValidated() const
+{
+ return mValidated;
+}
+
+void Program::updateSamplerMapping()
+{
+ return mProgram->updateSamplerMapping();
+}
+
+GLuint Program::getActiveUniformBlockCount()
+{
+ return mProgram->getUniformBlocks().size();
+}
+
+void Program::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
+{
+ ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
+
+ const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
+
+ if (bufSize > 0)
+ {
+ std::string string = uniformBlock.name;
+
+ if (uniformBlock.isArrayElement())
{
- if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+ string += ArrayString(uniformBlock.elementIndex);
+ }
+
+ strncpy(uniformBlockName, string.c_str(), bufSize);
+ uniformBlockName[bufSize - 1] = '\0';
+
+ if (length)
+ {
+ *length = strlen(uniformBlockName);
+ }
+ }
+}
+
+void Program::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
+{
+ ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
+
+ const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
+
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ *params = static_cast<GLint>(uniformBlock.dataSize);
+ break;
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ *params = static_cast<GLint>(uniformBlock.memberUniformIndexes.size());
+ break;
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ {
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < uniformBlock.memberUniformIndexes.size(); blockMemberIndex++)
{
- return false;
+ params[blockMemberIndex] = static_cast<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
}
}
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
+ break;
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
+ break;
+ default: UNREACHABLE();
}
+}
- return true;
+GLint Program::getActiveUniformBlockMaxLength()
+{
+ int maxLength = 0;
+
+ if (mLinked)
+ {
+ unsigned int numUniformBlocks = mProgram->getUniformBlocks().size();
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
+ {
+ const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
+ if (!uniformBlock.name.empty())
+ {
+ const int length = uniformBlock.name.length() + 1;
+
+ // Counting in "[0]".
+ const int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
+
+ maxLength = std::max(length + arrayLength, maxLength);
+ }
+ }
+ }
+
+ return maxLength;
}
-bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
- const sh::InterfaceBlock &fragmentInterfaceBlock)
+GLuint Program::getUniformBlockIndex(const std::string &name)
{
- const char* blockName = vertexInterfaceBlock.name.c_str();
+ return mProgram->getUniformBlockIndex(name);
+}
- // validate blocks for the same member types
- if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
+const UniformBlock *Program::getUniformBlockByIndex(GLuint index) const
+{
+ return mProgram->getUniformBlockByIndex(index);
+}
+
+void Program::bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ mUniformBlockBindings[uniformBlockIndex] = uniformBlockBinding;
+}
+
+GLuint Program::getUniformBlockBinding(GLuint uniformBlockIndex) const
+{
+ return mUniformBlockBindings[uniformBlockIndex];
+}
+
+void Program::resetUniformBlockBindings()
+{
+ for (unsigned int blockId = 0; blockId < IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS; blockId++)
{
- infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
- return false;
+ mUniformBlockBindings[blockId] = 0;
}
+}
- if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
+void Program::setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode)
+{
+ mTransformFeedbackVaryings.resize(count);
+ for (GLsizei i = 0; i < count; i++)
{
- infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
- return false;
+ mTransformFeedbackVaryings[i] = varyings[i];
}
- if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ mTransformFeedbackBufferMode = bufferMode;
+}
+
+void Program::getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const
+{
+ if (mLinked)
{
- infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
- return false;
+ ASSERT(index < mProgram->getTransformFeedbackLinkedVaryings().size());
+ const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[index];
+ GLsizei lastNameIdx = std::min(bufSize - 1, static_cast<GLsizei>(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';
+ }
}
+}
- const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
- for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+GLsizei Program::getTransformFeedbackVaryingCount() const
+{
+ if (mLinked)
{
- const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
- const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+ return static_cast<GLsizei>(mProgram->getTransformFeedbackLinkedVaryings().size());
+ }
+ else
+ {
+ return 0;
+ }
+}
- if (vertexMember.name != fragmentMember.name)
+GLsizei Program::getTransformFeedbackVaryingMaxLength() const
+{
+ if (mLinked)
+ {
+ GLsizei maxSize = 0;
+ for (size_t i = 0; i < mProgram->getTransformFeedbackLinkedVaryings().size(); i++)
{
- 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;
+ const LinkedVarying &varying = mProgram->getTransformFeedbackLinkedVaryings()[i];
+ maxSize = std::max(maxSize, static_cast<GLsizei>(varying.name.length() + 1));
}
- std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
- if (!gl::ProgramBinary::linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+ return maxSize;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+GLenum Program::getTransformFeedbackBufferMode() const
+{
+ return mTransformFeedbackBufferMode;
+}
+
+bool Program::linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader)
+{
+ std::vector<PackedVarying> &fragmentVaryings = fragmentShader->getVaryings();
+ std::vector<PackedVarying> &vertexVaryings = vertexShader->getVaryings();
+
+ for (size_t fragVaryingIndex = 0; fragVaryingIndex < fragmentVaryings.size(); fragVaryingIndex++)
+ {
+ PackedVarying *input = &fragmentVaryings[fragVaryingIndex];
+ bool matched = false;
+
+ // Built-in varyings obey special rules
+ if (input->isBuiltIn())
{
+ continue;
+ }
+
+ for (size_t vertVaryingIndex = 0; vertVaryingIndex < vertexVaryings.size(); vertVaryingIndex++)
+ {
+ PackedVarying *output = &vertexVaryings[vertVaryingIndex];
+ if (output->name == input->name)
+ {
+ if (!linkValidateVaryings(infoLog, output->name, *input, *output))
+ {
+ return false;
+ }
+
+ output->registerIndex = input->registerIndex;
+ output->columnIndex = input->columnIndex;
+
+ matched = true;
+ break;
+ }
+ }
+
+ // We permit unmatched, unreferenced varyings
+ if (!matched && input->staticUse)
+ {
+ infoLog.append("Fragment varying %s does not match any vertex varying", input->name.c_str());
return false;
}
}
@@ -665,11 +1284,25 @@ bool ProgramBinary::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::I
return true;
}
-// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
-bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
+bool Program::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
{
- const rx::ShaderD3D *vertexShaderD3D = rx::ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
+ if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
+ {
+ return false;
+ }
+
+ if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
+ {
+ infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
+ return false;
+ }
+ return true;
+}
+
+// Determines the mapping between GL attributes and Direct3D 9 vertex stream usage indices
+bool Program::linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader)
+{
unsigned int usedLocations = 0;
const std::vector<sh::Attribute> &shaderAttributes = vertexShader->getActiveAttributes();
@@ -744,21 +1377,111 @@ bool ProgramBinary::linkAttributes(InfoLog &infoLog, const AttributeBindings &at
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; )
{
- int index = vertexShaderD3D->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
+ int index = vertexShader->getSemanticIndex(mLinkedAttribute[attributeIndex].name);
int rows = VariableRegisterCount(mLinkedAttribute[attributeIndex].type);
for (int r = 0; r < rows; r++)
{
- mSemanticIndex[attributeIndex++] = index++;
+ mProgram->getSemanticIndexes()[attributeIndex++] = index++;
}
}
- initAttributesByLayout();
+ return true;
+}
+bool Program::linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps)
+{
+ const std::vector<sh::InterfaceBlock> &vertexInterfaceBlocks = vertexShader.getInterfaceBlocks();
+ const std::vector<sh::InterfaceBlock> &fragmentInterfaceBlocks = fragmentShader.getInterfaceBlocks();
+ // Check that interface blocks defined in the vertex and fragment shaders are identical
+ typedef std::map<std::string, const sh::InterfaceBlock*> UniformBlockMap;
+ UniformBlockMap linkedUniformBlocks;
+ for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &vertexInterfaceBlock = vertexInterfaceBlocks[blockIndex];
+ linkedUniformBlocks[vertexInterfaceBlock.name] = &vertexInterfaceBlock;
+ }
+ for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &fragmentInterfaceBlock = fragmentInterfaceBlocks[blockIndex];
+ UniformBlockMap::const_iterator entry = linkedUniformBlocks.find(fragmentInterfaceBlock.name);
+ if (entry != linkedUniformBlocks.end())
+ {
+ const sh::InterfaceBlock &vertexInterfaceBlock = *entry->second;
+ if (!areMatchingInterfaceBlocks(infoLog, vertexInterfaceBlock, fragmentInterfaceBlock))
+ {
+ return false;
+ }
+ }
+ }
+ for (unsigned int blockIndex = 0; blockIndex < vertexInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &interfaceBlock = vertexInterfaceBlocks[blockIndex];
+ // Note: shared and std140 layouts are always considered active
+ if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ if (!mProgram->defineUniformBlock(infoLog, vertexShader, interfaceBlock, caps))
+ {
+ return false;
+ }
+ }
+ }
+ for (unsigned int blockIndex = 0; blockIndex < fragmentInterfaceBlocks.size(); blockIndex++)
+ {
+ const sh::InterfaceBlock &interfaceBlock = fragmentInterfaceBlocks[blockIndex];
+ // Note: shared and std140 layouts are always considered active
+ if (interfaceBlock.staticUse || interfaceBlock.layout != sh::BLOCKLAYOUT_PACKED)
+ {
+ if (!mProgram->defineUniformBlock(infoLog, fragmentShader, interfaceBlock, caps))
+ {
+ return false;
+ }
+ }
+ }
return true;
}
-bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
+bool Program::areMatchingInterfaceBlocks(gl::InfoLog &infoLog, const sh::InterfaceBlock &vertexInterfaceBlock,
+ const sh::InterfaceBlock &fragmentInterfaceBlock)
+{
+ const char* blockName = vertexInterfaceBlock.name.c_str();
+ // validate blocks for the same member types
+ if (vertexInterfaceBlock.fields.size() != fragmentInterfaceBlock.fields.size())
+ {
+ infoLog.append("Types for interface block '%s' differ between vertex and fragment shaders", blockName);
+ return false;
+ }
+ if (vertexInterfaceBlock.arraySize != fragmentInterfaceBlock.arraySize)
+ {
+ infoLog.append("Array sizes differ for interface block '%s' between vertex and fragment shaders", blockName);
+ return false;
+ }
+ if (vertexInterfaceBlock.layout != fragmentInterfaceBlock.layout || vertexInterfaceBlock.isRowMajorLayout != fragmentInterfaceBlock.isRowMajorLayout)
+ {
+ infoLog.append("Layout qualifiers differ for interface block '%s' between vertex and fragment shaders", blockName);
+ return false;
+ }
+ const unsigned int numBlockMembers = vertexInterfaceBlock.fields.size();
+ for (unsigned int blockMemberIndex = 0; blockMemberIndex < numBlockMembers; blockMemberIndex++)
+ {
+ const sh::InterfaceBlockField &vertexMember = vertexInterfaceBlock.fields[blockMemberIndex];
+ const sh::InterfaceBlockField &fragmentMember = fragmentInterfaceBlock.fields[blockMemberIndex];
+ if (vertexMember.name != fragmentMember.name)
+ {
+ infoLog.append("Name mismatch for field %d of interface block '%s': (in vertex: '%s', in fragment: '%s')",
+ blockMemberIndex, blockName, vertexMember.name.c_str(), fragmentMember.name.c_str());
+ return false;
+ }
+ std::string memberName = "interface block '" + vertexInterfaceBlock.name + "' member '" + vertexMember.name + "'";
+ if (!linkValidateInterfaceBlockFields(infoLog, memberName, vertexMember, fragmentMember))
+ {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool Program::linkValidateVariablesBase(InfoLog &infoLog, const std::string &variableName, const sh::ShaderVariable &vertexVariable,
const sh::ShaderVariable &fragmentVariable, bool validatePrecision)
{
if (vertexVariable.type != fragmentVariable.type)
@@ -808,7 +1531,7 @@ bool ProgramBinary::linkValidateVariablesBase(InfoLog &infoLog, const std::strin
return true;
}
-bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
+bool Program::linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform)
{
if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
{
@@ -818,14 +1541,14 @@ bool ProgramBinary::linkValidateUniforms(InfoLog &infoLog, const std::string &un
return true;
}
-bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
+bool Program::linkValidateVaryings(InfoLog &infoLog, const std::string &varyingName, const sh::Varying &vertexVarying, const sh::Varying &fragmentVarying)
{
if (!linkValidateVariablesBase(infoLog, varyingName, vertexVarying, fragmentVarying, false))
{
return false;
}
- if (vertexVarying.interpolation != fragmentVarying.interpolation)
+ if (!sh::InterpolationTypesMatch(vertexVarying.interpolation, fragmentVarying.interpolation))
{
infoLog.append("Interpolation types for %s differ between vertex and fragment shaders", varyingName.c_str());
return false;
@@ -834,27 +1557,11 @@ bool ProgramBinary::linkValidateVaryings(InfoLog &infoLog, const std::string &va
return true;
}
-bool ProgramBinary::linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform)
-{
- if (!linkValidateVariablesBase(infoLog, uniformName, vertexUniform, fragmentUniform, true))
- {
- return false;
- }
-
- if (vertexUniform.isRowMajorLayout != fragmentUniform.isRowMajorLayout)
- {
- infoLog.append("Matrix packings for %s differ between vertex and fragment shaders", uniformName.c_str());
- return false;
- }
-
- return true;
-}
-
-bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
- const std::vector<std::string> &transformFeedbackVaryingNames,
- GLenum transformFeedbackBufferMode,
- std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
- const Caps &caps) const
+bool Program::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, const std::vector<LinkedVarying> &linkedVaryings,
+ const std::vector<std::string> &transformFeedbackVaryingNames,
+ GLenum transformFeedbackBufferMode,
+ std::vector<LinkedVarying> *outTransformFeedbackLinkedVaryings,
+ const Caps &caps) const
{
size_t totalComponents = 0;
@@ -907,327 +1614,4 @@ bool ProgramBinary::gatherTransformFeedbackLinkedVaryings(InfoLog &infoLog, cons
return true;
}
-bool ProgramBinary::isValidated() const
-{
- return mValidated;
-}
-
-void ProgramBinary::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
-{
- // Skip over inactive attributes
- unsigned int activeAttribute = 0;
- unsigned int attribute;
- for (attribute = 0; attribute < MAX_VERTEX_ATTRIBS; attribute++)
- {
- if (mLinkedAttribute[attribute].name.empty())
- {
- continue;
- }
-
- if (activeAttribute == index)
- {
- break;
- }
-
- activeAttribute++;
- }
-
- if (bufsize > 0)
- {
- const char *string = mLinkedAttribute[attribute].name.c_str();
-
- strncpy(name, string, bufsize);
- name[bufsize - 1] = '\0';
-
- if (length)
- {
- *length = strlen(name);
- }
- }
-
- *size = 1; // Always a single 'type' instance
-
- *type = mLinkedAttribute[attribute].type;
-}
-
-GLint ProgramBinary::getActiveAttributeCount() const
-{
- int count = 0;
-
- for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
- {
- if (!mLinkedAttribute[attributeIndex].name.empty())
- {
- count++;
- }
- }
-
- return count;
-}
-
-GLint ProgramBinary::getActiveAttributeMaxLength() const
-{
- int maxLength = 0;
-
- for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
- {
- if (!mLinkedAttribute[attributeIndex].name.empty())
- {
- maxLength = std::max((int)(mLinkedAttribute[attributeIndex].name.length() + 1), maxLength);
- }
- }
-
- return maxLength;
-}
-
-void ProgramBinary::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const
-{
- ASSERT(index < mProgram->getUniforms().size()); // index must be smaller than getActiveUniformCount()
-
- if (bufsize > 0)
- {
- std::string string = mProgram->getUniforms()[index]->name;
-
- if (mProgram->getUniforms()[index]->isArray())
- {
- string += "[0]";
- }
-
- strncpy(name, string.c_str(), bufsize);
- name[bufsize - 1] = '\0';
-
- if (length)
- {
- *length = strlen(name);
- }
- }
-
- *size = mProgram->getUniforms()[index]->elementCount();
-
- *type = mProgram->getUniforms()[index]->type;
-}
-
-GLint ProgramBinary::getActiveUniformCount() const
-{
- return mProgram->getUniforms().size();
-}
-
-GLint ProgramBinary::getActiveUniformMaxLength() const
-{
- int maxLength = 0;
-
- unsigned int numUniforms = mProgram->getUniforms().size();
- for (unsigned int uniformIndex = 0; uniformIndex < numUniforms; uniformIndex++)
- {
- if (!mProgram->getUniforms()[uniformIndex]->name.empty())
- {
- int length = (int)(mProgram->getUniforms()[uniformIndex]->name.length() + 1);
- if (mProgram->getUniforms()[uniformIndex]->isArray())
- {
- length += 3; // Counting in "[0]".
- }
- maxLength = std::max(length, maxLength);
- }
- }
-
- return maxLength;
-}
-
-GLint ProgramBinary::getActiveUniformi(GLuint index, GLenum pname) const
-{
- const gl::LinkedUniform& uniform = *mProgram->getUniforms()[index];
-
- switch (pname)
- {
- case GL_UNIFORM_TYPE: return static_cast<GLint>(uniform.type);
- case GL_UNIFORM_SIZE: return static_cast<GLint>(uniform.elementCount());
- case GL_UNIFORM_NAME_LENGTH: return static_cast<GLint>(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<GLint>(uniform.blockInfo.isRowMajorMatrix);
-
- default:
- UNREACHABLE();
- break;
- }
- return 0;
-}
-
-bool ProgramBinary::isValidUniformLocation(GLint location) const
-{
- ASSERT(rx::IsIntegerCastSafe<GLint>(mProgram->getUniformIndices().size()));
- return (location >= 0 && location < static_cast<GLint>(mProgram->getUniformIndices().size()));
-}
-
-LinkedUniform *ProgramBinary::getUniformByLocation(GLint location) const
-{
- return mProgram->getUniformByLocation(location);
-}
-
-LinkedUniform *ProgramBinary::getUniformByName(const std::string &name) const
-{
- return mProgram->getUniformByName(name);
-}
-
-void ProgramBinary::getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const
-{
- ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
-
- const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
-
- if (bufSize > 0)
- {
- std::string string = uniformBlock.name;
-
- if (uniformBlock.isArrayElement())
- {
- string += ArrayString(uniformBlock.elementIndex);
- }
-
- strncpy(uniformBlockName, string.c_str(), bufSize);
- uniformBlockName[bufSize - 1] = '\0';
-
- if (length)
- {
- *length = strlen(uniformBlockName);
- }
- }
-}
-
-void ProgramBinary::getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const
-{
- ASSERT(uniformBlockIndex < mProgram->getUniformBlocks().size()); // index must be smaller than getActiveUniformBlockCount()
-
- const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
-
- switch (pname)
- {
- case GL_UNIFORM_BLOCK_DATA_SIZE:
- *params = static_cast<GLint>(uniformBlock.dataSize);
- break;
- case GL_UNIFORM_BLOCK_NAME_LENGTH:
- *params = static_cast<GLint>(uniformBlock.name.size() + 1 + (uniformBlock.isArrayElement() ? 3 : 0));
- break;
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
- *params = static_cast<GLint>(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<GLint>(uniformBlock.memberUniformIndexes[blockMemberIndex]);
- }
- }
- break;
- case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- *params = static_cast<GLint>(uniformBlock.isReferencedByVertexShader());
- break;
- case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- *params = static_cast<GLint>(uniformBlock.isReferencedByFragmentShader());
- break;
- default: UNREACHABLE();
- }
-}
-
-GLuint ProgramBinary::getActiveUniformBlockCount() const
-{
- return mProgram->getUniformBlocks().size();
-}
-
-GLuint ProgramBinary::getActiveUniformBlockMaxLength() const
-{
- unsigned int maxLength = 0;
-
- unsigned int numUniformBlocks = mProgram->getUniformBlocks().size();
- for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < numUniformBlocks; uniformBlockIndex++)
- {
- const UniformBlock &uniformBlock = *mProgram->getUniformBlocks()[uniformBlockIndex];
- if (!uniformBlock.name.empty())
- {
- const unsigned int length = uniformBlock.name.length() + 1;
-
- // Counting in "[0]".
- const unsigned int arrayLength = (uniformBlock.isArrayElement() ? 3 : 0);
-
- maxLength = std::max(length + arrayLength, maxLength);
- }
- }
-
- return maxLength;
-}
-
-void ProgramBinary::validate(InfoLog &infoLog, const Caps &caps)
-{
- applyUniforms();
- if (!validateSamplers(&infoLog, caps))
- {
- mValidated = false;
- }
- else
- {
- mValidated = true;
- }
-}
-
-bool ProgramBinary::validateSamplers(InfoLog *infoLog, const Caps &caps)
-{
- return mProgram->validateSamplers(infoLog, caps);
-}
-
-struct AttributeSorter
-{
- AttributeSorter(const int (&semanticIndices)[MAX_VERTEX_ATTRIBS])
- : originalIndices(semanticIndices)
- {
- }
-
- bool operator()(int a, int b)
- {
- if (originalIndices[a] == -1) return false;
- if (originalIndices[b] == -1) return true;
- return (originalIndices[a] < originalIndices[b]);
- }
-
- const int (&originalIndices)[MAX_VERTEX_ATTRIBS];
-};
-
-void ProgramBinary::initAttributesByLayout()
-{
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- mAttributesByLayout[i] = i;
- }
-
- std::sort(&mAttributesByLayout[0], &mAttributesByLayout[MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
-}
-
-void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const
-{
- rx::TranslatedAttribute oldTranslatedAttributes[MAX_VERTEX_ATTRIBS];
-
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- oldTranslatedAttributes[i] = attributes[i];
- }
-
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- int oldIndex = mAttributesByLayout[i];
- sortedSemanticIndices[i] = oldIndex;
- attributes[i] = oldTranslatedAttributes[oldIndex];
- }
-}
-
-void ProgramBinary::reset()
-{
- mOutputVariables.clear();
-
- mProgram->reset();
-
- mValidated = false;
-}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h b/src/3rdparty/angle/src/libANGLE/Program.h
index 3142d66c6d..38fc83d29d 100644
--- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.h
+++ b/src/3rdparty/angle/src/libANGLE/Program.h
@@ -7,60 +7,79 @@
// Program.h: Defines the gl::Program class. Implements GL program objects
// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-#ifndef LIBGLESV2_PROGRAM_BINARY_H_
-#define LIBGLESV2_PROGRAM_BINARY_H_
+#ifndef LIBANGLE_PROGRAM_H_
+#define LIBANGLE_PROGRAM_H_
-#include "common/RefCountObject.h"
-#include "angletypes.h"
-#include "common/mathutil.h"
-#include "libGLESv2/Uniform.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
-#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
-#include "angle_gl.h"
+#include "common/angleutils.h"
-#include <string>
-#include <vector>
-
-namespace sh
-{
-class HLSLBlockEncoder;
-}
-
-#include <GLES3/gl3.h>
#include <GLES2/gl2.h>
-#include <GLES2/gl2ext.h>
+#include <GLSLANG/ShaderLang.h>
-#include <string>
#include <vector>
+#include <string>
+#include <set>
namespace rx
{
-class ShaderExecutable;
+class Renderer;
+class Renderer;
struct TranslatedAttribute;
-class UniformStorage;
class ProgramImpl;
}
namespace gl
{
struct Caps;
+struct Data;
+class ResourceManager;
class Shader;
class InfoLog;
class AttributeBindings;
class Buffer;
class Framebuffer;
-struct Data;
+struct UniformBlock;
+struct LinkedUniform;
+
+extern const char * const g_fakepath;
+
+class AttributeBindings
+{
+ public:
+ AttributeBindings();
+ ~AttributeBindings();
+
+ void bindAttributeLocation(GLuint index, const char *name);
+ int getAttributeBinding(const std::string &name) const;
+
+ private:
+ std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
+};
+
+class InfoLog : angle::NonCopyable
+{
+ public:
+ InfoLog();
+ ~InfoLog();
+
+ int getLength() const;
+ void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+
+ void appendSanitized(const char *message);
+ void append(const char *info, ...);
+ void reset();
+ private:
+ char *mInfoLog;
+};
// Struct used for correlating uniforms/elements of uniform arrays to handles
struct VariableLocation
{
- VariableLocation()
- {
- }
-
+ VariableLocation();
VariableLocation(const std::string &name, unsigned int element, unsigned int index);
std::string name;
@@ -72,7 +91,7 @@ struct LinkedVarying
{
LinkedVarying();
LinkedVarying(const std::string &name, GLenum type, GLsizei size, const std::string &semanticName,
- unsigned int semanticIndex, unsigned int semanticIndexCount);
+ unsigned int semanticIndex, unsigned int semanticIndexCount);
// Original GL name
std::string name;
@@ -86,35 +105,58 @@ struct LinkedVarying
unsigned int semanticIndexCount;
};
-struct LinkResult
-{
- bool linkSuccess;
- Error error;
-
- LinkResult(bool linkSuccess, const Error &error);
-};
-
-// This is the result of linking a program. It is the state that would be passed to ProgramBinary.
-class ProgramBinary : public RefCountObject
+class Program : angle::NonCopyable
{
public:
- explicit ProgramBinary(rx::ProgramImpl *impl);
- ~ProgramBinary();
+ Program(rx::ProgramImpl *impl, ResourceManager *manager, GLuint handle);
+ ~Program();
+
+ GLuint id() const { return mHandle; }
rx::ProgramImpl *getImplementation() { return mProgram; }
const rx::ProgramImpl *getImplementation() const { return mProgram; }
- GLuint getAttributeLocation(const char *name);
+ bool attachShader(Shader *shader);
+ bool detachShader(Shader *shader);
+ int getAttachedShadersCount() const;
+
+ void bindAttributeLocation(GLuint index, const char *name);
+
+ Error link(const Data &data);
+ bool isLinked();
+
+ Error loadBinary(GLenum binaryFormat, const void *binary, GLsizei length);
+ Error saveBinary(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length) const;
+ GLint getBinaryLength() const;
+
+ int getInfoLogLength() const;
+ void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
+ void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
+
+ GLuint getAttributeLocation(const std::string &name);
int getSemanticIndex(int attributeIndex);
+ void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ GLint getActiveAttributeCount();
+ GLint getActiveAttributeMaxLength();
+
GLint getSamplerMapping(SamplerType type, unsigned int samplerIndex, const Caps &caps);
GLenum getSamplerTextureType(SamplerType type, unsigned int samplerIndex);
GLint getUsedSamplerRange(SamplerType type);
bool usesPointSize() const;
- GLint getUniformLocation(std::string name);
- GLuint getUniformIndex(std::string name);
- GLuint getUniformBlockIndex(std::string name);
+ GLint getFragDataLocation(const std::string &name) const;
+
+ void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
+ GLint getActiveUniformCount();
+ GLint getActiveUniformMaxLength();
+ GLint getActiveUniformi(GLuint index, GLenum pname) const;
+ bool isValidUniformLocation(GLint location) const;
+ LinkedUniform *getUniformByLocation(GLint location) const;
+ LinkedUniform *getUniformByName(const std::string &name) const;
+
+ GLint getUniformLocation(const std::string &name);
+ GLuint getUniformIndex(const std::string &name);
void setUniform1fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform2fv(GLint location, GLsizei count, const GLfloat *v);
void setUniform3fv(GLint location, GLsizei count, const GLfloat *v);
@@ -142,59 +184,44 @@ class ProgramBinary : public RefCountObject
void getUniformuiv(GLint location, GLuint *params);
Error applyUniforms();
- Error applyUniformBuffers(const std::vector<Buffer*> boundBuffers, const Caps &caps);
-
- LinkResult load(InfoLog &infoLog, GLenum binaryFormat, const void *binary, GLsizei length);
- Error save(GLenum *binaryFormat, void *binary, GLsizei bufSize, GLsizei *length);
- GLint getLength();
-
- LinkResult link(const Data &data, InfoLog &infoLog, const AttributeBindings &attributeBindings,
- Shader *fragmentShader, Shader *vertexShader,
- const std::vector<std::string> &transformFeedbackVaryings,
- GLenum transformFeedbackBufferMode);
-
- void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
- GLint getActiveAttributeCount() const;
- GLint getActiveAttributeMaxLength() const;
-
- void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name) const;
- GLint getActiveUniformCount() const;
- GLint getActiveUniformMaxLength() const;
- GLint getActiveUniformi(GLuint index, GLenum pname) const;
- bool isValidUniformLocation(GLint location) const;
- LinkedUniform *getUniformByLocation(GLint location) const;
- LinkedUniform *getUniformByName(const std::string &name) const;
+ Error applyUniformBuffers(const gl::Data &data);
void getActiveUniformBlockName(GLuint uniformBlockIndex, GLsizei bufSize, GLsizei *length, GLchar *uniformBlockName) const;
void getActiveUniformBlockiv(GLuint uniformBlockIndex, GLenum pname, GLint *params) const;
- GLuint getActiveUniformBlockCount() const;
- GLuint getActiveUniformBlockMaxLength() const;
- UniformBlock *getUniformBlockByIndex(GLuint blockIndex);
+ GLuint getActiveUniformBlockCount();
+ GLint getActiveUniformBlockMaxLength();
- GLint getFragDataLocation(const char *name) const;
-
- size_t getTransformFeedbackVaryingCount() const;
- const LinkedVarying &getTransformFeedbackVarying(size_t idx) const;
- GLenum getTransformFeedbackBufferMode() const;
+ GLuint getUniformBlockIndex(const std::string &name);
- void validate(InfoLog &infoLog, const Caps &caps);
- bool validateSamplers(InfoLog *infoLog, const Caps &caps);
- bool isValidated() const;
- void updateSamplerMapping();
+ void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
- unsigned int getSerial() const;
+ const UniformBlock *getUniformBlockByIndex(GLuint index) const;
- void initAttributesByLayout();
- void sortAttributesByLayout(rx::TranslatedAttribute attributes[MAX_VERTEX_ATTRIBS], int sortedSemanticIndices[MAX_VERTEX_ATTRIBS]) const;
+ void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
+ void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
+ GLsizei getTransformFeedbackVaryingCount() const;
+ GLsizei getTransformFeedbackVaryingMaxLength() const;
+ GLenum getTransformFeedbackBufferMode() const;
static bool linkVaryings(InfoLog &infoLog, Shader *fragmentShader, Shader *vertexShader);
static bool linkValidateUniforms(InfoLog &infoLog, const std::string &uniformName, const sh::Uniform &vertexUniform, const sh::Uniform &fragmentUniform);
static bool linkValidateInterfaceBlockFields(InfoLog &infoLog, const std::string &uniformName, const sh::InterfaceBlockField &vertexUniform, const sh::InterfaceBlockField &fragmentUniform);
- private:
- DISALLOW_COPY_AND_ASSIGN(ProgramBinary);
+ void addRef();
+ void release();
+ unsigned int getRefCount() const;
+ void flagForDeletion();
+ bool isFlaggedForDeletion() const;
- void reset();
+ void validate(const Caps &caps);
+ bool validateSamplers(InfoLog *infoLog, const Caps &caps);
+ bool isValidated() const;
+ void updateSamplerMapping();
+
+ private:
+ void unlink(bool destroy = false);
+ void resetUniformBlockBindings();
bool linkAttributes(InfoLog &infoLog, const AttributeBindings &attributeBindings, const Shader *vertexShader);
bool linkUniformBlocks(InfoLog &infoLog, const Shader &vertexShader, const Shader &fragmentShader, const Caps &caps);
@@ -219,19 +246,31 @@ class ProgramBinary : public RefCountObject
rx::ProgramImpl *mProgram;
sh::Attribute mLinkedAttribute[MAX_VERTEX_ATTRIBS];
- int mSemanticIndex[MAX_VERTEX_ATTRIBS];
- int mAttributesByLayout[MAX_VERTEX_ATTRIBS];
std::map<int, VariableLocation> mOutputVariables;
bool mValidated;
- const unsigned int mSerial;
+ Shader *mFragmentShader;
+ Shader *mVertexShader;
- static unsigned int issueSerial();
- static unsigned int mCurrentSerial;
-};
+ AttributeBindings mAttributeBindings;
+
+ GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
+
+ std::vector<std::string> mTransformFeedbackVaryings;
+ GLenum mTransformFeedbackBufferMode;
+ bool mLinked;
+ bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
+
+ unsigned int mRefCount;
+
+ ResourceManager *mResourceManager;
+ const GLuint mHandle;
+
+ InfoLog mInfoLog;
+};
}
-#endif // LIBGLESV2_PROGRAM_BINARY_H_
+#endif // LIBANGLE_PROGRAM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.cpp b/src/3rdparty/angle/src/libANGLE/Query.cpp
index 4ee3525509..a402b732bf 100644
--- a/src/3rdparty/angle/src/libGLESv2/Query.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Query.cpp
@@ -6,8 +6,8 @@
// Query.cpp: Implements the gl::Query class
-#include "libGLESv2/Query.h"
-#include "libGLESv2/renderer/QueryImpl.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/renderer/QueryImpl.h"
namespace gl
{
diff --git a/src/3rdparty/angle/src/libGLESv2/Query.h b/src/3rdparty/angle/src/libANGLE/Query.h
index a7ec404f85..8585fde0e2 100644
--- a/src/3rdparty/angle/src/libGLESv2/Query.h
+++ b/src/3rdparty/angle/src/libANGLE/Query.h
@@ -6,12 +6,13 @@
// Query.h: Defines the gl::Query class
-#ifndef LIBGLESV2_QUERY_H_
-#define LIBGLESV2_QUERY_H_
+#ifndef LIBANGLE_QUERY_H_
+#define LIBANGLE_QUERY_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
-#include "libGLESv2/Error.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
#include "angle_gl.h"
@@ -38,11 +39,9 @@ class Query : public RefCountObject
GLenum getType() const;
private:
- DISALLOW_COPY_AND_ASSIGN(Query);
-
rx::QueryImpl *mQuery;
};
}
-#endif // LIBGLESV2_QUERY_H_
+#endif // LIBANGLE_QUERY_H_
diff --git a/src/3rdparty/angle/src/common/RefCountObject.cpp b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp
index c1ef90cdcc..b1210200cf 100644
--- a/src/3rdparty/angle/src/common/RefCountObject.cpp
+++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.cpp
@@ -12,9 +12,9 @@
#include "RefCountObject.h"
RefCountObject::RefCountObject(GLuint id)
+ : mId(id),
+ mRefCount(0)
{
- mId = id;
- mRefCount = 0;
}
RefCountObject::~RefCountObject()
@@ -37,11 +37,3 @@ void RefCountObject::release() const
}
}
-void RefCountObjectBindingPointer::set(RefCountObject *newObject)
-{
- // addRef first in case newObject == mObject and this is the last reference to it.
- if (newObject != NULL) newObject->addRef();
- if (mObject != NULL) mObject->release();
-
- mObject = newObject;
-}
diff --git a/src/3rdparty/angle/src/libANGLE/RefCountObject.h b/src/3rdparty/angle/src/libANGLE/RefCountObject.h
new file mode 100644
index 0000000000..48c0338c3f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/RefCountObject.h
@@ -0,0 +1,110 @@
+//
+// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RefCountObject.h: Defines the gl::RefCountObject base class that provides
+// lifecycle support for GL objects using the traditional BindObject scheme, but
+// that need to be reference counted for correct cross-context deletion.
+// (Concretely, textures, buffers and renderbuffers.)
+
+#ifndef LIBANGLE_REFCOUNTOBJECT_H_
+#define LIBANGLE_REFCOUNTOBJECT_H_
+
+#include "common/debug.h"
+
+#include "angle_gl.h"
+
+#include <cstddef>
+
+class RefCountObject : angle::NonCopyable
+{
+ public:
+ explicit RefCountObject(GLuint id);
+ virtual ~RefCountObject();
+
+ virtual void addRef() const;
+ virtual void release() const;
+
+ GLuint id() const { return mId; }
+
+ private:
+ GLuint mId;
+
+ mutable std::size_t mRefCount;
+};
+
+template <class ObjectType>
+class BindingPointer
+{
+public:
+ BindingPointer()
+ : mObject(nullptr)
+ {
+ }
+
+ BindingPointer(const BindingPointer<ObjectType> &other)
+ : mObject(nullptr)
+ {
+ set(other.mObject);
+ }
+
+ void operator=(const BindingPointer<ObjectType> &other)
+ {
+ set(other.mObject);
+ }
+
+ virtual ~BindingPointer()
+ {
+ // Objects have to be released before the resource manager is destroyed, so they must be explicitly cleaned up.
+ ASSERT(mObject == nullptr);
+ }
+
+ virtual void set(ObjectType *newObject)
+ {
+ // addRef first in case newObject == mObject and this is the last reference to it.
+ if (newObject != nullptr) reinterpret_cast<const RefCountObject*>(newObject)->addRef();
+ if (mObject != nullptr) reinterpret_cast<const RefCountObject*>(mObject)->release();
+ mObject = newObject;
+ }
+
+ ObjectType *get() const { return mObject; }
+ ObjectType *operator->() const { return mObject; }
+
+ GLuint id() const { return (mObject != nullptr) ? mObject->id() : 0; }
+ bool operator!() const { return (mObject == nullptr); }
+
+ private:
+ ObjectType *mObject;
+};
+
+template <class ObjectType>
+class OffsetBindingPointer : public BindingPointer<ObjectType>
+{
+ public:
+ OffsetBindingPointer() : mOffset(0), mSize(0) { }
+
+ void set(ObjectType *newObject) override
+ {
+ BindingPointer<ObjectType>::set(newObject);
+ mOffset = 0;
+ mSize = 0;
+ }
+
+ void set(ObjectType *newObject, GLintptr offset, GLsizeiptr size)
+ {
+ BindingPointer<ObjectType>::set(newObject);
+ mOffset = offset;
+ mSize = size;
+ }
+
+ GLintptr getOffset() const { return mOffset; }
+ GLsizeiptr getSize() const { return mSize; }
+
+ private:
+ GLintptr mOffset;
+ GLsizeiptr mSize;
+};
+
+#endif // LIBANGLE_REFCOUNTOBJECT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp
index 911a389dfa..6a0cde812b 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.cpp
@@ -8,29 +8,25 @@
// GL renderbuffer objects and related functionality.
// [OpenGL ES 2.0.24] section 4.4.3 page 108.
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/RenderbufferImpl.h"
+#include "libANGLE/Renderbuffer.h"
#include "common/utilities.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
namespace gl
{
Renderbuffer::Renderbuffer(rx::RenderbufferImpl *impl, GLuint id)
: RefCountObject(id),
- mRenderbuffer(impl)
+ mRenderbuffer(impl),
+ mWidth(0),
+ mHeight(0),
+ mInternalFormat(GL_RGBA4),
+ mSamples(0)
{
- ASSERT(mRenderbuffer);
-
- mWidth = mRenderbuffer->getWidth();
- mHeight = mRenderbuffer->getHeight();
- mInternalFormat = mRenderbuffer->getInternalFormat();
- mActualFormat = mRenderbuffer->getActualFormat();
- mSamples = mRenderbuffer->getSamples();
}
Renderbuffer::~Renderbuffer()
@@ -38,9 +34,25 @@ Renderbuffer::~Renderbuffer()
SafeDelete(mRenderbuffer);
}
-Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
+Error Renderbuffer::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ Error error = mRenderbuffer->setStorage(internalformat, width, height);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ mWidth = width;
+ mHeight = height;
+ mInternalFormat = internalformat;
+ mSamples = 0;
+
+ return Error(GL_NO_ERROR);
+}
+
+Error Renderbuffer::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
{
- Error error = mRenderbuffer->setStorage(width, height, internalformat, samples);
+ Error error = mRenderbuffer->setStorageMultisample(samples, internalformat, width, height);
if (error.isError())
{
return error;
@@ -50,7 +62,6 @@ Error Renderbuffer::setStorage(GLsizei width, GLsizei height, GLenum internalfor
mHeight = height;
mInternalFormat = internalformat;
mSamples = samples;
- mActualFormat = mRenderbuffer->getActualFormat();
return Error(GL_NO_ERROR);
}
@@ -61,6 +72,11 @@ rx::RenderbufferImpl *Renderbuffer::getImplementation()
return mRenderbuffer;
}
+const rx::RenderbufferImpl *Renderbuffer::getImplementation() const
+{
+ return mRenderbuffer;
+}
+
GLsizei Renderbuffer::getWidth() const
{
return mWidth;
@@ -76,11 +92,6 @@ GLenum Renderbuffer::getInternalFormat() const
return mInternalFormat;
}
-GLenum Renderbuffer::getActualFormat() const
-{
- return mActualFormat;
-}
-
GLsizei Renderbuffer::getSamples() const
{
return mSamples;
@@ -88,32 +99,32 @@ GLsizei Renderbuffer::getSamples() const
GLuint Renderbuffer::getRedSize() const
{
- return GetInternalFormatInfo(getActualFormat()).redBits;
+ return GetInternalFormatInfo(mInternalFormat).redBits;
}
GLuint Renderbuffer::getGreenSize() const
{
- return GetInternalFormatInfo(getActualFormat()).greenBits;
+ return GetInternalFormatInfo(mInternalFormat).greenBits;
}
GLuint Renderbuffer::getBlueSize() const
{
- return GetInternalFormatInfo(getActualFormat()).blueBits;
+ return GetInternalFormatInfo(mInternalFormat).blueBits;
}
GLuint Renderbuffer::getAlphaSize() const
{
- return GetInternalFormatInfo(getActualFormat()).alphaBits;
+ return GetInternalFormatInfo(mInternalFormat).alphaBits;
}
GLuint Renderbuffer::getDepthSize() const
{
- return GetInternalFormatInfo(getActualFormat()).depthBits;
+ return GetInternalFormatInfo(mInternalFormat).depthBits;
}
GLuint Renderbuffer::getStencilSize() const
{
- return GetInternalFormatInfo(getActualFormat()).stencilBits;
+ return GetInternalFormatInfo(mInternalFormat).stencilBits;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h
index e9f12af3ce..98c7eb0f10 100644
--- a/src/3rdparty/angle/src/libGLESv2/Renderbuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/Renderbuffer.h
@@ -8,15 +8,15 @@
// Implements GL renderbuffer objects and related functionality.
// [OpenGL ES 2.0.24] section 4.4.3 page 108.
-#ifndef LIBGLESV2_RENDERBUFFER_H_
-#define LIBGLESV2_RENDERBUFFER_H_
+#ifndef LIBANGLE_RENDERBUFFER_H_
+#define LIBANGLE_RENDERBUFFER_H_
#include "angle_gl.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
namespace rx
{
@@ -38,14 +38,15 @@ class Renderbuffer : public RefCountObject
Renderbuffer(rx::RenderbufferImpl *impl, GLuint id);
virtual ~Renderbuffer();
- Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples);
+ Error setStorage(GLenum internalformat, size_t width, size_t height);
+ Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height);
rx::RenderbufferImpl *getImplementation();
+ const rx::RenderbufferImpl *getImplementation() const;
GLsizei getWidth() const;
GLsizei getHeight() const;
GLenum getInternalFormat() const;
- GLenum getActualFormat() const;
GLsizei getSamples() const;
GLuint getRedSize() const;
GLuint getGreenSize() const;
@@ -55,17 +56,14 @@ class Renderbuffer : public RefCountObject
GLuint getStencilSize() const;
private:
- DISALLOW_COPY_AND_ASSIGN(Renderbuffer);
-
rx::RenderbufferImpl *mRenderbuffer;
GLsizei mWidth;
GLsizei mHeight;
GLenum mInternalFormat;
- GLenum mActualFormat;
GLsizei mSamples;
};
}
-#endif // LIBGLESV2_RENDERBUFFER_H_
+#endif // LIBANGLE_RENDERBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp
index 38d53cad81..aaf144cfa9 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.cpp
@@ -7,21 +7,21 @@
// ResourceManager.cpp: Implements the gl::ResourceManager class, which tracks and
// retrieves objects which may be shared by multiple Contexts.
-#include "libGLESv2/ResourceManager.h"
+#include "libANGLE/ResourceManager.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Sampler.h"
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/renderer/Renderer.h"
namespace gl
{
-ResourceManager::ResourceManager(rx::Renderer *renderer)
- : mRenderer(renderer),
+ResourceManager::ResourceManager(rx::ImplFactory *factory)
+ : mFactory(factory),
mRefCount(1)
{
}
@@ -94,7 +94,7 @@ GLuint ResourceManager::createShader(const gl::Data &data, GLenum type)
if (type == GL_VERTEX_SHADER || type == GL_FRAGMENT_SHADER)
{
- mShaderMap[handle] = new Shader(this, mRenderer->createShader(data, type), type, handle);
+ mShaderMap[handle] = new Shader(this, mFactory->createShader(type), type, handle);
}
else UNREACHABLE();
@@ -106,7 +106,7 @@ GLuint ResourceManager::createProgram()
{
GLuint handle = mProgramShaderHandleAllocator.allocate();
- mProgramMap[handle] = new Program(mRenderer, this, handle);
+ mProgramMap[handle] = new Program(mFactory->createProgram(), this, handle);
return handle;
}
@@ -146,7 +146,7 @@ GLuint ResourceManager::createFenceSync()
{
GLuint handle = mFenceSyncHandleAllocator.allocate();
- FenceSync *fenceSync = new FenceSync(mRenderer->createFenceSync(), handle);
+ FenceSync *fenceSync = new FenceSync(mFactory->createFenceSync(), handle);
fenceSync->addRef();
mFenceSyncMap[handle] = fenceSync;
@@ -356,56 +356,84 @@ void ResourceManager::setRenderbuffer(GLuint handle, Renderbuffer *buffer)
mRenderbufferMap[handle] = buffer;
}
-void ResourceManager::checkBufferAllocation(unsigned int buffer)
+void ResourceManager::checkBufferAllocation(GLuint handle)
{
- if (buffer != 0 && !getBuffer(buffer))
+ if (handle != 0)
{
- Buffer *bufferObject = new Buffer(mRenderer->createBuffer(), buffer);
- mBufferMap[buffer] = bufferObject;
- bufferObject->addRef();
- }
-}
+ auto bufferMapIt = mBufferMap.find(handle);
+ bool handleAllocated = (bufferMapIt != mBufferMap.end());
-void ResourceManager::checkTextureAllocation(GLuint texture, GLenum type)
-{
- if (!getTexture(texture) && texture != 0)
- {
- Texture *textureObject;
+ if (handleAllocated && bufferMapIt->second != nullptr)
+ {
+ return;
+ }
+
+ Buffer *buffer = new Buffer(mFactory->createBuffer(), handle);
+ buffer->addRef();
- if (type == GL_TEXTURE_2D)
+ if (handleAllocated)
{
- textureObject = new Texture2D(mRenderer->createTexture(GL_TEXTURE_2D), texture);
+ bufferMapIt->second = buffer;
}
- else if (type == GL_TEXTURE_CUBE_MAP)
+ else
{
- textureObject = new TextureCubeMap(mRenderer->createTexture(GL_TEXTURE_CUBE_MAP), texture);
+ mBufferHandleAllocator.reserve(handle);
+ mBufferMap[handle] = buffer;
}
- else if (type == GL_TEXTURE_3D)
+ }
+}
+
+void ResourceManager::checkTextureAllocation(GLuint handle, GLenum type)
+{
+ if (handle != 0)
+ {
+ auto textureMapIt = mTextureMap.find(handle);
+ bool handleAllocated = (textureMapIt != mTextureMap.end());
+
+ if (handleAllocated && textureMapIt->second != nullptr)
{
- textureObject = new Texture3D(mRenderer->createTexture(GL_TEXTURE_3D), texture);
+ return;
}
- else if (type == GL_TEXTURE_2D_ARRAY)
+
+ Texture *texture = new Texture(mFactory->createTexture(type), handle, type);
+ texture->addRef();
+
+ if (handleAllocated)
{
- textureObject = new Texture2DArray(mRenderer->createTexture(GL_TEXTURE_2D_ARRAY), texture);
+ textureMapIt->second = texture;
}
else
{
- UNREACHABLE();
- return;
+ mTextureHandleAllocator.reserve(handle);
+ mTextureMap[handle] = texture;
}
-
- mTextureMap[texture] = textureObject;
- textureObject->addRef();
}
}
-void ResourceManager::checkRenderbufferAllocation(GLuint renderbuffer)
+void ResourceManager::checkRenderbufferAllocation(GLuint handle)
{
- if (renderbuffer != 0 && !getRenderbuffer(renderbuffer))
+ if (handle != 0)
{
- Renderbuffer *renderbufferObject = new Renderbuffer(mRenderer->createRenderbuffer(), renderbuffer);
- mRenderbufferMap[renderbuffer] = renderbufferObject;
- renderbufferObject->addRef();
+ auto renderbufferMapIt = mRenderbufferMap.find(handle);
+ bool handleAllocated = (renderbufferMapIt != mRenderbufferMap.end());
+
+ if (handleAllocated && renderbufferMapIt->second != nullptr)
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = new Renderbuffer(mFactory->createRenderbuffer(), handle);
+ renderbuffer->addRef();
+
+ if (handleAllocated)
+ {
+ renderbufferMapIt->second = renderbuffer;
+ }
+ else
+ {
+ mRenderbufferHandleAllocator.reserve(handle);
+ mRenderbufferMap[handle] = renderbuffer;
+ }
}
}
@@ -416,6 +444,7 @@ void ResourceManager::checkSamplerAllocation(GLuint sampler)
Sampler *samplerObject = new Sampler(sampler);
mSamplerMap[sampler] = samplerObject;
samplerObject->addRef();
+ // Samplers cannot be created via Bind
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h b/src/3rdparty/angle/src/libANGLE/ResourceManager.h
index acad29b51d..8e95e8840a 100644
--- a/src/3rdparty/angle/src/libGLESv2/ResourceManager.h
+++ b/src/3rdparty/angle/src/libANGLE/ResourceManager.h
@@ -7,20 +7,19 @@
// ResourceManager.h : Defines the ResourceManager class, which tracks objects
// shared by multiple GL contexts.
-#ifndef LIBGLESV2_RESOURCEMANAGER_H_
-#define LIBGLESV2_RESOURCEMANAGER_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/HandleAllocator.h"
+#ifndef LIBANGLE_RESOURCEMANAGER_H_
+#define LIBANGLE_RESOURCEMANAGER_H_
#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/HandleAllocator.h"
-#include <unordered_map>
+#include <map>
namespace rx
{
-class Renderer;
+class ImplFactory;
}
namespace gl
@@ -34,10 +33,10 @@ class Sampler;
class FenceSync;
struct Data;
-class ResourceManager
+class ResourceManager : angle::NonCopyable
{
public:
- explicit ResourceManager(rx::Renderer *renderer);
+ explicit ResourceManager(rx::ImplFactory *factory);
~ResourceManager();
void addRef();
@@ -69,47 +68,47 @@ class ResourceManager
void setRenderbuffer(GLuint handle, Renderbuffer *renderbuffer);
- void checkBufferAllocation(unsigned int buffer);
- void checkTextureAllocation(GLuint texture, GLenum type);
- void checkRenderbufferAllocation(GLuint renderbuffer);
+ void checkBufferAllocation(GLuint handle);
+ void checkTextureAllocation(GLuint handle, GLenum type);
+ void checkRenderbufferAllocation(GLuint handle);
void checkSamplerAllocation(GLuint sampler);
bool isSampler(GLuint sampler);
private:
- DISALLOW_COPY_AND_ASSIGN(ResourceManager);
+ void createTextureInternal(GLuint handle);
- rx::Renderer *mRenderer;
+ rx::ImplFactory *mFactory;
std::size_t mRefCount;
- typedef std::unordered_map<GLuint, Buffer*> BufferMap;
+ typedef std::map<GLuint, Buffer*> BufferMap;
BufferMap mBufferMap;
HandleAllocator mBufferHandleAllocator;
- typedef std::unordered_map<GLuint, Shader*> ShaderMap;
+ typedef std::map<GLuint, Shader*> ShaderMap;
ShaderMap mShaderMap;
- typedef std::unordered_map<GLuint, Program*> ProgramMap;
+ typedef std::map<GLuint, Program*> ProgramMap;
ProgramMap mProgramMap;
HandleAllocator mProgramShaderHandleAllocator;
- typedef std::unordered_map<GLuint, Texture*> TextureMap;
+ typedef std::map<GLuint, Texture*> TextureMap;
TextureMap mTextureMap;
HandleAllocator mTextureHandleAllocator;
- typedef std::unordered_map<GLuint, Renderbuffer*> RenderbufferMap;
+ typedef std::map<GLuint, Renderbuffer*> RenderbufferMap;
RenderbufferMap mRenderbufferMap;
HandleAllocator mRenderbufferHandleAllocator;
- typedef std::unordered_map<GLuint, Sampler*> SamplerMap;
+ typedef std::map<GLuint, Sampler*> SamplerMap;
SamplerMap mSamplerMap;
HandleAllocator mSamplerHandleAllocator;
- typedef std::unordered_map<GLuint, FenceSync*> FenceMap;
+ typedef std::map<GLuint, FenceSync*> FenceMap;
FenceMap mFenceSyncMap;
HandleAllocator mFenceSyncHandleAllocator;
};
}
-#endif // LIBGLESV2_RESOURCEMANAGER_H_
+#endif // LIBANGLE_RESOURCEMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp b/src/3rdparty/angle/src/libANGLE/Sampler.cpp
index b906e65557..d58bd5a862 100644
--- a/src/3rdparty/angle/src/libGLESv2/Sampler.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Sampler.cpp
@@ -7,8 +7,8 @@
// 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"
+#include "libANGLE/Sampler.h"
+#include "libANGLE/angletypes.h"
namespace gl
{
diff --git a/src/3rdparty/angle/src/libGLESv2/Sampler.h b/src/3rdparty/angle/src/libANGLE/Sampler.h
index 257bc25d22..d33798ff15 100644
--- a/src/3rdparty/angle/src/libGLESv2/Sampler.h
+++ b/src/3rdparty/angle/src/libANGLE/Sampler.h
@@ -7,10 +7,10 @@
// 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_
+#ifndef LIBANGLE_SAMPLER_H_
+#define LIBANGLE_SAMPLER_H_
-#include "common/RefCountObject.h"
+#include "libANGLE/RefCountObject.h"
namespace gl
{
@@ -57,4 +57,4 @@ class Sampler : public RefCountObject
}
-#endif // LIBGLESV2_SAMPLER_H_
+#endif // LIBANGLE_SAMPLER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libANGLE/Shader.cpp
index 024ef8fb7c..7af4ff358d 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Shader.cpp
@@ -8,11 +8,11 @@
// VertexShader and FragmentShader. Implements GL shader objects and related
// functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section 3.8 page 84.
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/ShaderImpl.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/ResourceManager.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/ResourceManager.h"
#include "common/utilities.h"
@@ -131,9 +131,9 @@ void Shader::getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length,
getSourceImpl(debugInfo, bufSize, length, buffer);
}
-void Shader::compile(const gl::Data &data)
+void Shader::compile(Compiler *compiler)
{
- mCompiled = mShader->compile(data, mSource);
+ mCompiled = mShader->compile(compiler, mSource);
}
void Shader::addRef()
@@ -216,4 +216,28 @@ std::vector<sh::Attribute> &Shader::getActiveOutputVariables()
return mShader->getActiveOutputVariables();
}
+
+int Shader::getSemanticIndex(const std::string &attributeName) const
+{
+ if (!attributeName.empty())
+ {
+ const auto &activeAttributes = mShader->getActiveAttributes();
+
+ int semanticIndex = 0;
+ for (size_t attributeIndex = 0; attributeIndex < activeAttributes.size(); attributeIndex++)
+ {
+ const sh::ShaderVariable &attribute = activeAttributes[attributeIndex];
+
+ if (attribute.name == attributeName)
+ {
+ return semanticIndex;
+ }
+
+ semanticIndex += gl::VariableRegisterCount(attribute.type);
+ }
+ }
+
+ return -1;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.h b/src/3rdparty/angle/src/libANGLE/Shader.h
index 904217dab8..10e79c7499 100644
--- a/src/3rdparty/angle/src/libGLESv2/Shader.h
+++ b/src/3rdparty/angle/src/libANGLE/Shader.h
@@ -9,9 +9,8 @@
// related functionality. [OpenGL ES 2.0.24] section 2.10 page 24 and section
// 3.8 page 84.
-#ifndef LIBGLESV2_SHADER_H_
-#define LIBGLESV2_SHADER_H_
-
+#ifndef LIBANGLE_SHADER_H_
+#define LIBANGLE_SHADER_H_
#include <string>
#include <list>
@@ -21,7 +20,7 @@
#include <GLSLANG/ShaderLang.h>
#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/angletypes.h"
namespace rx
{
@@ -30,6 +29,7 @@ class ShaderImpl;
namespace gl
{
+class Compiler;
class ResourceManager;
struct Data;
@@ -53,7 +53,7 @@ struct PackedVarying : public sh::Varying
}
};
-class Shader
+class Shader : angle::NonCopyable
{
public:
Shader(ResourceManager *manager, rx::ShaderImpl *impl, GLenum type, GLuint handle);
@@ -76,7 +76,7 @@ class Shader
void getTranslatedSource(GLsizei bufSize, GLsizei *length, char *buffer) const;
void getTranslatedSourceWithDebugInfo(GLsizei bufSize, GLsizei *length, char *buffer) const;
- void compile(const gl::Data &data);
+ void compile(Compiler *compiler);
bool isCompiled() const { return mCompiled; }
void addRef();
@@ -97,9 +97,9 @@ class Shader
std::vector<sh::Attribute> &getActiveAttributes();
std::vector<sh::Attribute> &getActiveOutputVariables();
- private:
- DISALLOW_COPY_AND_ASSIGN(Shader);
+ int getSemanticIndex(const std::string &attributeName) const;
+ private:
static void getSourceImpl(const std::string &source, GLsizei bufSize, GLsizei *length, char *buffer);
rx::ShaderImpl *mShader;
@@ -115,4 +115,4 @@ class Shader
}
-#endif // LIBGLESV2_SHADER_H_
+#endif // LIBANGLE_SHADER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp
index b5b62f5848..4c044d2950 100644
--- a/src/3rdparty/angle/src/libGLESv2/State.cpp
+++ b/src/3rdparty/angle/src/libANGLE/State.cpp
@@ -6,16 +6,15 @@
// State.cpp: Implements the State class, encapsulating raw GL state.
-#include "libGLESv2/State.h"
+#include "libANGLE/State.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
namespace gl
{
@@ -36,7 +35,7 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
mMaxDrawBuffers = caps.maxDrawBuffers;
mMaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
- setClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ setColorClearValue(0.0f, 0.0f, 0.0f, 0.0f);
mDepthClearValue = 1.0f;
mStencilClearValue = 0;
@@ -76,11 +75,11 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
mDepthStencil.depthMask = true;
mDepthStencil.stencilTest = false;
mDepthStencil.stencilFunc = GL_ALWAYS;
- mDepthStencil.stencilMask = -1;
- mDepthStencil.stencilWritemask = -1;
+ mDepthStencil.stencilMask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilWritemask = static_cast<GLuint>(-1);
mDepthStencil.stencilBackFunc = GL_ALWAYS;
- mDepthStencil.stencilBackMask = -1;
- mDepthStencil.stencilBackWritemask = -1;
+ mDepthStencil.stencilBackMask = static_cast<GLuint>(-1);
+ mDepthStencil.stencilBackWritemask = static_cast<GLuint>(-1);
mDepthStencil.stencilFail = GL_KEEP;
mDepthStencil.stencilPassDepthFail = GL_KEEP;
mDepthStencil.stencilPassDepthPass = GL_KEEP;
@@ -138,11 +137,12 @@ void State::initialize(const Caps& caps, GLuint clientVersion)
mActiveQueries[GL_ANY_SAMPLES_PASSED_CONSERVATIVE].set(NULL);
mActiveQueries[GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN].set(NULL);
- mCurrentProgramId = 0;
- mCurrentProgramBinary.set(NULL);
+ mProgram = NULL;
mReadFramebuffer = NULL;
mDrawFramebuffer = NULL;
+
+ mPrimitiveRestart = false;
}
void State::reset()
@@ -163,6 +163,12 @@ void State::reset()
mArrayBuffer.set(NULL);
mRenderbuffer.set(NULL);
+ if (mProgram)
+ {
+ mProgram->release();
+ }
+ mProgram = NULL;
+
mTransformFeedback.set(NULL);
for (State::ActiveQueryMap::iterator i = mActiveQueries.begin(); i != mActiveQueries.end(); i++)
@@ -187,6 +193,8 @@ void State::reset()
mPack.pixelBuffer.set(NULL);
mUnpack.pixelBuffer.set(NULL);
+
+ mProgram = NULL;
}
const RasterizerState &State::getRasterizerState() const
@@ -204,7 +212,7 @@ const DepthStencilState &State::getDepthStencilState() const
return mDepthStencil;
}
-void State::setClearColor(float red, float green, float blue, float alpha)
+void State::setColorClearValue(float red, float green, float blue, float alpha)
{
mColorClearValue.red = red;
mColorClearValue.green = green;
@@ -212,72 +220,16 @@ void State::setClearColor(float red, float green, float blue, float alpha)
mColorClearValue.alpha = alpha;
}
-void State::setClearDepth(float depth)
+void State::setDepthClearValue(float depth)
{
mDepthClearValue = depth;
}
-void State::setClearStencil(int stencil)
+void State::setStencilClearValue(int stencil)
{
mStencilClearValue = stencil;
}
-ClearParameters State::getClearParameters(GLbitfield mask) const
-{
- ClearParameters clearParams = { 0 };
- for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
- {
- clearParams.clearColor[i] = false;
- }
- clearParams.colorFClearValue = mColorClearValue;
- clearParams.colorClearType = GL_FLOAT;
- clearParams.colorMaskRed = mBlend.colorMaskRed;
- clearParams.colorMaskGreen = mBlend.colorMaskGreen;
- clearParams.colorMaskBlue = mBlend.colorMaskBlue;
- clearParams.colorMaskAlpha = mBlend.colorMaskAlpha;
- clearParams.clearDepth = false;
- clearParams.depthClearValue = mDepthClearValue;
- clearParams.clearStencil = false;
- clearParams.stencilClearValue = mStencilClearValue;
- clearParams.stencilWriteMask = mDepthStencil.stencilWritemask;
- clearParams.scissorEnabled = mScissorTest;
- clearParams.scissor = mScissor;
-
- const Framebuffer *framebufferObject = getDrawFramebuffer();
- if (mask & GL_COLOR_BUFFER_BIT)
- {
- if (framebufferObject->hasEnabledColorAttachment())
- {
- for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
- {
- clearParams.clearColor[i] = true;
- }
- }
- }
-
- if (mask & GL_DEPTH_BUFFER_BIT)
- {
- if (mDepthStencil.depthMask && framebufferObject->getDepthbuffer() != NULL)
- {
- clearParams.clearDepth = true;
- }
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT)
- {
- if (framebufferObject->getStencilbuffer() != NULL)
- {
- GLenum stencilActualFormat = framebufferObject->getStencilbuffer()->getActualFormat();
- if (GetInternalFormatInfo(stencilActualFormat).stencilBits > 0)
- {
- clearParams.clearStencil = true;
- }
- }
- }
-
- return clearParams;
-}
-
void State::setColorMask(bool red, bool green, bool blue, bool alpha)
{
mBlend.colorMaskRed = red;
@@ -527,6 +479,16 @@ void State::setDither(bool enabled)
mBlend.dither = enabled;
}
+bool State::isPrimitiveRestartEnabled() const
+{
+ return mPrimitiveRestart;
+}
+
+void State::setPrimitiveRestart(bool enabled)
+{
+ mPrimitiveRestart = enabled;
+}
+
void State::setEnableFeature(GLenum feature, bool enabled)
{
switch (feature)
@@ -540,7 +502,7 @@ void State::setEnableFeature(GLenum feature, bool enabled)
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_PRIMITIVE_RESTART_FIXED_INDEX: setPrimitiveRestart(enabled); break;
case GL_RASTERIZER_DISCARD: setRasterizerDiscard(enabled); break;
default: UNREACHABLE();
}
@@ -559,7 +521,7 @@ bool State::getEnableFeature(GLenum feature)
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_PRIMITIVE_RESTART_FIXED_INDEX: return isPrimitiveRestartEnabled();
case GL_RASTERIZER_DISCARD: return isRasterizerDiscardEnabled();
default: UNREACHABLE(); return false;
}
@@ -613,12 +575,16 @@ void State::setSamplerTexture(GLenum type, Texture *texture)
Texture *State::getSamplerTexture(unsigned int sampler, GLenum type) const
{
- return mSamplerTextures.at(type)[sampler].get();
+ const auto it = mSamplerTextures.find(type);
+ ASSERT(it != mSamplerTextures.end());
+ return it->second[sampler].get();
}
GLuint State::getSamplerTextureId(unsigned int sampler, GLenum type) const
{
- return mSamplerTextures.at(type)[sampler].id();
+ const auto it = mSamplerTextures.find(type);
+ ASSERT(it != mSamplerTextures.end());
+ return it->second[sampler].id();
}
void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
@@ -641,8 +607,10 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
BindingPointer<Texture> &binding = textureVector[textureIdx];
if (binding.id() == texture)
{
+ auto it = zeroTextures.find(textureType);
+ ASSERT(it != zeroTextures.end());
// Zero textures are the "default" textures instead of NULL
- binding.set(zeroTextures.at(textureType).get());
+ binding.set(it->second.get());
}
}
}
@@ -665,13 +633,14 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
void State::initializeZeroTextures(const TextureMap &zeroTextures)
{
- for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++)
+ for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it)
{
- TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first];
+ const auto &zeroTexture = *it;
+ auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
{
- samplerTextureArray[textureUnit].set(i->second.get());
+ samplerTextureArray[textureUnit].set(zeroTexture.second.get());
}
}
}
@@ -845,31 +814,27 @@ bool State::removeVertexArrayBinding(GLuint vertexArray)
return false;
}
-void State::setCurrentProgram(GLuint programId, Program *newProgram)
+void State::setProgram(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)
+ if (mProgram != newProgram)
{
- newProgram->addRef();
- mCurrentProgramBinary.set(newProgram->getProgramBinary());
- }
-}
+ if (mProgram)
+ {
+ mProgram->release();
+ }
-void State::setCurrentProgramBinary(ProgramBinary *binary)
-{
- mCurrentProgramBinary.set(binary);
-}
+ mProgram = newProgram;
-GLuint State::getCurrentProgramId() const
-{
- return mCurrentProgramId;
+ if (mProgram)
+ {
+ newProgram->addRef();
+ }
+ }
}
-ProgramBinary *State::getCurrentProgramBinary() const
+Program *State::getProgram() const
{
- return mCurrentProgramBinary.get();
+ return mProgram;
}
void State::setTransformFeedbackBinding(TransformFeedback *transformFeedback)
@@ -882,6 +847,12 @@ TransformFeedback *State::getCurrentTransformFeedback() const
return mTransformFeedback.get();
}
+bool State::isTransformFeedbackActiveUnpaused() const
+{
+ gl::TransformFeedback *curTransformFeedback = getCurrentTransformFeedback();
+ return curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused();
+}
+
void State::detachTransformFeedback(GLuint transformFeedback)
{
if (mTransformFeedback.id() == transformFeedback)
@@ -917,10 +888,12 @@ GLuint State::getActiveQueryId(GLenum target) const
Query *State::getActiveQuery(GLenum target) const
{
+ const auto it = mActiveQueries.find(target);
+
// All query types should already exist in the activeQueries map
- ASSERT(mActiveQueries.find(target) != mActiveQueries.end());
+ ASSERT(it != mActiveQueries.end());
- return mActiveQueries.at(target).get();
+ return it->second.get();
}
void State::setArrayBufferBinding(Buffer *buffer)
@@ -968,6 +941,20 @@ Buffer *State::getIndexedUniformBuffer(GLuint index) const
return mUniformBuffers[index].get();
}
+GLintptr State::getIndexedUniformBufferOffset(GLuint index) const
+{
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+
+ return mUniformBuffers[index].getOffset();
+}
+
+GLsizeiptr State::getIndexedUniformBufferSize(GLuint index) const
+{
+ ASSERT(static_cast<size_t>(index) < mUniformBuffers.size());
+
+ return mUniformBuffers[index].getSize();
+}
+
void State::setGenericTransformFeedbackBufferBinding(Buffer *buffer)
{
mGenericTransformFeedbackBuffer.set(buffer);
@@ -1069,11 +1056,6 @@ void State::setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GL
getVertexArray()->setAttributeState(attribNum, boundBuffer, size, type, normalized, pureInteger, stride, pointer);
}
-const VertexAttribute &State::getVertexAttribState(unsigned int attribNum) const
-{
- return getVertexArray()->getVertexAttribute(attribNum);
-}
-
const VertexAttribCurrentValueData &State::getVertexAttribCurrentValue(unsigned int attribNum) const
{
ASSERT(static_cast<size_t>(attribNum) < mVertexAttribCurrentValues.size());
@@ -1110,6 +1092,11 @@ const PixelPackState &State::getPackState() const
return mPack;
}
+PixelPackState &State::getPackState()
+{
+ return mPack;
+}
+
void State::setUnpackAlignment(GLint alignment)
{
mUnpack.alignment = alignment;
@@ -1120,11 +1107,26 @@ GLint State::getUnpackAlignment() const
return mUnpack.alignment;
}
+void State::setUnpackRowLength(GLint rowLength)
+{
+ mUnpack.rowLength = rowLength;
+}
+
+GLint State::getUnpackRowLength() const
+{
+ return mUnpack.rowLength;
+}
+
const PixelUnpackState &State::getUnpackState() const
{
return mUnpack;
}
+PixelUnpackState &State::getUnpackState()
+{
+ return mUnpack;
+}
+
void State::getBooleanv(GLenum pname, GLboolean *params)
{
switch (pname)
@@ -1214,10 +1216,11 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
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_CURRENT_PROGRAM: *params = mProgram ? mProgram->id() : 0; break;
case GL_PACK_ALIGNMENT: *params = mPack.alignment; break;
case GL_PACK_REVERSE_ROW_ORDER_ANGLE: *params = mPack.reverseRowOrder; break;
case GL_UNPACK_ALIGNMENT: *params = mUnpack.alignment; break;
+ case GL_UNPACK_ROW_LENGTH: *params = mUnpack.rowLength; break;
case GL_GENERATE_MIPMAP_HINT: *params = mGenerateMipmapHint; break;
case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES: *params = mFragmentShaderDerivativeHint; break;
case GL_ACTIVE_TEXTURE: *params = (mActiveSampler + GL_TEXTURE0); break;
@@ -1243,11 +1246,13 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
case GL_STENCIL_WRITEMASK: *params = clampToInt(mDepthStencil.stencilWritemask); break;
case GL_STENCIL_BACK_WRITEMASK: *params = clampToInt(mDepthStencil.stencilBackWritemask); break;
case GL_STENCIL_CLEAR_VALUE: *params = mStencilClearValue; break;
+ case GL_IMPLEMENTATION_COLOR_READ_TYPE: *params = mReadFramebuffer->getImplementationColorReadType(); break;
+ case GL_IMPLEMENTATION_COLOR_READ_FORMAT: *params = mReadFramebuffer->getImplementationColorReadFormat(); break;
case GL_SAMPLE_BUFFERS:
case GL_SAMPLES:
{
gl::Framebuffer *framebuffer = mDrawFramebuffer;
- if (framebuffer->completeness(data) == GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE)
{
switch (pname)
{
@@ -1342,19 +1347,19 @@ void State::getIntegerv(const gl::Data &data, GLenum pname, GLint *params)
break;
case GL_TEXTURE_BINDING_2D:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
- *params = mSamplerTextures.at(GL_TEXTURE_2D)[mActiveSampler].id();
+ *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D) ;
break;
case GL_TEXTURE_BINDING_CUBE_MAP:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
- *params = mSamplerTextures.at(GL_TEXTURE_CUBE_MAP)[mActiveSampler].id();
+ *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_CUBE_MAP);
break;
case GL_TEXTURE_BINDING_3D:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
- *params = mSamplerTextures.at(GL_TEXTURE_3D)[mActiveSampler].id();
+ *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_3D);
break;
case GL_TEXTURE_BINDING_2D_ARRAY:
ASSERT(mActiveSampler < mMaxCombinedTextureImageUnits);
- *params = mSamplerTextures.at(GL_TEXTURE_2D_ARRAY)[mActiveSampler].id();
+ *params = getSamplerTextureId(mActiveSampler, GL_TEXTURE_2D_ARRAY);
break;
case GL_UNIFORM_BUFFER_BINDING:
*params = mGenericUniformBuffer.id();
@@ -1442,9 +1447,10 @@ bool State::hasMappedBuffer(GLenum target) const
{
if (target == GL_ARRAY_BUFFER)
{
+ const VertexArray *vao = getVertexArray();
for (size_t attribIndex = 0; attribIndex < mVertexAttribCurrentValues.size(); attribIndex++)
{
- const gl::VertexAttribute &vertexAttrib = getVertexAttribState(static_cast<unsigned int>(attribIndex));
+ const gl::VertexAttribute &vertexAttrib = vao->getVertexAttribute(attribIndex);
gl::Buffer *boundBuffer = vertexAttrib.buffer.get();
if (vertexAttrib.enabled && boundBuffer && boundBuffer->isMapped())
{
diff --git a/src/3rdparty/angle/src/libGLESv2/State.h b/src/3rdparty/angle/src/libANGLE/State.h
index c3e6106bd8..4370a2f16f 100644
--- a/src/3rdparty/angle/src/libGLESv2/State.h
+++ b/src/3rdparty/angle/src/libANGLE/State.h
@@ -6,18 +6,18 @@
// State.h: Defines the State class, encapsulating raw GL state
-#ifndef LIBGLESV2_STATE_H_
-#define LIBGLESV2_STATE_H_
+#ifndef LIBANGLE_STATE_H_
+#define LIBANGLE_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"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Sampler.h"
namespace gl
{
@@ -29,7 +29,7 @@ struct Data;
typedef std::map< GLenum, BindingPointer<Texture> > TextureMap;
-class State
+class State : angle::NonCopyable
{
public:
State();
@@ -44,10 +44,13 @@ class State
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;
+ void setColorClearValue(float red, float green, float blue, float alpha);
+ void setDepthClearValue(float depth);
+ void setStencilClearValue(int stencil);
+
+ const ColorF &getColorClearValue() const { return mColorClearValue; }
+ float getDepthClearValue() const { return mDepthClearValue; }
+ int getStencilClearValue() const { return mStencilClearValue; }
// Write mask manipulation
void setColorMask(bool red, bool green, bool blue, bool alpha);
@@ -57,6 +60,10 @@ class State
bool isRasterizerDiscardEnabled() const;
void setRasterizerDiscard(bool enabled);
+ // Primitive restart
+ bool isPrimitiveRestartEnabled() const;
+ void setPrimitiveRestart(bool enabled);
+
// Face culling state manipulation
bool isCullFaceEnabled() const;
void setCullFace(bool enabled);
@@ -167,14 +174,13 @@ class State
bool removeVertexArrayBinding(GLuint vertexArray);
// Program binding manipulation
- void setCurrentProgram(GLuint programId, Program *newProgram);
- void setCurrentProgramBinary(ProgramBinary *binary);
- GLuint getCurrentProgramId() const;
- ProgramBinary *getCurrentProgramBinary() const;
+ void setProgram(Program *newProgram);
+ Program *getProgram() const;
// Transform feedback object (not buffer) binding manipulation
void setTransformFeedbackBinding(TransformFeedback *transformFeedback);
TransformFeedback *getCurrentTransformFeedback() const;
+ bool isTransformFeedbackActiveUnpaused() const;
void detachTransformFeedback(GLuint transformFeedback);
// Query binding manipulation
@@ -194,6 +200,8 @@ class State
void setIndexedUniformBufferBinding(GLuint index, Buffer *buffer, GLintptr offset, GLsizeiptr size);
GLuint getIndexedUniformBufferId(GLuint index) const;
Buffer *getIndexedUniformBuffer(GLuint index) const;
+ GLintptr getIndexedUniformBufferOffset(GLuint index) const;
+ GLsizeiptr getIndexedUniformBufferSize(GLuint index) const;
// GL_TRANSFORM_FEEDBACK_BUFFER - Both indexed and generic targets
void setGenericTransformFeedbackBufferBinding(Buffer *buffer);
@@ -221,7 +229,6 @@ class State
void setVertexAttribi(GLuint index, const GLint values[4]);
void setVertexAttribState(unsigned int attribNum, Buffer *boundBuffer, GLint size, GLenum type,
bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
- const VertexAttribute &getVertexAttribState(unsigned int attribNum) const;
const VertexAttribCurrentValueData &getVertexAttribCurrentValue(unsigned int attribNum) const;
const void *getVertexAttribPointer(unsigned int attribNum) const;
@@ -231,11 +238,15 @@ class State
void setPackReverseRowOrder(bool reverseRowOrder);
bool getPackReverseRowOrder() const;
const PixelPackState &getPackState() const;
+ PixelPackState &getPackState();
// Pixel unpack state manipulation
void setUnpackAlignment(GLint alignment);
GLint getUnpackAlignment() const;
+ void setUnpackRowLength(GLint rowLength);
+ GLint getUnpackRowLength() const;
const PixelUnpackState &getUnpackState() const;
+ PixelUnpackState &getUnpackState();
// State query functions
void getBooleanv(GLenum pname, GLboolean *params);
@@ -247,8 +258,6 @@ class State
bool hasMappedBuffer(GLenum target) const;
private:
- DISALLOW_COPY_AND_ASSIGN(State);
-
// Cached values from Context's caps
GLuint mMaxDrawBuffers;
GLuint mMaxCombinedTextureImageUnits;
@@ -284,8 +293,7 @@ class State
Framebuffer *mReadFramebuffer;
Framebuffer *mDrawFramebuffer;
BindingPointer<Renderbuffer> mRenderbuffer;
- GLuint mCurrentProgramId;
- BindingPointer<ProgramBinary> mCurrentProgramBinary;
+ Program *mProgram;
typedef std::vector<VertexAttribCurrentValueData> VertexAttribVector;
VertexAttribVector mVertexAttribCurrentValues; // From glVertexAttrib
@@ -317,9 +325,11 @@ class State
PixelUnpackState mUnpack;
PixelPackState mPack;
+
+ bool mPrimitiveRestart;
};
}
-#endif // LIBGLESV2_STATE_H_
+#endif // LIBANGLE_STATE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Surface.cpp b/src/3rdparty/angle/src/libANGLE/Surface.cpp
new file mode 100644
index 0000000000..ac455f3905
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Surface.cpp
@@ -0,0 +1,166 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#include "libANGLE/Surface.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+#include <EGL/eglext.h>
+
+namespace egl
+{
+
+Surface::Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes)
+ : RefCountObject(0), // id unused
+ mImplementation(impl),
+ mType(surfaceType),
+ mConfig(config),
+ mPostSubBufferRequested(false),
+ mFixedSize(false),
+ mFixedWidth(0),
+ mFixedHeight(0),
+ mTextureFormat(EGL_NO_TEXTURE),
+ mTextureTarget(EGL_NO_TEXTURE),
+ // FIXME: Determine actual pixel aspect ratio
+ mPixelAspectRatio(static_cast<EGLint>(1.0 * EGL_DISPLAY_SCALING)),
+ mRenderBuffer(EGL_BACK_BUFFER),
+ mSwapBehavior(EGL_BUFFER_PRESERVED),
+ mTexture(NULL)
+{
+ addRef();
+
+ mPostSubBufferRequested = (attributes.get(EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_FALSE) == EGL_TRUE);
+
+ mFixedSize = (attributes.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE) == EGL_TRUE);
+ if (mFixedSize)
+ {
+ mFixedWidth = attributes.get(EGL_WIDTH, 0);
+ mFixedHeight = attributes.get(EGL_HEIGHT, 0);
+ }
+
+ if (mType != EGL_WINDOW_BIT)
+ {
+ mTextureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ mTextureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ }
+}
+
+Surface::~Surface()
+{
+ if (mTexture)
+ {
+ if (mImplementation)
+ {
+ mImplementation->releaseTexImage(mTexture->id());
+ }
+ mTexture->releaseTexImage();
+ mTexture = NULL;
+ }
+
+ SafeDelete(mImplementation);
+}
+
+EGLint Surface::getType() const
+{
+ return mType;
+}
+
+Error Surface::swap()
+{
+ return mImplementation->swap();
+}
+
+Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return mImplementation->postSubBuffer(x, y, width, height);
+}
+
+Error Surface::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ return mImplementation->querySurfacePointerANGLE(attribute, value);
+}
+
+EGLint Surface::isPostSubBufferSupported() const
+{
+ return mPostSubBufferRequested && mImplementation->isPostSubBufferSupported();
+}
+
+void Surface::setSwapInterval(EGLint interval)
+{
+ mImplementation->setSwapInterval(interval);
+}
+
+const Config *Surface::getConfig() const
+{
+ return mConfig;
+}
+
+EGLint Surface::getPixelAspectRatio() const
+{
+ return mPixelAspectRatio;
+}
+
+EGLenum Surface::getRenderBuffer() const
+{
+ return mRenderBuffer;
+}
+
+EGLenum Surface::getSwapBehavior() const
+{
+ return mSwapBehavior;
+}
+
+EGLenum Surface::getTextureFormat() const
+{
+ return mTextureFormat;
+}
+
+EGLenum Surface::getTextureTarget() const
+{
+ return mTextureTarget;
+}
+
+EGLint Surface::isFixedSize() const
+{
+ return mFixedSize;
+}
+
+EGLint Surface::getWidth() const
+{
+ return mFixedSize ? mFixedWidth : mImplementation->getWidth();
+}
+
+EGLint Surface::getHeight() const
+{
+ return mFixedSize ? mFixedHeight : mImplementation->getHeight();
+}
+
+Error Surface::bindTexImage(gl::Texture *texture, EGLint buffer)
+{
+ ASSERT(!mTexture);
+
+ texture->bindTexImage(this);
+ mTexture = texture;
+ return mImplementation->bindTexImage(buffer);
+}
+
+Error Surface::releaseTexImage(EGLint buffer)
+{
+ ASSERT(mTexture);
+ gl::Texture *boundTexture = mTexture;
+ mTexture = NULL;
+
+ boundTexture->releaseTexImage();
+ return mImplementation->releaseTexImage(buffer);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Surface.h b/src/3rdparty/angle/src/libANGLE/Surface.h
new file mode 100644
index 0000000000..430bf0195d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Surface.h
@@ -0,0 +1,98 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Surface.h: Defines the egl::Surface class, representing a drawing surface
+// such as the client area of a window, including any back buffers.
+// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
+
+#ifndef LIBANGLE_SURFACE_H_
+#define LIBANGLE_SURFACE_H_
+
+#include <EGL/egl.h>
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/RefCountObject.h"
+
+namespace gl
+{
+class Texture;
+}
+
+namespace rx
+{
+class SurfaceImpl;
+}
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct Config;
+
+class Surface final : public RefCountObject
+{
+ public:
+ Surface(rx::SurfaceImpl *impl, EGLint surfaceType, const egl::Config *config, const AttributeMap &attributes);
+
+ rx::SurfaceImpl *getImplementation() { return mImplementation; }
+ const rx::SurfaceImpl *getImplementation() const { return mImplementation; }
+
+ EGLint getType() const;
+
+ Error swap();
+ Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
+ Error querySurfacePointerANGLE(EGLint attribute, void **value);
+ Error bindTexImage(gl::Texture *texture, EGLint buffer);
+ Error releaseTexImage(EGLint buffer);
+
+ EGLint isPostSubBufferSupported() const;
+
+ void setSwapInterval(EGLint interval);
+
+ const Config *getConfig() const;
+
+ // width and height can change with client window resizing
+ EGLint getWidth() const;
+ EGLint getHeight() const;
+ EGLint getPixelAspectRatio() const;
+ EGLenum getRenderBuffer() const;
+ EGLenum getSwapBehavior() const;
+ EGLenum getTextureFormat() const;
+ EGLenum getTextureTarget() const;
+
+ gl::Texture *getBoundTexture() const { return mTexture; }
+
+ EGLint isFixedSize() const;
+
+ private:
+ virtual ~Surface();
+
+ rx::SurfaceImpl *mImplementation;
+
+ EGLint mType;
+
+ const egl::Config *mConfig;
+
+ bool mPostSubBufferRequested;
+
+ bool mFixedSize;
+ size_t mFixedWidth;
+ size_t mFixedHeight;
+
+ EGLenum mTextureFormat;
+ EGLenum mTextureTarget;
+
+ EGLint mPixelAspectRatio; // Display aspect ratio
+ EGLenum mRenderBuffer; // Render buffer
+ EGLenum mSwapBehavior; // Buffer swap behavior
+
+ gl::Texture *mTexture;
+};
+
+}
+
+#endif // LIBANGLE_SURFACE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp
new file mode 100644
index 0000000000..cd4584f694
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp
@@ -0,0 +1,573 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.cpp: Implements the gl::Texture class. [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#include "libANGLE/Texture.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/formatutils.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Surface.h"
+
+#include "common/mathutil.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+bool IsMipmapFiltered(const gl::SamplerState &samplerState)
+{
+ switch (samplerState.minFilter)
+ {
+ case GL_NEAREST:
+ case GL_LINEAR:
+ return false;
+ case GL_NEAREST_MIPMAP_NEAREST:
+ case GL_LINEAR_MIPMAP_NEAREST:
+ case GL_NEAREST_MIPMAP_LINEAR:
+ case GL_LINEAR_MIPMAP_LINEAR:
+ return true;
+ default: UNREACHABLE();
+ return false;
+ }
+}
+
+bool IsPointSampled(const gl::SamplerState &samplerState)
+{
+ return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
+}
+
+static size_t GetImageDescIndex(GLenum target, size_t level)
+{
+ return IsCubeMapTextureTarget(target) ? ((level * 6) + CubeMapTextureTargetToLayerIndex(target)) : level;
+}
+
+unsigned int Texture::mCurrentTextureSerial = 1;
+
+Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
+ : RefCountObject(id),
+ mTexture(impl),
+ mTextureSerial(issueTextureSerial()),
+ mUsage(GL_NONE),
+ mImmutableLevelCount(0),
+ mTarget(target),
+ mImageDescs(IMPLEMENTATION_MAX_TEXTURE_LEVELS * (target == GL_TEXTURE_CUBE_MAP ? 6 : 1)),
+ mCompletenessCache(),
+ mBoundSurface(NULL)
+{
+}
+
+Texture::~Texture()
+{
+ if (mBoundSurface)
+ {
+ mBoundSurface->releaseTexImage(EGL_BACK_BUFFER);
+ mBoundSurface = NULL;
+ }
+ SafeDelete(mTexture);
+}
+
+GLenum Texture::getTarget() const
+{
+ return mTarget;
+}
+
+void Texture::setUsage(GLenum usage)
+{
+ mUsage = usage;
+ getImplementation()->setUsage(usage);
+}
+
+GLenum Texture::getUsage() const
+{
+ return mUsage;
+}
+
+size_t Texture::getWidth(GLenum target, size_t level) const
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return getImageDesc(target, level).size.width;
+}
+
+size_t Texture::getHeight(GLenum target, size_t level) const
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return getImageDesc(target, level).size.height;
+}
+
+size_t Texture::getDepth(GLenum target, size_t level) const
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return getImageDesc(target, level).size.depth;
+}
+
+GLenum Texture::getInternalFormat(GLenum target, size_t level) const
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+ return getImageDesc(target, level).internalFormat;
+}
+
+bool Texture::isSamplerComplete(const SamplerState &samplerState, const Data &data) const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
+ const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
+ if (!mCompletenessCache.cacheValid ||
+ mCompletenessCache.samplerState != samplerState ||
+ mCompletenessCache.filterable != textureCaps.filterable ||
+ mCompletenessCache.clientVersion != data.clientVersion ||
+ mCompletenessCache.supportsNPOT != data.extensions->textureNPOT)
+ {
+ mCompletenessCache.cacheValid = true;
+ mCompletenessCache.samplerState = samplerState;
+ mCompletenessCache.filterable = textureCaps.filterable;
+ mCompletenessCache.clientVersion = data.clientVersion;
+ mCompletenessCache.supportsNPOT = data.extensions->textureNPOT;
+ mCompletenessCache.samplerComplete = computeSamplerCompleteness(samplerState, data);
+ }
+ return mCompletenessCache.samplerComplete;
+}
+
+// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
+bool Texture::isCubeComplete() const
+{
+ ASSERT(mTarget == GL_TEXTURE_CUBE_MAP);
+
+ const ImageDesc &baseImageDesc = getImageDesc(FirstCubeMapTextureTarget, 0);
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ for (GLenum face = FirstCubeMapTextureTarget + 1; face <= LastCubeMapTextureTarget; face++)
+ {
+ const ImageDesc &faceImageDesc = getImageDesc(face, 0);
+ if (faceImageDesc.size.width != baseImageDesc.size.width ||
+ faceImageDesc.size.height != baseImageDesc.size.height ||
+ faceImageDesc.internalFormat != baseImageDesc.internalFormat)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+unsigned int Texture::getTextureSerial() const
+{
+ return mTextureSerial;
+}
+
+unsigned int Texture::issueTextureSerial()
+{
+ return mCurrentTextureSerial++;
+}
+
+bool Texture::isImmutable() const
+{
+ return (mImmutableLevelCount > 0);
+}
+
+int Texture::immutableLevelCount()
+{
+ return mImmutableLevelCount;
+}
+
+Error Texture::setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
+ const PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ Error error = mTexture->setImage(target, level, internalFormat, size, format, type, unpack, pixels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ releaseTexImage();
+
+ setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, type)));
+
+ return Error(GL_NO_ERROR);
+}
+
+Error Texture::setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
+ const PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ return mTexture->setSubImage(target, level, area, format, type, unpack, pixels);
+}
+
+Error Texture::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
+ const PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ Error error = mTexture->setCompressedImage(target, level, internalFormat, size, unpack, pixels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ releaseTexImage();
+
+ setImageDesc(target, level, ImageDesc(size, GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
+
+ return Error(GL_NO_ERROR);
+}
+
+Error Texture::setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
+ const PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ return mTexture->setCompressedSubImage(target, level, area, format, unpack, pixels);
+}
+
+Error Texture::copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
+ const Framebuffer *source)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ Error error = mTexture->copyImage(target, level, sourceArea, internalFormat, source);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ releaseTexImage();
+
+ setImageDesc(target, level, ImageDesc(Extents(sourceArea.width, sourceArea.height, 1),
+ GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE)));
+
+ return Error(GL_NO_ERROR);
+}
+
+Error Texture::copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
+ const Framebuffer *source)
+{
+ ASSERT(target == mTarget || (mTarget == GL_TEXTURE_CUBE_MAP && IsCubeMapTextureTarget(target)));
+
+ return mTexture->copySubImage(target, level, destOffset, sourceArea, source);
+}
+
+Error Texture::setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size)
+{
+ ASSERT(target == mTarget);
+
+ Error error = mTexture->setStorage(target, levels, internalFormat, size);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ releaseTexImage();
+
+ mImmutableLevelCount = levels;
+ clearImageDescs();
+ setImageDescChain(levels, size, internalFormat);
+
+ return Error(GL_NO_ERROR);
+}
+
+
+Error Texture::generateMipmaps()
+{
+ Error error = mTexture->generateMipmaps();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ releaseTexImage();
+
+ const ImageDesc &baseImageInfo = getImageDesc(getBaseImageTarget(), 0);
+ size_t mipLevels = log2(std::max(std::max(baseImageInfo.size.width, baseImageInfo.size.height), baseImageInfo.size.depth)) + 1;
+ setImageDescChain(mipLevels, baseImageInfo.size, baseImageInfo.internalFormat);
+
+ return Error(GL_NO_ERROR);
+}
+
+void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat)
+{
+ for (size_t level = 0; level < levels; level++)
+ {
+ Extents levelSize(std::max<size_t>(baseSize.width >> level, 1),
+ std::max<size_t>(baseSize.height >> level, 1),
+ (mTarget == GL_TEXTURE_2D_ARRAY) ? baseSize.depth : std::max<size_t>(baseSize.depth >> level, 1));
+ ImageDesc levelInfo(levelSize, sizedInternalFormat);
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (size_t face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ setImageDesc(face, level, levelInfo);
+ }
+ }
+ else
+ {
+ setImageDesc(mTarget, level, levelInfo);
+ }
+ }
+}
+
+Texture::ImageDesc::ImageDesc()
+ : size(0, 0, 0), internalFormat(GL_NONE)
+{
+}
+
+Texture::ImageDesc::ImageDesc(const Extents &size, GLenum internalFormat)
+ : size(size),
+ internalFormat(internalFormat)
+{
+}
+
+const Texture::ImageDesc &Texture::getImageDesc(GLenum target, size_t level) const
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ return mImageDescs[descIndex];
+}
+
+void Texture::setImageDesc(GLenum target, size_t level, const ImageDesc &desc)
+{
+ size_t descIndex = GetImageDescIndex(target, level);
+ ASSERT(descIndex < mImageDescs.size());
+ mImageDescs[descIndex] = desc;
+ mCompletenessCache.cacheValid = false;
+}
+
+void Texture::clearImageDesc(GLenum target, size_t level)
+{
+ setImageDesc(target, level, ImageDesc());
+}
+
+void Texture::clearImageDescs()
+{
+ for (size_t descIndex = 0; descIndex < mImageDescs.size(); descIndex++)
+ {
+ mImageDescs[descIndex] = ImageDesc();
+ }
+ mCompletenessCache.cacheValid = false;
+}
+
+void Texture::bindTexImage(egl::Surface *surface)
+{
+ ASSERT(surface);
+
+ releaseTexImage();
+ mTexture->bindTexImage(surface);
+ mBoundSurface = surface;
+
+ // Set the image info to the size and format of the surface
+ ASSERT(mTarget == GL_TEXTURE_2D);
+ Extents size(surface->getWidth(), surface->getHeight(), 1);
+ ImageDesc desc(size, surface->getConfig()->renderTargetFormat);
+ setImageDesc(mTarget, 0, desc);
+}
+
+void Texture::releaseTexImage()
+{
+ if (mBoundSurface)
+ {
+ mBoundSurface = NULL;
+ mTexture->releaseTexImage();
+
+ // Erase the image info for level 0
+ ASSERT(mTarget == GL_TEXTURE_2D);
+ clearImageDesc(mTarget, 0);
+ }
+}
+
+GLenum Texture::getBaseImageTarget() const
+{
+ return mTarget == GL_TEXTURE_CUBE_MAP ? FirstCubeMapTextureTarget : mTarget;
+}
+
+size_t Texture::getExpectedMipLevels() const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), 0);
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ return log2(std::max(std::max(baseImageDesc.size.width, baseImageDesc.size.height), baseImageDesc.size.depth)) + 1;
+ }
+ else
+ {
+ return log2(std::max(baseImageDesc.size.width, baseImageDesc.size.height)) + 1;
+ }
+}
+
+bool Texture::computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const
+{
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+
+ if (mTarget == GL_TEXTURE_CUBE_MAP && baseImageDesc.size.width != baseImageDesc.size.height)
+ {
+ return false;
+ }
+
+ const TextureCaps &textureCaps = data.textureCaps->get(baseImageDesc.internalFormat);
+ if (!textureCaps.filterable && !IsPointSampled(samplerState))
+ {
+ return false;
+ }
+
+ bool npotSupport = data.extensions->textureNPOT || data.clientVersion >= 3;
+ if (!npotSupport)
+ {
+ if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.width)) ||
+ (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(baseImageDesc.size.height)))
+ {
+ return false;
+ }
+ }
+
+ if (IsMipmapFiltered(samplerState))
+ {
+ if (!npotSupport)
+ {
+ if (!gl::isPow2(baseImageDesc.size.width) || !gl::isPow2(baseImageDesc.size.height))
+ {
+ return false;
+ }
+ }
+
+ if (!computeMipmapCompleteness(samplerState))
+ {
+ return false;
+ }
+ }
+ else
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP && !isCubeComplete())
+ {
+ return false;
+ }
+ }
+
+ // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
+ // The internalformat specified for the texture arrays is a sized internal depth or
+ // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
+ // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
+ // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(baseImageDesc.internalFormat);
+ if (formatInfo.depthBits > 0 && data.clientVersion > 2)
+ {
+ if (samplerState.compareMode == GL_NONE)
+ {
+ if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
+ samplerState.magFilter != GL_NEAREST)
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+bool Texture::computeMipmapCompleteness(const gl::SamplerState &samplerState) const
+{
+ size_t expectedMipLevels = getExpectedMipLevels();
+
+ size_t maxLevel = std::min<size_t>(expectedMipLevels, samplerState.maxLevel + 1);
+
+ for (size_t level = samplerState.baseLevel; level < maxLevel; level++)
+ {
+ if (mTarget == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = FirstCubeMapTextureTarget; face <= LastCubeMapTextureTarget; face++)
+ {
+ if (!computeLevelCompleteness(face, level, samplerState))
+ {
+ return false;
+ }
+ }
+ }
+ else
+ {
+ if (!computeLevelCompleteness(mTarget, level, samplerState))
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+
+bool Texture::computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const
+{
+ ASSERT(level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
+
+ if (isImmutable())
+ {
+ return true;
+ }
+
+ const ImageDesc &baseImageDesc = getImageDesc(getBaseImageTarget(), samplerState.baseLevel);
+ if (baseImageDesc.size.width == 0 || baseImageDesc.size.height == 0 || baseImageDesc.size.depth == 0)
+ {
+ return false;
+ }
+
+ // The base image level is complete if the width and height are positive
+ if (level == 0)
+ {
+ return true;
+ }
+
+ const ImageDesc &levelImageDesc = getImageDesc(target, level);
+ if (levelImageDesc.internalFormat != baseImageDesc.internalFormat)
+ {
+ return false;
+ }
+
+ if (levelImageDesc.size.width != std::max(1, baseImageDesc.size.width >> level))
+ {
+ return false;
+ }
+
+ if (levelImageDesc.size.height != std::max(1, baseImageDesc.size.height >> level))
+ {
+ return false;
+ }
+
+ if (mTarget == GL_TEXTURE_3D)
+ {
+ if (levelImageDesc.size.depth != std::max(1, baseImageDesc.size.depth >> level))
+ {
+ return false;
+ }
+ }
+ else if (mTarget == GL_TEXTURE_2D_ARRAY)
+ {
+ if (levelImageDesc.size.depth != baseImageDesc.size.depth)
+ {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+Texture::SamplerCompletenessCache::SamplerCompletenessCache()
+ : cacheValid(false),
+ samplerState(),
+ filterable(false),
+ clientVersion(0),
+ supportsNPOT(false),
+ samplerComplete(false)
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/Texture.h b/src/3rdparty/angle/src/libANGLE/Texture.h
new file mode 100644
index 0000000000..b5a0717713
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/Texture.h
@@ -0,0 +1,156 @@
+//
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Texture.h: Defines the gl::Texture class [OpenGL ES 2.0.24] section 3.7 page 63.
+
+#ifndef LIBANGLE_TEXTURE_H_
+#define LIBANGLE_TEXTURE_H_
+
+#include "common/debug.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/Caps.h"
+
+#include "angle_gl.h"
+
+#include <vector>
+#include <map>
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+class Framebuffer;
+struct Data;
+
+bool IsMipmapFiltered(const gl::SamplerState &samplerState);
+
+class Texture final : public RefCountObject
+{
+ public:
+ Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
+
+ virtual ~Texture();
+
+ GLenum getTarget() const;
+
+ const SamplerState &getSamplerState() const { return mSamplerState; }
+ SamplerState &getSamplerState() { return mSamplerState; }
+
+ void setUsage(GLenum usage);
+ GLenum getUsage() const;
+
+ size_t getWidth(GLenum target, size_t level) const;
+ size_t getHeight(GLenum target, size_t level) const;
+ size_t getDepth(GLenum target, size_t level) const;
+ GLenum getInternalFormat(GLenum target, size_t level) const;
+
+ bool isSamplerComplete(const SamplerState &samplerState, const Data &data) const;
+ bool isCubeComplete() const;
+
+ virtual Error setImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size, GLenum format, GLenum type,
+ const PixelUnpackState &unpack, const uint8_t *pixels);
+ virtual Error setSubImage(GLenum target, size_t level, const Box &area, GLenum format, GLenum type,
+ const PixelUnpackState &unpack, const uint8_t *pixels);
+
+ virtual Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const Extents &size,
+ const PixelUnpackState &unpack, const uint8_t *pixels);
+ virtual Error setCompressedSubImage(GLenum target, size_t level, const Box &area, GLenum format,
+ const PixelUnpackState &unpack, const uint8_t *pixels);
+
+ virtual Error copyImage(GLenum target, size_t level, const Rectangle &sourceArea, GLenum internalFormat,
+ const Framebuffer *source);
+ virtual Error copySubImage(GLenum target, size_t level, const Offset &destOffset, const Rectangle &sourceArea,
+ const Framebuffer *source);
+
+ virtual Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const Extents &size);
+
+ virtual Error generateMipmaps();
+
+ // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer.
+ // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id.
+ unsigned int getTextureSerial() const;
+
+ bool isImmutable() const;
+ GLsizei immutableLevelCount();
+
+ void bindTexImage(egl::Surface *surface);
+ void releaseTexImage();
+
+ rx::TextureImpl *getImplementation() { return mTexture; }
+ const rx::TextureImpl *getImplementation() const { return mTexture; }
+
+ static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
+
+ private:
+ static unsigned int issueTextureSerial();
+
+ rx::TextureImpl *mTexture;
+
+ SamplerState mSamplerState;
+ GLenum mUsage;
+
+ GLsizei mImmutableLevelCount;
+
+ GLenum mTarget;
+
+
+ struct ImageDesc
+ {
+ Extents size;
+ GLenum internalFormat;
+
+ ImageDesc();
+ ImageDesc(const Extents &size, GLenum internalFormat);
+ };
+
+ const unsigned int mTextureSerial;
+ static unsigned int mCurrentTextureSerial;
+
+ GLenum getBaseImageTarget() const;
+ size_t getExpectedMipLevels() const;
+
+ bool computeSamplerCompleteness(const SamplerState &samplerState, const Data &data) const;
+ bool computeMipmapCompleteness(const gl::SamplerState &samplerState) const;
+ bool computeLevelCompleteness(GLenum target, size_t level, const gl::SamplerState &samplerState) const;
+
+ const ImageDesc &getImageDesc(GLenum target, size_t level) const;
+ void setImageDesc(GLenum target, size_t level, const ImageDesc &desc);
+ void setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInternalFormat);
+ void clearImageDesc(GLenum target, size_t level);
+ void clearImageDescs();
+
+ std::vector<ImageDesc> mImageDescs;
+
+ struct SamplerCompletenessCache
+ {
+ SamplerCompletenessCache();
+
+ bool cacheValid;
+
+ // All values that affect sampler completeness that are not stored within
+ // the texture itself
+ SamplerState samplerState;
+ bool filterable;
+ GLint clientVersion;
+ bool supportsNPOT;
+
+ // Result of the sampler completeness with the above parameters
+ bool samplerComplete;
+ };
+ mutable SamplerCompletenessCache mCompletenessCache;
+
+ egl::Surface *mBoundSurface;
+};
+
+}
+
+#endif // LIBANGLE_TEXTURE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp
index bfa7072326..6effaca976 100644
--- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.cpp
+++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.cpp
@@ -4,8 +4,8 @@
// found in the LICENSE file.
//
-#include "libGLESv2/TransformFeedback.h"
-#include "libGLESv2/renderer/TransformFeedbackImpl.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
namespace gl
{
diff --git a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h
index 885a4fe172..7673db93ff 100644
--- a/src/3rdparty/angle/src/libGLESv2/TransformFeedback.h
+++ b/src/3rdparty/angle/src/libANGLE/TransformFeedback.h
@@ -4,11 +4,12 @@
// found in the LICENSE file.
//
-#ifndef LIBGLESV2_TRANSFORM_FEEDBACK_H_
-#define LIBGLESV2_TRANSFORM_FEEDBACK_H_
+#ifndef LIBANGLE_TRANSFORM_FEEDBACK_H_
+#define LIBANGLE_TRANSFORM_FEEDBACK_H_
+
+#include "libANGLE/RefCountObject.h"
#include "common/angleutils.h"
-#include "common/RefCountObject.h"
#include "angle_gl.h"
@@ -37,8 +38,6 @@ class TransformFeedback : public RefCountObject
GLboolean isPaused() const;
private:
- DISALLOW_COPY_AND_ASSIGN(TransformFeedback);
-
rx::TransformFeedbackImpl* mTransformFeedback;
GLboolean mStarted;
@@ -48,4 +47,4 @@ class TransformFeedback : public RefCountObject
}
-#endif // LIBGLESV2_TRANSFORM_FEEDBACK_H_
+#endif // LIBANGLE_TRANSFORM_FEEDBACK_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp b/src/3rdparty/angle/src/libANGLE/Uniform.cpp
index bd0cd2eeec..f161b9d6bd 100644
--- a/src/3rdparty/angle/src/libGLESv2/Uniform.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Uniform.cpp
@@ -4,10 +4,12 @@
// found in the LICENSE file.
//
-#include "libGLESv2/Uniform.h"
+#include "libANGLE/Uniform.h"
#include "common/utilities.h"
+#include <cstring>
+
namespace gl
{
@@ -75,7 +77,7 @@ size_t LinkedUniform::dataSize() const
bool LinkedUniform::isSampler() const
{
- return IsSampler(type);
+ return IsSamplerType(type);
}
UniformBlock::UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize)
diff --git a/src/3rdparty/angle/src/libGLESv2/Uniform.h b/src/3rdparty/angle/src/libANGLE/Uniform.h
index 633d70bb19..dcf30f23cc 100644
--- a/src/3rdparty/angle/src/libGLESv2/Uniform.h
+++ b/src/3rdparty/angle/src/libANGLE/Uniform.h
@@ -4,24 +4,22 @@
// found in the LICENSE file.
//
-#ifndef LIBGLESV2_UNIFORM_H_
-#define LIBGLESV2_UNIFORM_H_
-
-#include "common/debug.h"
-#include "common/blocklayout.h"
-
-#include "libGLESv2/angletypes.h"
-
-#include "angle_gl.h"
+#ifndef LIBANGLE_UNIFORM_H_
+#define LIBANGLE_UNIFORM_H_
#include <string>
#include <vector>
+#include "angle_gl.h"
+#include "common/debug.h"
+#include "compiler/translator/blocklayout.h"
+#include "libANGLE/angletypes.h"
+
namespace gl
{
// Helper struct representing a single shader uniform
-struct LinkedUniform
+struct LinkedUniform : angle::NonCopyable
{
LinkedUniform(GLenum type, GLenum precision, const std::string &name, unsigned int arraySize, const int blockIndex, const sh::BlockMemberInfo &blockInfo);
@@ -55,7 +53,7 @@ struct LinkedUniform
};
// Helper struct representing a single shader uniform block
-struct UniformBlock
+struct UniformBlock : angle::NonCopyable
{
// use GL_INVALID_INDEX for non-array elements
UniformBlock(const std::string &name, unsigned int elementIndex, unsigned int dataSize);
@@ -76,4 +74,4 @@ struct UniformBlock
}
-#endif // LIBGLESV2_UNIFORM_H_
+#endif // LIBANGLE_UNIFORM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp
index f8ca661062..f0aded905d 100644
--- a/src/3rdparty/angle/src/libGLESv2/VertexArray.cpp
+++ b/src/3rdparty/angle/src/libANGLE/VertexArray.cpp
@@ -6,9 +6,9 @@
// 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"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
namespace gl
{
@@ -59,6 +59,11 @@ const VertexAttribute& VertexArray::getVertexAttribute(size_t attributeIndex) co
return mVertexAttributes[attributeIndex];
}
+const std::vector<VertexAttribute> &VertexArray::getVertexAttributes() const
+{
+ return mVertexAttributes;
+}
+
void VertexArray::setVertexAttribDivisor(GLuint index, GLuint divisor)
{
ASSERT(index < getMaxAttribs());
@@ -93,4 +98,4 @@ void VertexArray::setElementArrayBuffer(Buffer *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/libANGLE/VertexArray.h
index a724c0be1c..5c79b9953d 100644
--- a/src/3rdparty/angle/src/libGLESv2/VertexArray.h
+++ b/src/3rdparty/angle/src/libANGLE/VertexArray.h
@@ -10,12 +10,12 @@
// by the vertex processor is encapsulated in a vertex array object.
//
-#ifndef LIBGLESV2_VERTEXARRAY_H_
-#define LIBGLESV2_VERTEXARRAY_H_
+#ifndef LIBANGLE_VERTEXARRAY_H_
+#define LIBANGLE_VERTEXARRAY_H_
-#include "common/RefCountObject.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/RefCountObject.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/VertexAttribute.h"
#include <vector>
@@ -37,18 +37,22 @@ class VertexArray
GLuint id() const;
const VertexAttribute& getVertexAttribute(size_t attributeIndex) const;
+ const std::vector<VertexAttribute> &getVertexAttributes() const;
+
void detachBuffer(GLuint bufferName);
void setVertexAttribDivisor(GLuint index, GLuint divisor);
void enableAttribute(unsigned int attributeIndex, bool enabledState);
void setAttributeState(unsigned int attributeIndex, gl::Buffer *boundBuffer, GLint size, GLenum type,
bool normalized, bool pureInteger, GLsizei stride, const void *pointer);
- const VertexAttribute* getVertexAttributes() const { return &mVertexAttributes[0]; }
Buffer *getElementArrayBuffer() const { return mElementArrayBuffer.get(); }
void setElementArrayBuffer(Buffer *buffer);
GLuint getElementArrayBufferId() const { return mElementArrayBuffer.id(); }
size_t getMaxAttribs() const { return mVertexAttributes.size(); }
+ rx::VertexArrayImpl *getImplementation() { return mVertexArray; }
+ const rx::VertexArrayImpl *getImplementation() const { return mVertexArray; }
+
private:
GLuint mId;
@@ -59,4 +63,4 @@ class VertexArray
}
-#endif // LIBGLESV2_VERTEXARRAY_H_
+#endif // LIBANGLE_VERTEXARRAY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp
index 1096856b8a..19934e7fac 100644
--- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.cpp
+++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.cpp
@@ -6,7 +6,7 @@
// Implementation of the state class for mananging GLES 3 Vertex Array Objects.
//
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/VertexAttribute.h"
namespace gl
{
@@ -23,6 +23,24 @@ VertexAttribute::VertexAttribute()
{
}
+bool operator==(const VertexAttribute &a, const VertexAttribute &b)
+{
+ return a.enabled == b.enabled &&
+ a.type == b.type &&
+ a.size == b.size &&
+ a.normalized == b.normalized &&
+ a.pureInteger == b.pureInteger &&
+ a.stride == b.stride &&
+ a.pointer == b.pointer &&
+ a.buffer.get() == b.buffer.get() &&
+ a.divisor == b.divisor;
+}
+
+bool operator!=(const VertexAttribute &a, const VertexAttribute &b)
+{
+ return !(a == b);
+}
+
size_t ComputeVertexAttributeTypeSize(const VertexAttribute& attrib)
{
GLuint size = attrib.size;
@@ -52,4 +70,4 @@ size_t ComputeVertexAttributeStride(const VertexAttribute& attrib)
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/libANGLE/VertexAttribute.h
index e9757b618b..bdffe97466 100644
--- a/src/3rdparty/angle/src/libGLESv2/VertexAttribute.h
+++ b/src/3rdparty/angle/src/libANGLE/VertexAttribute.h
@@ -6,10 +6,10 @@
// Helper structure describing a single vertex attribute
//
-#ifndef LIBGLESV2_VERTEXATTRIBUTE_H_
-#define LIBGLESV2_VERTEXATTRIBUTE_H_
+#ifndef LIBANGLE_VERTEXATTRIBUTE_H_
+#define LIBANGLE_VERTEXATTRIBUTE_H_
-#include "libGLESv2/Buffer.h"
+#include "libANGLE/Buffer.h"
namespace gl
{
@@ -36,6 +36,9 @@ struct VertexAttribute
VertexAttribute();
};
+bool operator==(const VertexAttribute &a, const VertexAttribute &b);
+bool operator!=(const VertexAttribute &a, const VertexAttribute &b);
+
template <typename T>
T QuerySingleVertexAttributeParameter(const VertexAttribute& attrib, GLenum pname)
{
@@ -116,4 +119,4 @@ struct VertexAttribCurrentValueData
}
-#endif // LIBGLESV2_VERTEXATTRIBUTE_H_
+#endif // LIBANGLE_VERTEXATTRIBUTE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libANGLE/angletypes.cpp
index 5a0cfc5ad9..16879f8041 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
+++ b/src/3rdparty/angle/src/libANGLE/angletypes.cpp
@@ -6,17 +6,28 @@
// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/State.h"
-#include "libGLESv2/VertexArray.h"
-
-#include <float.h>
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
namespace gl
{
+bool operator==(const Rectangle &a, const Rectangle &b)
+{
+ return a.x == b.x &&
+ a.y == b.y &&
+ a.width == b.width &&
+ a.height == b.height;
+}
+
+bool operator!=(const Rectangle &a, const Rectangle &b)
+{
+ return !(a == b);
+}
+
SamplerState::SamplerState()
: minFilter(GL_NEAREST_MIPMAP_LINEAR),
magFilter(GL_LINEAR),
@@ -26,8 +37,8 @@ SamplerState::SamplerState()
maxAnisotropy(1.0f),
baseLevel(0),
maxLevel(1000),
- minLod(-FLT_MAX),
- maxLod(FLT_MAX),
+ minLod(-1000.0f),
+ maxLod(1000.0f),
compareMode(GL_NONE),
compareFunc(GL_LEQUAL),
swizzleRed(GL_RED),
@@ -42,6 +53,31 @@ bool SamplerState::swizzleRequired() const
swizzleBlue != GL_BLUE || swizzleAlpha != GL_ALPHA;
}
+bool SamplerState::operator==(const SamplerState &other) const
+{
+ return minFilter == other.minFilter &&
+ magFilter == other.magFilter &&
+ wrapS == other.wrapS &&
+ wrapT == other.wrapT &&
+ wrapR == other.wrapR &&
+ maxAnisotropy == other.maxAnisotropy &&
+ baseLevel == other.baseLevel &&
+ maxLevel == other.maxLevel &&
+ minLod == other.minLod &&
+ maxLod == other.maxLod &&
+ compareMode == other.compareMode &&
+ compareFunc == other.compareFunc &&
+ swizzleRed == other.swizzleRed &&
+ swizzleGreen == other.swizzleGreen &&
+ swizzleBlue == other.swizzleBlue &&
+ swizzleAlpha == other.swizzleAlpha;
+}
+
+bool SamplerState::operator!=(const SamplerState &other) const
+{
+ return !(*this == other);
+}
+
static void MinMax(int a, int b, int *minimum, int *maximum)
{
if (a < b)
@@ -151,13 +187,13 @@ VertexFormat::VertexFormat(const VertexAttribute &attrib, GLenum currentValueTyp
}
void VertexFormat::GetInputLayout(VertexFormat *inputLayout,
- ProgramBinary *programBinary,
+ Program *program,
const State &state)
{
- const VertexAttribute *vertexAttributes = state.getVertexArray()->getVertexAttributes();
- for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
+ const std::vector<VertexAttribute> &vertexAttributes = state.getVertexArray()->getVertexAttributes();
+ for (unsigned int attributeIndex = 0; attributeIndex < vertexAttributes.size(); attributeIndex++)
{
- int semanticIndex = programBinary->getSemanticIndex(attributeIndex);
+ int semanticIndex = program->getSemanticIndex(attributeIndex);
if (semanticIndex != -1)
{
diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h
index 78fe6b0e26..e4e08b5512 100644
--- a/src/3rdparty/angle/src/libGLESv2/angletypes.h
+++ b/src/3rdparty/angle/src/libANGLE/angletypes.h
@@ -6,17 +6,20 @@
// angletypes.h : Defines a variety of structures and enum types that are used throughout libGLESv2
-#ifndef LIBGLESV2_ANGLETYPES_H_
-#define LIBGLESV2_ANGLETYPES_H_
+#ifndef LIBANGLE_ANGLETYPES_H_
+#define LIBANGLE_ANGLETYPES_H_
-#include "libGLESv2/Constants.h"
-#include "common/RefCountObject.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/RefCountObject.h"
+
+#include <stdint.h>
+#include <float.h>
namespace gl
{
class Buffer;
class State;
-class ProgramBinary;
+class Program;
struct VertexAttribute;
struct VertexAttribCurrentValueData;
@@ -38,6 +41,21 @@ struct Color
Color(T r, T g, T b, T a) : red(r), green(g), blue(b), alpha(a) { }
};
+template <typename T>
+bool operator==(const Color<T> &a, const Color<T> &b)
+{
+ return a.red == b.red &&
+ a.green == b.green &&
+ a.blue == b.blue &&
+ a.alpha == b.alpha;
+}
+
+template <typename T>
+bool operator!=(const Color<T> &a, const Color<T> &b)
+{
+ return !(a == b);
+}
+
typedef Color<float> ColorF;
typedef Color<int> ColorI;
typedef Color<unsigned int> ColorUI;
@@ -53,21 +71,19 @@ struct Rectangle
Rectangle(int x_in, int y_in, int width_in, int height_in) : x(x_in), y(y_in), width(width_in), height(height_in) { }
};
+bool operator==(const Rectangle &a, const Rectangle &b);
+bool operator!=(const Rectangle &a, const Rectangle &b);
+
bool ClipRectangle(const Rectangle &source, const Rectangle &clip, Rectangle *intersection);
-struct Box
+struct Offset
{
int x;
int y;
int z;
- int width;
- int height;
- int depth;
- Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { }
- Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { }
- bool operator==(const Box &other) const;
- bool operator!=(const Box &other) const;
+ Offset() : x(0), y(0), z(0) { }
+ Offset(int x_in, int y_in, int z_in) : x(x_in), y(y_in), z(z_in) { }
};
struct Extents
@@ -78,8 +94,27 @@ struct Extents
Extents() : width(0), height(0), depth(0) { }
Extents(int width_, int height_, int depth_) : width(width_), height(height_), depth(depth_) { }
+
+ bool empty() const { return (width * height * depth) == 0; }
+};
+
+struct Box
+{
+ int x;
+ int y;
+ int z;
+ int width;
+ int height;
+ int depth;
+
+ Box() : x(0), y(0), z(0), width(0), height(0), depth(0) { }
+ Box(int x_in, int y_in, int z_in, int width_in, int height_in, int depth_in) : x(x_in), y(y_in), z(z_in), width(width_in), height(height_in), depth(depth_in) { }
+ Box(const Offset &offset, const Extents &size) : x(offset.x), y(offset.y), z(offset.z), width(size.width), height(size.height), depth(size.depth) { }
+ bool operator==(const Box &other) const;
+ bool operator!=(const Box &other) const;
};
+
struct RasterizerState
{
bool cullFace;
@@ -162,42 +197,37 @@ struct SamplerState
GLenum swizzleAlpha;
bool swizzleRequired() const;
-};
-
-struct ClearParameters
-{
- bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
- ColorF colorFClearValue;
- ColorI colorIClearValue;
- ColorUI colorUIClearValue;
- GLenum colorClearType;
- bool colorMaskRed;
- bool colorMaskGreen;
- bool colorMaskBlue;
- bool colorMaskAlpha;
-
- bool clearDepth;
- float depthClearValue;
-
- bool clearStencil;
- GLint stencilClearValue;
- GLuint stencilWriteMask;
- bool scissorEnabled;
- Rectangle scissor;
+ bool operator==(const SamplerState &other) const;
+ bool operator!=(const SamplerState &other) const;
};
struct PixelUnpackState
{
BindingPointer<Buffer> pixelBuffer;
GLint alignment;
+ GLint rowLength;
+ GLint skipRows;
+ GLint skipPixels;
+ GLint imageHeight;
+ GLint skipImages;
PixelUnpackState()
- : alignment(4)
+ : alignment(4),
+ rowLength(0),
+ skipRows(0),
+ skipPixels(0),
+ imageHeight(0),
+ skipImages(0)
{}
- explicit PixelUnpackState(GLint alignmentIn)
- : alignment(alignmentIn)
+ PixelUnpackState(GLint alignmentIn, GLint rowLengthIn)
+ : alignment(alignmentIn),
+ rowLength(rowLengthIn),
+ skipRows(0),
+ skipPixels(0),
+ imageHeight(0),
+ skipImages(0)
{}
};
@@ -206,15 +236,24 @@ struct PixelPackState
BindingPointer<Buffer> pixelBuffer;
GLint alignment;
bool reverseRowOrder;
+ GLint rowLength;
+ GLint skipRows;
+ GLint skipPixels;
PixelPackState()
: alignment(4),
- reverseRowOrder(false)
+ reverseRowOrder(false),
+ rowLength(0),
+ skipRows(0),
+ skipPixels(0)
{}
explicit PixelPackState(GLint alignmentIn, bool reverseRowOrderIn)
: alignment(alignmentIn),
- reverseRowOrder(reverseRowOrderIn)
+ reverseRowOrder(reverseRowOrderIn),
+ rowLength(0),
+ skipRows(0),
+ skipPixels(0)
{}
};
@@ -231,7 +270,7 @@ struct VertexFormat
VertexFormat(const VertexAttribute &attribute, GLenum currentValueType);
static void GetInputLayout(VertexFormat *inputLayout,
- ProgramBinary *programBinary,
+ Program *program,
const State& currentValues);
bool operator==(const VertexFormat &other) const;
@@ -244,14 +283,41 @@ struct VertexFormat
namespace rx
{
-enum VertexConversionType
+enum VendorID : uint32_t
{
- VERTEX_CONVERT_NONE = 0,
- VERTEX_CONVERT_CPU = 1,
- VERTEX_CONVERT_GPU = 2,
- VERTEX_CONVERT_BOTH = 3
+ VENDOR_ID_AMD = 0x1002,
+ VENDOR_ID_INTEL = 0x8086,
+ VENDOR_ID_NVIDIA = 0x10DE,
};
+// Downcast a base implementation object (EG TextureImpl to TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetAs(SrcT *src)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(DestT*, src));
+ return static_cast<DestT*>(src);
+}
+
+template <typename DestT, typename SrcT>
+inline const DestT *GetAs(const SrcT *src)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(const DestT*, src));
+ return static_cast<const DestT*>(src);
+}
+
+// Downcast a GL object to an Impl (EG gl::Texture to rx::TextureD3D)
+template <typename DestT, typename SrcT>
+inline DestT *GetImplAs(SrcT *src)
+{
+ return GetAs<DestT>(src->getImplementation());
+}
+
+template <typename DestT, typename SrcT>
+inline const DestT *GetImplAs(const SrcT *src)
+{
+ return GetAs<const DestT>(src->getImplementation());
+}
+
}
-#endif // LIBGLESV2_ANGLETYPES_H_
+#endif // LIBANGLE_ANGLETYPES_H_
diff --git a/src/3rdparty/angle/src/common/features.h b/src/3rdparty/angle/src/libANGLE/features.h
index b49a0ee852..fbe013f47d 100644
--- a/src/3rdparty/angle/src/common/features.h
+++ b/src/3rdparty/angle/src/libANGLE/features.h
@@ -4,6 +4,9 @@
// found in the LICENSE file.
//
+#ifndef LIBANGLE_FEATURES_H_
+#define LIBANGLE_FEATURES_H_
+
#define ANGLE_DISABLED 0
#define ANGLE_ENABLED 1
@@ -33,3 +36,5 @@
#if !defined(ANGLE_SHADER_DEBUG_INFO)
#define ANGLE_SHADER_DEBUG_INFO ANGLE_DISABLED
#endif
+
+#endif // LIBANGLE_FEATURES_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
index 8674d5337f..51e6a5a65d 100644
--- a/src/3rdparty/angle/src/libGLESv2/formatutils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/formatutils.cpp
@@ -7,12 +7,10 @@
// 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"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/Renderer.h"
namespace gl
{
@@ -21,145 +19,137 @@ namespace gl
// can decide the true, sized, internal format. The ES2FormatMap determines the internal format for all valid
// format and type combinations.
-FormatType::FormatType()
- : internalFormat(GL_NONE),
- colorWriteFunction(NULL)
-{
-}
-
typedef std::pair<GLenum, GLenum> FormatTypePair;
-typedef std::pair<FormatTypePair, FormatType> FormatPair;
-typedef std::map<FormatTypePair, FormatType> FormatMap;
+typedef std::pair<FormatTypePair, GLenum> FormatPair;
+typedef std::map<FormatTypePair, GLenum> 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)
+static inline void InsertFormatMapping(FormatMap *map, GLenum format, GLenum type, GLenum internalFormat)
{
- FormatType info;
- info.internalFormat = internalFormat;
- info.colorWriteFunction = writeFunc;
- map->insert(FormatPair(FormatTypePair(format, type), info));
+ map->insert(FormatPair(FormatTypePair(format, type), internalFormat));
}
FormatMap BuildFormatMap()
{
FormatMap map;
- using namespace rx;
-
- // | Format | Type | Internal format | Color write function |
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8, WriteColor<R8G8B8A8, GLfloat> );
- InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM, WriteColor<R8G8B8A8S, GLfloat> );
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4, WriteColor<R4G4B4A4, GLfloat> );
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1, WriteColor<R5G5B5A1, GLfloat> );
- InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2, WriteColor<R10G10B10A2, GLfloat> );
- InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F, WriteColor<R32G32B32A32F, GLfloat>);
- InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>);
- InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F, WriteColor<R16G16B16A16F, GLfloat>);
-
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI, WriteColor<R8G8B8A8, GLuint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I, WriteColor<R8G8B8A8S, GLint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI, WriteColor<R16G16B16A16, GLuint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I, WriteColor<R16G16B16A16S, GLint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI, WriteColor<R32G32B32A32, GLuint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I, WriteColor<R32G32B32A32S, GLint> );
- InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI, WriteColor<R10G10B10A2, GLuint> );
-
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8, WriteColor<R8G8B8, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM, WriteColor<R8G8B8S, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565, WriteColor<R5G6B5, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F, WriteColor<R11G11B10F, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5, WriteColor<R9G9B9E5, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F, WriteColor<R32G32B32F, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> );
- InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F, WriteColor<R16G16B16F, GLfloat> );
-
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI, WriteColor<R8G8B8, GLuint> );
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I, WriteColor<R8G8B8S, GLint> );
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI, WriteColor<R16G16B16, GLuint> );
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I, WriteColor<R16G16B16S, GLint> );
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI, WriteColor<R32G32B32, GLuint> );
- InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I, WriteColor<R32G32B32S, GLint> );
-
- InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8, WriteColor<R8G8, GLfloat> );
- InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM, WriteColor<R8G8S, GLfloat> );
- InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F, WriteColor<R32G32F, GLfloat> );
- InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F, WriteColor<R16G16F, GLfloat> );
- InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F, WriteColor<R16G16F, GLfloat> );
-
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI, WriteColor<R8G8, GLuint> );
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I, WriteColor<R8G8S, GLint> );
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI, WriteColor<R16G16, GLuint> );
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I, WriteColor<R16G16S, GLint> );
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI, WriteColor<R32G32, GLuint> );
- InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I, WriteColor<R32G32S, GLint> );
-
- InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8, WriteColor<R8, GLfloat> );
- InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM, WriteColor<R8S, GLfloat> );
- InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F, WriteColor<R32F, GLfloat> );
- InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F, WriteColor<R16F, GLfloat> );
- InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F, WriteColor<R16F, GLfloat> );
-
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI, WriteColor<R8, GLuint> );
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I, WriteColor<R8S, GLint> );
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI, WriteColor<R16, GLuint> );
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I, WriteColor<R16S, GLint> );
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI, WriteColor<R32, GLuint> );
- InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I, WriteColor<R32S, GLint> );
-
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT, WriteColor<L8A8, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT, WriteColor<L8, GLfloat> );
- InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT, WriteColor<A8, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT, WriteColor<L32A32F, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT, WriteColor<L32F, GLfloat> );
- InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT, WriteColor<A32F, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT, WriteColor<L16A16F, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> );
- InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT, WriteColor<L16F, GLfloat> );
- InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> );
- InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT, WriteColor<A16F, GLfloat> );
-
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT, WriteColor<B8G8R8A8, GLfloat> );
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX, WriteColor<B4G4R4A4, GLfloat> );
- InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX, WriteColor<B5G5R5A1, GLfloat> );
-
- InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8, WriteColor<R8G8B8, GLfloat> );
- InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8, WriteColor<R8G8B8A8, GLfloat> );
-
- 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 );
+ // | Format | Type | Internal format |
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, GL_RGBA8);
+ InsertFormatMapping(&map, GL_RGBA, GL_BYTE, GL_RGBA8_SNORM);
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, GL_RGBA4);
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, GL_RGB5_A1);
+ InsertFormatMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2);
+ InsertFormatMapping(&map, GL_RGBA, GL_FLOAT, GL_RGBA32F);
+ InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT, GL_RGBA16F);
+ InsertFormatMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, GL_RGBA16F);
+
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, GL_RGBA8UI);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_BYTE, GL_RGBA8I);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, GL_RGBA16UI);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_SHORT, GL_RGBA16I);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, GL_RGBA32UI);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_INT, GL_RGBA32I);
+ InsertFormatMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, GL_RGB10_A2UI);
+
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, GL_RGB8);
+ InsertFormatMapping(&map, GL_RGB, GL_BYTE, GL_RGB8_SNORM);
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, GL_RGB565);
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, GL_R11F_G11F_B10F);
+ InsertFormatMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, GL_RGB9_E5);
+ InsertFormatMapping(&map, GL_RGB, GL_FLOAT, GL_RGB32F);
+ InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT, GL_RGB16F);
+ InsertFormatMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, GL_RGB16F);
+
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, GL_RGB8UI);
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_BYTE, GL_RGB8I);
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, GL_RGB16UI);
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_SHORT, GL_RGB16I);
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, GL_RGB32UI);
+ InsertFormatMapping(&map, GL_RGB_INTEGER, GL_INT, GL_RGB32I);
+
+ InsertFormatMapping(&map, GL_RG, GL_UNSIGNED_BYTE, GL_RG8);
+ InsertFormatMapping(&map, GL_RG, GL_BYTE, GL_RG8_SNORM);
+ InsertFormatMapping(&map, GL_RG, GL_FLOAT, GL_RG32F);
+ InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT, GL_RG16F);
+ InsertFormatMapping(&map, GL_RG, GL_HALF_FLOAT_OES, GL_RG16F);
+
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, GL_RG8UI);
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_BYTE, GL_RG8I);
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, GL_RG16UI);
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_SHORT, GL_RG16I);
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, GL_RG32UI);
+ InsertFormatMapping(&map, GL_RG_INTEGER, GL_INT, GL_RG32I);
+
+ InsertFormatMapping(&map, GL_RED, GL_UNSIGNED_BYTE, GL_R8);
+ InsertFormatMapping(&map, GL_RED, GL_BYTE, GL_R8_SNORM);
+ InsertFormatMapping(&map, GL_RED, GL_FLOAT, GL_R32F);
+ InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT, GL_R16F);
+ InsertFormatMapping(&map, GL_RED, GL_HALF_FLOAT_OES, GL_R16F);
+
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, GL_R8UI);
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_BYTE, GL_R8I);
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, GL_R16UI);
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_SHORT, GL_R16I);
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, GL_R32UI);
+ InsertFormatMapping(&map, GL_RED_INTEGER, GL_INT, GL_R32I);
+
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, GL_LUMINANCE8_ALPHA8_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, GL_LUMINANCE8_EXT);
+ InsertFormatMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, GL_ALPHA8_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, GL_LUMINANCE_ALPHA32F_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_FLOAT, GL_LUMINANCE32F_EXT);
+ InsertFormatMapping(&map, GL_ALPHA, GL_FLOAT, GL_ALPHA32F_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, GL_LUMINANCE_ALPHA16F_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, GL_LUMINANCE_ALPHA16F_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, GL_LUMINANCE16F_EXT);
+ InsertFormatMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, GL_LUMINANCE16F_EXT);
+ InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT, GL_ALPHA16F_EXT);
+ InsertFormatMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, GL_ALPHA16F_EXT);
+
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_BGRA8_EXT);
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, GL_BGRA4_ANGLEX);
+ InsertFormatMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, GL_BGR5_A1_ANGLEX);
+
+ InsertFormatMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, GL_SRGB8);
+ InsertFormatMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, GL_SRGB8_ALPHA8);
+
+ InsertFormatMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGB_S3TC_DXT1_EXT);
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT);
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE);
+ InsertFormatMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE);
+
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, GL_DEPTH_COMPONENT16);
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_DEPTH_COMPONENT32_OES);
+ InsertFormatMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, GL_DEPTH_COMPONENT32F);
+
+ InsertFormatMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, GL_STENCIL_INDEX8);
+
+ InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_DEPTH24_STENCIL8);
+ InsertFormatMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_DEPTH32F_STENCIL8);
return map;
}
Type::Type()
: bytes(0),
+ bytesShift(0),
specialInterpretation(false)
{
}
-// Map of sizes of input types
-typedef std::pair<GLenum, Type> TypeInfoPair;
-typedef std::map<GLenum, Type> TypeInfoMap;
-
-static inline void InsertTypeInfo(TypeInfoMap *map, GLenum type, GLuint bytes, bool specialInterpretation)
+static Type GenTypeInfo(GLuint bytes, bool specialInterpretation)
{
Type info;
info.bytes = bytes;
+ GLuint i = 0;
+ while ((1u << i) < bytes)
+ {
+ ++i;
+ }
+ info.bytesShift = i;
+ ASSERT((1u << info.bytesShift) == bytes);
info.specialInterpretation = specialInterpretation;
-
- map->insert(std::make_pair(type, info));
+ return info;
}
bool operator<(const Type& a, const Type& b)
@@ -167,34 +157,6 @@ bool operator<(const Type& a, const Type& b)
return memcmp(&a, &b, sizeof(Type)) < 0;
}
-static TypeInfoMap BuildTypeInfoMap()
-{
- TypeInfoMap map;
-
- InsertTypeInfo(&map, GL_UNSIGNED_BYTE, 1, false);
- InsertTypeInfo(&map, GL_BYTE, 1, false);
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT, 2, false);
- InsertTypeInfo(&map, GL_SHORT, 2, false);
- InsertTypeInfo(&map, GL_UNSIGNED_INT, 4, false);
- InsertTypeInfo(&map, GL_INT, 4, false);
- InsertTypeInfo(&map, GL_HALF_FLOAT, 2, false);
- InsertTypeInfo(&map, GL_HALF_FLOAT_OES, 2, false);
- InsertTypeInfo(&map, GL_FLOAT, 4, false);
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_6_5, 2, true );
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4, 2, true );
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT_5_5_5_1, 2, true );
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, 2, true );
- InsertTypeInfo(&map, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, 2, true );
- InsertTypeInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, true );
- InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8, 4, true );
- InsertTypeInfo(&map, GL_UNSIGNED_INT_10F_11F_11F_REV, 4, true );
- InsertTypeInfo(&map, GL_UNSIGNED_INT_5_9_9_9_REV, 4, true );
- InsertTypeInfo(&map, GL_UNSIGNED_INT_24_8_OES, 4, true );
- InsertTypeInfo(&map, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8, true );
-
- return map;
-}
-
// Information about internal formats
static bool AlwaysSupported(GLuint, const Extensions &)
{
@@ -454,7 +416,7 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
map.insert(InternalFormatInfoPair(GL_DEPTH_COMPONENT32_OES, DepthStencilFormat(32, 0, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, GL_UNSIGNED_NORMALIZED, RequireExt<&Extensions::depthTextures>, RequireExt<&Extensions::depthTextures>, AlwaysSupported )));
map.insert(InternalFormatInfoPair(GL_DEPTH24_STENCIL8, DepthStencilFormat(24, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, GL_UNSIGNED_NORMALIZED, RequireESOrExt<3, &Extensions::depthTextures>, RequireESOrExtOrExt<3, &Extensions::depthTextures, &Extensions::packedDepthStencil>, AlwaysSupported )));
map.insert(InternalFormatInfoPair(GL_DEPTH32F_STENCIL8, DepthStencilFormat(32, 8, 24, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, GL_FLOAT, RequireES<3>, RequireES<3>, AlwaysSupported )));
- map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat( 0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_INT, RequireES<2>, RequireES<2>, NeverSupported )));
+ // STENCIL_INDEX8 is special-cased, see around the bottom of the list.
// Luminance alpha formats
// | Internal format | | L | A | Format | Type | Component type | Supported | Renderable | Filterable |
@@ -511,6 +473,13 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
// From GL_ANGLE_texture_compression_dxt5
map.insert(InternalFormatInfoPair(GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, CompressedFormat(4, 4, 128, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, false, RequireExt<&Extensions::textureCompressionDXT5>, NeverSupported, AlwaysSupported)));
+ // For STENCIL_INDEX8 we chose a normalized component type for the following reasons:
+ // - Multisampled buffer are disallowed for non-normalized integer component types and we want to support it for STENCIL_INDEX8
+ // - All other stencil formats (all depth-stencil) are either float or normalized
+ // - It affects only validation of internalformat in RenderbufferStorageMultisample.
+ // | Internal format | |D |S |X | Format | Type | Component type | Supported | Renderable | Filterable |
+ map.insert(InternalFormatInfoPair(GL_STENCIL_INDEX8, DepthStencilFormat(0, 8, 0, GL_DEPTH_STENCIL, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, RequireES<2>, RequireES<2>, NeverSupported)));
+
return map;
}
@@ -536,33 +505,59 @@ static FormatSet BuildAllSizedInternalFormatSet()
return result;
}
-const FormatType &GetFormatTypeInfo(GLenum format, GLenum type)
-{
- static const FormatMap formatMap = BuildFormatMap();
- FormatMap::const_iterator iter = formatMap.find(FormatTypePair(format, type));
- if (iter != formatMap.end())
- {
- return iter->second;
- }
- else
- {
- static const FormatType defaultInfo;
- return defaultInfo;
- }
-}
-
const Type &GetTypeInfo(GLenum type)
{
- static const TypeInfoMap infoMap = BuildTypeInfoMap();
- TypeInfoMap::const_iterator iter = infoMap.find(type);
- if (iter != infoMap.end())
+ switch (type)
{
- return iter->second;
- }
- else
- {
- static const Type defaultInfo;
- return defaultInfo;
+ case GL_UNSIGNED_BYTE:
+ case GL_BYTE:
+ {
+ static const Type info = GenTypeInfo(1, false);
+ return info;
+ }
+ case GL_UNSIGNED_SHORT:
+ case GL_SHORT:
+ case GL_HALF_FLOAT:
+ case GL_HALF_FLOAT_OES:
+ {
+ static const Type info = GenTypeInfo(2, false);
+ return info;
+ }
+ case GL_UNSIGNED_INT:
+ case GL_INT:
+ case GL_FLOAT:
+ {
+ static const Type info = GenTypeInfo(4, false);
+ return info;
+ }
+ case GL_UNSIGNED_SHORT_5_6_5:
+ case GL_UNSIGNED_SHORT_4_4_4_4:
+ case GL_UNSIGNED_SHORT_5_5_5_1:
+ case GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT:
+ case GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT:
+ {
+ static const Type info = GenTypeInfo(2, true);
+ return info;
+ }
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_24_8:
+ case GL_UNSIGNED_INT_10F_11F_11F_REV:
+ case GL_UNSIGNED_INT_5_9_9_9_REV:
+ {
+ ASSERT(GL_UNSIGNED_INT_24_8_OES == GL_UNSIGNED_INT_24_8);
+ static const Type info = GenTypeInfo(4, true);
+ return info;
+ }
+ case GL_FLOAT_32_UNSIGNED_INT_24_8_REV:
+ {
+ static const Type info = GenTypeInfo(8, true);
+ return info;
+ }
+ default:
+ {
+ static const Type defaultInfo;
+ return defaultInfo;
+ }
}
}
@@ -581,18 +576,28 @@ const InternalFormat &GetInternalFormatInfo(GLenum internalFormat)
}
}
-GLuint InternalFormat::computeRowPitch(GLenum type, GLsizei width, GLint alignment) const
+GLuint InternalFormat::computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const
{
ASSERT(alignment > 0 && isPow2(alignment));
- return rx::roundUp(computeBlockSize(type, width, 1), static_cast<GLuint>(alignment));
+ GLuint rowBytes;
+ if (rowLength > 0)
+ {
+ ASSERT(!compressed);
+ rowBytes = pixelBytes * rowLength;
+ }
+ else
+ {
+ rowBytes = computeBlockSize(formatType, width, 1);
+ }
+ return rx::roundUp(rowBytes, static_cast<GLuint>(alignment));
}
-GLuint InternalFormat::computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const
+GLuint InternalFormat::computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const
{
- return computeRowPitch(type, width, alignment) * height;
+ return computeRowPitch(formatType, width, alignment, rowLength) * height;
}
-GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei height) const
+GLuint InternalFormat::computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const
{
if (compressed)
{
@@ -602,7 +607,7 @@ GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei heig
}
else
{
- const Type &typeInfo = GetTypeInfo(type);
+ const Type &typeInfo = GetTypeInfo(formatType);
if (typeInfo.specialInterpretation)
{
return typeInfo.bytes * width * height;
@@ -617,7 +622,23 @@ GLuint InternalFormat::computeBlockSize(GLenum type, GLsizei width, GLsizei heig
GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type)
{
const InternalFormat& formatInfo = GetInternalFormatInfo(internalFormat);
- return (formatInfo.pixelBytes > 0) ? internalFormat : GetFormatTypeInfo(internalFormat, type).internalFormat;
+ if (formatInfo.pixelBytes > 0)
+ {
+ return internalFormat;
+ }
+ else
+ {
+ static const FormatMap formatMap = BuildFormatMap();
+ FormatMap::const_iterator iter = formatMap.find(FormatTypePair(internalFormat, type));
+ if (iter != formatMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return GL_NONE;
+ }
+ }
}
const FormatSet &GetAllSizedInternalFormats()
diff --git a/src/3rdparty/angle/src/libANGLE/formatutils.h b/src/3rdparty/angle/src/libANGLE/formatutils.h
new file mode 100644
index 0000000000..37d4a8f8ef
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/formatutils.h
@@ -0,0 +1,81 @@
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils.h: Queries for GL image formats.
+
+#ifndef LIBANGLE_FORMATUTILS_H_
+#define LIBANGLE_FORMATUTILS_H_
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/angletypes.h"
+
+#include "angle_gl.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+namespace gl
+{
+
+struct Type
+{
+ Type();
+
+ GLuint bytes;
+ GLuint bytesShift; // Bit shift by this value to effectively divide/multiply by "bytes" in a more optimal way
+ bool specialInterpretation;
+};
+const Type &GetTypeInfo(GLenum type);
+
+struct InternalFormat
+{
+ InternalFormat();
+
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+
+ GLuint luminanceBits;
+
+ GLuint alphaBits;
+ GLuint sharedBits;
+
+ GLuint depthBits;
+ GLuint stencilBits;
+
+ GLuint pixelBytes;
+
+ GLuint componentCount;
+
+ bool compressed;
+ GLuint compressedBlockWidth;
+ GLuint compressedBlockHeight;
+
+ GLenum format;
+ GLenum type;
+
+ GLenum componentType;
+ GLenum colorEncoding;
+
+ typedef bool (*SupportCheckFunction)(GLuint, const Extensions &);
+ SupportCheckFunction textureSupport;
+ SupportCheckFunction renderSupport;
+ SupportCheckFunction filterSupport;
+
+ GLuint computeRowPitch(GLenum formatType, GLsizei width, GLint alignment, GLint rowLength) const;
+ GLuint computeDepthPitch(GLenum formatType, GLsizei width, GLsizei height, GLint alignment, GLint rowLength) const;
+ GLuint computeBlockSize(GLenum formatType, GLsizei width, GLsizei height) const;
+};
+const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
+
+GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
+
+typedef std::set<GLenum> FormatSet;
+const FormatSet &GetAllSizedInternalFormats();
+
+}
+
+#endif // LIBANGLE_FORMATUTILS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp
index 7245902c51..460e346eac 100644
--- a/src/3rdparty/angle/src/libGLESv2/queryconversions.cpp
+++ b/src/3rdparty/angle/src/libANGLE/queryconversions.cpp
@@ -6,7 +6,7 @@
// queryconversions.cpp: Implementation of state query cast conversions
-#include "libGLESv2/Context.h"
+#include "libANGLE/Context.h"
#include "common/utilities.h"
namespace gl
diff --git a/src/3rdparty/angle/src/libGLESv2/queryconversions.h b/src/3rdparty/angle/src/libANGLE/queryconversions.h
index da7047f730..da7047f730 100644
--- a/src/3rdparty/angle/src/libGLESv2/queryconversions.h
+++ b/src/3rdparty/angle/src/libANGLE/queryconversions.h
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h
index c031effabd..9bc5eaff58 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/BufferImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/BufferImpl.h
@@ -6,18 +6,18 @@
// BufferImpl.h: Defines the abstract rx::BufferImpl class.
-#ifndef LIBGLESV2_RENDERER_BUFFERIMPL_H_
-#define LIBGLESV2_RENDERER_BUFFERIMPL_H_
+#ifndef LIBANGLE_RENDERER_BUFFERIMPL_H_
+#define LIBANGLE_RENDERER_BUFFERIMPL_H_
#include "common/angleutils.h"
-#include "libGLESv2/Buffer.h"
+#include "libANGLE/Buffer.h"
-#include <cstdint>
+#include <stdint.h>
namespace rx
{
-class BufferImpl
+class BufferImpl : angle::NonCopyable
{
public:
virtual ~BufferImpl() { }
@@ -27,9 +27,12 @@ class BufferImpl
virtual gl::Error copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size) = 0;
virtual gl::Error map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr) = 0;
virtual gl::Error unmap() = 0;
- virtual void markTransformFeedbackUsage() = 0;
+
+ // This method may not have a corresponding GL-backed function. It is necessary
+ // for validation, for certain indexed draw calls.
+ virtual gl::Error getData(const uint8_t **outData) = 0;
};
}
-#endif // LIBGLESV2_RENDERER_BUFFERIMPL_H_
+#endif // LIBANGLE_RENDERER_BUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h
new file mode 100644
index 0000000000..ccc78d8c2a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/CompilerImpl.h
@@ -0,0 +1,30 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerImpl.h: Defines the rx::CompilerImpl class, an implementation interface
+// for the gl::Compiler object.
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+#ifndef LIBANGLE_RENDERER_COMPILERIMPL_H_
+#define LIBANGLE_RENDERER_COMPILERIMPL_H_
+
+namespace rx
+{
+
+class CompilerImpl : angle::NonCopyable
+{
+ public:
+ CompilerImpl() {}
+ virtual ~CompilerImpl() {}
+
+ virtual gl::Error release() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp
new file mode 100644
index 0000000000..7713ee2d6d
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.cpp
@@ -0,0 +1,58 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.cpp: Implementation methods of egl::Display
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+#include "libANGLE/Surface.h"
+
+namespace rx
+{
+
+DisplayImpl::DisplayImpl()
+ : mExtensionsInitialized(false),
+ mCapsInitialized(false)
+{
+}
+
+DisplayImpl::~DisplayImpl()
+{
+ while (!mSurfaceSet.empty())
+ {
+ destroySurface(*mSurfaceSet.begin());
+ }
+}
+
+void DisplayImpl::destroySurface(egl::Surface *surface)
+{
+ mSurfaceSet.erase(surface);
+ surface->release();
+}
+
+const egl::DisplayExtensions &DisplayImpl::getExtensions() const
+{
+ if (!mExtensionsInitialized)
+ {
+ generateExtensions(&mExtensions);
+ mExtensionsInitialized = true;
+ }
+
+ return mExtensions;
+}
+
+const egl::Caps &DisplayImpl::getCaps() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps);
+ mCapsInitialized = true;
+ }
+
+ return mCaps;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h
new file mode 100644
index 0000000000..381fa67f71
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/DisplayImpl.h
@@ -0,0 +1,99 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayImpl.h: Implementation methods of egl::Display
+
+#ifndef LIBANGLE_RENDERER_DISPLAYIMPL_H_
+#define LIBANGLE_RENDERER_DISPLAYIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/Renderer.h"
+
+#include <set>
+#include <vector>
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+struct Config;
+class Surface;
+}
+
+namespace gl
+{
+class Context;
+}
+
+namespace rx
+{
+class SurfaceImpl;
+struct ConfigDesc;
+
+class DisplayImpl : angle::NonCopyable
+{
+ public:
+ DisplayImpl();
+ virtual ~DisplayImpl();
+
+ virtual egl::Error initialize(egl::Display *display) = 0;
+ virtual void terminate() = 0;
+
+ virtual egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs,
+ SurfaceImpl **outSurface) = 0;
+ virtual egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs,
+ SurfaceImpl **outSurface) = 0;
+ virtual egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0;
+ virtual egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface) = 0;
+ virtual egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
+ gl::Context **outContext) = 0;
+
+ virtual egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) = 0;
+
+ virtual egl::ConfigSet generateConfigs() const = 0;
+
+ virtual bool isDeviceLost() const = 0;
+ virtual bool testDeviceLost() = 0;
+ virtual egl::Error restoreLostDevice() = 0;
+
+ virtual bool isValidNativeWindow(EGLNativeWindowType window) const = 0;
+
+ virtual std::string getVendorString() const = 0;
+
+ const egl::Caps &getCaps() const;
+
+ typedef std::set<egl::Surface*> SurfaceSet;
+ const SurfaceSet &getSurfaceSet() const { return mSurfaceSet; }
+ SurfaceSet &getSurfaceSet() { return mSurfaceSet; }
+
+ void destroySurface(egl::Surface *surface);
+
+ const egl::DisplayExtensions &getExtensions() const;
+
+ protected:
+ // Place the surface set here so it can be accessible for handling
+ // context loss events. (It is shared between the Display and Impl.)
+ SurfaceSet mSurfaceSet;
+
+ private:
+ virtual void generateExtensions(egl::DisplayExtensions *outExtensions) const = 0;
+ virtual void generateCaps(egl::Caps *outCaps) const = 0;
+
+ mutable bool mExtensionsInitialized;
+ mutable egl::DisplayExtensions mExtensions;
+
+ mutable bool mCapsInitialized;
+ mutable egl::Caps mCaps;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_DISPLAYIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h
new file mode 100644
index 0000000000..3463921d6e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceNVImpl.h
@@ -0,0 +1,34 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceNVImpl.h: Defines the rx::FenceNVImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCENVIMPL_H_
+#define LIBANGLE_RENDERER_FENCENVIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class FenceNVImpl : angle::NonCopyable
+{
+ public:
+ FenceNVImpl() { };
+ virtual ~FenceNVImpl() { };
+
+ virtual gl::Error set() = 0;
+ virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0;
+ virtual gl::Error finishFence(GLboolean *outFinished) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCENVIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h
new file mode 100644
index 0000000000..321964113f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FenceSyncImpl.h
@@ -0,0 +1,35 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FenceSyncImpl.h: Defines the rx::FenceSyncImpl class.
+
+#ifndef LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+#define LIBANGLE_RENDERER_FENCESYNCIMPL_H_
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+namespace rx
+{
+
+class FenceSyncImpl : angle::NonCopyable
+{
+ public:
+ FenceSyncImpl() { };
+ virtual ~FenceSyncImpl() { };
+
+ virtual gl::Error set() = 0;
+ virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
+ virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
+ virtual gl::Error getStatus(GLint *outResult) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FENCESYNCIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h
new file mode 100644
index 0000000000..728f949a0f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/FramebufferImpl.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferImpl.h: Defines the abstract rx::FramebufferImpl class.
+
+#ifndef LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
+
+#include "angle_gl.h"
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+
+namespace gl
+{
+class State;
+class Framebuffer;
+class FramebufferAttachment;
+struct Rectangle;
+}
+
+namespace rx
+{
+
+class FramebufferImpl : angle::NonCopyable
+{
+ public:
+ explicit FramebufferImpl(const gl::Framebuffer::Data &data) : mData(data) { }
+ virtual ~FramebufferImpl() { }
+
+ virtual void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) = 0;
+ virtual void setDepthAttachment(const gl::FramebufferAttachment *attachment) = 0;
+ virtual void setStencilAttachment(const gl::FramebufferAttachment *attachment) = 0;
+ virtual void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) = 0;
+
+ virtual void setDrawBuffers(size_t count, const GLenum *buffers) = 0;
+ virtual void setReadBuffer(GLenum buffer) = 0;
+
+ virtual gl::Error invalidate(size_t count, const GLenum *attachments) = 0;
+ virtual gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) = 0;
+
+ virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
+ virtual gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0;
+ virtual gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0;
+ virtual gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) = 0;
+ virtual gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
+
+ virtual GLenum getImplementationColorReadFormat() const = 0;
+ virtual GLenum getImplementationColorReadType() const = 0;
+ virtual gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const = 0;
+
+ virtual gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) = 0;
+
+ virtual GLenum checkStatus() const = 0;
+
+ const gl::Framebuffer::Data &getData() const { return mData; }
+
+ protected:
+ const gl::Framebuffer::Data &mData;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_FRAMEBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h b/src/3rdparty/angle/src/libANGLE/renderer/Image.h
index 9071a88c67..62d854c9b6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Image.h
@@ -8,11 +8,11 @@
// renderer-specific classes which will define the interface to the underlying
// surfaces or resources.
-#ifndef LIBGLESV2_RENDERER_IMAGE_H_
-#define LIBGLESV2_RENDERER_IMAGE_H_
+#ifndef LIBANGLE_RENDERER_IMAGE_H_
+#define LIBANGLE_RENDERER_IMAGE_H_
#include "common/debug.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include <GLES2/gl2.h>
@@ -20,6 +20,9 @@ namespace gl
{
class Framebuffer;
struct Rectangle;
+struct Extents;
+struct Box;
+struct Offset;
struct ImageIndex;
}
@@ -39,7 +42,6 @@ class Image
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; }
@@ -47,16 +49,13 @@ class Image
void markClean() {mDirty = false;}
virtual bool isDirty() const = 0;
- virtual bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) = 0;
+ virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
- virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLint unpackAlignment, GLenum type, const void *input) = 0;
- virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- const void *input) = 0;
+ virtual gl::Error loadData(const gl::Box &area, GLint unpackAlignment, GLenum type, const void *input) = 0;
+ virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
- gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, gl::Framebuffer *source);
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source) = 0;
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source) = 0;
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea,
const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0;
protected:
@@ -64,7 +63,6 @@ class Image
GLsizei mHeight;
GLsizei mDepth;
GLenum mInternalFormat;
- GLenum mActualFormat;
bool mRenderable;
GLenum mTarget;
@@ -76,4 +74,4 @@ class Image
}
-#endif // LIBGLESV2_RENDERER_IMAGE_H_
+#endif // LIBANGLE_RENDERER_IMAGE_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h
new file mode 100644
index 0000000000..d77e59f7df
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ImplFactory.h
@@ -0,0 +1,68 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// ImplFactory.h:
+// Factory interface for Impl objects.
+//
+
+#ifndef LIBANGLE_RENDERER_IMPLFACTORY_H_
+#define LIBANGLE_RENDERER_IMPLFACTORY_H_
+
+#include "libANGLE/Framebuffer.h"
+
+namespace rx
+{
+class BufferImpl;
+class CompilerImpl;
+class FenceNVImpl;
+class FenceSyncImpl;
+class FramebufferImpl;
+class ProgramImpl;
+class QueryImpl;
+class RenderbufferImpl;
+class ShaderImpl;
+class TextureImpl;
+class TransformFeedbackImpl;
+class VertexArrayImpl;
+
+class ImplFactory : angle::NonCopyable
+{
+ public:
+ ImplFactory() {}
+ virtual ~ImplFactory() {}
+
+ // Shader creation
+ virtual CompilerImpl *createCompiler(const gl::Data &data) = 0;
+ virtual ShaderImpl *createShader(GLenum type) = 0;
+ virtual ProgramImpl *createProgram() = 0;
+
+ // Framebuffer creation
+ virtual FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) = 0;
+ virtual FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) = 0;
+
+ // Texture creation
+ virtual TextureImpl *createTexture(GLenum target) = 0;
+
+ // Renderbuffer creation
+ virtual RenderbufferImpl *createRenderbuffer() = 0;
+
+ // Buffer creation
+ virtual BufferImpl *createBuffer() = 0;
+
+ // Vertex Array creation
+ virtual VertexArrayImpl *createVertexArray() = 0;
+
+ // Query and Fence creation
+ virtual QueryImpl *createQuery(GLenum type) = 0;
+ virtual FenceNVImpl *createFenceNV() = 0;
+ virtual FenceSyncImpl *createFenceSync() = 0;
+
+ // Transform Feedback creation
+ virtual TransformFeedbackImpl *createTransformFeedback() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_IMPLFACTORY_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp
index d472e1499e..4a71cf4b45 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.cpp
@@ -7,13 +7,11 @@
// IndexRangeCache.cpp: Defines the rx::IndexRangeCache class which stores information about
// ranges of indices.
-#include "libGLESv2/renderer/IndexRangeCache.h"
-#include "libGLESv2/formatutils.h"
+#include "libANGLE/renderer/IndexRangeCache.h"
+#include "libANGLE/formatutils.h"
#include "common/debug.h"
-#include <tuple>
-
namespace rx
{
@@ -48,10 +46,9 @@ RangeUI IndexRangeCache::ComputeRange(GLenum type, const GLvoid *indices, GLsize
}
}
-void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range,
- unsigned int streamOffset)
+void IndexRangeCache::addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range)
{
- mIndexRangeCache[IndexRange(type, offset, count)] = IndexBounds(range, streamOffset);
+ mIndexRangeCache[IndexRange(type, offset, count)] = range;
}
void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
@@ -62,8 +59,8 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
IndexRangeMap::iterator i = mIndexRangeCache.begin();
while (i != mIndexRangeCache.end())
{
- unsigned int rangeStart = i->second.streamOffset;
- unsigned int rangeEnd = i->second.streamOffset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count);
+ unsigned int rangeStart = i->first.offset;
+ unsigned int rangeEnd = i->first.offset + (gl::GetTypeInfo(i->first.type).bytes * i->first.count);
if (invalidateEnd < rangeStart || invalidateStart > rangeEnd)
{
@@ -71,25 +68,23 @@ void IndexRangeCache::invalidateRange(unsigned int offset, unsigned int size)
}
else
{
- i = mIndexRangeCache.erase(i);
+ mIndexRangeCache.erase(i++);
}
}
}
bool IndexRangeCache::findRange(GLenum type, unsigned int offset, GLsizei count,
- RangeUI *outRange, unsigned int *outStreamOffset) const
+ RangeUI *outRange) const
{
IndexRangeMap::const_iterator i = mIndexRangeCache.find(IndexRange(type, offset, count));
if (i != mIndexRangeCache.end())
{
- if (outRange) *outRange = i->second.range;
- if (outStreamOffset) *outStreamOffset = i->second.streamOffset;
+ if (outRange) *outRange = i->second;
return true;
}
else
{
if (outRange) *outRange = RangeUI(0, 0);
- if (outStreamOffset) *outStreamOffset = 0;
return false;
}
}
@@ -111,18 +106,9 @@ IndexRangeCache::IndexRange::IndexRange(GLenum typ, intptr_t off, GLsizei c)
bool IndexRangeCache::IndexRange::operator<(const IndexRange& rhs) const
{
- return std::make_tuple(type, offset, count) < std::make_tuple(rhs.type, rhs.offset, rhs.count);
-}
-
-IndexRangeCache::IndexBounds::IndexBounds()
- : range(0, 0),
- streamOffset(0)
-{
-}
-
-IndexRangeCache::IndexBounds::IndexBounds(const RangeUI &rangeIn, unsigned int offset)
- : range(rangeIn), streamOffset(offset)
-{
+ if (type != rhs.type) return type < rhs.type;
+ if (offset != rhs.offset) return offset < rhs.offset;
+ return count < rhs.count;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h
index a7d91e035b..77249f5ff6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/IndexRangeCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/IndexRangeCache.h
@@ -7,8 +7,8 @@
// IndexRangeCache.h: Defines the rx::IndexRangeCache class which stores information about
// ranges of indices.
-#ifndef LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
-#define LIBGLESV2_RENDERER_INDEXRANGECACHE_H_
+#ifndef LIBANGLE_RENDERER_INDEXRANGECACHE_H_
+#define LIBANGLE_RENDERER_INDEXRANGECACHE_H_
#include "common/angleutils.h"
#include "common/mathutil.h"
@@ -23,10 +23,8 @@ namespace rx
class IndexRangeCache
{
public:
- void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range,
- unsigned int streamOffset);
- bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut,
- unsigned int *outStreamOffset) const;
+ void addRange(GLenum type, unsigned int offset, GLsizei count, const RangeUI &range);
+ bool findRange(GLenum type, unsigned int offset, GLsizei count, RangeUI *rangeOut) const;
void invalidateRange(unsigned int offset, unsigned int size);
void clear();
@@ -46,19 +44,10 @@ class IndexRangeCache
bool operator<(const IndexRange& rhs) const;
};
- struct IndexBounds
- {
- RangeUI range;
- unsigned int streamOffset;
-
- IndexBounds();
- IndexBounds(const RangeUI &range, unsigned int offset);
- };
-
- typedef std::map<IndexRange, IndexBounds> IndexRangeMap;
+ typedef std::map<IndexRange, RangeUI> IndexRangeMap;
IndexRangeMap mIndexRangeCache;
};
}
-#endif // LIBGLESV2_RENDERER_INDEXRANGECACHE_H
+#endif // LIBANGLE_RENDERER_INDEXRANGECACHE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp
index f9fcad38a4..8fbc53768f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.cpp
@@ -6,10 +6,9 @@
// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
-#include "libGLESv2/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/ProgramImpl.h"
#include "common/utilities.h"
-#include "libGLESv2/main.h"
namespace rx
{
@@ -35,6 +34,12 @@ unsigned int ParseAndStripArrayIndex(std::string* name)
}
+LinkResult::LinkResult(bool linkSuccess, const gl::Error &error)
+ : linkSuccess(linkSuccess),
+ error(error)
+{
+}
+
ProgramImpl::~ProgramImpl()
{
// Ensure that reset was called by the inherited class during destruction
@@ -137,6 +142,7 @@ GLuint ProgramImpl::getUniformBlockIndex(std::string name) const
void ProgramImpl::reset()
{
+ std::fill(mSemanticIndex, mSemanticIndex + ArraySize(mSemanticIndex), -1);
SafeDeleteContainer(mUniforms);
mUniformIndex.clear();
SafeDeleteContainer(mUniformBlocks);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h
index 6aaa23cf89..1128ab6741 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ProgramImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ProgramImpl.h
@@ -6,61 +6,50 @@
// ProgramImpl.h: Defines the abstract rx::ProgramImpl class.
-#ifndef LIBGLESV2_RENDERER_PROGRAMIMPL_H_
-#define LIBGLESV2_RENDERER_PROGRAMIMPL_H_
+#ifndef LIBANGLE_RENDERER_PROGRAMIMPL_H_
+#define LIBANGLE_RENDERER_PROGRAMIMPL_H_
#include "common/angleutils.h"
-#include "libGLESv2/BinaryStream.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/renderer/Renderer.h"
+#include "libANGLE/BinaryStream.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/renderer/Renderer.h"
#include <map>
namespace rx
{
-class ProgramImpl
+struct LinkResult
+{
+ bool linkSuccess;
+ gl::Error error;
+ LinkResult(bool linkSuccess, const gl::Error &error);
+};
+
+class ProgramImpl : angle::NonCopyable
{
public:
+ typedef int SemanticIndexArray[gl::MAX_VERTEX_ATTRIBS];
+
ProgramImpl() { }
virtual ~ProgramImpl();
- const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; }
- const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
- const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
- const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; }
- const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; }
-
- std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
- std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
- std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
- std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; }
- sh::Attribute *getShaderAttributes() { return mShaderAttributes; }
-
- gl::LinkedUniform *getUniformByLocation(GLint location) const;
- gl::LinkedUniform *getUniformByName(const std::string &name) const;
- gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const;
-
- GLint getUniformLocation(std::string name);
- GLuint getUniformIndex(std::string name);
- GLuint getUniformBlockIndex(std::string name) const;
-
virtual bool usesPointSize() const = 0;
virtual int getShaderVersion() const = 0;
virtual GLenum getTransformFeedbackBufferMode() const = 0;
virtual GLenum getBinaryFormat() = 0;
- virtual gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
+ virtual LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream) = 0;
virtual gl::Error save(gl::BinaryOutputStream *stream) = 0;
- virtual gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
- gl::Shader *fragmentShader, gl::Shader *vertexShader,
- const std::vector<std::string> &transformFeedbackVaryings,
- GLenum transformFeedbackBufferMode,
- int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
- std::map<int, gl::VariableLocation> *outputVariables) = 0;
+ virtual LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
+ gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings,
+ GLenum transformFeedbackBufferMode,
+ int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+ std::map<int, gl::VariableLocation> *outputVariables) = 0;
virtual void setUniform1fv(GLint location, GLsizei count, const GLfloat *v) = 0;
virtual void setUniform2fv(GLint location, GLsizei count, const GLfloat *v) = 0;
@@ -88,8 +77,6 @@ class ProgramImpl
virtual void getUniformiv(GLint location, GLint *params) = 0;
virtual void getUniformuiv(GLint location, GLuint *params) = 0;
- virtual void reset();
-
// TODO: The following functions are possibly only applicable to D3D backends. The should be carefully evaluated to
// determine if they can be removed from this interface.
virtual GLint getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const = 0;
@@ -98,8 +85,8 @@ class ProgramImpl
virtual void updateSamplerMapping() = 0;
virtual bool validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps) = 0;
- virtual gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
- int registers) = 0;
+ virtual LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ int registers) = 0;
virtual bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
const gl::Caps &caps) = 0;
@@ -107,21 +94,44 @@ class ProgramImpl
const gl::Caps &caps) = 0;
virtual gl::Error applyUniforms() = 0;
- virtual gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps) = 0;
+ virtual gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) = 0;
virtual bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
unsigned int registerIndex, const gl::Caps &caps) = 0;
- protected:
- DISALLOW_COPY_AND_ASSIGN(ProgramImpl);
+ const std::vector<gl::LinkedUniform*> &getUniforms() const { return mUniforms; }
+ const std::vector<gl::VariableLocation> &getUniformIndices() const { return mUniformIndex; }
+ const std::vector<gl::UniformBlock*> &getUniformBlocks() const { return mUniformBlocks; }
+ const std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() const { return mTransformFeedbackLinkedVaryings; }
+ const sh::Attribute *getShaderAttributes() const { return mShaderAttributes; }
+ const SemanticIndexArray &getSemanticIndexes() const { return mSemanticIndex; }
+
+ std::vector<gl::LinkedUniform*> &getUniforms() { return mUniforms; }
+ std::vector<gl::VariableLocation> &getUniformIndices() { return mUniformIndex; }
+ std::vector<gl::UniformBlock*> &getUniformBlocks() { return mUniformBlocks; }
+ std::vector<gl::LinkedVarying> &getTransformFeedbackLinkedVaryings() { return mTransformFeedbackLinkedVaryings; }
+ sh::Attribute *getShaderAttributes() { return mShaderAttributes; }
+ SemanticIndexArray &getSemanticIndexes() { return mSemanticIndex; }
+
+ gl::LinkedUniform *getUniformByLocation(GLint location) const;
+ gl::LinkedUniform *getUniformByName(const std::string &name) const;
+ gl::UniformBlock *getUniformBlockByIndex(GLuint blockIndex) const;
+
+ GLint getUniformLocation(std::string name);
+ GLuint getUniformIndex(std::string name);
+ GLuint getUniformBlockIndex(std::string name) const;
+ virtual void reset();
+
+ protected:
std::vector<gl::LinkedUniform*> mUniforms;
std::vector<gl::VariableLocation> mUniformIndex;
std::vector<gl::UniformBlock*> mUniformBlocks;
std::vector<gl::LinkedVarying> mTransformFeedbackLinkedVaryings;
+ SemanticIndexArray mSemanticIndex;
sh::Attribute mShaderAttributes[gl::MAX_VERTEX_ATTRIBS];
};
}
-#endif // LIBGLESV2_RENDERER_PROGRAMIMPL_H_
+#endif // LIBANGLE_RENDERER_PROGRAMIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h
index 6b45810a3b..bed63ea1b0 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/QueryImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/QueryImpl.h
@@ -6,10 +6,10 @@
// QueryImpl.h: Defines the abstract rx::QueryImpl class.
-#ifndef LIBGLESV2_RENDERER_QUERYIMPL_H_
-#define LIBGLESV2_RENDERER_QUERYIMPL_H_
+#ifndef LIBANGLE_RENDERER_QUERYIMPL_H_
+#define LIBANGLE_RENDERER_QUERYIMPL_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include "common/angleutils.h"
@@ -18,7 +18,7 @@
namespace rx
{
-class QueryImpl
+class QueryImpl : angle::NonCopyable
{
public:
explicit QueryImpl(GLenum type) { mType = type; }
@@ -32,11 +32,9 @@ class QueryImpl
GLenum getType() const { return mType; }
private:
- DISALLOW_COPY_AND_ASSIGN(QueryImpl);
-
GLenum mType;
};
}
-#endif // LIBGLESV2_RENDERER_QUERYIMPL_H_
+#endif // LIBANGLE_RENDERER_QUERYIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp
index 770ae8e9c6..ea5a40a21a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.cpp
@@ -6,7 +6,7 @@
// RenderbufferImpl.h: Implements the shared methods of the abstract class gl::RenderbufferImpl
-#include "libGLESv2/renderer/RenderbufferImpl.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h
new file mode 100644
index 0000000000..8ce257c833
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/RenderbufferImpl.h
@@ -0,0 +1,33 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl
+
+#ifndef LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+#define LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
+
+#include "angle_gl.h"
+
+#include "libANGLE/Error.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+class RenderbufferImpl : angle::NonCopyable
+{
+ public:
+ RenderbufferImpl();
+ virtual ~RenderbufferImpl() = 0;
+
+ virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) = 0;
+ virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp
new file mode 100644
index 0000000000..fbc2ad5d1c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.cpp
@@ -0,0 +1,72 @@
+//
+// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
+
+#include "common/utilities.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/renderer/Renderer.h"
+
+#include <EGL/eglext.h>
+
+namespace rx
+{
+
+Renderer::Renderer()
+ : mCapsInitialized(false),
+ mWorkaroundsInitialized(false)
+{
+}
+
+Renderer::~Renderer()
+{
+}
+
+const gl::Caps &Renderer::getRendererCaps() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
+ }
+
+ return mCaps;
+}
+
+const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
+ }
+
+ return mTextureCaps;
+}
+
+const gl::Extensions &Renderer::getRendererExtensions() const
+{
+ if (!mCapsInitialized)
+ {
+ generateCaps(&mCaps, &mTextureCaps, &mExtensions);
+ mCapsInitialized = true;
+ }
+
+ return mExtensions;
+}
+
+const Workarounds &Renderer::getWorkarounds() const
+{
+ if (!mWorkaroundsInitialized)
+ {
+ mWorkarounds = generateWorkarounds();
+ mWorkaroundsInitialized = true;
+ }
+
+ return mWorkarounds;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h
new file mode 100644
index 0000000000..b607fe5613
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Renderer.h
@@ -0,0 +1,91 @@
+//
+// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Renderer.h: Defines a back-end specific class that hides the details of the
+// implementation-specific renderer.
+
+#ifndef LIBANGLE_RENDERER_RENDERER_H_
+#define LIBANGLE_RENDERER_RENDERER_H_
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/ImplFactory.h"
+#include "libANGLE/renderer/Workarounds.h"
+#include "common/mathutil.h"
+
+#include <stdint.h>
+
+#include <EGL/egl.h>
+
+namespace egl
+{
+class AttributeMap;
+class Display;
+class Surface;
+}
+
+namespace gl
+{
+class Buffer;
+struct Data;
+}
+
+namespace rx
+{
+struct TranslatedIndexData;
+struct Workarounds;
+class DisplayImpl;
+
+class Renderer : public ImplFactory
+{
+ public:
+ Renderer();
+ virtual ~Renderer();
+
+ virtual gl::Error flush() = 0;
+ virtual gl::Error finish() = 0;
+
+ virtual gl::Error drawArrays(const gl::Data &data, GLenum mode,
+ GLint first, GLsizei count, GLsizei instances) = 0;
+ virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei instances,
+ const RangeUI &indexRange) = 0;
+
+ // lost device
+ //TODO(jmadill): investigate if this stuff is necessary in GL
+ virtual void notifyDeviceLost() = 0;
+ virtual bool isDeviceLost() const = 0;
+ virtual bool testDeviceLost() = 0;
+ virtual bool testDeviceResettable() = 0;
+
+ virtual VendorID getVendorId() const = 0;
+ virtual std::string getVendorString() const = 0;
+ virtual std::string getRendererDescription() const = 0;
+
+ // Renderer capabilities
+ const gl::Caps &getRendererCaps() const;
+ const gl::TextureCapsMap &getRendererTextureCaps() const;
+ const gl::Extensions &getRendererExtensions() const;
+ const Workarounds &getWorkarounds() const;
+
+ private:
+ virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0;
+ virtual Workarounds generateWorkarounds() const = 0;
+
+ mutable bool mCapsInitialized;
+ mutable gl::Caps mCaps;
+ mutable gl::TextureCapsMap mTextureCaps;
+ mutable gl::Extensions mExtensions;
+
+ mutable bool mWorkaroundsInitialized;
+ mutable Workarounds mWorkarounds;
+};
+
+}
+#endif // LIBANGLE_RENDERER_RENDERER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h
index cb0d360f0b..3011bc57f8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/ShaderImpl.h
@@ -6,28 +6,29 @@
// ShaderImpl.h: Defines the abstract rx::ShaderImpl class.
-#ifndef LIBGLESV2_RENDERER_SHADERIMPL_H_
-#define LIBGLESV2_RENDERER_SHADERIMPL_H_
+#ifndef LIBANGLE_RENDERER_SHADERIMPL_H_
+#define LIBANGLE_RENDERER_SHADERIMPL_H_
#include <vector>
#include "common/angleutils.h"
-#include "libGLESv2/Shader.h"
+#include "libANGLE/Shader.h"
namespace rx
{
-class ShaderImpl
+class ShaderImpl : angle::NonCopyable
{
public:
ShaderImpl() { }
virtual ~ShaderImpl() { }
- virtual bool compile(const gl::Data &data, const std::string &source) = 0;
- virtual const std::string &getInfoLog() const = 0;
- virtual const std::string &getTranslatedSource() const = 0;
+ virtual bool compile(gl::Compiler *compiler, const std::string &source) = 0;
virtual std::string getDebugInfo() const = 0;
+ virtual const std::string &getInfoLog() const { return mInfoLog; }
+ virtual const std::string &getTranslatedSource() const { return mTranslatedSource; }
+
const std::vector<gl::PackedVarying> &getVaryings() const { return mVaryings; }
const std::vector<sh::Uniform> &getUniforms() const { return mUniforms; }
const std::vector<sh::InterfaceBlock> &getInterfaceBlocks() const { return mInterfaceBlocks; }
@@ -41,7 +42,8 @@ class ShaderImpl
std::vector<sh::Attribute> &getActiveOutputVariables() { return mActiveOutputVariables; }
protected:
- DISALLOW_COPY_AND_ASSIGN(ShaderImpl);
+ std::string mInfoLog;
+ std::string mTranslatedSource;
std::vector<gl::PackedVarying> mVaryings;
std::vector<sh::Uniform> mUniforms;
@@ -52,4 +54,4 @@ class ShaderImpl
}
-#endif // LIBGLESV2_RENDERER_SHADERIMPL_H_
+#endif // LIBANGLE_RENDERER_SHADERIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp
new file mode 100644
index 0000000000..36f5fdca3f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.cpp
@@ -0,0 +1,22 @@
+//
+// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceImpl.cpp: Implementation of Surface stub method class
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+
+namespace rx
+{
+
+SurfaceImpl::SurfaceImpl()
+{
+}
+
+SurfaceImpl::~SurfaceImpl()
+{
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h
new file mode 100644
index 0000000000..ca04a42bd1
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/SurfaceImpl.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceImpl.h: Implementation methods of egl::Surface
+
+#ifndef LIBANGLE_RENDERER_SURFACEIMPL_H_
+#define LIBANGLE_RENDERER_SURFACEIMPL_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/Error.h"
+
+namespace egl
+{
+class Display;
+struct Config;
+}
+
+namespace rx
+{
+
+class SurfaceImpl : angle::NonCopyable
+{
+ public:
+ SurfaceImpl();
+ virtual ~SurfaceImpl();
+
+ virtual egl::Error initialize() = 0;
+ virtual egl::Error swap() = 0;
+ virtual egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+ virtual egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) = 0;
+ virtual egl::Error bindTexImage(EGLint buffer) = 0;
+ virtual egl::Error releaseTexImage(EGLint buffer) = 0;
+ virtual void setSwapInterval(EGLint interval) = 0;
+
+ // width and height can change with client window resizing
+ virtual EGLint getWidth() const = 0;
+ virtual EGLint getHeight() const = 0;
+
+ virtual EGLint isPostSubBufferSupported() const = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_SURFACEIMPL_H_
+
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h
new file mode 100644
index 0000000000..d628906116
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TextureImpl.h
@@ -0,0 +1,72 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
+
+#ifndef LIBANGLE_RENDERER_TEXTUREIMPL_H_
+#define LIBANGLE_RENDERER_TEXTUREIMPL_H_
+
+#include "libANGLE/Error.h"
+#include "libANGLE/ImageIndex.h"
+
+#include "common/angleutils.h"
+
+#include "angle_gl.h"
+
+#include <stdint.h>
+
+namespace egl
+{
+class Surface;
+}
+
+namespace gl
+{
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+class Framebuffer;
+struct PixelUnpackState;
+struct SamplerState;
+}
+
+namespace rx
+{
+
+class TextureImpl : angle::NonCopyable
+{
+ public:
+ virtual ~TextureImpl() {};
+
+ virtual void setUsage(GLenum usage) = 0;
+
+ virtual gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+ virtual gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+
+ virtual gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+ virtual gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) = 0;
+
+ virtual gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) = 0;
+ virtual gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) = 0;
+
+ virtual gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) = 0;
+
+ virtual gl::Error generateMipmaps() = 0;
+
+ virtual void bindTexImage(egl::Surface *surface) = 0;
+ virtual void releaseTexImage() = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_TEXTUREIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
index 8425604d87..8f9133cfe5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TransformFeedbackImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/TransformFeedbackImpl.h
@@ -6,16 +6,16 @@
// TransformFeedbackImpl.h: Defines the abstract rx::TransformFeedbackImpl class.
-#ifndef LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
-#define LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#ifndef LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#define LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
#include "common/angleutils.h"
-#include "libGLESv2/TransformFeedback.h"
+#include "libANGLE/TransformFeedback.h"
namespace rx
{
-class TransformFeedbackImpl
+class TransformFeedbackImpl : angle::NonCopyable
{
public:
virtual ~TransformFeedbackImpl() { }
@@ -28,4 +28,4 @@ class TransformFeedbackImpl
}
-#endif // LIBGLESV2_RENDERER_TRANSFORMFEEDBACKIMPL_H_
+#endif // LIBANGLE_RENDERER_TRANSFORMFEEDBACKIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h
index b013f9cdf4..0e25f952c2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/VertexArrayImpl.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/VertexArrayImpl.h
@@ -6,17 +6,17 @@
// VertexAttribImpl.h: Defines the abstract rx::VertexAttribImpl class.
-#ifndef LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
-#define LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
+#ifndef LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
+#define LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
#include "common/angleutils.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/VertexAttribute.h"
namespace rx
{
-class VertexArrayImpl
+class VertexArrayImpl : angle::NonCopyable
{
public:
virtual ~VertexArrayImpl() { }
@@ -29,4 +29,4 @@ class VertexArrayImpl
}
-#endif // LIBGLESV2_RENDERER_VERTEXARRAYIMPL_H_
+#endif // LIBANGLE_RENDERER_VERTEXARRAYIMPL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h
new file mode 100644
index 0000000000..b73f4a5472
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/Workarounds.h
@@ -0,0 +1,74 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// angletypes.h: Workarounds for driver bugs and other issues.
+
+#ifndef LIBANGLE_RENDERER_WORKAROUNDS_H_
+#define LIBANGLE_RENDERER_WORKAROUNDS_H_
+
+// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
+// independent of ANGLE's renderer. Workarounds should also be accessible
+// outside of the Renderer.
+
+namespace rx
+{
+
+struct D3DCompilerWorkarounds : angle::NonCopyable
+{
+ D3DCompilerWorkarounds()
+ : skipOptimization(false),
+ useMaxOptimization(false),
+ enableIEEEStrictness(false)
+ {}
+
+ void reset()
+ {
+ skipOptimization = false;
+ useMaxOptimization = false;
+ enableIEEEStrictness = false;
+ }
+
+ bool skipOptimization;
+ bool useMaxOptimization;
+
+ // IEEE strictness needs to be enabled for NANs to work.
+ bool enableIEEEStrictness;
+};
+
+struct Workarounds
+{
+ Workarounds()
+ : mrtPerfWorkaround(false),
+ setDataFasterThanImageUpload(false),
+ zeroMaxLodWorkaround(false),
+ useInstancedPointSpriteEmulation(false)
+ {}
+
+ // On some systems, having extra rendertargets than necessary slows down the shader.
+ // We can fix this by optimizing those out of the shader. At the same time, we can
+ // work around a bug on some nVidia drivers that they ignore "null" render targets
+ // in D3D11, by compacting the active color attachments list to omit null entries.
+ bool mrtPerfWorkaround;
+
+ bool setDataFasterThanImageUpload;
+
+ // Some renderers can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero, and ignore the other levels).
+ // D3D11 Feature Level 10+ does this by setting MaxLOD to 0.0f in the Sampler state. D3D9 sets D3DSAMP_MIPFILTER to D3DTEXF_NONE.
+ // There is no equivalent to this in D3D11 Feature Level 9_3.
+ // This causes problems when (for example) an application creates a mipmapped texture2D, but sets GL_TEXTURE_MIN_FILTER to GL_NEAREST (i.e disables mipmaps).
+ // To work around this, D3D11 FL9_3 has to create two copies of the texture. The textures' level zeros are identical, but only one texture has mips.
+ bool zeroMaxLodWorkaround;
+
+ // Some renderers do not support Geometry Shaders so the Geometry Shader-based
+ // PointSprite emulation will not work.
+ // To work around this, D3D11 FL9_3 has to use a different pointsprite
+ // emulation that is implemented using instanced quads.
+ bool useInstancedPointSpriteEmulation;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_WORKAROUNDS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
index dd0d3f52ad..1af8794356 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.cpp
@@ -6,20 +6,22 @@
// BufferD3D.cpp Defines common functionality between the Buffer9 and Buffer11 classes.
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/VertexBuffer.h"
-#include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
namespace rx
{
unsigned int BufferD3D::mNextSerial = 1;
-BufferD3D::BufferD3D()
+BufferD3D::BufferD3D(BufferFactoryD3D *factory)
: BufferImpl(),
- mStaticVertexBuffer(NULL),
- mStaticIndexBuffer(NULL)
+ mFactory(factory),
+ mStaticVertexBuffer(nullptr),
+ mStaticIndexBuffer(nullptr),
+ mUnmodifiedDataUse(0)
{
updateSerial();
}
@@ -30,19 +32,6 @@ BufferD3D::~BufferD3D()
SafeDelete(mStaticIndexBuffer);
}
-BufferD3D *BufferD3D::makeBufferD3D(BufferImpl *buffer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(BufferD3D*, buffer));
- return static_cast<BufferD3D*>(buffer);
-}
-
-BufferD3D *BufferD3D::makeFromBuffer(gl::Buffer *buffer)
-{
- BufferImpl *impl = buffer->getImplementation();
- ASSERT(impl);
- return makeBufferD3D(impl);
-}
-
void BufferD3D::updateSerial()
{
mSerial = mNextSerial++;
@@ -52,11 +41,11 @@ void BufferD3D::initializeStaticData()
{
if (!mStaticVertexBuffer)
{
- mStaticVertexBuffer = new StaticVertexBufferInterface(getRenderer());
+ mStaticVertexBuffer = new StaticVertexBufferInterface(mFactory);
}
if (!mStaticIndexBuffer)
{
- mStaticIndexBuffer = new StaticIndexBufferInterface(getRenderer());
+ mStaticIndexBuffer = new StaticIndexBufferInterface(mFactory);
}
}
@@ -66,6 +55,9 @@ void BufferD3D::invalidateStaticData()
{
SafeDelete(mStaticVertexBuffer);
SafeDelete(mStaticIndexBuffer);
+
+ // Re-init static data to track that we're in a static buffer
+ initializeStaticData();
}
mUnmodifiedDataUse = 0;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h
index 1a1308c545..a46398f911 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/BufferD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/BufferD3D.h
@@ -4,37 +4,33 @@
// found in the LICENSE file.
//
-// BufferImpl.h: Defines the abstract rx::BufferImpl class.
+// BufferD3D.h: Defines the rx::BufferD3D class, an implementation of BufferImpl.
-#ifndef LIBGLESV2_RENDERER_BUFFERD3D_H_
-#define LIBGLESV2_RENDERER_BUFFERD3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
-#include "libGLESv2/renderer/BufferImpl.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/angletypes.h"
-#include <cstdint>
+#include <stdint.h>
namespace rx
{
-class RendererD3D;
+class BufferFactoryD3D;
class StaticIndexBufferInterface;
class StaticVertexBufferInterface;
class BufferD3D : public BufferImpl
{
public:
- BufferD3D();
+ BufferD3D(BufferFactoryD3D *factory);
virtual ~BufferD3D();
- static BufferD3D *makeBufferD3D(BufferImpl *buffer);
- static BufferD3D *makeFromBuffer(gl::Buffer *buffer);
-
unsigned int getSerial() const { return mSerial; }
- virtual gl::Error getData(const uint8_t **outData) = 0;
virtual size_t getSize() const = 0;
virtual bool supportsDirectBinding() const = 0;
- virtual RendererD3D *getRenderer() = 0;
+ virtual void markTransformFeedbackUsage() = 0;
StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
@@ -44,11 +40,12 @@ class BufferD3D : public BufferImpl
void promoteStaticUsage(int dataSize);
protected:
+ void updateSerial();
+
+ BufferFactoryD3D *mFactory;
unsigned int mSerial;
static unsigned int mNextSerial;
- void updateSerial();
-
StaticVertexBufferInterface *mStaticVertexBuffer;
StaticIndexBufferInterface *mStaticIndexBuffer;
unsigned int mUnmodifiedDataUse;
@@ -56,4 +53,4 @@ class BufferD3D : public BufferImpl
}
-#endif // LIBGLESV2_RENDERER_BUFFERIMPLD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_BUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
new file mode 100644
index 0000000000..a22757cf9f
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.cpp
@@ -0,0 +1,128 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerD3D.cpp: Implementation of the rx::CompilerD3D class.
+
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+
+#include "libANGLE/Caps.h"
+#include "libANGLE/Data.h"
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+// Global count of active shader compiler handles. Needed to know when to call ShInitialize and ShFinalize.
+static size_t activeCompilerHandles = 0;
+
+CompilerD3D::CompilerD3D(const gl::Data &data, ShShaderOutput outputType)
+ : mSpec(data.clientVersion > 2 ? SH_GLES3_SPEC : SH_GLES2_SPEC),
+ mOutputType(outputType),
+ mResources(),
+ mFragmentCompiler(NULL),
+ mVertexCompiler(NULL)
+{
+ ASSERT(data.clientVersion == 2 || data.clientVersion == 3);
+
+ const gl::Caps &caps = *data.caps;
+ const gl::Extensions &extensions = *data.extensions;
+
+ ShInitBuiltInResources(&mResources);
+ mResources.MaxVertexAttribs = caps.maxVertexAttributes;
+ mResources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
+ mResources.MaxVaryingVectors = caps.maxVaryingVectors;
+ mResources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits;
+ mResources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
+ mResources.MaxTextureImageUnits = caps.maxTextureImageUnits;
+ mResources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
+ mResources.MaxDrawBuffers = caps.maxDrawBuffers;
+ mResources.OES_standard_derivatives = extensions.standardDerivatives;
+ mResources.EXT_draw_buffers = extensions.drawBuffers;
+ mResources.EXT_shader_texture_lod = 1;
+ // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
+ mResources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
+ mResources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
+
+ // GLSL ES 3.0 constants
+ mResources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
+ mResources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
+ mResources.MinProgramTexelOffset = caps.minProgramTexelOffset;
+ mResources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
+}
+
+CompilerD3D::~CompilerD3D()
+{
+ release();
+}
+
+CompilerD3D *CompilerD3D::makeCompilerD3D(CompilerImpl *compiler)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(CompilerD3D*, compiler));
+ return static_cast<CompilerD3D*>(compiler);
+}
+
+gl::Error CompilerD3D::release()
+{
+ if (mFragmentCompiler)
+ {
+ ShDestruct(mFragmentCompiler);
+ mFragmentCompiler = NULL;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
+ }
+
+ if (mVertexCompiler)
+ {
+ ShDestruct(mVertexCompiler);
+ mVertexCompiler = NULL;
+
+ ASSERT(activeCompilerHandles > 0);
+ activeCompilerHandles--;
+ }
+
+ if (activeCompilerHandles == 0)
+ {
+ ShFinalize();
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+ShHandle CompilerD3D::getCompilerHandle(GLenum type)
+{
+ ShHandle *compiler = NULL;
+ switch (type)
+ {
+ case GL_VERTEX_SHADER:
+ compiler = &mVertexCompiler;
+ break;
+
+ case GL_FRAGMENT_SHADER:
+ compiler = &mFragmentCompiler;
+ break;
+
+ default:
+ UNREACHABLE();
+ return NULL;
+ }
+
+ if (!(*compiler))
+ {
+ if (activeCompilerHandles == 0)
+ {
+ ShInitialize();
+ }
+
+ *compiler = ShConstructCompiler(type, mSpec, mOutputType, &mResources);
+ activeCompilerHandles++;
+ }
+
+ return *compiler;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
new file mode 100644
index 0000000000..0f83e4f8c8
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/CompilerD3D.h
@@ -0,0 +1,48 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CompilerD3D.h: Defines the rx::CompilerD3D class, an implementation of rx::CompilerImpl.
+
+#ifndef LIBANGLE_RENDERER_COMPILERD3D_H_
+#define LIBANGLE_RENDERER_COMPILERD3D_H_
+
+#include "libANGLE/renderer/CompilerImpl.h"
+#include "libANGLE/Caps.h"
+
+#include "GLSLANG/ShaderLang.h"
+
+namespace gl
+{
+struct Data;
+}
+
+namespace rx
+{
+
+class CompilerD3D : public CompilerImpl
+{
+ public:
+ CompilerD3D(const gl::Data &data, ShShaderOutput outputType);
+ virtual ~CompilerD3D();
+
+ static CompilerD3D *makeCompilerD3D(CompilerImpl *compiler);
+
+ gl::Error release() override;
+
+ ShHandle getCompilerHandle(GLenum type);
+
+ private:
+ ShShaderSpec mSpec;
+ ShShaderOutput mOutputType;
+ ShBuiltInResources mResources;
+
+ ShHandle mFragmentCompiler;
+ ShHandle mVertexCompiler;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_COMPILERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
new file mode 100644
index 0000000000..add5d62fae
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
@@ -0,0 +1,357 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.cpp: D3D implementation of egl::Display
+
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "platform/Platform.h"
+
+#include <EGL/eglext.h>
+
+#if defined (ANGLE_ENABLE_D3D9)
+# include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#endif // ANGLE_ENABLE_D3D9
+
+#if defined (ANGLE_ENABLE_D3D11)
+# include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#endif // ANGLE_ENABLE_D3D11
+
+#if defined (ANGLE_TEST_CONFIG)
+# define ANGLE_DEFAULT_D3D11 1
+#endif
+
+#if !defined(ANGLE_DEFAULT_D3D11)
+// Enables use of the Direct3D 11 API for a default display, when available
+# define ANGLE_DEFAULT_D3D11 0
+#endif
+
+namespace rx
+{
+
+typedef RendererD3D *(*CreateRendererD3DFunction)(egl::Display*);
+
+template <typename RendererType>
+static RendererD3D *CreateTypedRendererD3D(egl::Display *display)
+{
+ return new RendererType(display);
+}
+
+egl::Error CreateRendererD3D(egl::Display *display, RendererD3D **outRenderer)
+{
+ ASSERT(outRenderer != nullptr);
+
+ std::vector<CreateRendererD3DFunction> rendererCreationFunctions;
+
+ const auto &attribMap = display->getAttributeMap();
+ EGLNativeDisplayType nativeDisplay = display->getNativeDisplayId();
+
+ EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
+
+# if defined(ANGLE_ENABLE_D3D11)
+ if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+ }
+# endif
+
+# if defined(ANGLE_ENABLE_D3D9)
+ if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
+ {
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+ }
+# endif
+
+ if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
+ nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
+ requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
+ {
+ // The default display is requested, try the D3D9 and D3D11 renderers, order them using
+ // the definition of ANGLE_DEFAULT_D3D11
+# if ANGLE_DEFAULT_D3D11
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+# endif
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+# endif
+# else
+# if defined(ANGLE_ENABLE_D3D9)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer9>);
+# endif
+# if defined(ANGLE_ENABLE_D3D11)
+ rendererCreationFunctions.push_back(CreateTypedRendererD3D<Renderer11>);
+# endif
+# endif
+ }
+
+ egl::Error result(EGL_NOT_INITIALIZED, "No available renderers.");
+ for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
+ {
+ RendererD3D *renderer = rendererCreationFunctions[i](display);
+ result = renderer->initialize();
+
+# if defined(ANGLE_ENABLE_D3D11)
+ if (renderer->getRendererClass() == RENDERER_D3D11)
+ {
+ ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D11_INIT_ERRORS);
+
+ angle::Platform *platform = ANGLEPlatformCurrent();
+ platform->histogramEnumeration("GPU.ANGLE.D3D11InitializeResult",
+ result.getID(), NUM_D3D11_INIT_ERRORS);
+ }
+# endif
+
+# if defined(ANGLE_ENABLE_D3D9)
+ if (renderer->getRendererClass() == RENDERER_D3D9)
+ {
+ ASSERT(result.getID() >= 0 && result.getID() < NUM_D3D9_INIT_ERRORS);
+
+ angle::Platform *platform = ANGLEPlatformCurrent();
+ platform->histogramEnumeration("GPU.ANGLE.D3D9InitializeResult",
+ result.getID(), NUM_D3D9_INIT_ERRORS);
+ }
+# endif
+
+ if (!result.isError())
+ {
+ *outRenderer = renderer;
+ break;
+ }
+ else
+ {
+ // Failed to create the renderer, try the next
+ SafeDelete(renderer);
+ }
+ }
+
+ return result;
+}
+
+DisplayD3D::DisplayD3D()
+ : mRenderer(nullptr)
+{
+}
+
+egl::Error DisplayD3D::createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface)
+{
+ ASSERT(mRenderer != nullptr);
+
+ EGLint width = attribs.get(EGL_WIDTH, 0);
+ EGLint height = attribs.get(EGL_HEIGHT, 0);
+ EGLint fixedSize = attribs.get(EGL_FIXED_SIZE_ANGLE, EGL_FALSE);
+
+ if (!fixedSize)
+ {
+ width = -1;
+ height = -1;
+ }
+
+ SurfaceD3D *surface = SurfaceD3D::createFromWindow(mRenderer, mDisplay, configuration, window, fixedSize,
+ width, height);
+ egl::Error error = surface->initialize();
+ if (error.isError())
+ {
+ SafeDelete(surface);
+ return error;
+ }
+
+ *outSurface = surface;
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs,
+ SurfaceImpl **outSurface)
+{
+ ASSERT(mRenderer != nullptr);
+
+ EGLint width = attribs.get(EGL_WIDTH, 0);
+ EGLint height = attribs.get(EGL_HEIGHT, 0);
+
+ SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, NULL, width, height);
+ egl::Error error = surface->initialize();
+ if (error.isError())
+ {
+ SafeDelete(surface);
+ return error;
+ }
+
+ *outSurface = surface;
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface)
+{
+ ASSERT(mRenderer != nullptr);
+
+ EGLint width = attribs.get(EGL_WIDTH, 0);
+ EGLint height = attribs.get(EGL_HEIGHT, 0);
+
+ SurfaceD3D *surface = SurfaceD3D::createOffscreen(mRenderer, mDisplay, configuration, shareHandle,
+ width, height);
+ egl::Error error = surface->initialize();
+ if (error.isError())
+ {
+ SafeDelete(surface);
+ return error;
+ }
+
+ *outSurface = surface;
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface)
+{
+ ASSERT(mRenderer != nullptr);
+
+ UNIMPLEMENTED();
+ *outSurface = nullptr;
+ return egl::Error(EGL_BAD_DISPLAY);
+}
+
+egl::Error DisplayD3D::createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
+ gl::Context **outContext)
+{
+ ASSERT(mRenderer != nullptr);
+
+ EGLint clientVersion = attribs.get(EGL_CONTEXT_CLIENT_VERSION, 1);
+ bool notifyResets = (attribs.get(EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, EGL_NO_RESET_NOTIFICATION_EXT) == EGL_LOSE_CONTEXT_ON_RESET_EXT);
+ bool robustAccess = (attribs.get(EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT, EGL_FALSE) == EGL_TRUE);
+
+ *outContext = new gl::Context(config, clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error DisplayD3D::initialize(egl::Display *display)
+{
+ ASSERT(mRenderer == nullptr && display != nullptr);
+ mDisplay = display;
+ return CreateRendererD3D(display, &mRenderer);
+}
+
+void DisplayD3D::terminate()
+{
+ SafeDelete(mRenderer);
+}
+
+egl::ConfigSet DisplayD3D::generateConfigs() const
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->generateConfigs();
+}
+
+bool DisplayD3D::isDeviceLost() const
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->isDeviceLost();
+}
+
+bool DisplayD3D::testDeviceLost()
+{
+ ASSERT(mRenderer != nullptr);
+ return mRenderer->testDeviceLost();
+}
+
+egl::Error DisplayD3D::restoreLostDevice()
+{
+ // Release surface resources to make the Reset() succeed
+ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it)
+ {
+ const auto &surface = *it;
+ if (surface->getBoundTexture())
+ {
+ surface->releaseTexImage(EGL_BACK_BUFFER);
+ }
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ surfaceD3D->releaseSwapChain();
+ }
+
+ if (!mRenderer->resetDevice())
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ // Restore any surfaces that may have been lost
+ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it)
+ {
+ const auto &surface = *it;
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+
+ egl::Error error = surfaceD3D->resetSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+bool DisplayD3D::isValidNativeWindow(EGLNativeWindowType window) const
+{
+ return NativeWindow::isValidNativeWindow(window);
+}
+
+void DisplayD3D::generateExtensions(egl::DisplayExtensions *outExtensions) const
+{
+ outExtensions->createContextRobustness = true;
+
+ // ANGLE-specific extensions
+ if (mRenderer->getShareHandleSupport())
+ {
+ outExtensions->d3dShareHandleClientBuffer = true;
+ outExtensions->surfaceD3DTexture2DShareHandle = true;
+ }
+
+ outExtensions->querySurfacePointer = true;
+ outExtensions->windowFixedSize = true;
+
+ if (mRenderer->getPostSubBufferSupport())
+ {
+ outExtensions->postSubBuffer = true;
+ }
+
+ outExtensions->createContext = true;
+}
+
+std::string DisplayD3D::getVendorString() const
+{
+ std::string vendorString = "Google Inc.";
+ if (mRenderer)
+ {
+ vendorString += " " + mRenderer->getVendorString();
+ }
+
+ return vendorString;
+}
+
+void DisplayD3D::generateCaps(egl::Caps *outCaps) const
+{
+ // Display must be initialized to generate caps
+ ASSERT(mRenderer != nullptr);
+
+ outCaps->textureNPOT = mRenderer->getRendererExtensions().textureNPOT;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
new file mode 100644
index 0000000000..f007ba9a19
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.h
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// DisplayD3D.h: D3D implementation of egl::Display
+
+#ifndef LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+#define LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
+
+#include "libANGLE/renderer/DisplayImpl.h"
+
+namespace rx
+{
+class RendererD3D;
+
+class DisplayD3D : public DisplayImpl
+{
+ public:
+ DisplayD3D();
+
+ egl::Error initialize(egl::Display *display) override;
+ virtual void terminate() override;
+
+ egl::Error createWindowSurface(const egl::Config *configuration, EGLNativeWindowType window, const egl::AttributeMap &attribs,
+ SurfaceImpl **outSurface) override;
+ egl::Error createPbufferSurface(const egl::Config *configuration, const egl::AttributeMap &attribs,
+ SurfaceImpl **outSurface) override;
+ egl::Error createPbufferFromClientBuffer(const egl::Config *configuration, EGLClientBuffer shareHandle,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override;
+ egl::Error createPixmapSurface(const egl::Config *configuration, NativePixmapType nativePixmap,
+ const egl::AttributeMap &attribs, SurfaceImpl **outSurface) override;
+
+ egl::Error createContext(const egl::Config *config, const gl::Context *shareContext, const egl::AttributeMap &attribs,
+ gl::Context **outContext) override;
+
+ egl::Error makeCurrent(egl::Surface *drawSurface, egl::Surface *readSurface, gl::Context *context) override;
+
+ egl::ConfigSet generateConfigs() const override;
+
+ bool isDeviceLost() const override;
+ bool testDeviceLost() override;
+ egl::Error restoreLostDevice() override;
+
+ bool isValidNativeWindow(EGLNativeWindowType window) const override;
+
+ std::string getVendorString() const override;
+
+ private:
+ void generateExtensions(egl::DisplayExtensions *outExtensions) const override;
+ void generateCaps(egl::Caps *outCaps) const override;
+
+ egl::Display *mDisplay;
+
+ rx::RendererD3D *mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_DISPLAYD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
index 3d5bfe0cbe..0dbc30ae36 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.cpp
@@ -6,19 +6,18 @@
// DynamicHLSL.cpp: Implementation for link and run-time HLSL generation
//
-#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/formatutils.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include "common/utilities.h"
-#include "common/blocklayout.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/formatutils.h"
// For use with ArrayString, see angleutils.h
-META_ASSERT(GL_INVALID_INDEX == UINT_MAX);
+static_assert(GL_INVALID_INDEX == UINT_MAX, "GL_INVALID_INDEX must be equal to the max unsigned int.");
using namespace gl;
@@ -73,19 +72,18 @@ std::string HLSLTypeString(GLenum type)
return HLSLComponentTypeString(gl::VariableComponentType(type), gl::VariableComponentCount(type));
}
-const PixelShaderOutputVariable &GetOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables,
+const PixelShaderOutputVariable *FindOutputAtLocation(const std::vector<PixelShaderOutputVariable> &outputVariables,
unsigned int location)
{
for (size_t variableIndex = 0; variableIndex < outputVariables.size(); ++variableIndex)
{
if (outputVariables[variableIndex].outputIndex == location)
{
- return outputVariables[variableIndex];
+ return &outputVariables[variableIndex];
}
}
- UNREACHABLE();
- return outputVariables[0];
+ return NULL;
}
const std::string VERTEX_ATTRIBUTE_STUB_STRING = "@@ VERTEX ATTRIBUTES @@";
@@ -100,11 +98,21 @@ DynamicHLSL::DynamicHLSL(RendererD3D *const renderer)
static bool packVarying(PackedVarying *varying, const int maxVaryingVectors, VaryingPacking packing)
{
- GLenum transposedType = TransposeMatrixType(varying->type);
+ // Make sure we use transposed matrix types to count registers correctly.
+ int registers = 0;
+ int elements = 0;
- // 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 (varying->isStruct())
+ {
+ registers = HLSLVariableRegisterCount(*varying, true) * varying->elementCount();
+ elements = 4;
+ }
+ else
+ {
+ GLenum transposedType = TransposeMatrixType(varying->type);
+ registers = VariableRowCount(transposedType) * varying->elementCount();
+ elements = VariableColumnCount(transposedType);
+ }
if (elements >= 2 && elements <= 4)
{
@@ -342,15 +350,16 @@ std::string DynamicHLSL::generateVaryingHLSL(const ShaderD3D *shader) const
default: UNREACHABLE();
}
- unsigned int semanticIndex = elementIndex * variableRows + varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors + varying.registerIndex + row;
+ unsigned int semanticIndex = elementIndex * variableRows +
+ varying.columnIndex * mRenderer->getRendererCaps().maxVaryingVectors +
+ varying.registerIndex + row;
std::string n = Str(semanticIndex);
std::string typeString;
if (varying.isStruct())
{
- // matrices within structs are not transposed, so
- // do not use the special struct prefix "rm"
+ // TODO(jmadill): pass back translated name from the shader translator
typeString = decorateVariable(varying.structName);
}
else
@@ -377,6 +386,26 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
int semanticIndex = 0;
unsigned int inputIndex = 0;
+ // If gl_PointSize is used in the shader then pointsprites rendering is expected.
+ // If the renderer does not support Geometry shaders then Instanced PointSprite emulation
+ // must be used.
+ bool usesPointSize = sourceShader.find("GL_USES_POINT_SIZE") != std::string::npos;
+ bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
+
+ // Instanced PointSprite emulation requires additional entries in the
+ // VS_INPUT structure to support the vertices that make up the quad vertices.
+ // These values must be in sync with the cooresponding values added during inputlayout creation
+ // in InputLayoutCache::applyVertexBuffers().
+ //
+ // The additional entries must appear first in the VS_INPUT layout because
+ // Windows Phone 8 era devices require per vertex data to physically come
+ // before per instance data in the shader.
+ if (useInstancedPointSpriteEmulation)
+ {
+ structHLSL += " float3 spriteVertexPos : SPRITEPOSITION0;\n";
+ structHLSL += " float2 spriteTexCoord : SPRITETEXCOORD0;\n";
+ }
+
for (unsigned int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const sh::Attribute &shaderAttribute = shaderAttributes[attributeIndex];
@@ -394,11 +423,31 @@ std::string DynamicHLSL::generateVertexShaderForInputLayout(const std::string &s
else
{
GLenum componentType = mRenderer->getVertexComponentType(vertexFormat);
- structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type));
+
+ if (shaderAttribute.name == "gl_InstanceID")
+ {
+ // The input type of the instance ID in HLSL (uint) differs from the one in ESSL (int).
+ structHLSL += " uint";
+ }
+ else
+ {
+ structHLSL += " " + HLSLComponentTypeString(componentType, VariableComponentCount(shaderAttribute.type));
+ }
+ }
+
+ structHLSL += " " + decorateVariable(shaderAttribute.name) + " : ";
+
+ if (shaderAttribute.name == "gl_InstanceID")
+ {
+ structHLSL += "SV_InstanceID";
+ }
+ else
+ {
+ structHLSL += "TEXCOORD" + Str(semanticIndex);
+ semanticIndex += VariableRegisterCount(shaderAttribute.type);
}
- structHLSL += " " + decorateVariable(shaderAttribute.name) + " : TEXCOORD" + Str(semanticIndex) + ";\n";
- semanticIndex += VariableRegisterCount(shaderAttribute.type);
+ structHLSL += ";\n";
// HLSL code for initialization
initHLSL += " " + decorateVariable(shaderAttribute.name) + " = ";
@@ -458,12 +507,18 @@ std::string DynamicHLSL::generatePixelShaderForOutputSignature(const std::string
{
unsigned int location = (binding - GL_COLOR_ATTACHMENT0);
- const PixelShaderOutputVariable &outputVariable = GetOutputAtLocation(outputVariables, location);
+ const PixelShaderOutputVariable *outputVariable = FindOutputAtLocation(outputVariables, location);
- declarationHLSL += " " + HLSLTypeString(outputVariable.type) + " " + outputVariable.name +
- " : " + targetSemantic + Str(layoutIndex) + ";\n";
+ // OpenGL ES 3.0 spec $4.2.1
+ // If [...] not all user-defined output variables are written, the values of fragment colors
+ // corresponding to unwritten variables are similarly undefined.
+ if (outputVariable)
+ {
+ declarationHLSL += " " + HLSLTypeString(outputVariable->type) + " " + outputVariable->name +
+ " : " + targetSemantic + Str(layoutIndex) + ";\n";
- copyHLSL += " output." + outputVariable.name + " = " + outputVariable.source + ";\n";
+ copyHLSL += " output." + outputVariable->name + " = " + outputVariable->source + ";\n";
+ }
}
}
@@ -543,8 +598,8 @@ struct DynamicHLSL::SemanticInfo
BuiltinInfo glPointSize;
};
-DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord,
- bool pointSize, bool pixelShader) const
+DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool position, bool fragCoord,
+ bool pointCoord, bool pointSize, bool pixelShader) const
{
SemanticInfo info;
bool hlsl4 = (mRenderer->getMajorShaderModel() >= 4);
@@ -565,7 +620,10 @@ DynamicHLSL::SemanticInfo DynamicHLSL::getSemanticInfo(int startRegisters, bool
info.dxPosition.enableSystem("POSITION");
}
- info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
+ if (position)
+ {
+ info.glPosition.enable(varyingSemantic, reservedRegisterIndex++);
+ }
if (fragCoord)
{
@@ -599,10 +657,13 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const
{
std::string linkHLSL = "{\n";
- ASSERT(info.dxPosition.enabled && info.glPosition.enabled);
-
+ ASSERT(info.dxPosition.enabled);
linkHLSL += " float4 dx_Position : " + info.dxPosition.str() + ";\n";
- linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n";
+
+ if (info.glPosition.enabled)
+ {
+ linkHLSL += " float4 gl_Position : " + info.glPosition.str() + ";\n";
+ }
if (info.glFragCoord.enabled)
{
@@ -614,13 +675,14 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const
linkHLSL += " float2 gl_PointCoord : " + info.glPointCoord.str() + ";\n";
}
- linkHLSL += varyingHLSL;
-
if (info.glPointSize.enabled)
{
linkHLSL += " float gl_PointSize : " + info.glPointSize.str() + ";\n";
}
+ // Do this after glPointSize, to potentially combine gl_PointCoord and gl_PointSize into the same register.
+ linkHLSL += varyingHLSL;
+
linkHLSL += "};\n";
return linkHLSL;
@@ -629,10 +691,11 @@ std::string DynamicHLSL::generateVaryingLinkHLSL(const SemanticInfo &info, const
void DynamicHLSL::storeBuiltinLinkedVaryings(const SemanticInfo &info,
std::vector<LinkedVarying> *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.glPosition.enabled)
+ {
+ linkedVaryings->push_back(LinkedVarying("gl_Position", GL_FLOAT_VEC4, 1, info.glPosition.semantic,
+ info.glPosition.index, 1));
+ }
if (info.glFragCoord.enabled)
{
@@ -690,6 +753,7 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
bool usesFragCoord = fragmentShader->mUsesFragCoord;
bool usesPointCoord = fragmentShader->mUsesPointCoord;
bool usesPointSize = vertexShader->mUsesPointSize;
+ bool useInstancedPointSpriteEmulation = usesPointSize && mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
if (usesFragColor && usesFragData)
{
@@ -707,6 +771,11 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
const bool broadcast = (fragmentShader->mUsesFragColor && data.clientVersion < 3);
const unsigned int numRenderTargets = (broadcast || usesMRT ? data.caps->maxDrawBuffers : 1);
+ // gl_Position only needs to be outputted from the vertex shader if transform feedback is active.
+ // This isn't supported on D3D11 Feature Level 9_3, so we don't output gl_Position from the vertex shader in this case.
+ // This saves us 1 output vector.
+ bool outputPositionFromVS = !(shaderModel >= 4 && mRenderer->getShaderModelSuffix() != "");
+
int shaderVersion = vertexShader->getShaderVersion();
if (static_cast<GLuint>(registersNeeded) > data.caps->maxVaryingVectors)
@@ -716,12 +785,29 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
}
const std::string &varyingHLSL = generateVaryingHLSL(vertexShader);
- const SemanticInfo &vertexSemantics = getSemanticInfo(registers, usesFragCoord,
- false, usesPointSize, false);
+
+ // Instanced PointSprite emulation requires that gl_PointCoord is present in the vertex shader VS_OUTPUT
+ // structure to ensure compatibility with the generated PS_INPUT of the pixel shader.
+ // GeometryShader PointSprite emulation does not require this additional entry because the
+ // GS_OUTPUT of the Geometry shader contains the pointCoord value and already matches the PS_INPUT of the
+ // generated pixel shader.
+ // The Geometry Shader point sprite implementation needs gl_PointSize to be in VS_OUTPUT and GS_INPUT.
+ // Instanced point sprites doesn't need gl_PointSize in VS_OUTPUT.
+ const SemanticInfo &vertexSemantics = getSemanticInfo(registers, outputPositionFromVS,
+ usesFragCoord, (useInstancedPointSpriteEmulation && usesPointCoord),
+ (!useInstancedPointSpriteEmulation && usesPointSize), false);
storeUserLinkedVaryings(vertexShader, linkedVaryings);
storeBuiltinLinkedVaryings(vertexSemantics, linkedVaryings);
+ // Instanced PointSprite emulation requires additional entries originally generated in the
+ // GeometryShader HLSL. These include pointsize clamp values.
+ if (useInstancedPointSpriteEmulation)
+ {
+ vertexHLSL += "static float minPointSize = " + Str((int)mRenderer->getRendererCaps().minAliasedPointSize) + ".0f;\n"
+ "static float maxPointSize = " + Str((int)mRenderer->getRendererCaps().maxAliasedPointSize) + ".0f;\n";
+ }
+
// Add stub string to be replaced when shader is dynamically defined by its layout
vertexHLSL += "\n" + VERTEX_ATTRIBUTE_STUB_STRING + "\n"
"struct VS_OUTPUT\n" + generateVaryingLinkHLSL(vertexSemantics, varyingHLSL) + "\n"
@@ -729,32 +815,40 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
"{\n"
" initAttributes(input);\n";
- if (shaderModel >= 4)
+ if (vertexShader->usesDeferredInit())
{
vertexHLSL += "\n"
- " gl_main();\n"
- "\n"
- " VS_OUTPUT output;\n"
- " output.gl_Position = gl_Position;\n"
- " output.dx_Position.x = gl_Position.x;\n"
+ " initializeDeferredGlobals();\n";
+ }
+
+ vertexHLSL += "\n"
+ " gl_main();\n"
+ "\n"
+ " VS_OUTPUT output;\n";
+
+ if (outputPositionFromVS)
+ {
+ vertexHLSL += " output.gl_Position = gl_Position;\n";
+ }
+
+ // On D3D9 or D3D11 Feature Level 9, we need to emulate large viewports using dx_ViewAdjust.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
+ {
+ vertexHLSL += " output.dx_Position.x = gl_Position.x;\n"
" output.dx_Position.y = -gl_Position.y;\n"
" output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.dx_Position.w = gl_Position.w;\n";
}
else
{
- vertexHLSL += "\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"
+ vertexHLSL += " output.dx_Position.x = gl_Position.x * dx_ViewAdjust.z + dx_ViewAdjust.x * gl_Position.w;\n"
" output.dx_Position.y = -(gl_Position.y * dx_ViewAdjust.w + dx_ViewAdjust.y * gl_Position.w);\n"
" output.dx_Position.z = (gl_Position.z + gl_Position.w) * 0.5;\n"
" output.dx_Position.w = gl_Position.w;\n";
}
- if (usesPointSize && shaderModel >= 3)
+ // We don't need to output gl_PointSize if we use are emulating point sprites via instancing.
+ if (usesPointSize && shaderModel >= 3 && !useInstancedPointSpriteEmulation)
{
vertexHLSL += " output.gl_PointSize = gl_PointSize;\n";
}
@@ -797,12 +891,27 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
}
}
+ // Instanced PointSprite emulation requires additional entries to calculate
+ // the final output vertex positions of the quad that represents each sprite.
+ if (useInstancedPointSpriteEmulation)
+ {
+ vertexHLSL += "\n"
+ " gl_PointSize = clamp(gl_PointSize, minPointSize, maxPointSize);\n"
+ " output.dx_Position.xyz += float3(input.spriteVertexPos.x * gl_PointSize / (dx_ViewCoords.x*2), input.spriteVertexPos.y * gl_PointSize / (dx_ViewCoords.y*2), input.spriteVertexPos.z) * output.dx_Position.w;\n";
+
+ if (usesPointCoord)
+ {
+ vertexHLSL += "\n"
+ " output.gl_PointCoord = input.spriteTexCoord;\n";
+ }
+ }
+
vertexHLSL += "\n"
" return output;\n"
"}\n";
- const SemanticInfo &pixelSemantics = getSemanticInfo(registers, usesFragCoord, usesPointCoord,
- usesPointSize, true);
+ const SemanticInfo &pixelSemantics = getSemanticInfo(registers, outputPositionFromVS, usesFragCoord, usesPointCoord,
+ (!useInstancedPointSpriteEmulation && usesPointSize), true);
pixelHLSL += "struct PS_INPUT\n" + generateVaryingLinkHLSL(pixelSemantics, varyingHLSL) + "\n";
@@ -872,12 +981,14 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
{
pixelHLSL += " float rhw = 1.0 / input.gl_FragCoord.w;\n";
- if (shaderModel >= 4)
+ // Certain Shader Models (4_0+ and 3_0) allow reading from dx_Position in the pixel shader.
+ // Other Shader Models (4_0_level_9_3 and 2_x) don't support this, so we emulate it using dx_ViewCoords.
+ if (shaderModel >= 4 && mRenderer->getShaderModelSuffix() == "")
{
pixelHLSL += " gl_FragCoord.x = input.dx_Position.x;\n"
" gl_FragCoord.y = input.dx_Position.y;\n";
}
- else if (shaderModel >= 3)
+ 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";
@@ -961,6 +1072,12 @@ bool DynamicHLSL::generateShaderLinkHLSL(const gl::Data &data, InfoLog &infoLog,
}
}
+ if (fragmentShader->usesDeferredInit())
+ {
+ pixelHLSL += "\n"
+ " initializeDeferredGlobals();\n";
+ }
+
pixelHLSL += "\n"
" gl_main();\n"
"\n"
@@ -1013,9 +1130,9 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragm
std::string geomHLSL;
- const SemanticInfo &inSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
+ const SemanticInfo &inSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
false, true, false);
- const SemanticInfo &outSemantics = getSemanticInfo(registers, fragmentShader->mUsesFragCoord,
+ const SemanticInfo &outSemantics = getSemanticInfo(registers, true, fragmentShader->mUsesFragCoord,
fragmentShader->mUsesPointCoord, true, false);
std::string varyingHLSL = generateVaryingHLSL(vertexShader);
@@ -1028,31 +1145,31 @@ std::string DynamicHLSL::generatePointSpriteHLSL(int registers, ShaderD3D *fragm
"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<GS_OUTPUT> 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";
+ "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<GS_OUTPUT> 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++)
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
index c46bbf6ce0..26ae13b342 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/DynamicHLSL.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DynamicHLSL.h
@@ -6,11 +6,11 @@
// DynamicHLSL.h: Interface for link and run-time HLSL generation
//
-#ifndef LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
-#define LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
+#ifndef LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
+#define LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
#include "common/angleutils.h"
-#include "libGLESv2/Constants.h"
+#include "libANGLE/Constants.h"
#include "angle_gl.h"
@@ -49,7 +49,7 @@ struct PixelShaderOutputVariable
size_t outputIndex;
};
-class DynamicHLSL
+class DynamicHLSL : angle::NonCopyable
{
public:
explicit DynamicHLSL(RendererD3D *const renderer);
@@ -74,15 +74,13 @@ class DynamicHLSL
void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
private:
- DISALLOW_COPY_AND_ASSIGN(DynamicHLSL);
-
RendererD3D *const mRenderer;
struct SemanticInfo;
std::string getVaryingSemantic(bool pointSize) const;
- SemanticInfo getSemanticInfo(int startRegisters, bool fragCoord, bool pointCoord, bool pointSize,
- bool pixelShader) const;
+ SemanticInfo getSemanticInfo(int startRegisters, bool position, bool fragCoord, bool pointCoord,
+ bool pointSize, bool pixelShader) const;
std::string generateVaryingLinkHLSL(const SemanticInfo &info, const std::string &varyingHLSL) const;
std::string generateVaryingHLSL(const ShaderD3D *shader) const;
void storeUserLinkedVaryings(const ShaderD3D *vertexShader, std::vector<gl::LinkedVarying> *linkedVaryings) const;
@@ -98,4 +96,4 @@ class DynamicHLSL
}
-#endif // LIBGLESV2_RENDERER_DYNAMIC_HLSL_H_
+#endif // LIBANGLE_RENDERER_D3D_DYNAMICHLSL_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
new file mode 100644
index 0000000000..1a4734b269
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.cpp
@@ -0,0 +1,463 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferD3D.cpp: Implements the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+
+namespace rx
+{
+
+namespace
+{
+
+ClearParameters GetClearParameters(const gl::State &state, GLbitfield mask)
+{
+ ClearParameters clearParams;
+ memset(&clearParams, 0, sizeof(ClearParameters));
+
+ const auto &blendState = state.getBlendState();
+
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = false;
+ }
+ clearParams.colorFClearValue = state.getColorClearValue();
+ clearParams.colorClearType = GL_FLOAT;
+ clearParams.colorMaskRed = blendState.colorMaskRed;
+ clearParams.colorMaskGreen = blendState.colorMaskGreen;
+ clearParams.colorMaskBlue = blendState.colorMaskBlue;
+ clearParams.colorMaskAlpha = blendState.colorMaskAlpha;
+ clearParams.clearDepth = false;
+ clearParams.depthClearValue = state.getDepthClearValue();
+ clearParams.clearStencil = false;
+ clearParams.stencilClearValue = state.getStencilClearValue();
+ clearParams.stencilWriteMask = state.getDepthStencilState().stencilWritemask;
+ clearParams.scissorEnabled = state.isScissorTestEnabled();
+ clearParams.scissor = state.getScissor();
+
+ const gl::Framebuffer *framebufferObject = state.getDrawFramebuffer();
+ if (mask & GL_COLOR_BUFFER_BIT)
+ {
+ if (framebufferObject->hasEnabledColorAttachment())
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = true;
+ }
+ }
+ }
+
+ if (mask & GL_DEPTH_BUFFER_BIT)
+ {
+ if (state.getDepthStencilState().depthMask && framebufferObject->getDepthbuffer() != NULL)
+ {
+ clearParams.clearDepth = true;
+ }
+ }
+
+ if (mask & GL_STENCIL_BUFFER_BIT)
+ {
+ if (framebufferObject->getStencilbuffer() != NULL &&
+ framebufferObject->getStencilbuffer()->getStencilSize() > 0)
+ {
+ clearParams.clearStencil = true;
+ }
+ }
+
+ return clearParams;
+}
+
+}
+
+FramebufferD3D::FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer)
+ : FramebufferImpl(data),
+ mRenderer(renderer),
+ mColorAttachmentsForRender(mData.mColorAttachments.size(), nullptr),
+ mInvalidateColorAttachmentCache(true)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+FramebufferD3D::~FramebufferD3D()
+{
+}
+
+void FramebufferD3D::setColorAttachment(size_t, const gl::FramebufferAttachment *)
+{
+ mInvalidateColorAttachmentCache = true;
+}
+
+void FramebufferD3D::setDepthAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setStencilAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setDepthStencilAttachment(const gl::FramebufferAttachment *)
+{
+}
+
+void FramebufferD3D::setDrawBuffers(size_t, const GLenum *)
+{
+ mInvalidateColorAttachmentCache = true;
+}
+
+void FramebufferD3D::setReadBuffer(GLenum)
+{
+}
+
+gl::Error FramebufferD3D::invalidate(size_t, const GLenum *)
+{
+ // No-op in D3D
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FramebufferD3D::invalidateSub(size_t, const GLenum *, const gl::Rectangle &)
+{
+ // No-op in D3D
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error FramebufferD3D::clear(const gl::Data &data, GLbitfield mask)
+{
+ const gl::State &state = *data.state;
+ ClearParameters clearParams = GetClearParameters(state, mask);
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values)
+{
+ // glClearBufferfv can be called to clear the color buffer or depth buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_FLOAT;
+ }
+
+ if (buffer == GL_DEPTH)
+ {
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = values[0];
+ }
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values)
+{
+ // glClearBufferuiv can only be called to clear a color buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_UNSIGNED_INT;
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values)
+{
+ // glClearBufferiv can be called to clear the color buffer or stencil buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+
+ if (buffer == GL_COLOR)
+ {
+ for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
+ {
+ clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
+ }
+ clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
+ clearParams.colorClearType = GL_INT;
+ }
+
+ if (buffer == GL_STENCIL)
+ {
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = values[1];
+ }
+
+ return clear(state, clearParams);
+}
+
+gl::Error FramebufferD3D::clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ // glClearBufferfi can only be called to clear a depth stencil buffer
+ ClearParameters clearParams = GetClearParameters(state, 0);
+ clearParams.clearDepth = true;
+ clearParams.depthClearValue = depth;
+ clearParams.clearStencil = true;
+ clearParams.stencilClearValue = stencil;
+
+ return clear(state, clearParams);
+}
+
+GLenum FramebufferD3D::getImplementationColorReadFormat() const
+{
+ const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.format;
+}
+
+GLenum FramebufferD3D::getImplementationColorReadType() const
+{
+ const gl::FramebufferAttachment *readAttachment = mData.getReadAttachment();
+
+ if (readAttachment == nullptr)
+ {
+ return GL_NONE;
+ }
+
+ RenderTargetD3D *attachmentRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readAttachment, &attachmentRenderTarget);
+ if (error.isError())
+ {
+ return GL_NONE;
+ }
+
+ GLenum implementationFormat = getRenderTargetImplementationFormat(attachmentRenderTarget);
+ const gl::InternalFormat &implementationFormatInfo = gl::GetInternalFormatInfo(implementationFormat);
+
+ return implementationFormatInfo.type;
+}
+
+gl::Error FramebufferD3D::readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const
+{
+ const gl::PixelPackState &packState = state.getPackState();
+
+ if (packState.rowLength != 0 || packState.skipRows != 0 || packState.skipPixels != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "invalid pixel store parameters in readPixels");
+ }
+
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
+ const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
+ GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, area.width, packState.alignment, 0);
+
+ return readPixels(area, format, type, outputPitch, packState, reinterpret_cast<uint8_t*>(pixels));
+}
+
+gl::Error FramebufferD3D::blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer)
+{
+ bool blitRenderTarget = false;
+ if ((mask & GL_COLOR_BUFFER_BIT) &&
+ sourceFramebuffer->getReadColorbuffer() != nullptr &&
+ mData.getFirstColorAttachment() != nullptr)
+ {
+ blitRenderTarget = true;
+ }
+
+ bool blitStencil = false;
+ if ((mask & GL_STENCIL_BUFFER_BIT) &&
+ sourceFramebuffer->getStencilbuffer() != nullptr &&
+ mData.mStencilAttachment != nullptr)
+ {
+ blitStencil = true;
+ }
+
+ bool blitDepth = false;
+ if ((mask & GL_DEPTH_BUFFER_BIT) &&
+ sourceFramebuffer->getDepthbuffer() != nullptr &&
+ mData.mDepthAttachment != nullptr)
+ {
+ blitDepth = true;
+ }
+
+ if (blitRenderTarget || blitDepth || blitStencil)
+ {
+ const gl::Rectangle *scissor = state.isScissorTestEnabled() ? &state.getScissor() : NULL;
+ gl::Error error = blit(sourceArea, destArea, scissor, blitRenderTarget, blitDepth, blitStencil,
+ filter, sourceFramebuffer);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum FramebufferD3D::checkStatus() const
+{
+ // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
+ for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
+ {
+ const gl::FramebufferAttachment *attachment = mData.mColorAttachments[colorAttachment];
+ if (attachment != nullptr)
+ {
+ for (size_t prevColorAttachment = 0; prevColorAttachment < colorAttachment; prevColorAttachment++)
+ {
+ const gl::FramebufferAttachment *prevAttachment = mData.mColorAttachments[prevColorAttachment];
+ if (prevAttachment != nullptr &&
+ (attachment->id() == prevAttachment->id() &&
+ attachment->type() == prevAttachment->type()))
+ {
+ return GL_FRAMEBUFFER_UNSUPPORTED;
+ }
+ }
+ }
+ }
+
+ return GL_FRAMEBUFFER_COMPLETE;
+}
+
+const gl::AttachmentList &FramebufferD3D::getColorAttachmentsForRender(const Workarounds &workarounds) const
+{
+ if (!workarounds.mrtPerfWorkaround)
+ {
+ return mData.mColorAttachments;
+ }
+
+ if (!mInvalidateColorAttachmentCache)
+ {
+ return mColorAttachmentsForRender;
+ }
+
+ // Does not actually free memory
+ mColorAttachmentsForRender.clear();
+
+ for (size_t attachmentIndex = 0; attachmentIndex < mData.mColorAttachments.size(); ++attachmentIndex)
+ {
+ GLenum drawBufferState = mData.mDrawBufferStates[attachmentIndex];
+ gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[attachmentIndex];
+
+ if (colorAttachment != nullptr && drawBufferState != GL_NONE)
+ {
+ ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + attachmentIndex));
+ mColorAttachmentsForRender.push_back(colorAttachment);
+ }
+ }
+
+ mInvalidateColorAttachmentCache = false;
+ return mColorAttachmentsForRender;
+}
+
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT)
+{
+ if (attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTarget(*index, outRT);
+ }
+ else if (attachment->type() == GL_RENDERBUFFER)
+ {
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+ RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+ *outRT = renderbufferD3D->getRenderTarget();
+ return gl::Error(GL_NO_ERROR);
+ }
+ else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
+ const egl::Surface *surface = defaultAttachment->getSurface();
+ ASSERT(surface);
+ const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ if (defaultAttachment->getBinding() == GL_BACK)
+ {
+ *outRT = surfaceD3D->getSwapChain()->getColorRenderTarget();
+ }
+ else
+ {
+ *outRT = surfaceD3D->getSwapChain()->getDepthStencilRenderTarget();
+ }
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ UNREACHABLE();
+ return gl::Error(GL_INVALID_OPERATION);
+ }
+}
+
+// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
+unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment)
+{
+ if (attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+ ASSERT(texture);
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+ const gl::ImageIndex *index = attachment->getTextureImageIndex();
+ ASSERT(index);
+ return textureD3D->getRenderTargetSerial(*index);
+ }
+ else if (attachment->type() == GL_RENDERBUFFER)
+ {
+ gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
+ ASSERT(renderbuffer);
+ RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
+ return renderbufferD3D->getRenderTargetSerial();
+ }
+ else if (attachment->type() == GL_FRAMEBUFFER_DEFAULT)
+ {
+ const gl::DefaultAttachment *defaultAttachment = static_cast<const gl::DefaultAttachment *>(attachment);
+ const egl::Surface *surface = defaultAttachment->getSurface();
+ ASSERT(surface);
+ const SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ if (defaultAttachment->getBinding() == GL_BACK)
+ {
+ return surfaceD3D->getSwapChain()->getColorRenderTarget()->getSerial();
+ }
+ else
+ {
+ return surfaceD3D->getSwapChain()->getDepthStencilRenderTarget()->getSerial();
+ }
+ }
+ else
+ {
+ UNREACHABLE();
+ return 0;
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
new file mode 100644
index 0000000000..d5d2dae8bd
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/FramebufferD3D.h
@@ -0,0 +1,111 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// FramebufferD3D.h: Defines the DefaultAttachmentD3D and FramebufferD3D classes.
+
+#ifndef LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
+
+#include <vector>
+#include <cstdint>
+
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/FramebufferImpl.h"
+
+namespace gl
+{
+class FramebufferAttachment;
+struct PixelPackState;
+}
+
+namespace rx
+{
+class RenderTargetD3D;
+class RendererD3D;
+
+struct ClearParameters
+{
+ bool clearColor[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ gl::ColorF colorFClearValue;
+ gl::ColorI colorIClearValue;
+ gl::ColorUI colorUIClearValue;
+ GLenum colorClearType;
+ bool colorMaskRed;
+ bool colorMaskGreen;
+ bool colorMaskBlue;
+ bool colorMaskAlpha;
+
+ bool clearDepth;
+ float depthClearValue;
+
+ bool clearStencil;
+ GLint stencilClearValue;
+ GLuint stencilWriteMask;
+
+ bool scissorEnabled;
+ gl::Rectangle scissor;
+};
+
+class FramebufferD3D : public FramebufferImpl
+{
+ public:
+ FramebufferD3D(const gl::Framebuffer::Data &data, RendererD3D *renderer);
+ virtual ~FramebufferD3D();
+
+ void setColorAttachment(size_t index, const gl::FramebufferAttachment *attachment) override;
+ void setDepthAttachment(const gl::FramebufferAttachment *attachment) override;
+ void setStencilAttachment(const gl::FramebufferAttachment *attachment) override;
+ void setDepthStencilAttachment(const gl::FramebufferAttachment *attachment) override;
+
+ void setDrawBuffers(size_t count, const GLenum *buffers) override;
+ void setReadBuffer(GLenum buffer) override;
+
+ gl::Error invalidate(size_t count, const GLenum *attachments) override;
+ gl::Error invalidateSub(size_t count, const GLenum *attachments, const gl::Rectangle &area) override;
+
+ gl::Error clear(const gl::Data &data, GLbitfield mask) override;
+ gl::Error clearBufferfv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLfloat *values) override;
+ gl::Error clearBufferuiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLuint *values) override;
+ gl::Error clearBufferiv(const gl::State &state, GLenum buffer, GLint drawbuffer, const GLint *values) override;
+ gl::Error clearBufferfi(const gl::State &state, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
+
+ GLenum getImplementationColorReadFormat() const override;
+ GLenum getImplementationColorReadType() const override;
+ gl::Error readPixels(const gl::State &state, const gl::Rectangle &area, GLenum format, GLenum type, GLvoid *pixels) const override;
+
+ gl::Error blit(const gl::State &state, const gl::Rectangle &sourceArea, const gl::Rectangle &destArea,
+ GLbitfield mask, GLenum filter, const gl::Framebuffer *sourceFramebuffer) override;
+
+ GLenum checkStatus() const override;
+
+ const gl::AttachmentList &getColorAttachmentsForRender(const Workarounds &workarounds) const;
+
+ protected:
+ // Cache variable
+ mutable gl::AttachmentList mColorAttachmentsForRender;
+ mutable bool mInvalidateColorAttachmentCache;
+
+ private:
+ RendererD3D *const mRenderer;
+
+ virtual gl::Error clear(const gl::State &state, const ClearParameters &clearParams) = 0;
+
+ virtual gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
+ const gl::PixelPackState &pack, uint8_t *pixels) const = 0;
+
+ virtual gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
+ bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) = 0;
+
+ virtual GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const = 0;
+};
+
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTargetD3D **outRT);
+unsigned int GetAttachmentSerial(const gl::FramebufferAttachment *attachment);
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_FRAMBUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
index 776d92b202..8961a36ec5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
@@ -4,22 +4,17 @@
// found in the LICENSE file.
//
-#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/features.h"
-#include "common/features.h"
#include "common/utilities.h"
+#include "third_party/trace_event/trace_event.h"
+
#ifndef QT_D3DCOMPILER_DLL
#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
#endif
-#ifndef D3DCOMPILE_RESERVED16
-#define D3DCOMPILE_RESERVED16 (1 << 16)
-#endif
-#ifndef D3DCOMPILE_RESERVED17
-#define D3DCOMPILE_RESERVED17 (1 << 17)
-#endif
// Definitions local to the translation unit
namespace
@@ -31,6 +26,15 @@ namespace
#define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
+#if defined(ANGLE_MINGW32_COMPAT)
+#ifndef D3DCOMPILE_RESERVED16
+#define D3DCOMPILE_RESERVED16 0x10000
+#endif
+#ifndef D3DCOMPILE_RESERVED17
+#define D3DCOMPILE_RESERVED17 0x20000
+#endif
+#endif
+
struct CompilerFlagInfo
{
UINT mFlag;
@@ -128,6 +132,7 @@ HLSLCompiler::~HLSLCompiler()
bool HLSLCompiler::initialize()
{
+ TRACE_EVENT0("gpu", "initializeCompiler");
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
#if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
// Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
@@ -151,8 +156,6 @@ bool HLSLCompiler::initialize()
defaultCompiler,
L"d3dcompiler_47.dll",
L"d3dcompiler_46.dll",
- L"d3dcompiler_45.dll",
- L"d3dcompiler_44.dll",
L"d3dcompiler_43.dll",
0
};
@@ -215,7 +218,7 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
ASSERT(mD3DCompileFunc);
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- if (gl::perfActive())
+ if (gl::DebugAnnotationsActive())
{
std::string sourcePath = getTempPath();
std::string sourceText = FormatString("#line 2 \"%s\"\n\n%s", sourcePath.c_str(), hlsl.c_str());
@@ -242,7 +245,11 @@ gl::Error HLSLCompiler::compileToBinary(gl::InfoLog &infoLog, const std::string
TRACE("\n%s", hlsl.c_str());
TRACE("\n%s", message.c_str());
- if (message.find("error X3531:") != std::string::npos) // "can't unroll loops marked with loop attribute"
+ if (message.find("error X3531:") != std::string::npos || // "can't unroll loops marked with loop attribute"
+ message.find("error X4014:") != std::string::npos) // "cannot have gradient operations inside loops with divergent flow control",
+ // even though it is counter-intuitive to disable unrolling for this error,
+ // some very long shaders have trouble deciding which loops to unroll and
+ // turning off forced unrolls allows them to compile properly.
{
macros = NULL; // Disable [loop] and [flatten]
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
index ff56f8035a..a824952553 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.h
@@ -1,7 +1,7 @@
-#ifndef LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
-#define LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+#ifndef LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
+#define LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include "common/angleutils.h"
#include "common/platform.h"
@@ -26,7 +26,7 @@ struct CompileConfig
CompileConfig(UINT flags, const std::string &name);
};
-class HLSLCompiler
+class HLSLCompiler : angle::NonCopyable
{
public:
HLSLCompiler();
@@ -44,8 +44,6 @@ class HLSLCompiler
std::string disassembleBinary(ID3DBlob* shaderBinary) const;
private:
- DISALLOW_COPY_AND_ASSIGN(HLSLCompiler);
-
HMODULE mD3DCompilerModule;
pD3DCompile mD3DCompileFunc;
pD3DDisassemble mD3DDisassembleFunc;
@@ -53,4 +51,4 @@ class HLSLCompiler
}
-#endif // LIBGLESV2_RENDERER_HLSL_D3DCOMPILER_H_
+#endif // LIBANGLE_RENDERER_D3D_HLSLCOMPILER_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
new file mode 100644
index 0000000000..4e6f61150a
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.cpp
@@ -0,0 +1,47 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Image.h: Implements the rx::Image class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+namespace rx
+{
+
+ImageD3D::ImageD3D()
+ : mWidth(0),
+ mHeight(0),
+ mDepth(0),
+ mInternalFormat(GL_NONE),
+ mTarget(GL_NONE),
+ mRenderable(false),
+ mDirty(false)
+{
+}
+
+gl::Error ImageD3D::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source)
+{
+ gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
+ ASSERT(colorbuffer);
+
+ RenderTargetD3D *renderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ASSERT(renderTarget);
+ return copy(destOffset, sourceArea, renderTarget);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h
new file mode 100644
index 0000000000..0fe88a8f59
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ImageD3D.h
@@ -0,0 +1,84 @@
+//
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ImageD3D.h: Defines the rx::ImageD3D class, an abstract base class for the
+// renderer-specific classes which will define the interface to the underlying
+// surfaces or resources.
+
+#ifndef LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+#define LIBANGLE_RENDERER_D3D_IMAGED3D_H_
+
+#include "common/debug.h"
+
+#include "libANGLE/Error.h"
+
+namespace gl
+{
+class Framebuffer;
+struct ImageIndex;
+struct Box;
+struct Extents;
+struct Offset;
+struct Rectangle;
+struct PixelUnpackState;
+}
+
+namespace rx
+{
+class TextureStorage;
+class RendererD3D;
+class RenderTargetD3D;
+
+class ImageD3D : angle::NonCopyable
+{
+ public:
+ ImageD3D();
+ virtual ~ImageD3D() {};
+
+ GLsizei getWidth() const { return mWidth; }
+ GLsizei getHeight() const { return mHeight; }
+ GLsizei getDepth() const { return mDepth; }
+ GLenum getInternalFormat() const { return mInternalFormat; }
+ GLenum getTarget() const { return mTarget; }
+ bool isRenderableFormat() const { return mRenderable; }
+
+ void markDirty() { mDirty = true; }
+ void markClean() { mDirty = false; }
+ virtual bool isDirty() const = 0;
+
+ virtual bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) = 0;
+
+ virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input) = 0;
+ virtual gl::Error loadCompressedData(const gl::Box &area, const void *input) = 0;
+
+ virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); };
+ virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
+
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea,
+ const gl::ImageIndex &sourceIndex, TextureStorage *source) = 0;
+
+ gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, const gl::Framebuffer *source);
+
+ protected:
+ GLsizei mWidth;
+ GLsizei mHeight;
+ GLsizei mDepth;
+ GLenum mInternalFormat;
+ bool mRenderable;
+ GLenum mTarget;
+
+ bool mDirty;
+
+ private:
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source) = 0;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_IMAGED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
index aa614f6cc4..677b8bb240 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.cpp
@@ -7,8 +7,8 @@
// IndexBuffer.cpp: Defines the abstract IndexBuffer class and IndexBufferInterface
// class with derivations, classes that perform graphics API agnostic index buffer operations.
-#include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace rx
{
@@ -35,9 +35,9 @@ void IndexBuffer::updateSerial()
}
-IndexBufferInterface::IndexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer)
+IndexBufferInterface::IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
{
- mIndexBuffer = renderer->createIndexBuffer();
+ mIndexBuffer = factory->createIndexBuffer();
mDynamic = dynamic;
mWritePosition = 0;
@@ -66,7 +66,7 @@ unsigned int IndexBufferInterface::getSerial() const
return mIndexBuffer->getSerial();
}
-gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void** outMappedMemory, unsigned int *streamOffset)
+gl::Error IndexBufferInterface::mapBuffer(unsigned int size, void **outMappedMemory, unsigned int *streamOffset)
{
// Protect against integer overflow
if (mWritePosition + size < mWritePosition)
@@ -130,7 +130,8 @@ gl::Error IndexBufferInterface::setBufferSize(unsigned int bufferSize, GLenum in
}
}
-StreamingIndexBufferInterface::StreamingIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, true)
+StreamingIndexBufferInterface::StreamingIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, true)
{
}
@@ -165,7 +166,8 @@ gl::Error StreamingIndexBufferInterface::reserveBufferSpace(unsigned int size, G
}
-StaticIndexBufferInterface::StaticIndexBufferInterface(RendererD3D *renderer) : IndexBufferInterface(renderer, false)
+StaticIndexBufferInterface::StaticIndexBufferInterface(BufferFactoryD3D *factory)
+ : IndexBufferInterface(factory, false)
{
}
@@ -191,9 +193,4 @@ gl::Error StaticIndexBufferInterface::reserveBufferSpace(unsigned int size, GLen
}
}
-IndexRangeCache *StaticIndexBufferInterface::getIndexRangeCache()
-{
- return &mIndexRangeCache;
-}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
index a34d30bbf3..36262f1d09 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexBuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexBuffer.h
@@ -7,18 +7,18 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
#include "common/angleutils.h"
-#include "libGLESv2/Error.h"
-#include "libGLESv2/renderer/IndexRangeCache.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/IndexRangeCache.h"
namespace rx
{
-class RendererD3D;
+class BufferFactoryD3D;
-class IndexBuffer
+class IndexBuffer : angle::NonCopyable
{
public:
IndexBuffer();
@@ -41,16 +41,14 @@ class IndexBuffer
void updateSerial();
private:
- DISALLOW_COPY_AND_ASSIGN(IndexBuffer);
-
unsigned int mSerial;
static unsigned int mNextSerial;
};
-class IndexBufferInterface
+class IndexBufferInterface : angle::NonCopyable
{
public:
- IndexBufferInterface(RendererD3D *renderer, bool dynamic);
+ IndexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
virtual ~IndexBufferInterface();
virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) = 0;
@@ -74,11 +72,7 @@ class IndexBufferInterface
gl::Error setBufferSize(unsigned int bufferSize, GLenum indexType);
private:
- DISALLOW_COPY_AND_ASSIGN(IndexBufferInterface);
-
- RendererD3D *const mRenderer;
-
- IndexBuffer* mIndexBuffer;
+ IndexBuffer *mIndexBuffer;
unsigned int mWritePosition;
bool mDynamic;
@@ -87,26 +81,21 @@ class IndexBufferInterface
class StreamingIndexBufferInterface : public IndexBufferInterface
{
public:
- StreamingIndexBufferInterface(RendererD3D *renderer);
+ explicit StreamingIndexBufferInterface(BufferFactoryD3D *factory);
~StreamingIndexBufferInterface();
- virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
+ gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
};
class StaticIndexBufferInterface : public IndexBufferInterface
{
public:
- explicit StaticIndexBufferInterface(RendererD3D *renderer);
+ explicit StaticIndexBufferInterface(BufferFactoryD3D *factory);
~StaticIndexBufferInterface();
- virtual gl::Error reserveBufferSpace(unsigned int size, GLenum indexType);
-
- IndexRangeCache *getIndexRangeCache();
-
- private:
- IndexRangeCache mIndexRangeCache;
+ gl::Error reserveBufferSpace(unsigned int size, GLenum indexType) override;
};
}
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER_H_
+#endif // LIBANGLE_RENDERER_D3D_INDEXBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
index eddd9de887..7dad269435 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.cpp
@@ -7,13 +7,11 @@
// IndexDataManager.cpp: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.
-#include "libGLESv2/renderer/d3d/IndexDataManager.h"
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/IndexBuffer.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/formatutils.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/formatutils.h"
namespace rx
{
@@ -57,10 +55,11 @@ static void ConvertIndices(GLenum sourceType, GLenum destinationType, const void
else UNREACHABLE();
}
-IndexDataManager::IndexDataManager(RendererD3D *renderer)
- : mRenderer(renderer),
- mStreamingBufferShort(NULL),
- mStreamingBufferInt(NULL)
+IndexDataManager::IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass)
+ : mFactory(factory),
+ mRendererClass(rendererClass),
+ mStreamingBufferShort(nullptr),
+ mStreamingBufferInt(nullptr)
{
}
@@ -85,8 +84,10 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
{
offset = static_cast<unsigned int>(reinterpret_cast<uintptr_t>(indices));
- storage = BufferD3D::makeBufferD3D(buffer->getImplementation());
+ storage = GetImplAs<BufferD3D>(buffer);
+ // We'll trust that the compiler will optimize the % below:
+ // the operands are unsigned and the divisor is a constant.
switch (type)
{
case GL_UNSIGNED_BYTE: alignedOffset = (offset % sizeof(GLubyte) == 0); break;
@@ -116,26 +117,18 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
if (directStorage)
{
streamOffset = offset;
-
- if (!buffer->getIndexRangeCache()->findRange(type, offset, count, NULL, NULL))
- {
- buffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, offset);
- }
}
else if (staticBuffer && staticBuffer->getBufferSize() != 0 && staticBuffer->getIndexType() == type && alignedOffset)
{
indexBuffer = staticBuffer;
- if (!staticBuffer->getIndexRangeCache()->findRange(type, offset, count, NULL, &streamOffset))
- {
- streamOffset = (offset / typeInfo.bytes) * gl::GetTypeInfo(destinationIndexType).bytes;
- staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset);
- }
+ // Using bit-shift here is faster than using division.
+ streamOffset = (offset >> typeInfo.bytesShift) << gl::GetTypeInfo(destinationIndexType).bytesShift;
}
// Avoid D3D11's primitive restart index value
// see http://msdn.microsoft.com/en-us/library/windows/desktop/bb205124(v=vs.85).aspx
- if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRenderer->getMajorShaderModel() > 3)
+ if (translated->indexRange.end == 0xFFFF && type == GL_UNSIGNED_SHORT && mRendererClass == RENDERER_D3D11)
{
destinationIndexType = GL_UNSIGNED_INT;
directStorage = false;
@@ -159,7 +152,8 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
if (staticBuffer->getBufferSize() == 0 && alignedOffset)
{
indexBuffer = staticBuffer;
- convertCount = storage->getSize() / typeInfo.bytes;
+ // Using bit-shift here is faster than using division.
+ convertCount = storage->getSize() >> typeInfo.bytesShift;
}
else
{
@@ -170,13 +164,14 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
ASSERT(indexBuffer);
- if (convertCount > std::numeric_limits<unsigned int>::max() / destTypeInfo.bytes)
+ // Using bit-shift here is faster than using division.
+ if (convertCount > (std::numeric_limits<unsigned int>::max() >> destTypeInfo.bytesShift))
{
return gl::Error(GL_OUT_OF_MEMORY, "Reserving %u indices of %u bytes each exceeds the maximum buffer size.",
convertCount, destTypeInfo.bytes);
}
- unsigned int bufferSizeRequired = convertCount * destTypeInfo.bytes;
+ unsigned int bufferSizeRequired = convertCount << destTypeInfo.bytesShift;
error = indexBuffer->reserveBufferSpace(bufferSizeRequired, type);
if (error.isError())
{
@@ -209,21 +204,22 @@ gl::Error IndexDataManager::prepareIndexData(GLenum type, GLsizei count, gl::Buf
if (staticBuffer)
{
- streamOffset = (offset / typeInfo.bytes) * destTypeInfo.bytes;
- staticBuffer->getIndexRangeCache()->addRange(type, offset, count, translated->indexRange, streamOffset);
+ // Using bit-shift here is faster than using division.
+ streamOffset = (offset >> typeInfo.bytesShift) << destTypeInfo.bytesShift;
}
}
translated->storage = directStorage ? storage : NULL;
translated->indexBuffer = indexBuffer ? indexBuffer->getIndexBuffer() : NULL;
translated->serial = directStorage ? storage->getSerial() : indexBuffer->getSerial();
- translated->startIndex = streamOffset / destTypeInfo.bytes;
+ // Using bit-shift here is faster than using division.
+ translated->startIndex = (streamOffset >> destTypeInfo.bytesShift);
translated->startOffset = streamOffset;
translated->indexType = destinationIndexType;
if (storage)
{
- storage->promoteStaticUsage(count * typeInfo.bytes);
+ storage->promoteStaticUsage(count << typeInfo.bytesShift);
}
return gl::Error(GL_NO_ERROR);
@@ -236,7 +232,7 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
{
if (!mStreamingBufferInt)
{
- mStreamingBufferInt = new StreamingIndexBufferInterface(mRenderer);
+ mStreamingBufferInt = new StreamingIndexBufferInterface(mFactory);
gl::Error error = mStreamingBufferInt->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
@@ -254,7 +250,7 @@ gl::Error IndexDataManager::getStreamingIndexBuffer(GLenum destinationIndexType,
if (!mStreamingBufferShort)
{
- mStreamingBufferShort = new StreamingIndexBufferInterface(mRenderer);
+ mStreamingBufferShort = new StreamingIndexBufferInterface(mFactory);
gl::Error error = mStreamingBufferShort->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_SHORT);
if (error.isError())
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
index a1aee1588b..275b3720c5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/IndexDataManager.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/IndexDataManager.h
@@ -7,14 +7,15 @@
// IndexDataManager.h: Defines the IndexDataManager, a class that
// runs the Buffer translation process for index buffers.
-#ifndef LIBGLESV2_INDEXDATAMANAGER_H_
-#define LIBGLESV2_INDEXDATAMANAGER_H_
+#ifndef LIBANGLE_INDEXDATAMANAGER_H_
+#define LIBANGLE_INDEXDATAMANAGER_H_
+
+#include <GLES2/gl2.h>
#include "common/angleutils.h"
#include "common/mathutil.h"
-#include "libGLESv2/Error.h"
-
-#include <GLES2/gl2.h>
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
namespace
{
@@ -47,25 +48,23 @@ struct TranslatedIndexData
unsigned int serial;
};
-class IndexDataManager
+class IndexDataManager : angle::NonCopyable
{
public:
- explicit IndexDataManager(RendererD3D *renderer);
+ explicit IndexDataManager(BufferFactoryD3D *factory, RendererClass rendererClass);
virtual ~IndexDataManager();
gl::Error prepareIndexData(GLenum type, GLsizei count, gl::Buffer *arrayElementBuffer, const GLvoid *indices, TranslatedIndexData *translated);
private:
- gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer);
-
- DISALLOW_COPY_AND_ASSIGN(IndexDataManager);
-
- RendererD3D *const mRenderer;
+ gl::Error getStreamingIndexBuffer(GLenum destinationIndexType, IndexBufferInterface **outBuffer);
+ BufferFactoryD3D *const mFactory;
+ RendererClass mRendererClass;
StreamingIndexBufferInterface *mStreamingBufferShort;
StreamingIndexBufferInterface *mStreamingBufferInt;
};
}
-#endif // LIBGLESV2_INDEXDATAMANAGER_H_
+#endif // LIBANGLE_INDEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
index 75da78110e..9ce9a27cd3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.cpp
@@ -6,19 +6,19 @@
// ProgramD3D.cpp: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
-#include "libGLESv2/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
-#include "common/features.h"
#include "common/utilities.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/ShaderExecutable.h"
-#include "libGLESv2/renderer/d3d/DynamicHLSL.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/features.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
namespace rx
{
@@ -84,10 +84,12 @@ void GetDefaultInputLayoutFromShader(const std::vector<sh::Attribute> &shaderAtt
std::vector<GLenum> GetDefaultOutputLayoutFromShader(const std::vector<PixelShaderOutputVariable> &shaderOutputVars)
{
- std::vector<GLenum> defaultPixelOutput(1);
+ std::vector<GLenum> defaultPixelOutput;
- ASSERT(!shaderOutputVars.empty());
- defaultPixelOutput[0] = GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex;
+ if (!shaderOutputVars.empty())
+ {
+ defaultPixelOutput.push_back(GL_COLOR_ATTACHMENT0 + shaderOutputVars[0].outputIndex);
+ }
return defaultPixelOutput;
}
@@ -102,11 +104,31 @@ bool IsRowMajorLayout(const sh::ShaderVariable &var)
return false;
}
+struct AttributeSorter
+{
+ AttributeSorter(const ProgramImpl::SemanticIndexArray &semanticIndices)
+ : originalIndices(&semanticIndices)
+ {
+ }
+
+ bool operator()(int a, int b)
+ {
+ int indexA = (*originalIndices)[a];
+ int indexB = (*originalIndices)[b];
+
+ if (indexA == -1) return false;
+ if (indexB == -1) return true;
+ return (indexA < indexB);
+ }
+
+ const ProgramImpl::SemanticIndexArray *originalIndices;
+};
+
}
ProgramD3D::VertexExecutable::VertexExecutable(const gl::VertexFormat inputLayout[],
const GLenum signature[],
- ShaderExecutable *shaderExecutable)
+ ShaderExecutableD3D *shaderExecutable)
: mShaderExecutable(shaderExecutable)
{
for (size_t attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
@@ -134,7 +156,7 @@ bool ProgramD3D::VertexExecutable::matchesSignature(const GLenum signature[]) co
return true;
}
-ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable)
+ProgramD3D::PixelExecutable::PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable)
: mOutputSignature(outputSignature),
mShaderExecutable(shaderExecutable)
{
@@ -149,20 +171,22 @@ ProgramD3D::Sampler::Sampler() : active(false), logicalTextureUnit(0), textureTy
{
}
+unsigned int ProgramD3D::mCurrentSerial = 1;
+
ProgramD3D::ProgramD3D(RendererD3D *renderer)
: ProgramImpl(),
mRenderer(renderer),
mDynamicHLSL(NULL),
mGeometryExecutable(NULL),
- mVertexWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
- mPixelWorkarounds(ANGLE_D3D_WORKAROUND_NONE),
mUsesPointSize(false),
mVertexUniformStorage(NULL),
mFragmentUniformStorage(NULL),
mUsedVertexSamplerRange(0),
mUsedPixelSamplerRange(0),
mDirtySamplerMapping(true),
- mShaderVersion(100)
+ mTextureUnitTypesCache(renderer->getRendererCaps().maxCombinedTextureImageUnits),
+ mShaderVersion(100),
+ mSerial(issueSerial())
{
mDynamicHLSL = new DynamicHLSL(renderer);
}
@@ -173,18 +197,6 @@ ProgramD3D::~ProgramD3D()
SafeDelete(mDynamicHLSL);
}
-ProgramD3D *ProgramD3D::makeProgramD3D(ProgramImpl *impl)
-{
- ASSERT(HAS_DYNAMIC_TYPE(ProgramD3D*, impl));
- return static_cast<ProgramD3D*>(impl);
-}
-
-const ProgramD3D *ProgramD3D::makeProgramD3D(const ProgramImpl *impl)
-{
- ASSERT(HAS_DYNAMIC_TYPE(const ProgramD3D*, impl));
- return static_cast<const ProgramD3D*>(impl);
-}
-
bool ProgramD3D::usesPointSpriteEmulation() const
{
return mUsesPointSize && mRenderer->getMajorShaderModel() >= 4;
@@ -192,7 +204,12 @@ bool ProgramD3D::usesPointSpriteEmulation() const
bool ProgramD3D::usesGeometryShader() const
{
- return usesPointSpriteEmulation();
+ return usesPointSpriteEmulation() && !usesInstancedPointSpriteEmulation();
+}
+
+bool ProgramD3D::usesInstancedPointSpriteEmulation() const
+{
+ return mRenderer->getWorkarounds().useInstancedPointSpriteEmulation;
}
GLint ProgramD3D::getSamplerMapping(gl::SamplerType type, unsigned int samplerIndex, const gl::Caps &caps) const
@@ -276,7 +293,7 @@ void ProgramD3D::updateSamplerMapping()
if (targetUniform->dirty)
{
- if (gl::IsSampler(targetUniform->type))
+ if (gl::IsSamplerType(targetUniform->type))
{
int count = targetUniform->elementCount();
GLint (*v)[4] = reinterpret_cast<GLint(*)[4]>(targetUniform->data);
@@ -324,7 +341,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
// DrawArrays and DrawElements will issue the INVALID_OPERATION error.
updateSamplerMapping();
- std::vector<GLenum> textureUnitTypes(caps.maxCombinedTextureImageUnits, GL_NONE);
+ std::fill(mTextureUnitTypesCache.begin(), mTextureUnitTypesCache.end(), GL_NONE);
for (unsigned int i = 0; i < mUsedPixelSamplerRange; ++i)
{
@@ -332,19 +349,19 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
{
unsigned int unit = mSamplersPS[i].logicalTextureUnit;
- if (unit >= textureUnitTypes.size())
+ if (unit >= caps.maxCombinedTextureImageUnits)
{
if (infoLog)
{
- infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
+ infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits);
}
return false;
}
- if (textureUnitTypes[unit] != GL_NONE)
+ if (mTextureUnitTypesCache[unit] != GL_NONE)
{
- if (mSamplersPS[i].textureType != textureUnitTypes[unit])
+ if (mSamplersPS[i].textureType != mTextureUnitTypesCache[unit])
{
if (infoLog)
{
@@ -356,7 +373,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
}
else
{
- textureUnitTypes[unit] = mSamplersPS[i].textureType;
+ mTextureUnitTypesCache[unit] = mSamplersPS[i].textureType;
}
}
}
@@ -367,19 +384,19 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
{
unsigned int unit = mSamplersVS[i].logicalTextureUnit;
- if (unit >= textureUnitTypes.size())
+ if (unit >= caps.maxCombinedTextureImageUnits)
{
if (infoLog)
{
- infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, textureUnitTypes.size());
+ infoLog->append("Sampler uniform (%d) exceeds GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS (%d)", unit, caps.maxCombinedTextureImageUnits);
}
return false;
}
- if (textureUnitTypes[unit] != GL_NONE)
+ if (mTextureUnitTypesCache[unit] != GL_NONE)
{
- if (mSamplersVS[i].textureType != textureUnitTypes[unit])
+ if (mSamplersVS[i].textureType != mTextureUnitTypesCache[unit])
{
if (infoLog)
{
@@ -391,7 +408,7 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
}
else
{
- textureUnitTypes[unit] = mSamplersVS[i].textureType;
+ mTextureUnitTypesCache[unit] = mSamplersVS[i].textureType;
}
}
}
@@ -399,8 +416,15 @@ bool ProgramD3D::validateSamplers(gl::InfoLog *infoLog, const gl::Caps &caps)
return true;
}
-gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
+LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream)
{
+ int compileFlags = stream->readInt<int>();
+ if (compileFlags != ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+ {
+ infoLog.append("Mismatched compilation flags.");
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
+ }
+
stream->readInt(&mShaderVersion);
const unsigned int psSamplerCount = stream->readInt<unsigned int>();
@@ -429,7 +453,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
if (stream->error())
{
infoLog.append("Invalid program binary.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUniforms.resize(uniformCount);
@@ -462,7 +486,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
if (stream->error())
{
infoLog.append("Invalid program binary.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUniformIndex.resize(uniformIndexCount);
@@ -477,7 +501,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
if (stream->error())
{
infoLog.append("Invalid program binary.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUniformBlocks.resize(uniformBlockCount);
@@ -518,9 +542,9 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
}
stream->readString(&mVertexHLSL);
- stream->readInt(&mVertexWorkarounds);
+ stream->readBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->readString(&mPixelHLSL);
- stream->readInt(&mPixelWorkarounds);
+ stream->readBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->readBool(&mUsesFragDepth);
stream->readBool(&mUsesPointSize);
@@ -553,7 +577,7 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
unsigned int vertexShaderSize = stream->readInt<unsigned int>();
const unsigned char *vertexShaderFunction = binary + stream->offset();
- ShaderExecutable *shaderExecutable = NULL;
+ ShaderExecutableD3D *shaderExecutable = NULL;
gl::Error error = mRenderer->loadExecutable(vertexShaderFunction, vertexShaderSize,
SHADER_VERTEX,
mTransformFeedbackLinkedVaryings,
@@ -561,13 +585,13 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
&shaderExecutable);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
if (!shaderExecutable)
{
infoLog.append("Could not create vertex shader.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
// generated converted input layout
@@ -592,20 +616,20 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
const size_t pixelShaderSize = stream->readInt<unsigned int>();
const unsigned char *pixelShaderFunction = binary + stream->offset();
- ShaderExecutable *shaderExecutable = NULL;
+ ShaderExecutableD3D *shaderExecutable = NULL;
gl::Error error = mRenderer->loadExecutable(pixelShaderFunction, pixelShaderSize, SHADER_PIXEL,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
&shaderExecutable);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
if (!shaderExecutable)
{
infoLog.append("Could not create pixel shader.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
// add new binary
@@ -625,13 +649,13 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
&mGeometryExecutable);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
if (!mGeometryExecutable)
{
infoLog.append("Could not create geometry shader.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
stream->skip(geometryShaderSize);
}
@@ -643,16 +667,19 @@ gl::LinkResult ProgramD3D::load(gl::InfoLog &infoLog, gl::BinaryInputStream *str
if (memcmp(&identifier, &binaryIdentifier, sizeof(GUID)) != 0)
{
infoLog.append("Invalid program binary.");
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
initializeUniformStorage();
+ initAttributesByLayout();
- return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
+ return LinkResult(true, gl::Error(GL_NO_ERROR));
}
gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
{
+ stream->writeInt(ANGLE_COMPILE_OPTIMIZATION_LEVEL);
+
stream->writeInt(mShaderVersion);
stream->writeInt(mSamplersPS.size());
@@ -738,9 +765,9 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
}
stream->writeString(mVertexHLSL);
- stream->writeInt(mVertexWorkarounds);
+ stream->writeBytes(reinterpret_cast<unsigned char*>(&mVertexWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->writeString(mPixelHLSL);
- stream->writeInt(mPixelWorkarounds);
+ stream->writeBytes(reinterpret_cast<unsigned char*>(&mPixelWorkarounds), sizeof(D3DCompilerWorkarounds));
stream->writeInt(mUsesFragDepth);
stream->writeInt(mUsesPointSize);
@@ -810,11 +837,12 @@ gl::Error ProgramD3D::save(gl::BinaryOutputStream *stream)
return gl::Error(GL_NO_ERROR);
}
-gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExecutable)
+gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExecutable)
{
- std::vector<GLenum> outputs;
+ mPixelShaderOutputFormatCache.clear();
- const gl::ColorbufferInfo &colorbuffers = fbo->getColorbuffersForRender(mRenderer->getWorkarounds());
+ const FramebufferD3D *fboD3D = GetImplAs<FramebufferD3D>(fbo);
+ const gl::AttachmentList &colorbuffers = fboD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
@@ -822,18 +850,20 @@ gl::Error ProgramD3D::getPixelExecutableForFramebuffer(const gl::Framebuffer *fb
if (colorbuffer)
{
- outputs.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
+ mPixelShaderOutputFormatCache.push_back(colorbuffer->getBinding() == GL_BACK ? GL_COLOR_ATTACHMENT0 : colorbuffer->getBinding());
}
else
{
- outputs.push_back(GL_NONE);
+ mPixelShaderOutputFormatCache.push_back(GL_NONE);
}
}
- return getPixelExecutableForOutputLayout(outputs, outExecutable);
+ return getPixelExecutableForOutputLayout(mPixelShaderOutputFormatCache, outExecutable, nullptr);
}
-gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature, ShaderExecutable **outExectuable)
+gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputSignature,
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
{
for (size_t executableIndex = 0; executableIndex < mPixelExecutables.size(); executableIndex++)
{
@@ -848,9 +878,12 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum
outputSignature);
// Generate new pixel executable
+ ShaderExecutableD3D *pixelExecutable = NULL;
+
gl::InfoLog tempInfoLog;
- ShaderExecutable *pixelExecutable = NULL;
- gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalPixelHLSL, SHADER_PIXEL,
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalPixelHLSL, SHADER_PIXEL,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
mPixelWorkarounds, &pixelExecutable);
@@ -859,22 +892,24 @@ gl::Error ProgramD3D::getPixelExecutableForOutputLayout(const std::vector<GLenum
return error;
}
- if (!pixelExecutable)
+ if (pixelExecutable)
+ {
+ mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
+ }
+ else if (!infoLog)
{
std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
ERR("Error compiling dynamic pixel executable:\n%s\n", &tempCharBuffer[0]);
}
- else
- {
- mPixelExecutables.push_back(new PixelExecutable(outputSignature, pixelExecutable));
- }
*outExectuable = pixelExecutable;
return gl::Error(GL_NO_ERROR);
}
-gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable)
+gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
+ ShaderExecutableD3D **outExectuable,
+ gl::InfoLog *infoLog)
{
GLenum signature[gl::MAX_VERTEX_ATTRIBS];
getInputLayoutSignature(inputLayout, signature);
@@ -892,9 +927,12 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i
std::string finalVertexHLSL = mDynamicHLSL->generateVertexShaderForInputLayout(mVertexHLSL, inputLayout, mShaderAttributes);
// Generate new vertex executable
+ ShaderExecutableD3D *vertexExecutable = NULL;
+
gl::InfoLog tempInfoLog;
- ShaderExecutable *vertexExecutable = NULL;
- gl::Error error = mRenderer->compileToExecutable(tempInfoLog, finalVertexHLSL, SHADER_VERTEX,
+ gl::InfoLog *currentInfoLog = infoLog ? infoLog : &tempInfoLog;
+
+ gl::Error error = mRenderer->compileToExecutable(*currentInfoLog, finalVertexHLSL, SHADER_VERTEX,
mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
mVertexWorkarounds, &vertexExecutable);
@@ -903,42 +941,42 @@ gl::Error ProgramD3D::getVertexExecutableForInputLayout(const gl::VertexFormat i
return error;
}
- if (!vertexExecutable)
+ if (vertexExecutable)
{
- std::vector<char> tempCharBuffer(tempInfoLog.getLength()+3);
- tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
- ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
+ mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
}
- else
+ else if (!infoLog)
{
- mVertexExecutables.push_back(new VertexExecutable(inputLayout, signature, vertexExecutable));
+ std::vector<char> tempCharBuffer(tempInfoLog.getLength() + 3);
+ tempInfoLog.getLog(tempInfoLog.getLength(), NULL, &tempCharBuffer[0]);
+ ERR("Error compiling dynamic vertex executable:\n%s\n", &tempCharBuffer[0]);
}
*outExectuable = vertexExecutable;
return gl::Error(GL_NO_ERROR);
}
-gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
- int registers)
+LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ int registers)
{
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
gl::VertexFormat defaultInputLayout[gl::MAX_VERTEX_ATTRIBS];
GetDefaultInputLayoutFromShader(vertexShader->getActiveAttributes(), defaultInputLayout);
- ShaderExecutable *defaultVertexExecutable = NULL;
- gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable);
+ ShaderExecutableD3D *defaultVertexExecutable = NULL;
+ gl::Error error = getVertexExecutableForInputLayout(defaultInputLayout, &defaultVertexExecutable, &infoLog);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
std::vector<GLenum> defaultPixelOutput = GetDefaultOutputLayoutFromShader(getPixelShaderKey());
- ShaderExecutable *defaultPixelExecutable = NULL;
- error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable);
+ ShaderExecutableD3D *defaultPixelExecutable = NULL;
+ error = getPixelExecutableForOutputLayout(defaultPixelOutput, &defaultPixelExecutable, &infoLog);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
if (usesGeometryShader())
@@ -948,10 +986,10 @@ gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::S
error = mRenderer->compileToExecutable(infoLog, geometryHLSL, SHADER_GEOMETRY, mTransformFeedbackLinkedVaryings,
(mTransformFeedbackBufferMode == GL_SEPARATE_ATTRIBS),
- ANGLE_D3D_WORKAROUND_NONE, &mGeometryExecutable);
+ D3DCompilerWorkarounds(), &mGeometryExecutable);
if (error.isError())
{
- return gl::LinkResult(false, error);
+ return LinkResult(false, error);
}
}
@@ -977,15 +1015,15 @@ gl::LinkResult ProgramD3D::compileProgramExecutables(gl::InfoLog &infoLog, gl::S
#endif
bool linkSuccess = (defaultVertexExecutable && defaultPixelExecutable && (!usesGeometryShader() || mGeometryExecutable));
- return gl::LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
+ return LinkResult(linkSuccess, gl::Error(GL_NO_ERROR));
}
-gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
- gl::Shader *fragmentShader, gl::Shader *vertexShader,
- const std::vector<std::string> &transformFeedbackVaryings,
- GLenum transformFeedbackBufferMode,
- int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
- std::map<int, gl::VariableLocation> *outputVariables)
+LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
+ gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings,
+ GLenum transformFeedbackBufferMode,
+ int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+ std::map<int, gl::VariableLocation> *outputVariables)
{
ShaderD3D *vertexShaderD3D = ShaderD3D::makeShaderD3D(vertexShader->getImplementation());
ShaderD3D *fragmentShaderD3D = ShaderD3D::makeShaderD3D(fragmentShader->getImplementation());
@@ -996,10 +1034,10 @@ gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
mTransformFeedbackBufferMode = transformFeedbackBufferMode;
mPixelHLSL = fragmentShaderD3D->getTranslatedSource();
- mPixelWorkarounds = fragmentShaderD3D->getD3DWorkarounds();
+ fragmentShaderD3D->generateWorkarounds(&mPixelWorkarounds);
mVertexHLSL = vertexShaderD3D->getTranslatedSource();
- mVertexWorkarounds = vertexShaderD3D->getD3DWorkarounds();
+ vertexShaderD3D->generateWorkarounds(&mVertexWorkarounds);
mShaderVersion = vertexShaderD3D->getShaderVersion();
// Map the varyings to the register file
@@ -1008,24 +1046,26 @@ gl::LinkResult ProgramD3D::link(const gl::Data &data, gl::InfoLog &infoLog,
if (*registers < 0)
{
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
- if (!gl::ProgramBinary::linkVaryings(infoLog, fragmentShader, vertexShader))
+ if (!gl::Program::linkVaryings(infoLog, fragmentShader, vertexShader))
{
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
if (!mDynamicHLSL->generateShaderLinkHLSL(data, infoLog, *registers, packing, mPixelHLSL, mVertexHLSL,
fragmentShaderD3D, vertexShaderD3D, transformFeedbackVaryings,
linkedVaryings, outputVariables, &mPixelShaderKey, &mUsesFragDepth))
{
- return gl::LinkResult(false, gl::Error(GL_NO_ERROR));
+ return LinkResult(false, gl::Error(GL_NO_ERROR));
}
mUsesPointSize = vertexShaderD3D->usesPointSize();
- return gl::LinkResult(true, gl::Error(GL_NO_ERROR));
+ initAttributesByLayout();
+
+ return LinkResult(true, gl::Error(GL_NO_ERROR));
}
void ProgramD3D::getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const
@@ -1042,7 +1082,7 @@ void ProgramD3D::initializeUniformStorage()
{
const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
- if (!gl::IsSampler(uniform.type))
+ if (!gl::IsSamplerType(uniform.type))
{
if (uniform.isReferencedByVertexShader())
{
@@ -1077,12 +1117,20 @@ gl::Error ProgramD3D::applyUniforms()
return gl::Error(GL_NO_ERROR);
}
-gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps)
+gl::Error ProgramD3D::applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[])
{
- ASSERT(boundBuffers.size() == mUniformBlocks.size());
+ GLint vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ GLint fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
- const gl::Buffer *vertexUniformBuffers[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS] = {NULL};
- const gl::Buffer *fragmentUniformBuffers[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS] = {NULL};
+ for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; ++registerIndex)
+ {
+ vertexUniformBuffers[registerIndex] = -1;
+ }
+
+ for (unsigned int registerIndex = 0; registerIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; ++registerIndex)
+ {
+ fragmentUniformBuffers[registerIndex] = -1;
+ }
const unsigned int reservedBuffersInVS = mRenderer->getReservedVertexUniformBuffers();
const unsigned int reservedBuffersInFS = mRenderer->getReservedFragmentUniformBuffers();
@@ -1090,15 +1138,9 @@ gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBu
for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < mUniformBlocks.size(); uniformBlockIndex++)
{
gl::UniformBlock *uniformBlock = mUniformBlocks[uniformBlockIndex];
- gl::Buffer *uniformBuffer = boundBuffers[uniformBlockIndex];
+ GLuint blockBinding = uniformBlockBindings[uniformBlockIndex];
- ASSERT(uniformBlock && uniformBuffer);
-
- if (uniformBuffer->getSize() < uniformBlock->dataSize)
- {
- // undefined behaviour
- return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small.");
- }
+ ASSERT(uniformBlock);
// Unnecessary to apply an unreferenced standard or shared UBO
if (!uniformBlock->isReferencedByVertexShader() && !uniformBlock->isReferencedByFragmentShader())
@@ -1109,21 +1151,21 @@ gl::Error ProgramD3D::applyUniformBuffers(const std::vector<gl::Buffer*> boundBu
if (uniformBlock->isReferencedByVertexShader())
{
unsigned int registerIndex = uniformBlock->vsRegisterIndex - reservedBuffersInVS;
- ASSERT(vertexUniformBuffers[registerIndex] == NULL);
- ASSERT(registerIndex < caps.maxVertexUniformBlocks);
- vertexUniformBuffers[registerIndex] = uniformBuffer;
+ ASSERT(vertexUniformBuffers[registerIndex] == -1);
+ ASSERT(registerIndex < data.caps->maxVertexUniformBlocks);
+ vertexUniformBuffers[registerIndex] = blockBinding;
}
if (uniformBlock->isReferencedByFragmentShader())
{
unsigned int registerIndex = uniformBlock->psRegisterIndex - reservedBuffersInFS;
- ASSERT(fragmentUniformBuffers[registerIndex] == NULL);
- ASSERT(registerIndex < caps.maxFragmentUniformBlocks);
- fragmentUniformBuffers[registerIndex] = uniformBuffer;
+ ASSERT(fragmentUniformBuffers[registerIndex] == -1);
+ ASSERT(registerIndex < data.caps->maxFragmentUniformBlocks);
+ fragmentUniformBuffers[registerIndex] = blockBinding;
}
}
- return mRenderer->setUniformBuffers(vertexUniformBuffers, fragmentUniformBuffers);
+ return mRenderer->setUniformBuffers(data, vertexUniformBuffers, fragmentUniformBuffers);
}
bool ProgramD3D::assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
@@ -1308,7 +1350,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
{
const sh::Uniform &vertexUniform = *entry->second;
const std::string &uniformName = "uniform '" + vertexUniform.name + "'";
- if (!gl::ProgramBinary::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
+ if (!gl::Program::linkValidateUniforms(infoLog, uniformName, vertexUniform, fragmentUniform))
{
return false;
}
@@ -1321,7 +1363,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
if (uniform.staticUse)
{
- defineUniformBase(GL_VERTEX_SHADER, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
+ defineUniformBase(vertexShaderD3D, uniform, vertexShaderD3D->getUniformRegister(uniform.name));
}
}
@@ -1331,7 +1373,7 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
if (uniform.staticUse)
{
- defineUniformBase(GL_FRAGMENT_SHADER, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
+ defineUniformBase(fragmentShaderD3D, uniform, fragmentShaderD3D->getUniformRegister(uniform.name));
}
}
@@ -1355,17 +1397,17 @@ bool ProgramD3D::linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShad
return true;
}
-void ProgramD3D::defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister)
+void ProgramD3D::defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister)
{
- ShShaderOutput outputType = ShaderD3D::getCompilerOutputType(shader);
+ ShShaderOutput outputType = shader->getCompilerOutputType();
sh::HLSLBlockEncoder encoder(sh::HLSLBlockEncoder::GetStrategyFor(outputType));
encoder.skipRegisters(uniformRegister);
defineUniform(shader, uniform, uniform.name, &encoder);
}
-void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
- const std::string &fullName, sh::HLSLBlockEncoder *encoder)
+void ProgramD3D::defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform,
+ const std::string &fullName, sh::HLSLBlockEncoder *encoder)
{
if (uniform.isStruct())
{
@@ -1396,30 +1438,28 @@ void ProgramD3D::defineUniform(GLenum shader, const sh::ShaderVariable &uniform,
gl::LinkedUniform *linkedUniform = getUniformByName(fullName);
+ // Advance the uniform offset, to track registers allocation for structs
+ sh::BlockMemberInfo blockInfo = encoder->encodeType(uniform.type, uniform.arraySize, false);
+
if (!linkedUniform)
{
linkedUniform = new gl::LinkedUniform(uniform.type, uniform.precision, fullName, uniform.arraySize,
- -1, sh::BlockMemberInfo::getDefaultBlockInfo());
+ -1, sh::BlockMemberInfo::getDefaultBlockInfo());
ASSERT(linkedUniform);
- linkedUniform->registerElement = encoder->getCurrentElement();
+ linkedUniform->registerElement = sh::HLSLBlockEncoder::getBlockRegisterElement(blockInfo);
mUniforms.push_back(linkedUniform);
}
- ASSERT(linkedUniform->registerElement == encoder->getCurrentElement());
-
- if (shader == GL_FRAGMENT_SHADER)
+ if (shader->getShaderType() == GL_FRAGMENT_SHADER)
{
- linkedUniform->psRegisterIndex = encoder->getCurrentRegister();
+ linkedUniform->psRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
}
- else if (shader == GL_VERTEX_SHADER)
+ else if (shader->getShaderType() == GL_VERTEX_SHADER)
{
- linkedUniform->vsRegisterIndex = encoder->getCurrentRegister();
+ linkedUniform->vsRegisterIndex = sh::HLSLBlockEncoder::getBlockRegister(blockInfo);
}
else UNREACHABLE();
- // Advance the uniform offset, to track registers allocation for structs
- encoder->encodeType(uniform.type, uniform.arraySize, false);
-
// Arrays are treated as aggregate types
if (uniform.isArray())
{
@@ -1488,7 +1528,7 @@ void ProgramD3D::setUniform(GLint location, GLsizei count, const T* v, GLenum ta
}
}
}
- else if (gl::IsSampler(targetUniform->type))
+ else if (gl::IsSamplerType(targetUniform->type))
{
ASSERT(targetUniformType == GL_INT);
@@ -1824,7 +1864,7 @@ bool ProgramD3D::assignSamplers(unsigned int startSamplerIndex,
bool ProgramD3D::indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps)
{
- ASSERT(gl::IsSampler(uniform.type));
+ ASSERT(gl::IsSamplerType(uniform.type));
ASSERT(uniform.vsRegisterIndex != GL_INVALID_INDEX || uniform.psRegisterIndex != GL_INVALID_INDEX);
if (uniform.vsRegisterIndex != GL_INVALID_INDEX)
@@ -1874,7 +1914,7 @@ bool ProgramD3D::indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps)
{
const gl::LinkedUniform &uniform = *mUniforms[uniformIndex];
- if (gl::IsSampler(uniform.type))
+ if (gl::IsSamplerType(uniform.type))
{
if (!indexSamplerUniform(uniform, infoLog, caps))
{
@@ -1902,11 +1942,11 @@ void ProgramD3D::reset()
mTransformFeedbackBufferMode = GL_NONE;
mVertexHLSL.clear();
- mVertexWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
+ mVertexWorkarounds.reset();
mShaderVersion = 100;
mPixelHLSL.clear();
- mPixelWorkarounds = ANGLE_D3D_WORKAROUND_NONE;
+ mPixelWorkarounds.reset();
mUsesFragDepth = false;
mPixelShaderKey.clear();
mUsesPointSize = false;
@@ -1920,6 +1960,46 @@ void ProgramD3D::reset()
mUsedVertexSamplerRange = 0;
mUsedPixelSamplerRange = 0;
mDirtySamplerMapping = true;
+
+ std::fill(mAttributesByLayout, mAttributesByLayout + ArraySize(mAttributesByLayout), -1);
+}
+
+unsigned int ProgramD3D::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int ProgramD3D::issueSerial()
+{
+ return mCurrentSerial++;
+}
+
+void ProgramD3D::initAttributesByLayout()
+{
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mAttributesByLayout[i] = i;
+ }
+
+ std::sort(&mAttributesByLayout[0], &mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS], AttributeSorter(mSemanticIndex));
+}
+
+void ProgramD3D::sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const
+{
+ rx::TranslatedAttribute oldTranslatedAttributes[gl::MAX_VERTEX_ATTRIBS];
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ oldTranslatedAttributes[i] = attributes[i];
+ }
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ int oldIndex = mAttributesByLayout[i];
+ sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
+ attributes[i] = oldTranslatedAttributes[oldIndex];
+ }
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
index 4baab9aa19..6f3eade81d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ProgramD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ProgramD3D.h
@@ -6,11 +6,14 @@
// ProgramD3D.h: Defines the rx::ProgramD3D class which implements rx::ProgramImpl.
-#ifndef LIBGLESV2_RENDERER_PROGRAMD3D_H_
-#define LIBGLESV2_RENDERER_PROGRAMD3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
+#define LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
-#include "libGLESv2/renderer/ProgramImpl.h"
-#include "libGLESv2/renderer/Workarounds.h"
+#include "compiler/translator/blocklayoutHLSL.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/renderer/ProgramImpl.h"
+#include "libANGLE/renderer/Workarounds.h"
+#include "libANGLE/renderer/d3d/DynamicHLSL.h"
#include <string>
#include <vector>
@@ -25,7 +28,14 @@ struct VertexFormat;
namespace rx
{
class RendererD3D;
-class UniformStorage;
+class UniformStorageD3D;
+class ShaderExecutableD3D;
+
+#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
+// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang.
+// It should only be used selectively to work around specific bugs.
+#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
+#endif
class ProgramD3D : public ProgramImpl
{
@@ -33,9 +43,6 @@ class ProgramD3D : public ProgramImpl
ProgramD3D(RendererD3D *renderer);
virtual ~ProgramD3D();
- static ProgramD3D *makeProgramD3D(ProgramImpl *impl);
- static const ProgramD3D *makeProgramD3D(const ProgramImpl *impl);
-
const std::vector<PixelShaderOutputVariable> &getPixelShaderKey() { return mPixelShaderKey; }
int getShaderVersion() const { return mShaderVersion; }
GLenum getTransformFeedbackBufferMode() const { return mTransformFeedbackBufferMode; }
@@ -49,31 +56,32 @@ class ProgramD3D : public ProgramImpl
bool usesPointSize() const { return mUsesPointSize; }
bool usesPointSpriteEmulation() const;
bool usesGeometryShader() const;
+ bool usesInstancedPointSpriteEmulation() const;
GLenum getBinaryFormat() { return GL_PROGRAM_BINARY_ANGLE; }
- gl::LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
+ LinkResult load(gl::InfoLog &infoLog, gl::BinaryInputStream *stream);
gl::Error save(gl::BinaryOutputStream *stream);
- gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutable **outExectuable);
- gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutable **outExectuable);
- gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutable **outExectuable);
- ShaderExecutable *getGeometryExecutable() const { return mGeometryExecutable; }
+ gl::Error getPixelExecutableForFramebuffer(const gl::Framebuffer *fbo, ShaderExecutableD3D **outExectuable);
+ gl::Error getPixelExecutableForOutputLayout(const std::vector<GLenum> &outputLayout, ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
+ gl::Error getVertexExecutableForInputLayout(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS], ShaderExecutableD3D **outExectuable, gl::InfoLog *infoLog);
+ ShaderExecutableD3D *getGeometryExecutable() const { return mGeometryExecutable; }
- gl::LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
- int registers);
+ LinkResult compileProgramExecutables(gl::InfoLog &infoLog, gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ int registers);
- gl::LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
- gl::Shader *fragmentShader, gl::Shader *vertexShader,
- const std::vector<std::string> &transformFeedbackVaryings,
- GLenum transformFeedbackBufferMode,
- int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
- std::map<int, gl::VariableLocation> *outputVariables);
+ LinkResult link(const gl::Data &data, gl::InfoLog &infoLog,
+ gl::Shader *fragmentShader, gl::Shader *vertexShader,
+ const std::vector<std::string> &transformFeedbackVaryings,
+ GLenum transformFeedbackBufferMode,
+ int *registers, std::vector<gl::LinkedVarying> *linkedVaryings,
+ std::map<int, gl::VariableLocation> *outputVariables);
void getInputLayoutSignature(const gl::VertexFormat inputLayout[], GLenum signature[]) const;
void initializeUniformStorage();
gl::Error applyUniforms();
- gl::Error applyUniformBuffers(const std::vector<gl::Buffer*> boundBuffers, const gl::Caps &caps);
+ gl::Error applyUniformBuffers(const gl::Data &data, GLuint uniformBlockBindings[]) override;
bool assignUniformBlockRegister(gl::InfoLog &infoLog, gl::UniformBlock *uniformBlock, GLenum shader,
unsigned int registerIndex, const gl::Caps &caps);
void dirtyAllUniforms();
@@ -104,8 +112,8 @@ class ProgramD3D : public ProgramImpl
void getUniformiv(GLint location, GLint *params);
void getUniformuiv(GLint location, GLuint *params);
- const UniformStorage &getVertexUniformStorage() const { return *mVertexUniformStorage; }
- const UniformStorage &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
+ const UniformStorageD3D &getVertexUniformStorage() const { return *mVertexUniformStorage; }
+ const UniformStorageD3D &getFragmentUniformStorage() const { return *mFragmentUniformStorage; }
bool linkUniforms(gl::InfoLog &infoLog, const gl::Shader &vertexShader, const gl::Shader &fragmentShader,
const gl::Caps &caps);
@@ -113,43 +121,47 @@ class ProgramD3D : public ProgramImpl
void reset();
- private:
- DISALLOW_COPY_AND_ASSIGN(ProgramD3D);
+ unsigned int getSerial() const;
+ void initAttributesByLayout();
+ void sortAttributesByLayout(rx::TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS]) const;
+
+ private:
class VertexExecutable
{
public:
VertexExecutable(const gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS],
const GLenum signature[gl::MAX_VERTEX_ATTRIBS],
- ShaderExecutable *shaderExecutable);
+ ShaderExecutableD3D *shaderExecutable);
~VertexExecutable();
bool matchesSignature(const GLenum convertedLayout[gl::MAX_VERTEX_ATTRIBS]) const;
const gl::VertexFormat *inputs() const { return mInputs; }
const GLenum *signature() const { return mSignature; }
- ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+ ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
private:
gl::VertexFormat mInputs[gl::MAX_VERTEX_ATTRIBS];
GLenum mSignature[gl::MAX_VERTEX_ATTRIBS];
- ShaderExecutable *mShaderExecutable;
+ ShaderExecutableD3D *mShaderExecutable;
};
class PixelExecutable
{
public:
- PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutable *shaderExecutable);
+ PixelExecutable(const std::vector<GLenum> &outputSignature, ShaderExecutableD3D *shaderExecutable);
~PixelExecutable();
bool matchesSignature(const std::vector<GLenum> &signature) const { return mOutputSignature == signature; }
const std::vector<GLenum> &outputSignature() const { return mOutputSignature; }
- ShaderExecutable *shaderExecutable() const { return mShaderExecutable; }
+ ShaderExecutableD3D *shaderExecutable() const { return mShaderExecutable; }
private:
std::vector<GLenum> mOutputSignature;
- ShaderExecutable *mShaderExecutable;
+ ShaderExecutableD3D *mShaderExecutable;
};
struct Sampler
@@ -161,8 +173,8 @@ class ProgramD3D : public ProgramImpl
GLenum textureType;
};
- void defineUniformBase(GLenum shader, const sh::Uniform &uniform, unsigned int uniformRegister);
- void defineUniform(GLenum shader, const sh::ShaderVariable &uniform, const std::string &fullName,
+ void defineUniformBase(const ShaderD3D *shader, const sh::Uniform &uniform, unsigned int uniformRegister);
+ void defineUniform(const ShaderD3D *shader, const sh::ShaderVariable &uniform, const std::string &fullName,
sh::HLSLBlockEncoder *encoder);
bool indexSamplerUniform(const gl::LinkedUniform &uniform, gl::InfoLog &infoLog, const gl::Caps &caps);
bool indexUniforms(gl::InfoLog &infoLog, const gl::Caps &caps);
@@ -188,20 +200,20 @@ class ProgramD3D : public ProgramImpl
std::vector<VertexExecutable *> mVertexExecutables;
std::vector<PixelExecutable *> mPixelExecutables;
- ShaderExecutable *mGeometryExecutable;
+ ShaderExecutableD3D *mGeometryExecutable;
std::string mVertexHLSL;
- D3DWorkaroundType mVertexWorkarounds;
+ D3DCompilerWorkarounds mVertexWorkarounds;
std::string mPixelHLSL;
- D3DWorkaroundType mPixelWorkarounds;
+ D3DCompilerWorkarounds mPixelWorkarounds;
bool mUsesFragDepth;
std::vector<PixelShaderOutputVariable> mPixelShaderKey;
bool mUsesPointSize;
- UniformStorage *mVertexUniformStorage;
- UniformStorage *mFragmentUniformStorage;
+ UniformStorageD3D *mVertexUniformStorage;
+ UniformStorageD3D *mFragmentUniformStorage;
GLenum mTransformFeedbackBufferMode;
@@ -211,9 +223,22 @@ class ProgramD3D : public ProgramImpl
GLuint mUsedPixelSamplerRange;
bool mDirtySamplerMapping;
+ // Cache for validateSamplers
+ std::vector<GLenum> mTextureUnitTypesCache;
+
+ // Cache for getPixelExecutableForFramebuffer
+ std::vector<GLenum> mPixelShaderOutputFormatCache;
+
int mShaderVersion;
+
+ int mAttributesByLayout[gl::MAX_VERTEX_ATTRIBS];
+
+ unsigned int mSerial;
+
+ static unsigned int issueSerial();
+ static unsigned int mCurrentSerial;
};
}
-#endif // LIBGLESV2_RENDERER_PROGRAMD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_PROGRAMD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
new file mode 100644
index 0000000000..84b30aa106
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.cpp: Implements serial handling for rx::RenderTargetD3D
+
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+
+namespace rx
+{
+unsigned int RenderTargetD3D::mCurrentSerial = 1;
+
+RenderTargetD3D::RenderTargetD3D()
+ : mSerial(issueSerials(1))
+{
+}
+
+RenderTargetD3D::~RenderTargetD3D()
+{
+}
+
+unsigned int RenderTargetD3D::getSerial() const
+{
+ return mSerial;
+}
+
+unsigned int RenderTargetD3D::issueSerials(unsigned int count)
+{
+ unsigned int firstSerial = mCurrentSerial;
+ mCurrentSerial += count;
+ return firstSerial;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
new file mode 100644
index 0000000000..fe6afcecae
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderTargetD3D.h
@@ -0,0 +1,42 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderTargetD3D.h: Defines an abstract wrapper class to manage IDirect3DSurface9
+// and ID3D11View objects belonging to renderbuffers and renderable textures.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+
+namespace rx
+{
+
+class RenderTargetD3D : angle::NonCopyable
+{
+ public:
+ RenderTargetD3D();
+ virtual ~RenderTargetD3D();
+
+ virtual GLsizei getWidth() const = 0;
+ virtual GLsizei getHeight() const = 0;
+ virtual GLsizei getDepth() const = 0;
+ virtual GLenum getInternalFormat() const = 0;
+ virtual GLsizei getSamples() const = 0;
+ gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
+
+ virtual unsigned int getSerial() const;
+ static unsigned int issueSerials(unsigned int count);
+
+ private:
+ const unsigned int mSerial;
+ static unsigned int mCurrentSerial;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERTARGETD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
index cb4af367a2..c91fedff06 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp
@@ -7,10 +7,10 @@
// RenderbufferD3d.cpp: Implements the RenderbufferD3D class, a specialization of RenderbufferImpl
-#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
namespace rx
{
@@ -30,7 +30,12 @@ RenderbufferD3D *RenderbufferD3D::makeRenderbufferD3D(RenderbufferImpl *renderbu
return static_cast<RenderbufferD3D*>(renderbuffer);
}
-gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples)
+gl::Error RenderbufferD3D::setStorage(GLenum internalformat, size_t width, size_t height)
+{
+ return setStorageMultisample(0, internalformat, width, height);
+}
+
+gl::Error RenderbufferD3D::setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height)
{
// If the renderbuffer parameters are queried, the calling function
// will expect one of the valid renderbuffer formats for use in
@@ -42,7 +47,7 @@ gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum inte
creationFormat = GL_DEPTH24_STENCIL8_OES;
}
- RenderTarget *newRT = NULL;
+ RenderTargetD3D *newRT = NULL;
gl::Error error = mRenderer->createRenderTarget(width, height, creationFormat, samples, &newRT);
if (error.isError())
{
@@ -55,47 +60,7 @@ gl::Error RenderbufferD3D::setStorage(GLsizei width, GLsizei height, GLenum inte
return gl::Error(GL_NO_ERROR);
}
-gl::Error RenderbufferD3D::setStorage(SwapChain *swapChain, bool depth)
-{
- RenderTarget *newRT = NULL;
- gl::Error error = mRenderer->createRenderTarget(swapChain, depth, &newRT);
- if (error.isError())
- {
- return error;
- }
-
- SafeDelete(mRenderTarget);
- mRenderTarget = newRT;
-
- return gl::Error(GL_NO_ERROR);
-}
-
-GLsizei RenderbufferD3D::getWidth() const
-{
- return (mRenderTarget ? mRenderTarget->getWidth() : 0);
-}
-
-GLsizei RenderbufferD3D::getHeight() const
-{
- return (mRenderTarget ? mRenderTarget->getHeight() : 0);
-}
-
-GLenum RenderbufferD3D::getInternalFormat() const
-{
- return (mRenderTarget ? mRenderTarget->getInternalFormat() : GL_RGBA4);
-}
-
-GLenum RenderbufferD3D::getActualFormat() const
-{
- return (mRenderTarget ? mRenderTarget->getActualFormat() : GL_RGBA4);
-}
-
-GLsizei RenderbufferD3D::getSamples() const
-{
- return (mRenderTarget ? mRenderTarget->getSamples() : 0);
-}
-
-RenderTarget *RenderbufferD3D::getRenderTarget()
+RenderTargetD3D *RenderbufferD3D::getRenderTarget()
{
return mRenderTarget;
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
new file mode 100644
index 0000000000..4c4b998683
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RenderbufferD3D.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl.
+
+#ifndef LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
+
+#include "angle_gl.h"
+
+#include "common/angleutils.h"
+#include "libANGLE/renderer/RenderbufferImpl.h"
+
+namespace rx
+{
+class RendererD3D;
+class RenderTargetD3D;
+class SwapChainD3D;
+
+class RenderbufferD3D : public RenderbufferImpl
+{
+ public:
+ RenderbufferD3D(RendererD3D *renderer);
+ virtual ~RenderbufferD3D();
+
+ static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer);
+
+ virtual gl::Error setStorage(GLenum internalformat, size_t width, size_t height) override;
+ virtual gl::Error setStorageMultisample(size_t samples, GLenum internalformat, size_t width, size_t height) override;
+
+ RenderTargetD3D *getRenderTarget();
+ unsigned int getRenderTargetSerial() const;
+
+ private:
+ RendererD3D *mRenderer;
+ RenderTargetD3D *mRenderTarget;
+};
+}
+
+#endif // LIBANGLE_RENDERER_D3D_RENDERBUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
new file mode 100644
index 0000000000..2ce0ce5a1b
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
@@ -0,0 +1,628 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// RendererD3D.cpp: Implementation of the base D3D Renderer.
+
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+
+#include "common/MemoryBuffer.h"
+#include "common/utilities.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/ResourceManager.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/DisplayD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+
+namespace rx
+{
+
+namespace
+{
+// If we request a scratch buffer requesting a smaller size this many times,
+// release and recreate the scratch buffer. This ensures we don't have a
+// degenerate case where we are stuck hogging memory.
+const int ScratchMemoryBufferLifetime = 1000;
+}
+
+RendererD3D::RendererD3D(egl::Display *display)
+ : mDisplay(display),
+ mDeviceLost(false),
+ mScratchMemoryBufferResetCounter(0)
+{
+}
+
+RendererD3D::~RendererD3D()
+{
+ cleanup();
+}
+
+void RendererD3D::cleanup()
+{
+ mScratchMemoryBuffer.resize(0);
+ for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it)
+ {
+ it->second.set(NULL);
+ }
+ mIncompleteTextures.clear();
+}
+
+// static
+RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer));
+ return static_cast<RendererD3D*>(renderer);
+}
+
+gl::Error RendererD3D::drawElements(const gl::Data &data,
+ GLenum mode, GLsizei count, GLenum type,
+ const GLvoid *indices, GLsizei instances,
+ const RangeUI &indexRange)
+{
+ if (data.state->isPrimitiveRestartEnabled())
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "Primitive restart not implemented");
+ }
+
+ gl::Program *program = data.state->getProgram();
+ ASSERT(program != NULL);
+
+ program->updateSamplerMapping();
+
+ gl::Error error = generateSwizzles(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!applyPrimitiveType(mode, count, program->usesPointSize()))
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ error = applyRenderTarget(data, mode, false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyState(data, mode);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ gl::VertexArray *vao = data.state->getVertexArray();
+ TranslatedIndexData indexInfo;
+ indexInfo.indexRange = indexRange;
+ error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ applyTransformFeedbackBuffers(*data.state);
+ // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
+ // layer.
+ ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
+
+ GLsizei vertexCount = indexInfo.indexRange.length() + 1;
+ error = applyVertexBuffer(*data.state, mode, indexInfo.indexRange.start, vertexCount, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyShaders(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyTextures(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = program->applyUniformBuffers(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!skipDraw(data, mode))
+ {
+ error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::drawArrays(const gl::Data &data,
+ GLenum mode, GLint first,
+ GLsizei count, GLsizei instances)
+{
+ gl::Program *program = data.state->getProgram();
+ ASSERT(program != NULL);
+
+ program->updateSamplerMapping();
+
+ gl::Error error = generateSwizzles(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!applyPrimitiveType(mode, count, program->usesPointSize()))
+ {
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ error = applyRenderTarget(data, mode, false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyState(data, mode);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ applyTransformFeedbackBuffers(*data.state);
+
+ error = applyVertexBuffer(*data.state, mode, first, count, instances);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyShaders(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyTextures(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = program->applyUniformBuffers(data);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!skipDraw(data, mode))
+ {
+ error = drawArrays(data, mode, count, instances, program->usesPointSize());
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (data.state->isTransformFeedbackActiveUnpaused())
+ {
+ markTransformFeedbackUsage(data);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type)
+{
+ gl::Program *program = data.state->getProgram();
+
+ size_t samplerRange = program->getUsedSamplerRange(type);
+
+ for (size_t i = 0; i < samplerRange; i++)
+ {
+ GLenum textureType = program->getSamplerTextureType(type, i);
+ GLint textureUnit = program->getSamplerMapping(type, i, *data.caps);
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+ if (texture->getSamplerState().swizzleRequired())
+ {
+ gl::Error error = generateSwizzle(texture);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
+{
+ gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = generateSwizzles(data, gl::SAMPLER_PIXEL);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// Applies the render target surface, depth stencil surface, viewport rectangle and
+// scissor rectangle to the renderer
+gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport)
+{
+ const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+ ASSERT(framebufferObject && framebufferObject->checkStatus(data) == GL_FRAMEBUFFER_COMPLETE);
+
+ gl::Error error = applyRenderTarget(framebufferObject);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ float nearZ, farZ;
+ data.state->getDepthRange(&nearZ, &farZ);
+ setViewport(data.state->getViewport(), nearZ, farZ, drawMode,
+ data.state->getRasterizerState().frontFace, ignoreViewport);
+
+ setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device
+gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
+{
+ const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
+ int samples = framebufferObject->getSamples(data);
+
+ gl::RasterizerState rasterizer = data.state->getRasterizerState();
+ rasterizer.pointDrawMode = (drawMode == GL_POINTS);
+ rasterizer.multiSample = (samples != 0);
+
+ gl::Error error = setRasterizerState(rasterizer);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ unsigned int mask = 0;
+ if (data.state->isSampleCoverageEnabled())
+ {
+ GLclampf coverageValue;
+ bool coverageInvert = false;
+ data.state->getSampleCoverageParams(&coverageValue, &coverageInvert);
+ if (coverageValue != 0)
+ {
+ float threshold = 0.5f;
+
+ for (int i = 0; i < samples; ++i)
+ {
+ mask <<= 1;
+
+ if ((i + 1) * coverageValue >= threshold)
+ {
+ threshold += 1.0f;
+ mask |= 1;
+ }
+ }
+ }
+
+ if (coverageInvert)
+ {
+ mask = ~mask;
+ }
+ }
+ else
+ {
+ mask = 0xFFFFFFFF;
+ }
+ error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(),
+ data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+// Applies the shaders and shader constants to the Direct3D device
+gl::Error RendererD3D::applyShaders(const gl::Data &data)
+{
+ gl::Program *program = data.state->getProgram();
+
+ gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
+ gl::VertexFormat::GetInputLayout(inputLayout, program, *data.state);
+
+ const gl::Framebuffer *fbo = data.state->getDrawFramebuffer();
+
+ gl::Error error = applyShaders(program, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, data.state->isTransformFeedbackActiveUnpaused());
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return program->applyUniforms();
+}
+
+// For each Direct3D sampler of either the pixel or vertex stage,
+// looks up the corresponding OpenGL texture image unit and texture type,
+// and sets the texture and its addressing/filtering state (or NULL when inactive).
+gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType,
+ const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
+{
+ gl::Program *program = data.state->getProgram();
+
+ size_t samplerRange = program->getUsedSamplerRange(shaderType);
+ for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
+ {
+ GLenum textureType = program->getSamplerTextureType(shaderType, samplerIndex);
+ GLint textureUnit = program->getSamplerMapping(shaderType, samplerIndex, *data.caps);
+ if (textureUnit != -1)
+ {
+ gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
+ ASSERT(texture);
+ gl::SamplerState sampler = texture->getSamplerState();
+
+ gl::Sampler *samplerObject = data.state->getSampler(textureUnit);
+ if (samplerObject)
+ {
+ samplerObject->getState(&sampler);
+ }
+
+ // TODO: std::binary_search may become unavailable using older versions of GCC
+ if (texture->isSamplerComplete(sampler, data) &&
+ !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
+ {
+ gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = setTexture(shaderType, samplerIndex, texture);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ else
+ {
+ // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
+ gl::Texture *incompleteTexture = getIncompleteTexture(textureType);
+ gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ else
+ {
+ // No texture bound to this slot even though it is used by the shader, bind a NULL texture
+ gl::Error error = setTexture(shaderType, samplerIndex, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+
+ // Set all the remaining textures to NULL
+ size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits
+ : data.caps->maxVertexTextureImageUnits;
+ for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
+ {
+ gl::Error error = setTexture(shaderType, samplerIndex, NULL);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error RendererD3D::applyTextures(const gl::Data &data)
+{
+ FramebufferTextureSerialArray framebufferSerials;
+ size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials);
+
+ gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
+{
+ if (drawMode == GL_POINTS)
+ {
+ // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
+ // which affects varying interpolation. Since the value of gl_PointSize is
+ // undefined when not written, just skip drawing to avoid unexpected results.
+ if (!data.state->getProgram()->usesPointSize() && !data.state->isTransformFeedbackActiveUnpaused())
+ {
+ // This is stictly speaking not an error, but developers should be
+ // notified of risking undefined behavior.
+ ERR("Point rendering without writing to gl_PointSize.");
+
+ return true;
+ }
+ }
+ else if (gl::IsTriangleMode(drawMode))
+ {
+ if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK)
+ {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void RendererD3D::markTransformFeedbackUsage(const gl::Data &data)
+{
+ for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++)
+ {
+ gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i);
+ if (buffer)
+ {
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(buffer);
+ bufferD3D->markTransformFeedbackUsage();
+ }
+ }
+}
+
+size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data,
+ FramebufferTextureSerialArray *outSerialArray)
+{
+ size_t serialCount = 0;
+
+ const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
+ for (unsigned int i = 0; i < data.caps->maxColorAttachments; i++)
+ {
+ gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
+ if (attachment && attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+ (*outSerialArray)[serialCount++] = texture->getTextureSerial();
+ }
+ }
+
+ gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
+ if (depthStencilAttachment && depthStencilAttachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture();
+ (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
+ }
+
+ std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
+
+ return serialCount;
+}
+
+gl::Texture *RendererD3D::getIncompleteTexture(GLenum type)
+{
+ if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
+ {
+ const GLubyte color[] = { 0, 0, 0, 255 };
+ const gl::Extents colorSize(1, 1, 1);
+ const gl::PixelUnpackState incompleteUnpackState(1, 0);
+
+ gl::Texture* t = new gl::Texture(createTexture(type), gl::Texture::INCOMPLETE_TEXTURE_ID, type);
+
+ if (type == GL_TEXTURE_CUBE_MAP)
+ {
+ for (GLenum face = GL_TEXTURE_CUBE_MAP_POSITIVE_X; face <= GL_TEXTURE_CUBE_MAP_NEGATIVE_Z; face++)
+ {
+ t->setImage(face, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ }
+ }
+ else
+ {
+ t->setImage(type, 0, GL_RGBA, colorSize, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
+ }
+
+ mIncompleteTextures[type].set(t);
+ }
+
+ return mIncompleteTextures[type].get();
+}
+
+bool RendererD3D::isDeviceLost() const
+{
+ return mDeviceLost;
+}
+
+void RendererD3D::notifyDeviceLost()
+{
+ mDeviceLost = true;
+ mDisplay->notifyDeviceLost();
+}
+
+std::string RendererD3D::getVendorString() const
+{
+ LUID adapterLuid = { 0 };
+
+ if (getLUID(&adapterLuid))
+ {
+ char adapterLuidString[64];
+ sprintf_s(adapterLuidString, sizeof(adapterLuidString), "(adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
+ return std::string(adapterLuidString);
+ }
+
+ return std::string("");
+}
+
+gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut)
+{
+ if (mScratchMemoryBuffer.size() == requestedSize)
+ {
+ mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
+ *bufferOut = &mScratchMemoryBuffer;
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ if (mScratchMemoryBuffer.size() > requestedSize)
+ {
+ mScratchMemoryBufferResetCounter--;
+ }
+
+ if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize)
+ {
+ mScratchMemoryBuffer.resize(0);
+ if (!mScratchMemoryBuffer.resize(requestedSize))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+ }
+ mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
+ }
+
+ ASSERT(mScratchMemoryBuffer.size() >= requestedSize);
+
+ *bufferOut = &mScratchMemoryBuffer;
+ return gl::Error(GL_NO_ERROR);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h
index a2f778763c..3de6c20886 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.h
@@ -6,15 +6,23 @@
// RendererD3D.h: Defines a back-end specific class for the DirectX renderer.
-#ifndef LIBGLESV2_RENDERER_RENDERERD3D_H_
-#define LIBGLESV2_RENDERER_RENDERERD3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
+#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Data.h"
+#include "common/MemoryBuffer.h"
+#include "libANGLE/Data.h"
+#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
#include <array>
+namespace egl
+{
+class ConfigSet;
+}
+
namespace gl
{
class InfoLog;
@@ -24,24 +32,55 @@ class Texture;
namespace rx
{
-class TextureStorage;
-class VertexBuffer;
+class ImageD3D;
class IndexBuffer;
-class ShaderExecutable;
-class SwapChain;
-class RenderTarget;
-class Image;
+class RenderTargetD3D;
+class ShaderExecutableD3D;
+class SwapChainD3D;
class TextureStorage;
-class UniformStorage;
+class UniformStorageD3D;
+class VertexBuffer;
+
+enum ShaderType
+{
+ SHADER_VERTEX,
+ SHADER_PIXEL,
+ SHADER_GEOMETRY
+};
+
+enum RendererClass
+{
+ RENDERER_D3D11,
+ RENDERER_D3D9,
+};
+
+// Useful for unit testing
+class BufferFactoryD3D
+{
+ public:
+ BufferFactoryD3D() {}
+ virtual ~BufferFactoryD3D() {}
+
+ virtual VertexBuffer *createVertexBuffer() = 0;
+ virtual IndexBuffer *createIndexBuffer() = 0;
+
+ // TODO(jmadill): add VertexFormatCaps
+ virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0;
+ virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
+};
-class RendererD3D : public Renderer
+class RendererD3D : public Renderer, public BufferFactoryD3D
{
public:
explicit RendererD3D(egl::Display *display);
virtual ~RendererD3D();
+ virtual egl::Error initialize() = 0;
+
static RendererD3D *makeRendererD3D(Renderer *renderer);
+ virtual egl::ConfigSet generateConfigs() const = 0;
+
gl::Error drawArrays(const gl::Data &data,
GLenum mode, GLint first,
GLsizei count, GLsizei instances) override;
@@ -51,28 +90,24 @@ class RendererD3D : public Renderer
const GLvoid *indices, GLsizei instances,
const RangeUI &indexRange) override;
- gl::Error clear(const gl::Data &data, GLbitfield mask) override;
- gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLfloat *values) override;
- gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLuint *values) override;
- gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, int drawbuffer, const GLint *values) override;
- gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) override;
-
- gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, void* pixels) override;
+ bool isDeviceLost() const override;
+ std::string getVendorString() const override;
- gl::Error blitFramebuffer(const gl::Data &data,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter) override;
+ virtual int getMinorShaderModel() const = 0;
+ virtual std::string getShaderModelSuffix() const = 0;
// Direct3D Specific methods
- virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
+ virtual GUID getAdapterIdentifier() const = 0;
+
+ virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat) = 0;
virtual gl::Error generateSwizzle(gl::Texture *texture) = 0;
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler) = 0;
virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture) = 0;
- virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]) = 0;
+ virtual gl::Error setUniformBuffers(const gl::Data &data,
+ const GLint vertexUniformBuffers[],
+ const GLint fragmentUniformBuffers[]) = 0;
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState) = 0;
virtual gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
@@ -85,11 +120,11 @@ class RendererD3D : public Renderer
bool ignoreViewport) = 0;
virtual gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) = 0;
- virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive) = 0;
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray) = 0;
- virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount) = 0;
- virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances) = 0;
+ virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize) = 0;
+ virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances) = 0;
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo) = 0;
virtual void applyTransformFeedbackBuffers(const gl::State& state) = 0;
@@ -102,71 +137,66 @@ class RendererD3D : public Renderer
virtual bool getShareHandleSupport() const = 0;
virtual bool getPostSubBufferSupport() const = 0;
+ virtual int getMajorShaderModel() const = 0;
+
// Pixel operations
- virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level) = 0;
- virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level) = 0;
- virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
- virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level) = 0;
-
- virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) = 0;
+ virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+ virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level) = 0;
+ virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
+ virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level) = 0;
// RenderTarget creation
- virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT) = 0;
- virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT) = 0;
+ virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT) = 0;
// Shader operations
- virtual void releaseShaderCompiler() = 0;
virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutable **outExecutable) = 0;
+ bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable) = 0;
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, D3DWorkaroundType workaround,
- ShaderExecutable **outExectuable) = 0;
- virtual UniformStorage *createUniformStorage(size_t storageSize) = 0;
+ bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable) = 0;
+ virtual UniformStorageD3D *createUniformStorage(size_t storageSize) = 0;
// Image operations
- virtual Image *createImage() = 0;
- virtual gl::Error generateMipmap(Image *dest, Image *source) = 0;
- virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain) = 0;
- virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels) = 0;
- virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels) = 0;
+ virtual ImageD3D *createImage() = 0;
+ virtual gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) = 0;
+ virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain) = 0;
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly) = 0;
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly) = 0;
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels) = 0;
// Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const = 0;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea) = 0;
- virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const = 0;
- virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const = 0;
+ // Device lost
+ void notifyDeviceLost() override;
+ virtual bool resetDevice() = 0;
- virtual VertexBuffer *createVertexBuffer() = 0;
- virtual IndexBuffer *createIndexBuffer() = 0;
+ virtual RendererClass getRendererClass() const = 0;
+
+ gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
protected:
- virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
+ virtual gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) = 0;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances) = 0;
- virtual gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) = 0;
- virtual gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
- const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- const gl::Rectangle *scissor, bool blitRenderTarget,
- bool blitDepth, bool blitStencil, GLenum filter) = 0;
+
+ virtual bool getLUID(LUID *adapterLuid) const = 0;
void cleanup();
egl::Display *mDisplay;
+ bool mDeviceLost;
private:
- DISALLOW_COPY_AND_ASSIGN(RendererD3D);
-
//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
typedef std::array<unsigned int, gl::IMPLEMENTATION_MAX_FRAMEBUFFER_ATTACHMENTS> FramebufferTextureSerialArray;
@@ -175,12 +205,10 @@ class RendererD3D : public Renderer
gl::Error applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport);
gl::Error applyState(const gl::Data &data, GLenum drawMode);
- bool applyTransformFeedbackBuffers(const gl::Data &data);
- gl::Error applyShaders(const gl::Data &data, bool transformFeedbackActive);
+ gl::Error applyShaders(const gl::Data &data);
gl::Error applyTextures(const gl::Data &data, gl::SamplerType shaderType,
const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount);
gl::Error applyTextures(const gl::Data &data);
- gl::Error applyUniformBuffers(const gl::Data &data);
bool skipDraw(const gl::Data &data, GLenum drawMode);
void markTransformFeedbackUsage(const gl::Data &data);
@@ -190,8 +218,24 @@ class RendererD3D : public Renderer
gl::Texture *getIncompleteTexture(GLenum type);
gl::TextureMap mIncompleteTextures;
+ MemoryBuffer mScratchMemoryBuffer;
+ unsigned int mScratchMemoryBufferResetCounter;
+};
+
+struct dx_VertexConstants
+{
+ float depthRange[4];
+ float viewAdjust[4];
+ float viewCoords[4];
+};
+
+struct dx_PixelConstants
+{
+ float depthRange[4];
+ float viewCoords[4];
+ float depthFront[4];
};
}
-#endif // LIBGLESV2_RENDERER_RENDERERD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
index 8a97579e16..7d522a95d4 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.cpp
@@ -6,12 +6,13 @@
// ShaderD3D.cpp: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
-#include "libGLESv2/Shader.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/features.h"
-#include "common/features.h"
#include "common/utilities.h"
// Definitions local to the translation unit
@@ -57,9 +58,6 @@ void FilterInactiveVariables(std::vector<VarT> *variableList)
}
}
-void *ShaderD3D::mFragmentCompiler = NULL;
-void *ShaderD3D::mVertexCompiler = NULL;
-
template <typename VarT>
const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableList)
{
@@ -67,13 +65,11 @@ const std::vector<VarT> *GetShaderVariables(const std::vector<VarT> *variableLis
return variableList;
}
-ShaderD3D::ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer)
- : mType(type),
- mRenderer(renderer),
+ShaderD3D::ShaderD3D(GLenum type)
+ : mShaderType(type),
mShaderVersion(100)
{
uncompile();
- initializeCompiler(data);
}
ShaderD3D::~ShaderD3D()
@@ -94,67 +90,13 @@ const ShaderD3D *ShaderD3D::makeShaderD3D(const ShaderImpl *impl)
std::string ShaderD3D::getDebugInfo() const
{
- return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mType) + " SHADER END\n";
+ return mDebugInfo + std::string("\n// ") + GetShaderTypeString(mShaderType) + " SHADER END\n";
}
-// Perform a one-time initialization of the shader compiler (or after being destructed by releaseCompiler)
-void ShaderD3D::initializeCompiler(const gl::Data &data)
-{
- if (!mFragmentCompiler)
- {
- bool result = ShInitialize();
- if (result)
- {
- ShShaderSpec specVersion = (data.clientVersion >= 3) ? SH_GLES3_SPEC : SH_GLES2_SPEC;
- ShShaderOutput hlslVersion = (mRenderer->getMajorShaderModel() >= 4) ? SH_HLSL11_OUTPUT : SH_HLSL9_OUTPUT;
-
- ShBuiltInResources resources;
- ShInitBuiltInResources(&resources);
-
- const gl::Caps &caps = *data.caps;
- const gl::Extensions &extensions = *data.extensions;
-
- resources.MaxVertexAttribs = caps.maxVertexAttributes;
- resources.MaxVertexUniformVectors = caps.maxVertexUniformVectors;
- resources.MaxVaryingVectors = caps.maxVaryingVectors;
- resources.MaxVertexTextureImageUnits = caps.maxVertexTextureImageUnits;
- resources.MaxCombinedTextureImageUnits = caps.maxCombinedTextureImageUnits;
- resources.MaxTextureImageUnits = caps.maxTextureImageUnits;
- resources.MaxFragmentUniformVectors = caps.maxFragmentUniformVectors;
- resources.MaxDrawBuffers = caps.maxDrawBuffers;
- resources.OES_standard_derivatives = extensions.standardDerivatives;
- resources.EXT_draw_buffers = extensions.drawBuffers;
- resources.EXT_shader_texture_lod = 1;
- // resources.OES_EGL_image_external = mRenderer->getShareHandleSupport() ? 1 : 0; // TODO: commented out until the extension is actually supported.
- resources.FragmentPrecisionHigh = 1; // Shader Model 2+ always supports FP24 (s16e7) which corresponds to highp
- resources.EXT_frag_depth = 1; // Shader Model 2+ always supports explicit depth output
- // GLSL ES 3.0 constants
- resources.MaxVertexOutputVectors = caps.maxVertexOutputComponents / 4;
- resources.MaxFragmentInputVectors = caps.maxFragmentInputComponents / 4;
- resources.MinProgramTexelOffset = caps.minProgramTexelOffset;
- resources.MaxProgramTexelOffset = caps.maxProgramTexelOffset;
-
- mFragmentCompiler = ShConstructCompiler(GL_FRAGMENT_SHADER, specVersion, hlslVersion, &resources);
- mVertexCompiler = ShConstructCompiler(GL_VERTEX_SHADER, specVersion, hlslVersion, &resources);
- }
- }
-}
-
-void ShaderD3D::releaseCompiler()
+void ShaderD3D::parseVaryings(ShHandle compiler)
{
- ShDestruct(mFragmentCompiler);
- ShDestruct(mVertexCompiler);
-
- mFragmentCompiler = NULL;
- mVertexCompiler = NULL;
-
- ShFinalize();
-}
-
-void ShaderD3D::parseVaryings(void *compiler)
-{
- if (!mHlsl.empty())
+ if (!mTranslatedSource.empty())
{
const std::vector<sh::Varying> *varyings = ShGetVaryings(compiler);
ASSERT(varyings);
@@ -164,17 +106,19 @@ void ShaderD3D::parseVaryings(void *compiler)
mVaryings.push_back(gl::PackedVarying((*varyings)[varyingIndex]));
}
- mUsesMultipleRenderTargets = mHlsl.find("GL_USES_MRT") != std::string::npos;
- mUsesFragColor = mHlsl.find("GL_USES_FRAG_COLOR") != std::string::npos;
- mUsesFragData = mHlsl.find("GL_USES_FRAG_DATA") != std::string::npos;
- mUsesFragCoord = mHlsl.find("GL_USES_FRAG_COORD") != std::string::npos;
- mUsesFrontFacing = mHlsl.find("GL_USES_FRONT_FACING") != std::string::npos;
- mUsesPointSize = mHlsl.find("GL_USES_POINT_SIZE") != std::string::npos;
- mUsesPointCoord = mHlsl.find("GL_USES_POINT_COORD") != std::string::npos;
- mUsesDepthRange = mHlsl.find("GL_USES_DEPTH_RANGE") != std::string::npos;
- mUsesFragDepth = mHlsl.find("GL_USES_FRAG_DEPTH") != std::string::npos;
- mUsesDiscardRewriting = mHlsl.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
- mUsesNestedBreak = mHlsl.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+ mUsesMultipleRenderTargets = mTranslatedSource.find("GL_USES_MRT") != std::string::npos;
+ mUsesFragColor = mTranslatedSource.find("GL_USES_FRAG_COLOR") != std::string::npos;
+ mUsesFragData = mTranslatedSource.find("GL_USES_FRAG_DATA") != std::string::npos;
+ mUsesFragCoord = mTranslatedSource.find("GL_USES_FRAG_COORD") != std::string::npos;
+ mUsesFrontFacing = mTranslatedSource.find("GL_USES_FRONT_FACING") != std::string::npos;
+ mUsesPointSize = mTranslatedSource.find("GL_USES_POINT_SIZE") != std::string::npos;
+ mUsesPointCoord = mTranslatedSource.find("GL_USES_POINT_COORD") != std::string::npos;
+ mUsesDepthRange = mTranslatedSource.find("GL_USES_DEPTH_RANGE") != std::string::npos;
+ mUsesFragDepth = mTranslatedSource.find("GL_USES_FRAG_DEPTH") != std::string::npos;
+ mUsesDiscardRewriting = mTranslatedSource.find("ANGLE_USES_DISCARD_REWRITING") != std::string::npos;
+ mUsesNestedBreak = mTranslatedSource.find("ANGLE_USES_NESTED_BREAK") != std::string::npos;
+ mUsesDeferredInit = mTranslatedSource.find("ANGLE_USES_DEFERRED_INIT") != std::string::npos;
+ mRequiresIEEEStrictCompiling = mTranslatedSource.find("ANGLE_REQUIRES_IEEE_STRICT_COMPILING") != std::string::npos;
}
}
@@ -190,7 +134,8 @@ void ShaderD3D::resetVaryingsRegisterAssignment()
void ShaderD3D::uncompile()
{
// set by compileToHLSL
- mHlsl.clear();
+ mCompilerOutputType = SH_ESSL_OUTPUT;
+ mTranslatedSource.clear();
mInfoLog.clear();
mUsesMultipleRenderTargets = false;
@@ -205,6 +150,8 @@ void ShaderD3D::uncompile()
mShaderVersion = 100;
mUsesDiscardRewriting = false;
mUsesNestedBreak = false;
+ mUsesDeferredInit = false;
+ mRequiresIEEEStrictCompiling = false;
mVaryings.clear();
mUniforms.clear();
@@ -214,16 +161,13 @@ void ShaderD3D::uncompile()
mDebugInfo.clear();
}
-void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::string &source)
+void ShaderD3D::compileToHLSL(ShHandle compiler, const std::string &source)
{
- // ensure the compiler is loaded
- initializeCompiler(data);
-
int compileOptions = (SH_OBJECT_CODE | SH_VARIABLES);
std::string sourcePath;
#if !defined (ANGLE_ENABLE_WINDOWS_STORE)
- if (gl::perfActive())
+ if (gl::DebugAnnotationsActive())
{
sourcePath = getTempPath();
writeFile(sourcePath.c_str(), source.c_str(), source.length());
@@ -254,14 +198,9 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s
mShaderVersion = ShGetShaderVersion(compiler);
- if (mShaderVersion == 300 && data.clientVersion < 3)
- {
- mInfoLog = "GLSL ES 3.00 is not supported by OpenGL ES 2.0 contexts";
- TRACE("\n%s", mInfoLog.c_str());
- }
- else if (result)
+ if (result)
{
- mHlsl = ShGetObjectCode(compiler);
+ mTranslatedSource = ShGetObjectCode(compiler);
#ifdef _DEBUG
// Prefix hlsl shader with commented out glsl shader
@@ -281,8 +220,8 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s
curPos = (nextLine == std::string::npos) ? std::string::npos : (nextLine + 1);
}
hlslStream << "\n\n";
- hlslStream << mHlsl;
- mHlsl = hlslStream.str();
+ hlslStream << mTranslatedSource;
+ mTranslatedSource = hlslStream.str();
#endif
mUniforms = *GetShaderVariables(ShGetUniforms(compiler));
@@ -293,10 +232,10 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s
if (uniform.staticUse)
{
- unsigned int index = -1;
- bool result = ShGetUniformRegister(compiler, uniform.name, &index);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(result);
+ unsigned int index = static_cast<unsigned int>(-1);
+ bool getUniformRegisterResult = ShGetUniformRegister(compiler, uniform.name, &index);
+ UNUSED_ASSERTION_VARIABLE(getUniformRegisterResult);
+ ASSERT(getUniformRegisterResult);
mUniformRegisterMap[uniform.name] = index;
}
@@ -310,10 +249,10 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s
if (interfaceBlock.staticUse)
{
- unsigned int index = -1;
- bool result = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
- UNUSED_ASSERTION_VARIABLE(result);
- ASSERT(result);
+ unsigned int index = static_cast<unsigned int>(-1);
+ bool blockRegisterResult = ShGetInterfaceBlockRegister(compiler, interfaceBlock.name, &index);
+ UNUSED_ASSERTION_VARIABLE(blockRegisterResult);
+ ASSERT(blockRegisterResult);
mInterfaceBlockRegisterMap[interfaceBlock.name] = index;
}
@@ -327,24 +266,27 @@ void ShaderD3D::compileToHLSL(const gl::Data &data, void *compiler, const std::s
}
}
-D3DWorkaroundType ShaderD3D::getD3DWorkarounds() const
+void ShaderD3D::generateWorkarounds(D3DCompilerWorkarounds *workarounds) const
{
if (mUsesDiscardRewriting)
{
// ANGLE issue 486:
// Work-around a D3D9 compiler bug that presents itself when using conditional discard, by disabling optimization
- return ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION;
+ workarounds->skipOptimization = true;
}
-
- if (mUsesNestedBreak)
+ else if (mUsesNestedBreak)
{
// ANGLE issue 603:
// Work-around a D3D9 compiler bug that presents itself when using break in a nested loop, by maximizing optimization
// We want to keep the use of ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION minimal to prevent hangs, so usesDiscard takes precedence
- return ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION;
+ workarounds->useMaxOptimization = true;
}
- return ANGLE_D3D_WORKAROUND_NONE;
+ if (mRequiresIEEEStrictCompiling)
+ {
+ // IEEE Strictness for D3D compiler needs to be enabled for NaNs to work.
+ workarounds->enableIEEEStrictness = true;
+ }
}
// true if varying x has a higher priority in packing than y
@@ -381,62 +323,48 @@ unsigned int ShaderD3D::getInterfaceBlockRegister(const std::string &blockName)
return mInterfaceBlockRegisterMap.find(blockName)->second;
}
-void *ShaderD3D::getCompiler()
+GLenum ShaderD3D::getShaderType() const
{
- if (mType == GL_VERTEX_SHADER)
- {
- return mVertexCompiler;
- }
- else
- {
- ASSERT(mType == GL_FRAGMENT_SHADER);
- return mFragmentCompiler;
- }
+ return mShaderType;
}
-ShShaderOutput ShaderD3D::getCompilerOutputType(GLenum shader)
+ShShaderOutput ShaderD3D::getCompilerOutputType() const
{
- void *compiler = NULL;
-
- switch (shader)
- {
- case GL_VERTEX_SHADER: compiler = mVertexCompiler; break;
- case GL_FRAGMENT_SHADER: compiler = mFragmentCompiler; break;
- default: UNREACHABLE(); return SH_HLSL9_OUTPUT;
- }
-
- return ShGetShaderOutputType(compiler);
+ return mCompilerOutputType;
}
-bool ShaderD3D::compile(const gl::Data &data, const std::string &source)
+bool ShaderD3D::compile(gl::Compiler *compiler, const std::string &source)
{
uncompile();
- void *compiler = getCompiler();
+ CompilerD3D *compilerD3D = CompilerD3D::makeCompilerD3D(compiler->getImplementation());
+ ShHandle compilerHandle = compilerD3D->getCompilerHandle(mShaderType);
+
+ mCompilerOutputType = ShGetShaderOutputType(compilerHandle);
- compileToHLSL(data, compiler, source);
+ compileToHLSL(compilerHandle, source);
- if (mType == GL_VERTEX_SHADER)
+ if (mShaderType == GL_VERTEX_SHADER)
{
- parseAttributes(compiler);
+ parseAttributes(compilerHandle);
}
- parseVaryings(compiler);
+ parseVaryings(compilerHandle);
- if (mType == GL_FRAGMENT_SHADER)
+ if (mShaderType == GL_FRAGMENT_SHADER)
{
std::sort(mVaryings.begin(), mVaryings.end(), compareVarying);
const std::string &hlsl = getTranslatedSource();
if (!hlsl.empty())
{
- mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compiler));
+ mActiveOutputVariables = *GetShaderVariables(ShGetOutputVariables(compilerHandle));
FilterInactiveVariables(&mActiveOutputVariables);
}
}
#if ANGLE_SHADER_DEBUG_INFO == ANGLE_ENABLED
- mDebugInfo += std::string("// ") + GetShaderTypeString(mType) + " SHADER BEGIN\n";
+ mDebugInfo += std::string("// ") + GetShaderTypeString(mShaderType) + " SHADER BEGIN\n";
mDebugInfo += "\n// GLSL BEGIN\n\n" + source + "\n\n// GLSL END\n\n\n";
mDebugInfo += "// INITIAL HLSL BEGIN\n\n" + getTranslatedSource() + "\n// INITIAL HLSL END\n\n\n";
// Successive steps will append more info
@@ -447,7 +375,7 @@ bool ShaderD3D::compile(const gl::Data &data, const std::string &source)
return !getTranslatedSource().empty();
}
-void ShaderD3D::parseAttributes(void *compiler)
+void ShaderD3D::parseAttributes(ShHandle compiler)
{
const std::string &hlsl = getTranslatedSource();
if (!hlsl.empty())
@@ -457,25 +385,4 @@ void ShaderD3D::parseAttributes(void *compiler)
}
}
-int ShaderD3D::getSemanticIndex(const std::string &attributeName) const
-{
- if (!attributeName.empty())
- {
- int semanticIndex = 0;
- for (size_t attributeIndex = 0; attributeIndex < mActiveAttributes.size(); attributeIndex++)
- {
- const sh::ShaderVariable &attribute = mActiveAttributes[attributeIndex];
-
- if (attribute.name == attributeName)
- {
- return semanticIndex;
- }
-
- semanticIndex += gl::VariableRegisterCount(attribute.type);
- }
- }
-
- return -1;
-}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
index 3c9aac2c12..d0237b5985 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ShaderD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderD3D.h
@@ -6,12 +6,12 @@
// ShaderD3D.h: Defines the rx::ShaderD3D class which implements rx::ShaderImpl.
-#ifndef LIBGLESV2_RENDERER_SHADERD3D_H_
-#define LIBGLESV2_RENDERER_SHADERD3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_SHADERD3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADERD3D_H_
-#include "libGLESv2/renderer/ShaderImpl.h"
-#include "libGLESv2/renderer/Workarounds.h"
-#include "libGLESv2/Shader.h"
+#include "libANGLE/renderer/ShaderImpl.h"
+#include "libANGLE/renderer/Workarounds.h"
+#include "libANGLE/Shader.h"
#include <map>
@@ -25,15 +25,13 @@ class ShaderD3D : public ShaderImpl
friend class DynamicHLSL;
public:
- ShaderD3D(const gl::Data &data, GLenum type, RendererD3D *renderer);
+ ShaderD3D(GLenum type);
virtual ~ShaderD3D();
static ShaderD3D *makeShaderD3D(ShaderImpl *impl);
static const ShaderD3D *makeShaderD3D(const ShaderImpl *impl);
// ShaderImpl implementation
- virtual const std::string &getInfoLog() const { return mInfoLog; }
- virtual const std::string &getTranslatedSource() const { return mHlsl; }
virtual std::string getDebugInfo() const;
// D3D-specific methods
@@ -41,36 +39,28 @@ class ShaderD3D : public ShaderImpl
void resetVaryingsRegisterAssignment();
unsigned int getUniformRegister(const std::string &uniformName) const;
unsigned int getInterfaceBlockRegister(const std::string &blockName) const;
- int getSemanticIndex(const std::string &attributeName) const;
void appendDebugInfo(const std::string &info) { mDebugInfo += info; }
- D3DWorkaroundType getD3DWorkarounds() const;
+ void generateWorkarounds(D3DCompilerWorkarounds *workarounds) const;
int getShaderVersion() const { return mShaderVersion; }
bool usesDepthRange() const { return mUsesDepthRange; }
bool usesPointSize() const { return mUsesPointSize; }
+ bool usesDeferredInit() const { return mUsesDeferredInit; }
- static void releaseCompiler();
- static ShShaderOutput getCompilerOutputType(GLenum shader);
+ GLenum getShaderType() const;
+ ShShaderOutput getCompilerOutputType() const;
- virtual bool compile(const gl::Data &data, const std::string &source);
+ virtual bool compile(gl::Compiler *compiler, const std::string &source);
private:
- DISALLOW_COPY_AND_ASSIGN(ShaderD3D);
+ void compileToHLSL(ShHandle compiler, const std::string &source);
+ void parseVaryings(ShHandle compiler);
- void compileToHLSL(const gl::Data &data, void *compiler, const std::string &source);
- void parseVaryings(void *compiler);
-
- void initializeCompiler(const gl::Data &data);
- void parseAttributes(void *compiler);
- void *getCompiler();
+ void parseAttributes(ShHandle compiler);
static bool compareVarying(const gl::PackedVarying &x, const gl::PackedVarying &y);
- static void *mFragmentCompiler;
- static void *mVertexCompiler;
-
- GLenum mType;
- RendererD3D *mRenderer;
+ GLenum mShaderType;
int mShaderVersion;
@@ -85,9 +75,10 @@ class ShaderD3D : public ShaderImpl
bool mUsesFragDepth;
bool mUsesDiscardRewriting;
bool mUsesNestedBreak;
+ bool mUsesDeferredInit;
+ bool mRequiresIEEEStrictCompiling;
- std::string mHlsl;
- std::string mInfoLog;
+ ShShaderOutput mCompilerOutputType;
std::string mDebugInfo;
std::map<std::string, unsigned int> mUniformRegisterMap;
std::map<std::string, unsigned int> mInterfaceBlockRegisterMap;
@@ -95,4 +86,4 @@ class ShaderD3D : public ShaderImpl
}
-#endif // LIBGLESV2_RENDERER_SHADERD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_SHADERD3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
new file mode 100644
index 0000000000..97ffdf5094
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp
@@ -0,0 +1,61 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.cpp: Implements a class to contain D3D shader executable
+// implementation details.
+
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
+
+#include "common/angleutils.h"
+
+namespace rx
+{
+
+ShaderExecutableD3D::ShaderExecutableD3D(const void *function, size_t length)
+ : mFunctionBuffer(length)
+{
+ memcpy(mFunctionBuffer.data(), function, length);
+}
+
+ShaderExecutableD3D::~ShaderExecutableD3D()
+{
+}
+
+const uint8_t *ShaderExecutableD3D::getFunction() const
+{
+ return mFunctionBuffer.data();
+}
+
+size_t ShaderExecutableD3D::getLength() const
+{
+ return mFunctionBuffer.size();
+}
+
+const std::string &ShaderExecutableD3D::getDebugInfo() const
+{
+ return mDebugInfo;
+}
+
+void ShaderExecutableD3D::appendDebugInfo(const std::string &info)
+{
+ mDebugInfo += info;
+}
+
+
+UniformStorageD3D::UniformStorageD3D(size_t initialSize) : mSize(initialSize)
+{
+}
+
+UniformStorageD3D::~UniformStorageD3D()
+{
+}
+
+size_t UniformStorageD3D::size() const
+{
+ return mSize;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
new file mode 100644
index 0000000000..71b83b7954
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h
@@ -0,0 +1,54 @@
+//
+// Copyright (c) 2012-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// ShaderExecutable.h: Defines a class to contain D3D shader executable
+// implementation details.
+
+#ifndef LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+#define LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
+
+#include "common/debug.h"
+
+#include <vector>
+#include <cstdint>
+
+namespace rx
+{
+
+class ShaderExecutableD3D : angle::NonCopyable
+{
+ public:
+ ShaderExecutableD3D(const void *function, size_t length);
+ virtual ~ShaderExecutableD3D();
+
+ const uint8_t *getFunction() const;
+
+ size_t getLength() const;
+
+ const std::string &getDebugInfo() const;
+
+ void appendDebugInfo(const std::string &info);
+
+ private:
+ std::vector<uint8_t> mFunctionBuffer;
+ std::string mDebugInfo;
+};
+
+class UniformStorageD3D : angle::NonCopyable
+{
+ public:
+ UniformStorageD3D(size_t initialSize);
+ virtual ~UniformStorageD3D();
+
+ size_t size() const;
+
+ private:
+ size_t mSize;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_SHADEREXECUTABLED3D_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
new file mode 100644
index 0000000000..4fde295443
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
@@ -0,0 +1,396 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.cpp: D3D implementation of an EGL surface
+
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+
+#include <tchar.h>
+#include <EGL/eglext.h>
+#include <algorithm>
+
+namespace rx
+{
+
+SurfaceD3D *SurfaceD3D::createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLClientBuffer shareHandle,
+ EGLint width, EGLint height)
+{
+ return new SurfaceD3D(renderer, display, config, width, height, EGL_TRUE, shareHandle, NULL);
+}
+
+SurfaceD3D *SurfaceD3D::createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLNativeWindowType window,
+ EGLint fixedSize, EGLint width, EGLint height)
+{
+ return new SurfaceD3D(renderer, display, config, width, height, fixedSize, static_cast<EGLClientBuffer>(0), window);
+}
+
+SurfaceD3D::SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height, EGLint fixedSize,
+ EGLClientBuffer shareHandle, EGLNativeWindowType window)
+ : SurfaceImpl(),
+ mRenderer(renderer),
+ mDisplay(display),
+ mFixedSize(fixedSize == EGL_TRUE),
+ mRenderTargetFormat(config->renderTargetFormat),
+ mDepthStencilFormat(config->depthStencilFormat),
+ mSwapChain(nullptr),
+ mSwapIntervalDirty(true),
+ mWindowSubclassed(false),
+ mNativeWindow(window),
+ mWidth(width),
+ mHeight(height),
+ mSwapInterval(1),
+ mShareHandle(reinterpret_cast<HANDLE*>(shareHandle))
+{
+ subclassWindow();
+}
+
+SurfaceD3D::~SurfaceD3D()
+{
+ unsubclassWindow();
+ releaseSwapChain();
+}
+
+void SurfaceD3D::releaseSwapChain()
+{
+ SafeDelete(mSwapChain);
+}
+
+egl::Error SurfaceD3D::initialize()
+{
+ if (mNativeWindow.getNativeWindow())
+ {
+ if (!mNativeWindow.initialize())
+ {
+ return egl::Error(EGL_BAD_SURFACE);
+ }
+ }
+
+ egl::Error error = resetSwapChain();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::bindTexImage(EGLint)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::releaseTexImage(EGLint)
+{
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resetSwapChain()
+{
+ ASSERT(!mSwapChain);
+
+ int width;
+ int height;
+
+ if (!mFixedSize)
+ {
+ RECT windowRect;
+ if (!mNativeWindow.getClientRect(&windowRect))
+ {
+ ASSERT(false);
+
+ return egl::Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
+ }
+
+ width = windowRect.right - windowRect.left;
+ height = windowRect.bottom - windowRect.top;
+ }
+ else
+ {
+ // non-window surface - size is determined at creation
+ width = mWidth;
+ height = mHeight;
+ }
+
+ mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle, mRenderTargetFormat, mDepthStencilFormat);
+ if (!mSwapChain)
+ {
+ return egl::Error(EGL_BAD_ALLOC);
+ }
+
+ egl::Error error = resetSwapChain(width, height);
+ if (error.isError())
+ {
+ SafeDelete(mSwapChain);
+ return error;
+ }
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resizeSwapChain(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mDisplay->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::resetSwapChain(int backbufferWidth, int backbufferHeight)
+{
+ ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
+ ASSERT(mSwapChain);
+
+ EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mRenderer->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+ mSwapIntervalDirty = false;
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+egl::Error SurfaceD3D::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ if (!mSwapChain)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ if (x + width > mWidth)
+ {
+ width = mWidth - x;
+ }
+
+ if (y + height > mHeight)
+ {
+ height = mHeight - y;
+ }
+
+ if (width == 0 || height == 0)
+ {
+ return egl::Error(EGL_SUCCESS);
+ }
+
+ EGLint status = mSwapChain->swapRect(x, y, width, height);
+
+ if (status == EGL_CONTEXT_LOST)
+ {
+ mRenderer->notifyDeviceLost();
+ return egl::Error(status);
+ }
+ else if (status != EGL_SUCCESS)
+ {
+ return egl::Error(status);
+ }
+
+ checkForOutOfDateSwapChain();
+
+ return egl::Error(EGL_SUCCESS);
+}
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
+#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
+
+static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
+{
+ if (message == WM_SIZE)
+ {
+ SurfaceD3D* surf = reinterpret_cast<SurfaceD3D*>(GetProp(hwnd, kSurfaceProperty));
+ if(surf)
+ {
+ surf->checkForOutOfDateSwapChain();
+ }
+ }
+ WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
+ return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
+}
+#endif
+
+void SurfaceD3D::subclassWindow()
+{
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ HWND window = mNativeWindow.getNativeWindow();
+ if (!window)
+ {
+ return;
+ }
+
+ DWORD processId;
+ DWORD threadId = GetWindowThreadProcessId(window, &processId);
+ if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
+ {
+ return;
+ }
+
+ SetLastError(0);
+ LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+ if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
+ {
+ mWindowSubclassed = false;
+ return;
+ }
+
+ SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
+ SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
+ mWindowSubclassed = true;
+#endif
+}
+
+void SurfaceD3D::unsubclassWindow()
+{
+ if (!mWindowSubclassed)
+ {
+ return;
+ }
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ HWND window = mNativeWindow.getNativeWindow();
+ if (!window)
+ {
+ return;
+ }
+
+ // un-subclass
+ LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
+
+ // Check the windowproc is still SurfaceWindowProc.
+ // If this assert fails, then it is likely the application has subclassed the
+ // hwnd as well and did not unsubclass before destroying its EGL context. The
+ // application should be modified to either subclass before initializing the
+ // EGL context, or to unsubclass before destroying the EGL context.
+ if(parentWndFunc)
+ {
+ LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
+ UNUSED_ASSERTION_VARIABLE(prevWndFunc);
+ ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
+ }
+
+ RemoveProp(window, kSurfaceProperty);
+ RemoveProp(window, kParentWndProc);
+#endif
+ mWindowSubclassed = false;
+}
+
+bool SurfaceD3D::checkForOutOfDateSwapChain()
+{
+ RECT client;
+ int clientWidth = getWidth();
+ int clientHeight = getHeight();
+ bool sizeDirty = false;
+ if (!mFixedSize && !mNativeWindow.isIconic())
+ {
+ // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
+ // because that's not a useful size to render to.
+ if (!mNativeWindow.getClientRect(&client))
+ {
+ ASSERT(false);
+ return false;
+ }
+
+ // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
+ clientWidth = client.right - client.left;
+ clientHeight = client.bottom - client.top;
+ sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
+ }
+
+ bool wasDirty = (mSwapIntervalDirty || sizeDirty);
+
+ if (mSwapIntervalDirty)
+ {
+ resetSwapChain(clientWidth, clientHeight);
+ }
+ else if (sizeDirty)
+ {
+ resizeSwapChain(clientWidth, clientHeight);
+ }
+
+ return wasDirty;
+}
+
+egl::Error SurfaceD3D::swap()
+{
+ return swapRect(0, 0, mWidth, mHeight);
+}
+
+egl::Error SurfaceD3D::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return swapRect(x, y, width, height);
+}
+
+rx::SwapChainD3D *SurfaceD3D::getSwapChain() const
+{
+ return mSwapChain;
+}
+
+void SurfaceD3D::setSwapInterval(EGLint interval)
+{
+ if (mSwapInterval == interval)
+ {
+ return;
+ }
+
+ mSwapInterval = interval;
+ mSwapIntervalDirty = true;
+}
+
+EGLint SurfaceD3D::getWidth() const
+{
+ return mWidth;
+}
+
+EGLint SurfaceD3D::getHeight() const
+{
+ return mHeight;
+}
+
+EGLint SurfaceD3D::isPostSubBufferSupported() const
+{
+ // post sub buffer is always possible on D3D surfaces
+ return EGL_TRUE;
+}
+
+egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
+{
+ ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT);
+ if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+ *value = mSwapChain->getShareHandle();
+ else if (attribute == EGL_DEVICE_EXT)
+ *value = mSwapChain->getDevice();
+ return egl::Error(EGL_SUCCESS);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
new file mode 100644
index 0000000000..070b7cdbc4
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.h
@@ -0,0 +1,92 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// SurfaceD3D.h: D3D implementation of an EGL surface
+
+#ifndef LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+#define LIBANGLE_RENDERER_D3D_SURFACED3D_H_
+
+#include "libANGLE/renderer/SurfaceImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+
+namespace egl
+{
+class Surface;
+}
+
+namespace rx
+{
+class SwapChainD3D;
+class RendererD3D;
+
+class SurfaceD3D : public SurfaceImpl
+{
+ public:
+ static SurfaceD3D *createFromWindow(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
+ EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height);
+ static SurfaceD3D *createOffscreen(RendererD3D *renderer, egl::Display *display, const egl::Config *config,
+ EGLClientBuffer shareHandle, EGLint width, EGLint height);
+ ~SurfaceD3D() override;
+ void releaseSwapChain();
+
+ egl::Error initialize() override;
+
+ egl::Error swap() override;
+ egl::Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height) override;
+ egl::Error querySurfacePointerANGLE(EGLint attribute, void **value) override;
+ egl::Error bindTexImage(EGLint buffer) override;
+ egl::Error releaseTexImage(EGLint buffer) override;
+ void setSwapInterval(EGLint interval) override;
+
+ EGLint getWidth() const override;
+ EGLint getHeight() const override;
+
+ EGLint isPostSubBufferSupported() const override;
+
+ // D3D implementations
+ SwapChainD3D *getSwapChain() const;
+
+ egl::Error resetSwapChain();
+
+ // Returns true if swapchain changed due to resize or interval update
+ bool checkForOutOfDateSwapChain();
+
+ private:
+ SurfaceD3D(RendererD3D *renderer, egl::Display *display, const egl::Config *config, EGLint width, EGLint height,
+ EGLint fixedSize, EGLClientBuffer shareHandle, EGLNativeWindowType window);
+
+ egl::Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
+ egl::Error resetSwapChain(int backbufferWidth, int backbufferHeight);
+ egl::Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
+
+ void subclassWindow();
+ void unsubclassWindow();
+
+ RendererD3D *mRenderer;
+ egl::Display *mDisplay;
+
+ bool mFixedSize;
+
+ GLenum mRenderTargetFormat;
+ GLenum mDepthStencilFormat;
+
+ SwapChainD3D *mSwapChain;
+ bool mSwapIntervalDirty;
+ bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
+
+ NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
+ EGLint mWidth;
+ EGLint mHeight;
+
+ EGLint mSwapInterval;
+
+ HANDLE mShareHandle;
+};
+
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_SURFACED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
index 1417e0bdf6..da36e52ea7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/SwapChain.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
@@ -4,18 +4,20 @@
// found in the LICENSE file.
//
-// SwapChain.h: Defines a back-end specific class that hides the details of the
+// SwapChainD3D.h: Defines a back-end specific class that hides the details of the
// implementation-specific swapchain.
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN_H_
+#ifndef LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+#define LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
+
+#include <GLES2/gl2.h>
+#include <EGL/egl.h>
#include "common/angleutils.h"
-#include "common/NativeWindow.h"
#include "common/platform.h"
-#include <GLES2/gl2.h>
-#include <EGL/egl.h>
+// TODO: move out of D3D11
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
#if !defined(ANGLE_FORCE_VSYNC_OFF)
#define ANGLE_FORCE_VSYNC_OFF 0
@@ -23,26 +25,31 @@
namespace rx
{
+class RenderTargetD3D;
-class SwapChain
+class SwapChainD3D : angle::NonCopyable
{
public:
- SwapChain(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+ SwapChainD3D(rx::NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
: mNativeWindow(nativeWindow), mShareHandle(shareHandle), mBackBufferFormat(backBufferFormat), mDepthBufferFormat(depthBufferFormat)
{
}
- virtual ~SwapChain() {};
+ virtual ~SwapChainD3D() {};
virtual EGLint resize(EGLint backbufferWidth, EGLint backbufferSize) = 0;
virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
virtual void recreate() = 0;
+ virtual void *getDevice() { return NULL; }
+
+ virtual RenderTargetD3D *getColorRenderTarget() = 0;
+ virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
GLenum GetBackBufferInternalFormat() const { return mBackBufferFormat; }
GLenum GetDepthBufferInternalFormat() const { return mDepthBufferFormat; }
- virtual HANDLE getShareHandle() {return mShareHandle;};
+ HANDLE getShareHandle() { return mShareHandle; }
protected:
rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
@@ -53,4 +60,4 @@ class SwapChain
};
}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN_H_
+#endif // LIBANGLE_RENDERER_D3D_SWAPCHAIND3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
index 4a67701fdf..78b03f2283 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.cpp
@@ -6,23 +6,23 @@
// TextureD3D.cpp: Implementations of the Texture interfaces shared betweeen the D3D backends.
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/renderer/BufferImpl.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
-#include "libGLESv2/renderer/d3d/ImageD3D.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-
-#include "libEGL/Surface.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
#include "common/mathutil.h"
#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Config.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/BufferImpl.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
namespace rx
{
@@ -30,7 +30,8 @@ namespace rx
namespace
{
-gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixels, const uint8_t **pointerOut)
+gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+ ptrdiff_t layerOffset, const uint8_t **pointerOut)
{
if (unpack.pixelBuffer.id() != 0)
{
@@ -40,7 +41,7 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixel
// TODO: this is the only place outside of renderer that asks for a buffers raw data.
// This functionality should be moved into renderer and the getData method of BufferImpl removed.
- BufferD3D *bufferD3D = BufferD3D::makeBufferD3D(pixelBuffer->getImplementation());
+ BufferD3D *bufferD3D = GetImplAs<BufferD3D>(pixelBuffer);
ASSERT(bufferD3D);
const uint8_t *bufferData = NULL;
gl::Error error = bufferD3D->getData(&bufferData);
@@ -53,7 +54,13 @@ gl::Error GetUnpackPointer(const gl::PixelUnpackState &unpack, const void *pixel
}
else
{
- *pointerOut = static_cast<const uint8_t *>(pixels);
+ *pointerOut = pixels;
+ }
+
+ // Offset the pointer for 2D array layer (if it's valid)
+ if (*pointerOut != nullptr)
+ {
+ *pointerOut += layerOffset;
}
return gl::Error(GL_NO_ERROR);
@@ -79,40 +86,45 @@ TextureD3D::~TextureD3D()
{
}
-TextureD3D *TextureD3D::makeTextureD3D(TextureImpl *texture)
-{
- ASSERT(HAS_DYNAMIC_TYPE(TextureD3D*, texture));
- return static_cast<TextureD3D*>(texture);
-}
-
-TextureStorage *TextureD3D::getNativeTexture()
+gl::Error TextureD3D::getNativeTexture(TextureStorage **outStorage)
{
// ensure the underlying texture is created
- initializeStorage(false);
+ gl::Error error = initializeStorage(false);
+ if (error.isError())
+ {
+ return error;
+ }
if (mTexStorage)
{
- updateStorage();
+ error = updateStorage();
+ if (error.isError())
+ {
+ return error;
+ }
}
- return mTexStorage;
+ ASSERT(outStorage);
+
+ *outStorage = mTexStorage;
+ return gl::Error(GL_NO_ERROR);
}
GLint TextureD3D::getBaseLevelWidth() const
{
- const Image *baseImage = getBaseLevelImage();
+ const ImageD3D *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getWidth() : 0);
}
GLint TextureD3D::getBaseLevelHeight() const
{
- const Image *baseImage = getBaseLevelImage();
+ const ImageD3D *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getHeight() : 0);
}
GLint TextureD3D::getBaseLevelDepth() const
{
- const Image *baseImage = getBaseLevelImage();
+ const ImageD3D *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getDepth() : 0);
}
@@ -121,11 +133,11 @@ GLint TextureD3D::getBaseLevelDepth() const
// the base level image for anything except querying texture format and size.
GLenum TextureD3D::getBaseLevelInternalFormat() const
{
- const Image *baseImage = getBaseLevelImage();
+ const ImageD3D *baseImage = getBaseLevelImage();
return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
}
-bool TextureD3D::shouldUseSetData(const Image *image) const
+bool TextureD3D::shouldUseSetData(const ImageD3D *image) const
{
if (!mRenderer->getWorkarounds().setDataFasterThanImageUpload)
{
@@ -145,9 +157,17 @@ bool TextureD3D::shouldUseSetData(const Image *image) const
return (mTexStorage && !internalFormat.compressed);
}
-gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index)
+gl::Error TextureD3D::setImage(const gl::ImageIndex &index, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+ ptrdiff_t layerOffset)
{
- Image *image = getImage(index);
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
+ }
+
+ ImageD3D *image = getImage(index);
ASSERT(image);
// No-op
@@ -159,7 +179,7 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type,
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+ gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
if (error.isError())
{
return error;
@@ -167,15 +187,14 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type,
if (pixelData != NULL)
{
- gl::Error error(GL_NO_ERROR);
-
if (shouldUseSetData(image))
{
error = mTexStorage->setData(index, image, NULL, type, unpack, pixelData);
}
else
{
- error = image->loadData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), unpack.alignment, type, pixelData);
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ error = image->loadData(fullImageArea, unpack, type, pixelData);
}
if (error.isError())
@@ -189,12 +208,12 @@ gl::Error TextureD3D::setImage(const gl::PixelUnpackState &unpack, GLenum type,
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index)
+gl::Error TextureD3D::subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset)
{
// CPU readback & copy where direct GPU copy is not supported
const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+ gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
if (error.isError())
{
return error;
@@ -202,23 +221,21 @@ gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsi
if (pixelData != NULL)
{
- Image *image = getImage(index);
+ ImageD3D *image = getImage(index);
ASSERT(image);
- gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
if (shouldUseSetData(image))
{
- return mTexStorage->setData(index, image, &region, type, unpack, pixelData);
+ return mTexStorage->setData(index, image, &area, type, unpack, pixelData);
}
- gl::Error error = image->loadData(xoffset, yoffset, zoffset, width, height, depth, unpack.alignment,
- type, pixelData);
+ error = image->loadData(area, unpack, type, pixelData);
if (error.isError())
{
return error;
}
- error = commitRegion(index, region);
+ error = commitRegion(index, area);
if (error.isError())
{
return error;
@@ -230,12 +247,19 @@ gl::Error TextureD3D::subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsi
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image)
+gl::Error TextureD3D::setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels, ptrdiff_t layerOffset)
{
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
+ }
+
// We no longer need the "GLenum format" parameter to TexImage to determine what data format "pixels" contains.
// From our image internal format we know how many channels to expect, and "type" gives the format of pixel's components.
const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+ gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
if (error.isError())
{
return error;
@@ -243,7 +267,11 @@ gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLs
if (pixelData != NULL)
{
- gl::Error error = image->loadCompressedData(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth(), pixelData);
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ gl::Box fullImageArea(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ error = image->loadCompressedData(fullImageArea, pixelData);
if (error.isError())
{
return error;
@@ -255,11 +283,18 @@ gl::Error TextureD3D::setCompressedImage(const gl::PixelUnpackState &unpack, GLs
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image)
+gl::Error TextureD3D::subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+ ptrdiff_t layerOffset)
{
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
+ }
+
const uint8_t *pixelData = NULL;
- gl::Error error = GetUnpackPointer(unpack, pixels, &pixelData);
+ gl::Error error = GetUnpackPointer(unpack, pixels, layerOffset, &pixelData);
if (error.isError())
{
return error;
@@ -267,7 +302,10 @@ gl::Error TextureD3D::subImageCompressed(GLint xoffset, GLint yoffset, GLint zof
if (pixelData != NULL)
{
- gl::Error error = image->loadCompressedData(xoffset, yoffset, zoffset, width, height, depth, pixelData);
+ ImageD3D *image = getImage(index);
+ ASSERT(image);
+
+ error = image->loadCompressedData(area, pixelData);
if (error.isError())
{
return error;
@@ -284,8 +322,8 @@ bool TextureD3D::isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum siz
return unpack.pixelBuffer.id() != 0 && mRenderer->supportsFastCopyBufferToTexture(sizedInternalFormat);
}
-gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
- GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget)
+gl::Error TextureD3D::fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget)
{
// No-op
if (destArea.width <= 0 && destArea.height <= 0 && destArea.depth <= 0)
@@ -333,7 +371,7 @@ TextureStorage *TextureD3D::getStorage()
return mTexStorage;
}
-Image *TextureD3D::getBaseLevelImage() const
+ImageD3D *TextureD3D::getBaseLevelImage() const
{
return getImage(getImageIndex(0, 0));
}
@@ -347,6 +385,23 @@ gl::Error TextureD3D::generateMipmaps()
return gl::Error(GL_NO_ERROR); // no-op
}
+ if (mTexStorage && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // Switch to using the mipmapped texture.
+ TextureStorage *textureStorage = NULL;
+ gl::Error error = getNativeTexture(&textureStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = textureStorage->useLevelZeroWorkaroundTexture(false);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
// Set up proper mipmap chain in our Image array.
initMipmapsImages();
@@ -365,9 +420,10 @@ gl::Error TextureD3D::generateMipmaps()
{
gl::ImageIndex srcIndex = getImageIndex(0, layer);
- Image *image = getImage(srcIndex);
- gl::Rectangle area(0, 0, image->getWidth(), image->getHeight());
- gl::Error error = image->copy(0, 0, 0, area, srcIndex, mTexStorage);
+ ImageD3D *image = getImage(srcIndex);
+ gl::Box area(0, 0, 0, image->getWidth(), image->getHeight(), image->getDepth());
+ gl::Offset offset(0, 0, 0);
+ gl::Error error = image->copy(offset, area, srcIndex, mTexStorage);
if (error.isError())
{
return error;
@@ -384,7 +440,12 @@ gl::Error TextureD3D::generateMipmaps()
}
}
- bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget());
+ // TODO: Decouple this from zeroMaxLodWorkaround. This is a 9_3 restriction, unrelated to zeroMaxLodWorkaround.
+ // The restriction is because Feature Level 9_3 can't create SRVs on individual levels of the texture.
+ // As a result, even if the storage is a rendertarget, we can't use the GPU to generate the mipmaps without further work.
+ // The D3D9 renderer works around this by copying each level of the texture into its own single-layer GPU texture (in Blit9::boxFilter).
+ // Feature Level 9_3 could do something similar, or it could continue to use CPU-side mipmap generation, or something else.
+ bool renderableStorage = (mTexStorage && mTexStorage->isRenderTarget() && !(mRenderer->getWorkarounds().zeroMaxLodWorkaround));
for (GLint layer = 0; layer < layerCount; ++layer)
{
@@ -416,19 +477,24 @@ gl::Error TextureD3D::generateMipmaps()
}
}
+ if (mTexStorage)
+ {
+ updateStorage();
+ }
+
return gl::Error(GL_NO_ERROR);
}
bool TextureD3D::isBaseImageZeroSize() const
{
- Image *baseImage = getBaseLevelImage();
+ ImageD3D *baseImage = getBaseLevelImage();
if (!baseImage || baseImage->getWidth() <= 0)
{
return true;
}
- if (!gl::IsCubemapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
+ if (!gl::IsCubeMapTextureTarget(baseImage->getTarget()) && baseImage->getHeight() <= 0)
{
return true;
}
@@ -487,7 +553,7 @@ gl::Error TextureD3D::ensureRenderTarget()
bool TextureD3D::canCreateRenderTargetForImage(const gl::ImageIndex &index) const
{
- Image *image = getImage(index);
+ ImageD3D *image = getImage(index);
bool levelsComplete = (isImageComplete(index) && isImageComplete(getImageIndex(0, 0)));
return (image->isRenderableFormat() && levelsComplete);
}
@@ -497,9 +563,8 @@ gl::Error TextureD3D::commitRegion(const gl::ImageIndex &index, const gl::Box &r
if (mTexStorage)
{
ASSERT(isValidIndex(index));
- Image *image = getImage(index);
- ImageD3D *imageD3D = ImageD3D::makeImageD3D(image);
- gl::Error error = imageD3D->copyToStorage(mTexStorage, index, region);
+ ImageD3D *image = getImage(index);
+ gl::Error error = image->copyToStorage(mTexStorage, index, region);
if (error.isError())
{
return error;
@@ -516,7 +581,7 @@ TextureD3D_2D::TextureD3D_2D(RendererD3D *renderer)
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
- mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
+ mImageArray[i] = renderer->createImage();
}
}
@@ -533,14 +598,14 @@ TextureD3D_2D::~TextureD3D_2D()
SafeDelete(mTexStorage);
}
-Image *TextureD3D_2D::getImage(int level, int layer) const
+ImageD3D *TextureD3D_2D::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(layer == 0);
return mImageArray[level];
}
-Image *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
+ImageD3D *TextureD3D_2D::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(!index.hasLayer());
@@ -578,30 +643,21 @@ GLenum TextureD3D_2D::getInternalFormat(GLint level) const
return GL_NONE;
}
-GLenum TextureD3D_2D::getActualFormat(GLint level) const
-{
- if (level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mImageArray[level]->getActualFormat();
- else
- return GL_NONE;
-}
-
bool TextureD3D_2D::isDepth(GLint level) const
{
return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
- GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
- const void *pixels)
+gl::Error TextureD3D_2D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(target == GL_TEXTURE_2D && depth == 1);
+ ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
bool fastUnpacked = false;
- redefineImage(level, sizedInternalFormat, width, height);
+ redefineImage(level, sizedInternalFormat, size);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
@@ -609,7 +665,7 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs
if (isFastUnpackable(unpack, sizedInternalFormat) && isLevelComplete(level))
{
// Will try to create RT storage if it does not exist
- RenderTarget *destRenderTarget = NULL;
+ RenderTargetD3D *destRenderTarget = NULL;
gl::Error error = getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -632,7 +688,7 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs
if (!fastUnpacked)
{
- gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
+ gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0);
if (error.isError())
{
return error;
@@ -642,89 +698,80 @@ gl::Error TextureD3D_2D::setImage(GLenum target, GLint level, GLsizei width, GLs
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2D::setCompressedImage(GLenum target, GLint level, GLenum format,
- GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(target == GL_TEXTURE_2D && depth == 1);
+ ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, format, width, height);
-
- return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]);
-}
-
-gl::Error TextureD3D_2D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const void *pixels)
-{
- ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
-
- bool fastUnpacked = false;
+ if (unpack.skipRows != 0 || unpack.skipPixels != 0 || unpack.imageHeight != 0 || unpack.skipImages != 0)
+ {
+ UNIMPLEMENTED();
+ return gl::Error(GL_INVALID_OPERATION, "unimplemented pixel store state");
+ }
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- gl::Box destArea(xoffset, yoffset, 0, width, height, 1);
if (isFastUnpackable(unpack, getInternalFormat(level)) && isLevelComplete(level))
{
- RenderTarget *renderTarget = NULL;
+ RenderTargetD3D *renderTarget = NULL;
gl::Error error = getRenderTarget(index, &renderTarget);
if (error.isError())
{
return error;
}
- error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- // Ensure we don't overwrite our newly initialized data
- mImageArray[level]->markClean();
+ ASSERT(!mImageArray[level]->isDirty());
- fastUnpacked = true;
+ return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, renderTarget);
}
-
- if (!fastUnpacked)
+ else
{
- return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type,
- unpack, pixels, index);
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
}
+}
- return gl::Error(GL_NO_ERROR);
+
+gl::Error TextureD3D_2D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_2D && size.depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size);
+
+ return TextureD3D::setCompressedImage(gl::ImageIndex::Make2D(level), unpack, pixels, 0);
}
-gl::Error TextureD3D_2D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(target == GL_TEXTURE_2D && depth == 1 && zoffset == 0);
+ ASSERT(target == GL_TEXTURE_2D && area.depth == 1 && area.z == 0);
- gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[level]);
+ gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
if (error.isError())
{
return error;
}
- gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- gl::Box region(xoffset, yoffset, 0, width, height, 1);
- return commitRegion(index, region);
+ return commitRegion(index, area);
}
-gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
- gl::Framebuffer *source)
+gl::Error TextureD3D_2D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
{
ASSERT(target == GL_TEXTURE_2D);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
- redefineImage(level, sizedInternalFormat, width, height);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
+ redefineImage(level, sizedInternalFormat, gl::Extents(sourceArea.width, sourceArea.height, 1));
- gl::Rectangle sourceRect(x, y, width, height);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
+ gl::Offset destOffset(0, 0, 0);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error = mImageArray[level]->copy(0, 0, 0, sourceRect, source);
+ gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -742,9 +789,9 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GL
mImageArray[level]->markClean();
- if (width != 0 && height != 0 && isValidLevel(level))
+ if (sourceArea.width != 0 && sourceArea.height != 0 && isValidLevel(level))
{
- gl::Error error = mRenderer->copyImage2D(source, sourceRect, format, 0, 0, mTexStorage, level);
+ error = mRenderer->copyImage2D(source, sourceArea, internalFormat, destOffset, mTexStorage, level);
if (error.isError())
{
return error;
@@ -755,20 +802,21 @@ gl::Error TextureD3D_2D::copyImage(GLenum target, GLint level, GLenum format, GL
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
{
- ASSERT(target == GL_TEXTURE_2D && zoffset == 0);
+ ASSERT(target == GL_TEXTURE_2D && destOffset.z == 0);
// can only make our texture storage to a render target if level 0 is defined (with a width & height) and
// the current level we're copying to is defined (with appropriate format, width & height)
- gl::Rectangle sourceRect(x, y, width, height);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error = mImageArray[level]->copy(xoffset, yoffset, 0, sourceRect, source);
+ gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -792,9 +840,9 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset,
return error;
}
- error = mRenderer->copyImage2D(source, sourceRect,
+ error = mRenderer->copyImage2D(source, sourceArea,
gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- xoffset, yoffset, mTexStorage, level);
+ destOffset, mTexStorage, level);
if (error.isError())
{
return error;
@@ -805,25 +853,26 @@ gl::Error TextureD3D_2D::copySubImage(GLenum target, GLint level, GLint xoffset,
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_2D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
- ASSERT(target == GL_TEXTURE_2D && depth == 1);
+ ASSERT(GL_TEXTURE_2D && size.depth == 1);
- for (int level = 0; level < levels; level++)
+ for (size_t 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);
+ gl::Extents levelSize(std::max(1, size.width >> level),
+ std::max(1, size.height >> level),
+ 1);
+ mImageArray[level]->redefine(GL_TEXTURE_2D, internalFormat, levelSize, true);
}
for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
+ mImageArray[level]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true);
}
// TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorage2D(internalformat, renderTarget, width, height, levels);
+ TextureStorage *storage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, size.width, size.height, levels, false);
gl::Error error = setCompleteTexStorage(storage);
if (error.isError())
@@ -832,6 +881,13 @@ gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalf
return error;
}
+ error = updateStorage();
+
+ if (error.isError())
+ {
+ return error;
+ }
+
mImmutable = true;
return gl::Error(GL_NO_ERROR);
@@ -839,16 +895,20 @@ gl::Error TextureD3D_2D::storage(GLenum target, GLsizei levels, GLenum internalf
void TextureD3D_2D::bindTexImage(egl::Surface *surface)
{
- GLenum internalformat = surface->getFormat();
+ GLenum internalformat = surface->getConfig()->renderTargetFormat;
- mImageArray[0]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, surface->getWidth(), surface->getHeight(), 1, true);
+ gl::Extents size(surface->getWidth(), surface->getHeight(), 1);
+ mImageArray[0]->redefine(GL_TEXTURE_2D, internalformat, size, true);
if (mTexStorage)
{
SafeDelete(mTexStorage);
}
- mTexStorage = mRenderer->createTextureStorage2D(surface->getSwapChain());
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+ ASSERT(surfaceD3D);
+
+ mTexStorage = mRenderer->createTextureStorage2D(surfaceD3D->getSwapChain());
mDirtyImages = true;
}
@@ -862,7 +922,7 @@ void TextureD3D_2D::releaseTexImage()
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
- mImageArray[i]->redefine(mRenderer, GL_TEXTURE_2D, GL_NONE, 0, 0, 0, true);
+ mImageArray[i]->redefine(GL_TEXTURE_2D, GL_NONE, gl::Extents(0, 0, 0), true);
}
}
@@ -872,9 +932,11 @@ void TextureD3D_2D::initMipmapsImages()
int levelCount = mipLevels();
for (int level = 1; level < levelCount; level++)
{
- redefineImage(level, getBaseLevelInternalFormat(),
- std::max(getBaseLevelWidth() >> level, 1),
- std::max(getBaseLevelHeight() >> level, 1));
+ gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1),
+ std::max(getBaseLevelHeight() >> level, 1),
+ 1);
+
+ redefineImage(level, getBaseLevelInternalFormat(), levelSize);
}
}
@@ -884,7 +946,7 @@ unsigned int TextureD3D_2D::getRenderTargetSerial(const gl::ImageIndex &index)
return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
}
-gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureD3D_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
@@ -916,7 +978,7 @@ bool TextureD3D_2D::isLevelComplete(int level) const
return true;
}
- const Image *baseImage = getBaseLevelImage();
+ const ImageD3D *baseImage = getBaseLevelImage();
GLsizei width = baseImage->getWidth();
GLsizei height = baseImage->getHeight();
@@ -1012,8 +1074,20 @@ gl::Error TextureD3D_2D::createCompleteStorage(bool renderTarget, TextureStorage
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(width, height, 1));
+ bool hintLevelZeroOnly = false;
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorage2D should use the mipped texture to begin with.
+ // Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+ {
+ hintLevelZeroOnly = !(mImageArray[level]->isDirty() && isLevelComplete(level));
+ }
+ }
+
// TODO(geofflang): Determine if the texture creation succeeded
- *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels);
+ *outTexStorage = mRenderer->createTextureStorage2D(internalFormat, renderTarget, width, height, levels, hintLevelZeroOnly);
return gl::Error(GL_NO_ERROR);
}
@@ -1078,22 +1152,24 @@ gl::Error TextureD3D_2D::updateStorageLevel(int level)
return gl::Error(GL_NO_ERROR);
}
-void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height)
+void TextureD3D_2D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
{
+ ASSERT(size.depth == 1);
+
// If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
- mImageArray[level]->redefine(mRenderer, GL_TEXTURE_2D, internalformat, width, height, 1, false);
+ mImageArray[level]->redefine(GL_TEXTURE_2D, internalformat, size, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
internalformat != storageFormat) // Discard mismatched storage
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
@@ -1131,7 +1207,7 @@ TextureD3D_Cube::TextureD3D_Cube(RendererD3D *renderer)
{
for (int j = 0; j < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++j)
{
- mImageArray[i][j] = ImageD3D::makeImageD3D(renderer->createImage());
+ mImageArray[i][j] = renderer->createImage();
}
}
}
@@ -1152,17 +1228,17 @@ TextureD3D_Cube::~TextureD3D_Cube()
SafeDelete(mTexStorage);
}
-Image *TextureD3D_Cube::getImage(int level, int layer) const
+ImageD3D *TextureD3D_Cube::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(layer < 6);
+ ASSERT(layer >= 0 && layer < 6);
return mImageArray[layer][level];
}
-Image *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
+ImageD3D *TextureD3D_Cube::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(index.layerIndex < 6);
+ ASSERT(index.layerIndex >= 0 && index.layerIndex < 6);
return mImageArray[index.layerIndex][index.mipIndex];
}
@@ -1185,75 +1261,75 @@ bool TextureD3D_Cube::isDepth(GLint level, GLint layer) const
return gl::GetInternalFormatInfo(getInternalFormat(level, layer)).depthBits > 0;
}
-gl::Error TextureD3D_Cube::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
- GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
- const void *pixels)
+gl::Error TextureD3D_Cube::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(depth == 1);
+ ASSERT(size.depth == 1);
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- redefineImage(index.layerIndex, level, sizedInternalFormat, width, height);
+ redefineImage(index.layerIndex, level, sizedInternalFormat, size);
- return TextureD3D::setImage(unpack, type, pixels, index);
+ return TextureD3D::setImage(index, type, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, GLint level, GLenum format,
- GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_Cube::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(depth == 1);
-
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+ ASSERT(area.depth == 1 && area.z == 0);
- redefineImage(faceIndex, level, format, width, height);
-
- return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[faceIndex][level]);
+ gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_Cube::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(depth == 1 && zoffset == 0);
+ ASSERT(size.depth == 1);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
+
+ redefineImage(faceIndex, level, internalFormat, size);
+
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- return TextureD3D::subImage(xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels, index);
+ return TextureD3D::setCompressedImage(index, unpack, pixels, 0);
}
-gl::Error TextureD3D_Cube::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_Cube::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
- ASSERT(depth == 1 && zoffset == 0);
+ ASSERT(area.depth == 1 && area.z == 0);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels, mImageArray[index.layerIndex][level]);
+ gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
if (error.isError())
{
return error;
}
- gl::Box region(xoffset, yoffset, 0, width, height, 1);
- return commitRegion(index, region);
+ return commitRegion(index, area);
}
-gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
- GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_Cube::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
{
- int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, GL_UNSIGNED_BYTE);
+ size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
+ GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, GL_UNSIGNED_BYTE);
- redefineImage(faceIndex, level, sizedInternalFormat, width, height);
+ gl::Extents size(sourceArea.width, sourceArea.height, 1);
+ redefineImage(faceIndex, level, sizedInternalFormat, size);
- gl::Rectangle sourceRect(x, y, width, height);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
+ gl::Offset destOffset(0, 0, 0);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error = mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
+ gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -1271,11 +1347,11 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format,
mImageArray[faceIndex][level]->markClean();
- ASSERT(width == height);
+ ASSERT(size.width == size.height);
- if (width > 0 && isValidFaceLevel(faceIndex, level))
+ if (size.width > 0 && isValidFaceLevel(faceIndex, level))
{
- error = mRenderer->copyImageCube(source, sourceRect, format, 0, 0, mTexStorage, target, level);
+ error = mRenderer->copyImageCube(source, sourceArea, internalFormat, destOffset, mTexStorage, target, level);
if (error.isError())
{
return error;
@@ -1286,17 +1362,18 @@ gl::Error TextureD3D_Cube::copyImage(GLenum target, GLint level, GLenum format,
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_Cube::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
{
- int faceIndex = gl::TextureCubeMap::targetToLayerIndex(target);
+ size_t faceIndex = gl::CubeMapTextureTargetToLayerIndex(target);
- gl::Rectangle sourceRect(x, y, width, height);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- if (!canCreateRenderTargetForImage(index))
+ // If the zero max LOD workaround is active, then we can't sample from individual layers of the framebuffer in shaders,
+ // so we should use the non-rendering copy path.
+ if (!canCreateRenderTargetForImage(index) || mRenderer->getWorkarounds().zeroMaxLodWorkaround)
{
- gl::Error error =mImageArray[faceIndex][level]->copy(0, 0, 0, sourceRect, source);
+ gl::Error error = mImageArray[faceIndex][level]->copy(destOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -1320,8 +1397,8 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffse
return error;
}
- error = mRenderer->copyImageCube(source, sourceRect, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- xoffset, yoffset, mTexStorage, target, level);
+ error = mRenderer->copyImageCube(source, sourceArea, gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
+ destOffset, mTexStorage, target, level);
if (error.isError())
{
return error;
@@ -1332,17 +1409,17 @@ gl::Error TextureD3D_Cube::copySubImage(GLenum target, GLint level, GLint xoffse
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_Cube::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
- ASSERT(width == height);
- ASSERT(depth == 1);
+ ASSERT(size.width == size.height);
+ ASSERT(size.depth == 1);
- for (int level = 0; level < levels; level++)
+ for (size_t level = 0; level < levels; level++)
{
- GLsizei mipSize = std::max(1, width >> level);
+ GLsizei mipSize = std::max(1, size.width >> level);
for (int faceIndex = 0; faceIndex < 6; faceIndex++)
{
- mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, mipSize, mipSize, 1, true);
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalFormat, gl::Extents(mipSize, mipSize, 1), true);
}
}
@@ -1350,13 +1427,14 @@ gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum interna
{
for (int faceIndex = 0; faceIndex < 6; faceIndex++)
{
- mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, GL_NONE, 0, 0, 0, true);
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, GL_NONE, gl::Extents(0, 0, 0), true);
}
}
// TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorageCube(internalformat, renderTarget, width, levels);
+
+ TextureStorage *storage = mRenderer->createTextureStorageCube(internalFormat, renderTarget, size.width, levels, false);
gl::Error error = setCompleteTexStorage(storage);
if (error.isError())
@@ -1365,6 +1443,13 @@ gl::Error TextureD3D_Cube::storage(GLenum target, GLsizei levels, GLenum interna
return error;
}
+ error = updateStorage();
+
+ if (error.isError())
+ {
+ return error;
+ }
+
mImmutable = true;
return gl::Error(GL_NO_ERROR);
@@ -1417,19 +1502,20 @@ void TextureD3D_Cube::initMipmapsImages()
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);
+ redefineImage(faceIndex, level, mImageArray[faceIndex][0]->getInternalFormat(),
+ gl::Extents(faceLevelSize, faceLevelSize, 1));
}
}
}
unsigned int TextureD3D_Cube::getRenderTargetSerial(const gl::ImageIndex &index)
{
- return (ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
+ return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
}
-gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureD3D_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
- ASSERT(gl::IsCubemapTextureTarget(index.type));
+ ASSERT(gl::IsCubeMapTextureTarget(index.type));
// ensure the underlying texture is created
gl::Error error = ensureRenderTarget();
@@ -1498,8 +1584,23 @@ gl::Error TextureD3D_Cube::createCompleteStorage(bool renderTarget, TextureStora
// use existing storage level count, when previously specified by TexStorage*D
GLint levels = (mTexStorage ? mTexStorage->getLevelCount() : creationLevels(size, size, 1));
+ bool hintLevelZeroOnly = false;
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // If any of the CPU images (levels >= 1) are dirty, then the textureStorage should use the mipped texture to begin with.
+ // Otherwise, it should use the level-zero-only texture.
+ hintLevelZeroOnly = true;
+ for (int faceIndex = 0; faceIndex < 6 && hintLevelZeroOnly; faceIndex++)
+ {
+ for (int level = 1; level < levels && hintLevelZeroOnly; level++)
+ {
+ hintLevelZeroOnly = !(mImageArray[faceIndex][level]->isDirty() && isFaceLevelComplete(faceIndex, level));
+ }
+ }
+ }
+
// TODO (geofflang): detect if storage creation succeeded
- *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels);
+ *outTexStorage = mRenderer->createTextureStorageCube(getBaseLevelInternalFormat(), renderTarget, size, levels, hintLevelZeroOnly);
return gl::Error(GL_NO_ERROR);
}
@@ -1607,7 +1708,7 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
if (image->isDirty())
{
- GLenum faceTarget = gl::TextureCubeMap::layerIndexToTarget(faceIndex);
+ GLenum faceTarget = gl::LayerIndexToCubeMapTextureTarget(faceIndex);
gl::ImageIndex index = gl::ImageIndex::MakeCube(faceTarget, level);
gl::Box region(0, 0, 0, image->getWidth(), image->getHeight(), 1);
gl::Error error = commitRegion(index, region);
@@ -1620,29 +1721,29 @@ gl::Error TextureD3D_Cube::updateStorageFaceLevel(int faceIndex, int level)
return gl::Error(GL_NO_ERROR);
}
-void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height)
+void TextureD3D_Cube::redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size)
{
// If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
const int storageHeight = std::max(1, getBaseLevelHeight() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
- mImageArray[faceIndex][level]->redefine(mRenderer, GL_TEXTURE_CUBE_MAP, internalformat, width, height, 1, false);
+ mImageArray[faceIndex][level]->redefine(GL_TEXTURE_CUBE_MAP, internalformat, size, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
internalformat != storageFormat) // Discard mismatched storage
{
- for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
{
- for (int faceIndex = 0; faceIndex < 6; faceIndex++)
+ for (int dirtyFace = 0; dirtyFace < 6; dirtyFace++)
{
- mImageArray[faceIndex][level]->markDirty();
+ mImageArray[dirtyFace][dirtyLevel]->markDirty();
}
}
@@ -1661,12 +1762,12 @@ gl::ImageIndexIterator TextureD3D_Cube::imageIterator() const
gl::ImageIndex TextureD3D_Cube::getImageIndex(GLint mip, GLint layer) const
{
// The "layer" of the image index corresponds to the cube face
- return gl::ImageIndex::MakeCube(gl::TextureCubeMap::layerIndexToTarget(layer), mip);
+ return gl::ImageIndex::MakeCube(gl::LayerIndexToCubeMapTextureTarget(layer), mip);
}
bool TextureD3D_Cube::isValidIndex(const gl::ImageIndex &index) const
{
- return (mTexStorage && gl::IsCubemapTextureTarget(index.type) &&
+ return (mTexStorage && gl::IsCubeMapTextureTarget(index.type) &&
index.mipIndex >= 0 && index.mipIndex < mTexStorage->getLevelCount());
}
@@ -1675,7 +1776,7 @@ TextureD3D_3D::TextureD3D_3D(RendererD3D *renderer)
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; ++i)
{
- mImageArray[i] = ImageD3D::makeImageD3D(renderer->createImage());
+ mImageArray[i] = renderer->createImage();
}
}
@@ -1692,14 +1793,14 @@ TextureD3D_3D::~TextureD3D_3D()
SafeDelete(mTexStorage);
}
-Image *TextureD3D_3D::getImage(int level, int layer) const
+ImageD3D *TextureD3D_3D::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(layer == 0);
return mImageArray[level];
}
-Image *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
+ImageD3D *TextureD3D_3D::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
ASSERT(!index.hasLayer());
@@ -1750,24 +1851,23 @@ bool TextureD3D_3D::isDepth(GLint level) const
return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
- GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
- const void *pixels)
+gl::Error TextureD3D_3D::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_3D);
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
- redefineImage(level, sizedInternalFormat, width, height, depth);
+ redefineImage(level, sizedInternalFormat, size);
bool fastUnpacked = false;
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
- if (isFastUnpackable(unpack, sizedInternalFormat))
+ if (isFastUnpackable(unpack, sizedInternalFormat) && !size.empty())
{
// Will try to create RT storage if it does not exist
- RenderTarget *destRenderTarget = NULL;
+ RenderTargetD3D *destRenderTarget = NULL;
gl::Error error = getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -1790,7 +1890,7 @@ gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLs
if (!fastUnpacked)
{
- gl::Error error = TextureD3D::setImage(unpack, type, pixels, index);
+ gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, 0);
if (error.isError())
{
return error;
@@ -1800,96 +1900,77 @@ gl::Error TextureD3D_3D::setImage(GLenum target, GLint level, GLsizei width, GLs
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_3D::setCompressedImage(GLenum target, GLint level, GLenum format,
- GLsizei width, GLsizei height,GLsizei depth,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_3D::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_3D);
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, format, width, height, depth);
-
- return TextureD3D::setCompressedImage(unpack, imageSize, pixels, mImageArray[level]);
-}
-
-gl::Error TextureD3D_3D::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const void *pixels)
-{
- ASSERT(target == GL_TEXTURE_3D);
-
- bool fastUnpacked = false;
-
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
// Attempt a fast gpu copy of the pixel data to the surface if the app bound an unpack buffer
if (isFastUnpackable(unpack, getInternalFormat(level)))
{
- RenderTarget *destRenderTarget = NULL;
+ RenderTargetD3D *destRenderTarget = NULL;
gl::Error error = getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
return error;
}
- gl::Box destArea(xoffset, yoffset, zoffset, width, height, depth);
- error = fastUnpackPixels(unpack, pixels, destArea, getInternalFormat(level), type, destRenderTarget);
- if (error.isError())
- {
- return error;
- }
-
- // Ensure we don't overwrite our newly initialized data
- mImageArray[level]->markClean();
+ ASSERT(!mImageArray[level]->isDirty());
- fastUnpacked = true;
+ return fastUnpackPixels(unpack, pixels, area, getInternalFormat(level), type, destRenderTarget);
}
-
- if (!fastUnpacked)
+ else
{
- return TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, depth, format, type,
- unpack, pixels, index);
+ return TextureD3D::subImage(index, area, format, type, unpack, pixels, 0);
}
+}
- return gl::Error(GL_NO_ERROR);
+gl::Error TextureD3D_3D::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
+{
+ ASSERT(target == GL_TEXTURE_3D);
+
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size);
+
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ return TextureD3D::setCompressedImage(index, unpack, pixels, 0);
}
-gl::Error TextureD3D_3D::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_3D::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_3D);
- gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, depth,
- format, imageSize, unpack, pixels, mImageArray[level]);
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level);
+ gl::Error error = TextureD3D::subImageCompressed(index, area, format, unpack, pixels, 0);
if (error.isError())
{
return error;
}
- gl::ImageIndex index = gl::ImageIndex::Make3D(level);
- gl::Box region(xoffset, yoffset, zoffset, width, height, depth);
- return commitRegion(index, region);
+ return commitRegion(index, area);
}
-gl::Error TextureD3D_3D::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
- GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_3D::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION, "Copying 3D textures is unimplemented.");
}
-gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_3D::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
{
ASSERT(target == GL_TEXTURE_3D);
- gl::Rectangle sourceRect(x, y, width, height);
gl::ImageIndex index = gl::ImageIndex::Make3D(level);
if (canCreateRenderTargetForImage(index))
{
- gl::Error error = mImageArray[level]->copy(xoffset, yoffset, zoffset, sourceRect, source);
+ gl::Error error = mImageArray[level]->copy(destOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -1913,9 +1994,9 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset,
return error;
}
- error = mRenderer->copyImage3D(source, sourceRect,
+ error = mRenderer->copyImage3D(source, sourceArea,
gl::GetInternalFormatInfo(getBaseLevelInternalFormat()).format,
- xoffset, yoffset, zoffset, mTexStorage, level);
+ destOffset, mTexStorage, level);
if (error.isError())
{
return error;
@@ -1926,26 +2007,26 @@ gl::Error TextureD3D_3D::copySubImage(GLenum target, GLint level, GLint xoffset,
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_3D::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
ASSERT(target == GL_TEXTURE_3D);
- for (int level = 0; level < levels; level++)
+ for (size_t 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);
+ gl::Extents levelSize(std::max(1, size.width >> level),
+ std::max(1, size.height >> level),
+ std::max(1, size.depth >> level));
+ mImageArray[level]->redefine(GL_TEXTURE_3D, internalFormat, levelSize, true);
}
for (int level = levels; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, GL_NONE, 0, 0, 0, true);
+ mImageArray[level]->redefine(GL_TEXTURE_3D, GL_NONE, gl::Extents(0, 0, 0), true);
}
// TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorage3D(internalformat, renderTarget, width, height, depth, levels);
+ TextureStorage *storage = mRenderer->createTextureStorage3D(internalFormat, renderTarget, size.width, size.height, size.depth, levels);
gl::Error error = setCompleteTexStorage(storage);
if (error.isError())
@@ -1954,6 +2035,13 @@ gl::Error TextureD3D_3D::storage(GLenum target, GLsizei levels, GLenum internalf
return error;
}
+ error = updateStorage();
+
+ if (error.isError())
+ {
+ return error;
+ }
+
mImmutable = true;
return gl::Error(GL_NO_ERROR);
@@ -1976,10 +2064,10 @@ void TextureD3D_3D::initMipmapsImages()
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));
+ gl::Extents levelSize(std::max(getBaseLevelWidth() >> level, 1),
+ std::max(getBaseLevelHeight() >> level, 1),
+ std::max(getBaseLevelDepth() >> level, 1));
+ redefineImage(level, getBaseLevelInternalFormat(), levelSize);
}
}
@@ -1988,7 +2076,7 @@ unsigned int TextureD3D_3D::getRenderTargetSerial(const gl::ImageIndex &index)
return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
}
-gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureD3D_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
// ensure the underlying texture is created
gl::Error error = ensureRenderTarget();
@@ -2031,7 +2119,7 @@ gl::Error TextureD3D_3D::initializeStorage(bool renderTarget)
return gl::Error(GL_NO_ERROR);
}
- bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
TextureStorage *storage = NULL;
gl::Error error = createCompleteStorage(createRenderTarget, &storage);
@@ -2185,7 +2273,7 @@ gl::Error TextureD3D_3D::updateStorageLevel(int level)
return gl::Error(GL_NO_ERROR);
}
-void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
{
// If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
@@ -2193,16 +2281,16 @@ void TextureD3D_3D::redefineImage(GLint level, GLenum internalformat, GLsizei wi
const int storageDepth = std::max(1, getBaseLevelDepth() >> level);
const GLenum storageFormat = getBaseLevelInternalFormat();
- mImageArray[level]->redefine(mRenderer, GL_TEXTURE_3D, internalformat, width, height, depth, false);
+ mImageArray[level]->redefine(GL_TEXTURE_3D, internalformat, size, false);
if (mTexStorage)
{
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
- depth != storageDepth ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
+ size.depth != storageDepth ||
internalformat != storageFormat) // Discard mismatched storage
{
for (int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
@@ -2253,19 +2341,21 @@ TextureD3D_2DArray::~TextureD3D_2DArray()
SafeDelete(mTexStorage);
}
-Image *TextureD3D_2DArray::getImage(int level, int layer) const
+ImageD3D *TextureD3D_2DArray::getImage(int level, int layer) const
{
ASSERT(level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(layer < mLayerCounts[level]);
- return mImageArray[level][layer];
+ ASSERT((layer == 0 && mLayerCounts[level] == 0) ||
+ layer < mLayerCounts[level]);
+ return (mImageArray[level] ? mImageArray[level][layer] : NULL);
}
-Image *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
+ImageD3D *TextureD3D_2DArray::getImage(const gl::ImageIndex &index) const
{
ASSERT(index.mipIndex < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS);
- ASSERT(index.layerIndex < mLayerCounts[index.mipIndex]);
+ ASSERT((index.layerIndex == 0 && mLayerCounts[index.mipIndex] == 0) ||
+ index.layerIndex < mLayerCounts[index.mipIndex]);
ASSERT(index.type == GL_TEXTURE_2D_ARRAY);
- return mImageArray[index.mipIndex][index.layerIndex];
+ return (mImageArray[index.mipIndex] ? mImageArray[index.mipIndex][index.layerIndex] : NULL);
}
GLsizei TextureD3D_2DArray::getLayerCount(int level) const
@@ -2294,24 +2384,23 @@ bool TextureD3D_2DArray::isDepth(GLint level) const
return gl::GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
}
-gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth,
- GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack,
- const void *pixels)
+gl::Error TextureD3D_2DArray::setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
GLenum sizedInternalFormat = gl::GetSizedInternalFormat(internalFormat, type);
- redefineImage(level, sizedInternalFormat, width, height, depth);
+ redefineImage(level, sizedInternalFormat, size);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, size.width, size.height, unpack.alignment, unpack.rowLength);
- for (int i = 0; i < depth; i++)
+ for (int i = 0; i < size.depth; i++)
{
- const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
- gl::Error error = TextureD3D::setImage(unpack, type, layerPixels, index);
+ gl::Error error = TextureD3D::setImage(index, type, unpack, pixels, layerOffset);
if (error.isError())
{
return error;
@@ -2321,22 +2410,23 @@ gl::Error TextureD3D_2DArray::setImage(GLenum target, GLint level, GLsizei width
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLenum format,
- GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2DArray::setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
- // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
- redefineImage(level, format, width, height, depth);
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
- for (int i = 0; i < depth; i++)
+ for (int i = 0; i < area.depth; i++)
{
- const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
- gl::Error error = TextureD3D::setCompressedImage(unpack, imageSize, layerPixels, mImageArray[level][i]);
+ int layer = area.z + i;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
+
+ gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+ gl::Error error = TextureD3D::subImage(index, layerArea, format, type, unpack, pixels, layerOffset);
if (error.isError())
{
return error;
@@ -2346,23 +2436,23 @@ gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, GLint level, GLe
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type,
- const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2DArray::setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(level));
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+ // compressed formats don't have separate sized internal formats-- we can just use the compressed format directly
+ redefineImage(level, internalFormat, size);
- for (int i = 0; i < depth; i++)
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, size.width, size.height, 1, 0);
+
+ for (int i = 0; i < size.depth; i++)
{
- int layer = zoffset + i;
- const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
- gl::Error error = TextureD3D::subImage(xoffset, yoffset, zoffset, width, height, 1, format, type,
- unpack, layerPixels, index);
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, i);
+ gl::Error error = TextureD3D::setCompressedImage(index, unpack, pixels, layerOffset);
if (error.isError())
{
return error;
@@ -2372,29 +2462,29 @@ gl::Error TextureD3D_2DArray::subImage(GLenum target, GLint level, GLint xoffset
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels)
+gl::Error TextureD3D_2DArray::setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
- for (int i = 0; i < depth; i++)
+ for (int i = 0; i < area.depth; i++)
{
- int layer = zoffset + i;
- const void *layerPixels = pixels ? (reinterpret_cast<const unsigned char*>(pixels) + (inputDepthPitch * i)) : NULL;
+ int layer = area.z + i;
+ const ptrdiff_t layerOffset = (inputDepthPitch * i);
- gl::Error error = TextureD3D::subImageCompressed(xoffset, yoffset, zoffset, width, height, 1, format, imageSize, unpack, layerPixels, mImageArray[level][layer]);
+ gl::Box layerArea(area.x, area.y, 0, area.width, area.height, 1);
+
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
+ gl::Error error = TextureD3D::subImageCompressed(index, layerArea, format, unpack, pixels, layerOffset);
if (error.isError())
{
return error;
}
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, layer);
- gl::Box region(xoffset, yoffset, 0, width, height, 1);
- error = commitRegion(index, region);
+ error = commitRegion(index, layerArea);
if (error.isError())
{
return error;
@@ -2404,22 +2494,24 @@ gl::Error TextureD3D_2DArray::subImageCompressed(GLenum target, GLint level, GLi
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2DArray::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2DArray::copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source)
{
UNIMPLEMENTED();
return gl::Error(GL_INVALID_OPERATION, "Copying 2D array textures is unimplemented.");
}
-gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source)
+gl::Error TextureD3D_2DArray::copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
- gl::Rectangle sourceRect(x, y, width, height);
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zoffset);
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
if (canCreateRenderTargetForImage(index))
{
- gl::Error error = mImageArray[level][zoffset]->copy(xoffset, yoffset, 0, sourceRect, source);
+ gl::Offset destLayerOffset(destOffset.x, destOffset.y, 0);
+ gl::Error error = mImageArray[level][destOffset.z]->copy(destLayerOffset, sourceArea, source);
if (error.isError())
{
return error;
@@ -2443,8 +2535,8 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xof
return error;
}
- error = mRenderer->copyImage2DArray(source, sourceRect, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
- xoffset, yoffset, zoffset, mTexStorage, level);
+ error = mRenderer->copyImage2DArray(source, sourceArea, gl::GetInternalFormatInfo(getInternalFormat(0)).format,
+ destOffset, mTexStorage, level);
if (error.isError())
{
return error;
@@ -2454,18 +2546,19 @@ gl::Error TextureD3D_2DArray::copySubImage(GLenum target, GLint level, GLint xof
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+gl::Error TextureD3D_2DArray::setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size)
{
ASSERT(target == GL_TEXTURE_2D_ARRAY);
deleteImages();
- for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ for (size_t level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
- GLsizei levelWidth = std::max(1, width >> level);
- GLsizei levelHeight = std::max(1, height >> level);
+ gl::Extents levelLayerSize(std::max(1, size.width >> level),
+ std::max(1, size.height >> level),
+ 1);
- mLayerCounts[level] = (level < levels ? depth : 0);
+ mLayerCounts[level] = (level < levels ? size.depth : 0);
if (mLayerCounts[level] > 0)
{
@@ -2474,16 +2567,15 @@ gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum inte
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);
+ mImageArray[level][layer] = mRenderer->createImage();
+ mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalFormat, levelLayerSize, true);
}
}
}
// TODO(geofflang): Verify storage creation had no errors
bool renderTarget = IsRenderTargetUsage(mUsage);
- TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalformat, renderTarget, width, height, depth, levels);
+ TextureStorage *storage = mRenderer->createTextureStorage2DArray(internalFormat, renderTarget, size.width, size.height, size.depth, levels);
gl::Error error = setCompleteTexStorage(storage);
if (error.isError())
@@ -2492,6 +2584,13 @@ gl::Error TextureD3D_2DArray::storage(GLenum target, GLsizei levels, GLenum inte
return error;
}
+ error = updateStorage();
+
+ if (error.isError())
+ {
+ return error;
+ }
+
mImmutable = true;
return gl::Error(GL_NO_ERROR);
@@ -2512,14 +2611,17 @@ void TextureD3D_2DArray::initMipmapsImages()
{
int baseWidth = getBaseLevelWidth();
int baseHeight = getBaseLevelHeight();
- int baseDepth = getBaseLevelDepth();
+ int baseDepth = getLayerCount(0);
GLenum baseFormat = getBaseLevelInternalFormat();
// Purge array levels 1 through q and reset them to represent the generated mipmap levels.
int levelCount = mipLevels();
for (int level = 1; level < levelCount; level++)
{
- redefineImage(level, baseFormat, std::max(baseWidth >> level, 1), std::max(baseHeight >> level, 1), baseDepth);
+ gl::Extents levelLayerSize(std::max(baseWidth >> level, 1),
+ std::max(baseHeight >> level, 1),
+ baseDepth);
+ redefineImage(level, baseFormat, levelLayerSize);
}
}
@@ -2528,7 +2630,7 @@ unsigned int TextureD3D_2DArray::getRenderTargetSerial(const gl::ImageIndex &ind
return (!ensureRenderTarget().isError() ? mTexStorage->getRenderTargetSerial(index) : 0);
}
-gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureD3D_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
// ensure the underlying texture is created
gl::Error error = ensureRenderTarget();
@@ -2560,7 +2662,7 @@ gl::Error TextureD3D_2DArray::initializeStorage(bool renderTarget)
return gl::Error(GL_NO_ERROR);
}
- bool createRenderTarget = (renderTarget || mUsage == GL_FRAMEBUFFER_ATTACHMENT_ANGLE);
+ bool createRenderTarget = (renderTarget || IsRenderTargetUsage(mUsage));
TextureStorage *storage = NULL;
gl::Error error = createCompleteStorage(createRenderTarget, &storage);
@@ -2730,7 +2832,7 @@ void TextureD3D_2DArray::deleteImages()
}
}
-void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, const gl::Extents &size)
{
// If there currently is a corresponding storage texture image, it has these parameters
const int storageWidth = std::max(1, getBaseLevelWidth() >> level);
@@ -2744,16 +2846,17 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz
}
delete[] mImageArray[level];
mImageArray[level] = NULL;
- mLayerCounts[level] = depth;
+ mLayerCounts[level] = size.depth;
- if (depth > 0)
+ if (size.depth > 0)
{
- mImageArray[level] = new ImageD3D*[depth]();
+ mImageArray[level] = new ImageD3D*[size.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);
+ mImageArray[level][layer] = mRenderer->createImage();
+ mImageArray[level][layer]->redefine(GL_TEXTURE_2D_ARRAY, internalformat,
+ gl::Extents(size.width, size.height, 1), false);
}
}
@@ -2762,16 +2865,16 @@ void TextureD3D_2DArray::redefineImage(GLint level, GLenum internalformat, GLsiz
const int storageLevels = mTexStorage->getLevelCount();
if ((level >= storageLevels && storageLevels != 0) ||
- width != storageWidth ||
- height != storageHeight ||
- depth != storageDepth ||
+ size.width != storageWidth ||
+ size.height != storageHeight ||
+ size.depth != storageDepth ||
internalformat != storageFormat) // Discard mismatched storage
{
- for (int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
+ for (int dirtyLevel = 0; dirtyLevel < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; dirtyLevel++)
{
- for (int layer = 0; layer < mLayerCounts[level]; layer++)
+ for (int dirtyLayer = 0; dirtyLayer < mLayerCounts[dirtyLevel]; dirtyLayer++)
{
- mImageArray[level][layer]->markDirty();
+ mImageArray[dirtyLevel][dirtyLayer]->markDirty();
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h
index 083a6335b9..d94be49a08 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureD3D.h
@@ -6,12 +6,12 @@
// TextureD3D.h: Implementations of the Texture interfaces shared betweeen the D3D backends.
-#ifndef LIBGLESV2_RENDERER_TEXTURED3D_H_
-#define LIBGLESV2_RENDERER_TEXTURED3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
-#include "libGLESv2/renderer/TextureImpl.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Constants.h"
+#include "libANGLE/renderer/TextureImpl.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Constants.h"
namespace gl
{
@@ -21,10 +21,10 @@ class Framebuffer;
namespace rx
{
-class Image;
+class ImageD3D;
class ImageD3D;
class RendererD3D;
-class RenderTarget;
+class RenderTargetD3D;
class TextureStorage;
class TextureD3D : public TextureImpl
@@ -33,14 +33,15 @@ class TextureD3D : public TextureImpl
TextureD3D(RendererD3D *renderer);
virtual ~TextureD3D();
- static TextureD3D *makeTextureD3D(TextureImpl *texture);
-
- TextureStorage *getNativeTexture();
+ gl::Error getNativeTexture(TextureStorage **outStorage);
virtual void setUsage(GLenum usage) { mUsage = usage; }
bool hasDirtyImages() const { return mDirtyImages; }
void resetDirty() { mDirtyImages = false; }
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const = 0;
+ virtual GLsizei getLayerCount(int level) const = 0;
+
GLint getBaseLevelWidth() const;
GLint getBaseLevelHeight() const;
GLint getBaseLevelDepth() const;
@@ -48,7 +49,7 @@ class TextureD3D : public TextureImpl
bool isImmutable() const { return mImmutable; }
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index) = 0;
// Returns an iterator over all "Images" for this particular Texture.
@@ -61,18 +62,21 @@ class TextureD3D : public TextureImpl
virtual gl::Error generateMipmaps();
TextureStorage *getStorage();
- Image *getBaseLevelImage() const;
+ ImageD3D *getBaseLevelImage() const;
protected:
- gl::Error setImage(const gl::PixelUnpackState &unpack, GLenum type, const void *pixels, const gl::ImageIndex &index);
- gl::Error subImage(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels, const gl::ImageIndex &index);
- gl::Error setCompressedImage(const gl::PixelUnpackState &unpack, GLsizei imageSize, const void *pixels, Image *image);
- gl::Error subImageCompressed(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels, Image *image);
+ gl::Error setImage(const gl::ImageIndex &index, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels,
+ ptrdiff_t layerOffset);
+ gl::Error subImage(const gl::ImageIndex &index, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
+ gl::Error setCompressedImage(const gl::ImageIndex &index, const gl::PixelUnpackState &unpack,
+ const uint8_t *pixels, ptrdiff_t layerOffset);
+ gl::Error subImageCompressed(const gl::ImageIndex &index, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels, ptrdiff_t layerOffset);
bool isFastUnpackable(const gl::PixelUnpackState &unpack, GLenum sizedInternalFormat);
- gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const void *pixels, const gl::Box &destArea,
- GLenum sizedInternalFormat, GLenum type, RenderTarget *destRenderTarget);
+ gl::Error fastUnpackPixels(const gl::PixelUnpackState &unpack, const uint8_t *pixels, const gl::Box &destArea,
+ GLenum sizedInternalFormat, GLenum type, RenderTargetD3D *destRenderTarget);
GLint creationLevels(GLsizei width, GLsizei height, GLsizei depth) const;
int mipLevels() const;
@@ -97,13 +101,11 @@ class TextureD3D : public TextureImpl
TextureStorage *mTexStorage;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureD3D);
-
virtual gl::Error initializeStorage(bool renderTarget) = 0;
virtual gl::Error updateStorage() = 0;
- bool shouldUseSetData(const Image *image) const;
+ bool shouldUseSetData(const ImageD3D *image) const;
};
class TextureD3D_2D : public TextureD3D
@@ -112,28 +114,36 @@ class TextureD3D_2D : public TextureD3D
TextureD3D_2D(RendererD3D *renderer);
virtual ~TextureD3D_2D();
- virtual Image *getImage(int level, int layer) const;
- virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
virtual GLsizei getLayerCount(int level) const;
GLsizei getWidth(GLint level) const;
GLsizei getHeight(GLint level) const;
GLenum getInternalFormat(GLint level) const;
- GLenum getActualFormat(GLint level) const;
bool isDepth(GLint level) const;
- virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
virtual gl::ImageIndexIterator imageIterator() const;
@@ -141,8 +151,6 @@ class TextureD3D_2D : public TextureD3D
virtual bool isValidIndex(const gl::ImageIndex &index) const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureD3D_2D);
-
virtual gl::Error initializeStorage(bool renderTarget);
virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
@@ -156,7 +164,7 @@ class TextureD3D_2D : public TextureD3D
gl::Error updateStorageLevel(int level);
- void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height);
+ void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
@@ -167,8 +175,8 @@ class TextureD3D_Cube : public TextureD3D
TextureD3D_Cube(RendererD3D *renderer);
virtual ~TextureD3D_Cube();
- virtual Image *getImage(int level, int layer) const;
- virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
virtual GLsizei getLayerCount(int level) const;
virtual bool hasDirtyImages() const { return mDirtyImages; }
@@ -178,18 +186,27 @@ class TextureD3D_Cube : public TextureD3D
GLenum getInternalFormat(GLint level, GLint layer) const;
bool isDepth(GLint level, GLint layer) const;
- virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
virtual gl::ImageIndexIterator imageIterator() const;
@@ -197,8 +214,6 @@ class TextureD3D_Cube : public TextureD3D
virtual bool isValidIndex(const gl::ImageIndex &index) const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureD3D_Cube);
-
virtual gl::Error initializeStorage(bool renderTarget);
virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outTexStorage) const;
virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
@@ -212,7 +227,7 @@ class TextureD3D_Cube : public TextureD3D
virtual bool isImageComplete(const gl::ImageIndex &index) const;
gl::Error updateStorageFaceLevel(int faceIndex, int level);
- void redefineImage(int faceIndex, GLint level, GLenum internalformat, GLsizei width, GLsizei height);
+ void redefineImage(int faceIndex, GLint level, GLenum internalformat, const gl::Extents &size);
ImageD3D *mImageArray[6][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
@@ -223,8 +238,8 @@ class TextureD3D_3D : public TextureD3D
TextureD3D_3D(RendererD3D *renderer);
virtual ~TextureD3D_3D();
- virtual Image *getImage(int level, int layer) const;
- virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
virtual GLsizei getLayerCount(int level) const;
GLsizei getWidth(GLint level) const;
@@ -233,18 +248,27 @@ class TextureD3D_3D : public TextureD3D
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
- virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
virtual gl::ImageIndexIterator imageIterator() const;
@@ -252,8 +276,6 @@ class TextureD3D_3D : public TextureD3D
virtual bool isValidIndex(const gl::ImageIndex &index) const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureD3D_3D);
-
virtual gl::Error initializeStorage(bool renderTarget);
virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
@@ -266,7 +288,7 @@ class TextureD3D_3D : public TextureD3D
virtual bool isImageComplete(const gl::ImageIndex &index) const;
gl::Error updateStorageLevel(int level);
- void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
ImageD3D *mImageArray[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
};
@@ -277,8 +299,8 @@ class TextureD3D_2DArray : public TextureD3D
TextureD3D_2DArray(RendererD3D *renderer);
virtual ~TextureD3D_2DArray();
- virtual Image *getImage(int level, int layer) const;
- virtual Image *getImage(const gl::ImageIndex &index) const;
+ virtual ImageD3D *getImage(int level, int layer) const;
+ virtual ImageD3D *getImage(const gl::ImageIndex &index) const;
virtual GLsizei getLayerCount(int level) const;
GLsizei getWidth(GLint level) const;
@@ -286,18 +308,27 @@ class TextureD3D_2DArray : public TextureD3D
GLenum getInternalFormat(GLint level) const;
bool isDepth(GLint level) const;
- virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels);
- virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source);
- virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ gl::Error setImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format, GLenum type,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error setCompressedImage(GLenum target, size_t level, GLenum internalFormat, const gl::Extents &size,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+ gl::Error setCompressedSubImage(GLenum target, size_t level, const gl::Box &area, GLenum format,
+ const gl::PixelUnpackState &unpack, const uint8_t *pixels) override;
+
+ gl::Error copyImage(GLenum target, size_t level, const gl::Rectangle &sourceArea, GLenum internalFormat,
+ const gl::Framebuffer *source) override;
+ gl::Error copySubImage(GLenum target, size_t level, const gl::Offset &destOffset, const gl::Rectangle &sourceArea,
+ const gl::Framebuffer *source) override;
+
+ gl::Error setStorage(GLenum target, size_t levels, GLenum internalFormat, const gl::Extents &size) override;
virtual void bindTexImage(egl::Surface *surface);
virtual void releaseTexImage();
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual unsigned int getRenderTargetSerial(const gl::ImageIndex &index);
virtual gl::ImageIndexIterator imageIterator() const;
@@ -305,8 +336,6 @@ class TextureD3D_2DArray : public TextureD3D
virtual bool isValidIndex(const gl::ImageIndex &index) const;
private:
- DISALLOW_COPY_AND_ASSIGN(TextureD3D_2DArray);
-
virtual gl::Error initializeStorage(bool renderTarget);
virtual gl::Error createCompleteStorage(bool renderTarget, TextureStorage **outStorage) const;
virtual gl::Error setCompleteTexStorage(TextureStorage *newCompleteTexStorage);
@@ -320,7 +349,7 @@ class TextureD3D_2DArray : public TextureD3D
gl::Error updateStorageLevel(int level);
void deleteImages();
- void redefineImage(GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ void redefineImage(GLint level, GLenum internalformat, const gl::Extents &size);
// Storing images as an array of single depth textures since D3D11 treats each array level of a
// Texture2D object as a separate subresource. Each layer would have to be looped over
@@ -332,4 +361,4 @@ class TextureD3D_2DArray : public TextureD3D
}
-#endif // LIBGLESV2_RENDERER_TEXTURED3D_H_
+#endif // LIBANGLE_RENDERER_D3D_TEXTURED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp
index 320b74b8ed..abb83a14d5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.cpp
@@ -6,12 +6,12 @@
// TextureStorage.cpp: Shared members of abstract rx::TextureStorage class.
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Texture.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Texture.h"
#include "common/debug.h"
#include "common/mathutil.h"
@@ -26,7 +26,7 @@ TextureStorage::TextureStorage()
void TextureStorage::initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride)
{
- mFirstRenderTargetSerial = RenderTarget::issueSerials(rtSerialsToReserve);
+ mFirstRenderTargetSerial = RenderTargetD3D::issueSerials(rtSerialsToReserve);
mRenderTargetSerialsLayerStride = rtSerialsLayerStride;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h
index da92be3c74..ae2d42ca8a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TextureStorage.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TextureStorage.h
@@ -6,16 +6,16 @@
// TextureStorage.h: Defines the abstract rx::TextureStorage class.
-#ifndef LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
-#define LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
+#ifndef LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
+#define LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include "common/debug.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include <GLES2/gl2.h>
-#include <cstdint>
+#include <stdint.h>
namespace gl
{
@@ -26,11 +26,11 @@ struct PixelUnpackState;
namespace rx
{
-class SwapChain;
-class RenderTarget;
-class Image;
+class SwapChainD3D;
+class RenderTargetD3D;
+class ImageD3D;
-class TextureStorage
+class TextureStorage : angle::NonCopyable
{
public:
TextureStorage();
@@ -41,26 +41,27 @@ class TextureStorage
virtual bool isManaged() const = 0;
virtual int getLevelCount() const = 0;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex) = 0;
virtual gl::Error copyToStorage(TextureStorage *destStorage) = 0;
- virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+ virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData) = 0;
unsigned int getRenderTargetSerial(const gl::ImageIndex &index) const;
unsigned int getTextureSerial() const;
+ // This is a no-op for most implementations of TextureStorage. Some (e.g. TextureStorage11_2D) might override it.
+ virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture) { return gl::Error(GL_NO_ERROR); }
+
protected:
void initializeSerials(unsigned int rtSerialsToReserve, unsigned int rtSerialsLayerStride);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage);
-
unsigned int mFirstRenderTargetSerial;
unsigned int mRenderTargetSerialsLayerStride;
};
}
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE_H_
+#endif // LIBANGLE_RENDERER_D3D_TEXTURESTORAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp
index 11596006d0..5c0bfdcd5b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp
@@ -6,7 +6,7 @@
// TransformFeedbackD3D.cpp is a no-op implementation for both the D3D9 and D3D11 renderers.
-#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
+#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h
index 7c367aba1d..6b255b4a2b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h
@@ -6,11 +6,11 @@
// TransformFeedbackD3D.h: Implements the abstract rx::TransformFeedbackImpl class.
-#ifndef LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
-#define LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+#ifndef LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+#define LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
-#include "libGLESv2/renderer/TransformFeedbackImpl.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/renderer/TransformFeedbackImpl.h"
+#include "libANGLE/angletypes.h"
namespace rx
{
@@ -29,4 +29,4 @@ class TransformFeedbackD3D : public TransformFeedbackImpl
}
-#endif // LIBGLESV2_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
+#endif // LIBANGLE_RENDERER_D3D_TRANSFORMFEEDBACKD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
index 73f0c79e19..19bd548fce 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.cpp
@@ -7,10 +7,10 @@
// VertexBuffer.cpp: Defines the abstract VertexBuffer class and VertexBufferInterface
// class with derivations, classes that perform graphics API agnostic vertex buffer operations.
-#include "libGLESv2/renderer/d3d/VertexBuffer.h"
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/VertexAttribute.h"
#include "common/mathutil.h"
@@ -38,13 +38,14 @@ unsigned int VertexBuffer::getSerial() const
return mSerial;
}
-VertexBufferInterface::VertexBufferInterface(RendererD3D *renderer, bool dynamic) : mRenderer(renderer)
+VertexBufferInterface::VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic)
+ : mFactory(factory)
{
mDynamic = dynamic;
mWritePosition = 0;
mReservedSpace = 0;
- mVertexBuffer = renderer->createVertexBuffer();
+ mVertexBuffer = factory->createVertexBuffer();
}
VertexBufferInterface::~VertexBufferInterface()
@@ -167,7 +168,7 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att
const gl::VertexAttribCurrentValueData &currentValue) const
{
gl::Buffer *buffer = attrib.buffer.get();
- BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+ BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
if (!storage || !storage->supportsDirectBinding())
{
@@ -188,7 +189,8 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att
getVertexBuffer()->getSpaceRequired(attrib, 1, 0, &outputElementSize);
alignment = std::min<size_t>(outputElementSize, 4);
- requiresConversion = (mRenderer->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0;
+ // TODO(jmadill): add VertexFormatCaps
+ requiresConversion = (mFactory->getVertexConversionType(vertexFormat) & VERTEX_CONVERT_CPU) != 0;
}
bool isAligned = (static_cast<size_t>(ComputeVertexAttributeStride(attrib)) % alignment == 0) &&
@@ -197,7 +199,8 @@ bool VertexBufferInterface::directStoragePossible(const gl::VertexAttribute &att
return !requiresConversion && isAligned;
}
-StreamingVertexBufferInterface::StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize) : VertexBufferInterface(renderer, true)
+StreamingVertexBufferInterface::StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize)
+ : VertexBufferInterface(factory, true)
{
setBufferSize(initialSize);
}
@@ -231,7 +234,8 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
return gl::Error(GL_NO_ERROR);
}
-StaticVertexBufferInterface::StaticVertexBufferInterface(RendererD3D *renderer) : VertexBufferInterface(renderer, false)
+StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
+ : VertexBufferInterface(factory, false)
{
}
@@ -293,7 +297,7 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt
}
size_t attributeOffset = static_cast<size_t>(attrib.offset) % ComputeVertexAttributeStride(attrib);
- VertexElement element = { attrib.type, attrib.size, ComputeVertexAttributeStride(attrib), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset };
+ VertexElement element = { attrib.type, attrib.size, static_cast<GLuint>(ComputeVertexAttributeStride(attrib)), attrib.normalized, attrib.pureInteger, attributeOffset, streamOffset };
mCache.push_back(element);
if (outStreamOffset)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
index 4b40818f8e..5cb03fe3a1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexBuffer.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexBuffer.h
@@ -7,11 +7,11 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
#include "common/angleutils.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include <GLES2/gl2.h>
@@ -26,9 +26,9 @@ struct VertexAttribCurrentValueData;
namespace rx
{
-class RendererD3D;
+class BufferFactoryD3D;
-class VertexBuffer
+class VertexBuffer : angle::NonCopyable
{
public:
VertexBuffer();
@@ -47,20 +47,21 @@ class VertexBuffer
unsigned int getSerial() const;
+ // This may be overridden (e.g. by VertexBuffer11) if necessary.
+ virtual void hintUnmapResource() { };
+
protected:
void updateSerial();
private:
- DISALLOW_COPY_AND_ASSIGN(VertexBuffer);
-
unsigned int mSerial;
static unsigned int mNextSerial;
};
-class VertexBufferInterface
+class VertexBufferInterface : angle::NonCopyable
{
public:
- VertexBufferInterface(RendererD3D *renderer, bool dynamic);
+ VertexBufferInterface(BufferFactoryD3D *factory, bool dynamic);
virtual ~VertexBufferInterface();
gl::Error reserveVertexSpace(const gl::VertexAttribute &attribute, GLsizei count, GLsizei instances);
@@ -88,9 +89,7 @@ class VertexBufferInterface
gl::Error setBufferSize(unsigned int size);
private:
- DISALLOW_COPY_AND_ASSIGN(VertexBufferInterface);
-
- RendererD3D *const mRenderer;
+ BufferFactoryD3D *const mFactory;
VertexBuffer* mVertexBuffer;
@@ -102,7 +101,7 @@ class VertexBufferInterface
class StreamingVertexBufferInterface : public VertexBufferInterface
{
public:
- StreamingVertexBufferInterface(RendererD3D *renderer, std::size_t initialSize);
+ StreamingVertexBufferInterface(BufferFactoryD3D *factory, std::size_t initialSize);
~StreamingVertexBufferInterface();
protected:
@@ -112,7 +111,7 @@ class StreamingVertexBufferInterface : public VertexBufferInterface
class StaticVertexBufferInterface : public VertexBufferInterface
{
public:
- explicit StaticVertexBufferInterface(RendererD3D *renderer);
+ explicit StaticVertexBufferInterface(BufferFactoryD3D *factory);
~StaticVertexBufferInterface();
gl::Error storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
@@ -141,4 +140,4 @@ class StaticVertexBufferInterface : public VertexBufferInterface
}
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER_H_ \ No newline at end of file
+#endif // LIBANGLE_RENDERER_D3D_VERTEXBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
index 8d3df31c8b..cb70b9e4ef 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.cpp
@@ -7,14 +7,15 @@
// VertexDataManager.h: Defines the VertexDataManager, a class that
// runs the Buffer translation process.
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/VertexBuffer.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/State.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
namespace
{
@@ -46,13 +47,16 @@ static int StreamingBufferElementCount(const gl::VertexAttribute &attrib, int ve
// non-instanced vertices, and the instanced vertex index advances once every "mDivisor" instances.
if (instanceDrawCount > 0 && attrib.divisor > 0)
{
- return instanceDrawCount / attrib.divisor;
+ // When instanceDrawCount is not a multiple attrib.divisor, the division must round up.
+ // For instance, with 5 non-instanced vertices and a divisor equal to 3, we need 2 instanced vertices.
+ return (instanceDrawCount + attrib.divisor - 1) / attrib.divisor;
}
return vertexDrawCount;
}
-VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer)
+VertexDataManager::VertexDataManager(BufferFactoryD3D *factory)
+ : mFactory(factory)
{
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
@@ -65,7 +69,7 @@ VertexDataManager::VertexDataManager(RendererD3D *renderer) : mRenderer(renderer
mCurrentValueOffsets[i] = 0;
}
- mStreamingBuffer = new StreamingVertexBufferInterface(renderer, INITIAL_STREAM_BUFFER_SIZE);
+ mStreamingBuffer = new StreamingVertexBufferInterface(factory, INITIAL_STREAM_BUFFER_SIZE);
if (!mStreamingBuffer)
{
@@ -83,6 +87,35 @@ VertexDataManager::~VertexDataManager()
}
}
+void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes)
+{
+ mStreamingBuffer->getVertexBuffer()->hintUnmapResource();
+
+ for (size_t i = 0; i < vertexAttributes.size(); i++)
+ {
+ const gl::VertexAttribute &attrib = vertexAttributes[i];
+ if (attrib.enabled)
+ {
+ gl::Buffer *buffer = attrib.buffer.get();
+ BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
+ StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
+
+ if (staticBuffer)
+ {
+ staticBuffer->getVertexBuffer()->hintUnmapResource();
+ }
+ }
+ }
+
+ for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (mCurrentValueBuffer[i] != NULL)
+ {
+ mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource();
+ }
+ }
+}
+
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
TranslatedAttribute *translated, GLsizei instances)
{
@@ -91,25 +124,25 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
return gl::Error(GL_OUT_OF_MEMORY, "Internal streaming vertex buffer is unexpectedly NULL.");
}
+ const gl::VertexArray *vertexArray = state.getVertexArray();
+ const std::vector<gl::VertexAttribute> &vertexAttributes = vertexArray->getVertexAttributes();
+
// Invalidate static buffers that don't contain matching attributes
for (int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
{
- translated[attributeIndex].active = (state.getCurrentProgramBinary()->getSemanticIndex(attributeIndex) != -1);
- const gl::VertexAttribute &curAttrib = state.getVertexAttribState(attributeIndex);
-
- if (translated[attributeIndex].active && curAttrib.enabled)
+ translated[attributeIndex].active = (state.getProgram()->getSemanticIndex(attributeIndex) != -1);
+ if (translated[attributeIndex].active && vertexAttributes[attributeIndex].enabled)
{
- invalidateMatchingStaticData(curAttrib, state.getVertexAttribCurrentValue(attributeIndex));
+ invalidateMatchingStaticData(vertexAttributes[attributeIndex], state.getVertexAttribCurrentValue(attributeIndex));
}
}
// Reserve the required space in the buffers
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
- if (translated[i].active && curAttrib.enabled)
+ if (translated[i].active && vertexAttributes[i].enabled)
{
- gl::Error error = reserveSpaceForAttrib(curAttrib, state.getVertexAttribCurrentValue(i), count, instances);
+ gl::Error error = reserveSpaceForAttrib(vertexAttributes[i], state.getVertexAttribCurrentValue(i), count, instances);
if (error.isError())
{
return error;
@@ -120,7 +153,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
// Perform the vertex data translations
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
+ const gl::VertexAttribute &curAttrib = vertexAttributes[i];
if (translated[i].active)
{
if (curAttrib.enabled)
@@ -130,6 +163,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
if (error.isError())
{
+ hintUnmapAllResources(vertexAttributes);
return error;
}
}
@@ -137,7 +171,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
{
if (!mCurrentValueBuffer[i])
{
- mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mRenderer, CONSTANT_VERTEX_BUFFER_SIZE);
+ mCurrentValueBuffer[i] = new StreamingVertexBufferInterface(mFactory, CONSTANT_VERTEX_BUFFER_SIZE);
}
gl::Error error = storeCurrentValue(curAttrib, state.getVertexAttribCurrentValue(i), &translated[i],
@@ -145,22 +179,26 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
mCurrentValueBuffer[i]);
if (error.isError())
{
+ hintUnmapAllResources(vertexAttributes);
return error;
}
}
}
}
+ // Hint to unmap all the resources
+ hintUnmapAllResources(vertexAttributes);
+
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
- const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
+ const gl::VertexAttribute &curAttrib = vertexAttributes[i];
if (translated[i].active && curAttrib.enabled)
{
gl::Buffer *buffer = curAttrib.buffer.get();
if (buffer)
{
- BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
+ BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
bufferImpl->promoteStaticUsage(count * ComputeVertexAttributeTypeSize(curAttrib));
}
}
@@ -176,7 +214,7 @@ void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &
if (buffer)
{
- BufferD3D *bufferImpl = BufferD3D::makeBufferD3D(buffer->getImplementation());
+ BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
if (staticBuffer &&
@@ -195,7 +233,7 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const gl::VertexAttribute &at
GLsizei instances) const
{
gl::Buffer *buffer = attrib.buffer.get();
- BufferD3D *bufferImpl = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+ BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
@@ -239,7 +277,7 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
gl::Buffer *buffer = attrib.buffer.get();
ASSERT(buffer || attrib.pointer);
- BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
+ BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
bool directStorage = vertexBuffer->directStoragePossible(attrib, currentValue);
@@ -247,10 +285,13 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
unsigned int streamOffset = 0;
unsigned int outputElementSize = 0;
+ // Instanced vertices do not apply the 'start' offset
+ GLint firstVertexIndex = (instances > 0 && attrib.divisor > 0 ? 0 : start);
+
if (directStorage)
{
outputElementSize = ComputeVertexAttributeStride(attrib);
- streamOffset = attrib.offset + outputElementSize * start;
+ streamOffset = attrib.offset + outputElementSize * firstVertexIndex;
}
else if (staticBuffer)
{
@@ -266,8 +307,8 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
int totalCount = ElementsInBuffer(attrib, storage->getSize());
int startIndex = attrib.offset / ComputeVertexAttributeStride(attrib);
- gl::Error error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
- 0, &streamOffset);
+ error = staticBuffer->storeVertexAttributes(attrib, currentValue, -startIndex, totalCount,
+ 0, &streamOffset);
if (error.isError())
{
return error;
@@ -275,7 +316,7 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
}
unsigned int firstElementOffset = (attrib.offset / ComputeVertexAttributeStride(attrib)) * outputElementSize;
- unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? start * outputElementSize : 0;
+ unsigned int startOffset = (instances == 0 || attrib.divisor == 0) ? firstVertexIndex * outputElementSize : 0;
if (streamOffset + firstElementOffset + startOffset < streamOffset)
{
return gl::Error(GL_OUT_OF_MEMORY);
@@ -292,7 +333,8 @@ gl::Error VertexDataManager::storeAttribute(const gl::VertexAttribute &attrib,
return error;
}
- error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, start, totalCount, instances, &streamOffset);
+ error = mStreamingBuffer->storeVertexAttributes(attrib, currentValue, firstVertexIndex,
+ totalCount, instances, &streamOffset);
if (error.isError())
{
return error;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
index 64ef653221..898ed340b8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/VertexDataManager.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/VertexDataManager.h
@@ -7,16 +7,15 @@
// VertexDataManager.h: Defines the VertexDataManager, a class that
// runs the Buffer translation process.
-#ifndef LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
-#define LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
+#ifndef LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
+#define LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/VertexAttribute.h"
#include "common/angleutils.h"
namespace gl
{
-class ProgramBinary;
class State;
struct VertexAttribute;
struct VertexAttribCurrentValueData;
@@ -25,9 +24,9 @@ struct VertexAttribCurrentValueData;
namespace rx
{
class BufferD3D;
+class BufferFactoryD3D;
class StreamingVertexBufferInterface;
class VertexBuffer;
-class RendererD3D;
struct TranslatedAttribute
{
@@ -47,18 +46,16 @@ struct TranslatedAttribute
unsigned int divisor;
};
-class VertexDataManager
+class VertexDataManager : angle::NonCopyable
{
public:
- VertexDataManager(RendererD3D *renderer);
+ VertexDataManager(BufferFactoryD3D *factory);
virtual ~VertexDataManager();
gl::Error prepareVertexData(const gl::State &state, GLint start, GLsizei count,
TranslatedAttribute *outAttribs, GLsizei instances);
private:
- DISALLOW_COPY_AND_ASSIGN(VertexDataManager);
-
gl::Error reserveSpaceForAttrib(const gl::VertexAttribute &attrib,
const gl::VertexAttribCurrentValueData &currentValue,
GLsizei count,
@@ -81,7 +78,9 @@ class VertexDataManager
size_t *cachedOffset,
StreamingVertexBufferInterface *buffer);
- RendererD3D *const mRenderer;
+ void hintUnmapAllResources(const std::vector<gl::VertexAttribute> &vertexAttributes);
+
+ BufferFactoryD3D *const mFactory;
StreamingVertexBufferInterface *mStreamingBuffer;
@@ -93,4 +92,4 @@ class VertexDataManager
}
-#endif // LIBGLESV2_RENDERER_VERTEXDATAMANAGER_H_
+#endif // LIBANGLE_RENDERER_D3D_VERTEXDATAMANAGER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp
index aabc9f04e9..b1798454ca 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.cpp
@@ -6,7 +6,7 @@
// copyimage.cpp: Defines image copying functions
-#include "libGLESv2/renderer/copyimage.h"
+#include "libANGLE/renderer/d3d/copyimage.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h
index 513eb5cb3d..189654ca39 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.h
@@ -6,13 +6,13 @@
// copyimage.h: Defines image copying functions
-#ifndef LIBGLESV2_RENDERER_COPYIMAGE_H_
-#define LIBGLESV2_RENDERER_COPYIMAGE_H_
+#ifndef LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
+#define LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
#include "common/mathutil.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/angletypes.h"
-#include <cstdint>
+#include <stdint.h>
namespace rx
{
@@ -32,4 +32,4 @@ void CopyBGRA8ToRGBA8(const uint8_t *source, uint8_t *dest);
#include "copyimage.inl"
-#endif // LIBGLESV2_RENDERER_COPYIMAGE_H_
+#endif // LIBANGLE_RENDERER_D3D_COPYIMAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl
index 0498cf7750..0498cf7750 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyimage.inl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/copyimage.inl
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
index 06aea9befe..e38b61709f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp
@@ -6,56 +6,58 @@
// Blit11.cpp: Texture copy utility class.
-#include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/formatutils.h"
-
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h"
-
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h"
-
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+
+#include <float.h>
+
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/formatutils.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
+
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui3dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlef2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzlei2darrayps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/swizzleui2darrayps.h"
namespace rx
{
@@ -209,7 +211,7 @@ Blit11::Blit11(Renderer11 *renderer)
pointSamplerDesc.BorderColor[2] = 0.0f;
pointSamplerDesc.BorderColor[3] = 0.0f;
pointSamplerDesc.MinLOD = 0.0f;
- pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
+ pointSamplerDesc.MaxLOD = FLT_MAX;
result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
ASSERT(SUCCEEDED(result));
@@ -228,7 +230,7 @@ Blit11::Blit11(Renderer11 *renderer)
linearSamplerDesc.BorderColor[2] = 0.0f;
linearSamplerDesc.BorderColor[3] = 0.0f;
linearSamplerDesc.MinLOD = 0.0f;
- linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
+ linearSamplerDesc.MaxLOD = FLT_MAX;
result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
ASSERT(SUCCEEDED(result));
@@ -290,7 +292,7 @@ Blit11::Blit11(Renderer11 *renderer)
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
- if (!renderer->isLevel9())
+ if (renderer->isES3Capable())
{
result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
ASSERT(SUCCEEDED(result));
@@ -524,7 +526,7 @@ gl::Error Blit11::copyTexture(ID3D11ShaderResourceView *source, const gl::Box &s
BlitParameters parameters = { 0 };
parameters.mDestinationFormat = destFormat;
parameters.mSignedInteger = (internalFormatInfo.componentType == GL_INT);
- parameters.m3DBlit = sourceArea.depth > 1;
+ parameters.m3DBlit = sourceSRVDesc.ViewDimension == D3D11_SRV_DIMENSION_TEXTURE3D;
BlitShaderMap::const_iterator i = mBlitShaderMap.find(parameters);
if (i == mBlitShaderMap.end())
@@ -972,6 +974,7 @@ void Blit11::buildShaderMap()
{
ID3D11Device *device = mRenderer->getDevice();
+ // 2D shaders (OpenGL ES 2+)
add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" ));
add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" ));
add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" ));
@@ -981,50 +984,59 @@ void Blit11::buildShaderMap()
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" ));
+ // 2D shaders (OpenGL ES 3+)
+ if (mRenderer->isES3Capable())
+ {
+ add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" ));
+ add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" ));
+ add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" ));
+ add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" ));
+ add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" ));
+ }
+
+ // 3D shaders (OpenGL ES 3+)
+ if (mRenderer->isES3Capable())
+ {
+ add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" ));
+ add3DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D BGRA pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3D, "Blit11 3D RGB pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB3DUI, "Blit11 3D RGB UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB3DI, "Blit11 3D RGB I pixel shader" ));
+ add3DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG3D, "Blit11 3D RG pixel shader" ));
+ add3DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG3DUI, "Blit11 3D RG UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG3DI, "Blit11 3D RG I pixel shader" ));
+ add3DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR3D, "Blit11 3D R pixel shader" ));
+ add3DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR3DUI, "Blit11 3D R UI pixel shader" ));
+ add3DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR3DI, "Blit11 3D R I pixel shader" ));
+ add3DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D alpha pixel shader" ));
+ add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" ));
+ add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
+ }
+
+ // Swizzling shaders (OpenGL ES 3+)
+ if (mRenderer->isES3Capable())
+ {
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Cube F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Cube UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURECUBE, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Cube I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleF3D, "Blit11 3D F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleUI3D, "Blit11 3D UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE3D, d3d11::CompilePS(device, g_PS_SwizzleI3D, "Blit11 3D I swizzle pixel shader" ));
+
+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleF2DArray, "Blit11 2D Array F swizzle pixel shader" ));
+ addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleUI2DArray, "Blit11 2D Array UI swizzle pixel shader"));
+ addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2DARRAY, d3d11::CompilePS(device, g_PS_SwizzleI2DArray, "Blit11 2D Array I swizzle pixel shader" ));
+ }
}
void Blit11::clearShaderMap()
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
index 821fa9d0cc..d3a8c2c8a3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Blit11.h
@@ -6,12 +6,12 @@
// Blit11.cpp: Texture copy utility class.
-#ifndef LIBGLESV2_BLIT11_H_
-#define LIBGLESV2_BLIT11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
#include <map>
@@ -19,7 +19,7 @@ namespace rx
{
class Renderer11;
-class Blit11
+class Blit11 : angle::NonCopyable
{
public:
explicit Blit11(Renderer11 *renderer);
@@ -114,10 +114,8 @@ class Blit11
ID3D11GeometryShader *mQuad3DGS;
ID3D11Buffer *mSwizzleCB;
-
- DISALLOW_COPY_AND_ASSIGN(Blit11);
};
}
-#endif // LIBGLESV2_BLIT11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BLIT11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
index 5aab37938f..d56b0ea7ad 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
@@ -6,10 +6,17 @@
// Buffer11.cpp Defines the Buffer11 class.
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+
+#include "common/MemoryBuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+#if defined(ANGLE_MINGW32_COMPAT)
+typedef enum D3D11_MAP_FLAG {
+ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000
+} D3D11_MAP_FLAG;
+#endif
namespace rx
{
@@ -67,32 +74,34 @@ D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
}
-// Each instance of Buffer11::BufferStorage11 is specialized for a class of D3D binding points
+// Each instance of Buffer11::BufferStorage is specialized for a class of D3D binding points
// - vertex/transform feedback buffers
// - index buffers
// - pixel unpack buffers
// - uniform buffers
-class Buffer11::BufferStorage11
+class Buffer11::BufferStorage : angle::NonCopyable
{
public:
- virtual ~BufferStorage11() {}
+ virtual ~BufferStorage() {}
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,
+ virtual bool isMappable() const = 0;
+
+ virtual bool copyFromStorage(BufferStorage *source, size_t sourceOffset,
size_t size, size_t destOffset) = 0;
virtual gl::Error resize(size_t size, bool preserveData) = 0;
- virtual void *map(size_t offset, size_t length, GLbitfield access) = 0;
+ virtual uint8_t *map(size_t offset, size_t length, GLbitfield access) = 0;
virtual void unmap() = 0;
+ gl::Error setData(const uint8_t *data, size_t offset, size_t size);
+
protected:
- BufferStorage11(Renderer11 *renderer, BufferUsage usage);
+ BufferStorage(Renderer11 *renderer, BufferUsage usage);
Renderer11 *mRenderer;
DataRevision mRevision;
@@ -102,48 +111,49 @@ class Buffer11::BufferStorage11
// A native buffer storage represents an underlying D3D11 buffer for a particular
// type of storage.
-class Buffer11::NativeBuffer11 : public Buffer11::BufferStorage11
+class Buffer11::NativeStorage : public Buffer11::BufferStorage
{
public:
- NativeBuffer11(Renderer11 *renderer, BufferUsage usage);
- ~NativeBuffer11();
+ NativeStorage(Renderer11 *renderer, BufferUsage usage);
+ ~NativeStorage() override;
- ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; }
+ bool isMappable() const override { return mUsage == BUFFER_USAGE_STAGING; }
- virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
- size_t size, size_t destOffset);
- virtual gl::Error resize(size_t size, bool preserveData);
+ ID3D11Buffer *getNativeStorage() const { return mNativeStorage; }
- virtual void *map(size_t offset, size_t length, GLbitfield access);
- virtual void unmap();
+ bool copyFromStorage(BufferStorage *source, size_t sourceOffset,
+ size_t size, size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
- gl::Error setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
+ uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ void unmap() override;
private:
- ID3D11Buffer *mNativeBuffer;
-
static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer, BufferUsage usage, unsigned int bufferSize);
+
+ ID3D11Buffer *mNativeStorage;
};
// Pack storage represents internal storage for pack buffers. We implement pack buffers
// as CPU memory, tied to a staging texture, for asynchronous texture readback.
-class Buffer11::PackStorage11 : public Buffer11::BufferStorage11
+class Buffer11::PackStorage : public Buffer11::BufferStorage
{
public:
- PackStorage11(Renderer11 *renderer);
- ~PackStorage11();
+ explicit PackStorage(Renderer11 *renderer);
+ ~PackStorage() override;
+
+ bool isMappable() const override { return true; }
- virtual bool copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
- size_t size, size_t destOffset);
- virtual gl::Error resize(size_t size, bool preserveData);
+ bool copyFromStorage(BufferStorage *source, size_t sourceOffset,
+ size_t size, size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
- virtual void *map(size_t offset, size_t length, GLbitfield access);
- virtual void unmap();
+ uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ void unmap() override;
gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
private:
-
gl::Error flushQueuedPackCommand();
ID3D11Texture2D *mStagingTexture;
@@ -155,14 +165,37 @@ class Buffer11::PackStorage11 : public Buffer11::BufferStorage11
bool mDataModified;
};
+// System memory storage stores a CPU memory buffer with our buffer data.
+// For dynamic data, it's much faster to update the CPU memory buffer than
+// it is to update a D3D staging buffer and read it back later.
+class Buffer11::SystemMemoryStorage : public Buffer11::BufferStorage
+{
+ public:
+ explicit SystemMemoryStorage(Renderer11 *renderer);
+ ~SystemMemoryStorage() override {}
+
+ bool isMappable() const override { return true; }
+
+ bool copyFromStorage(BufferStorage *source, size_t sourceOffset,
+ size_t size, size_t destOffset) override;
+ gl::Error resize(size_t size, bool preserveData) override;
+
+ uint8_t *map(size_t offset, size_t length, GLbitfield access) override;
+ void unmap() override;
+
+ MemoryBuffer *getSystemCopy() { return &mSystemCopy; }
+
+ protected:
+ MemoryBuffer mSystemCopy;
+};
Buffer11::Buffer11(Renderer11 *renderer)
- : BufferD3D(),
+ : BufferD3D(renderer),
mRenderer(renderer),
mSize(0),
mMappedStorage(NULL),
- mResolvedDataRevision(0),
- mReadUsageCount(0)
+ mReadUsageCount(0),
+ mHasSystemMemoryStorage(false)
{}
Buffer11::~Buffer11()
@@ -197,54 +230,34 @@ gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
gl::Error Buffer11::getData(const uint8_t **outData)
{
- NativeBuffer11 *stagingBuffer = getStagingBuffer();
+ SystemMemoryStorage *systemMemoryStorage = nullptr;
+ gl::Error error = getSystemMemoryStorage(&systemMemoryStorage);
- if (!stagingBuffer)
+ if (error.isError())
{
- // Out-of-memory
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get internal staging buffer.");
+ *outData = nullptr;
+ return error;
}
- if (stagingBuffer->getDataRevision() > mResolvedDataRevision)
- {
- if (stagingBuffer->getSize() > mResolvedData.size())
- {
- if (!mResolvedData.resize(stagingBuffer->getSize()))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer.");
- }
- }
-
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result);
- }
-
- memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize());
+ mReadUsageCount = 0;
- context->Unmap(stagingBuffer->getNativeBuffer(), 0);
+ ASSERT(systemMemoryStorage->getSize() >= mSize);
- mResolvedDataRevision = stagingBuffer->getDataRevision();
- }
+ *outData = systemMemoryStorage->getSystemCopy()->data();
+ return gl::Error(GL_NO_ERROR);
+}
- mReadUsageCount = 0;
+gl::Error Buffer11::getSystemMemoryStorage(SystemMemoryStorage **storageOut)
+{
+ BufferStorage *memStorageUntyped = getBufferStorage(BUFFER_USAGE_SYSTEM_MEMORY);
- // Only happens if we initialized the buffer with no data (NULL)
- if (mResolvedData.empty())
+ if (memStorageUntyped == nullptr)
{
- if (!mResolvedData.resize(mSize))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize data resolve buffer.");
- }
+ // TODO(jmadill): convert all to errors
+ return gl::Error(GL_OUT_OF_MEMORY);
}
- ASSERT(mResolvedData.size() >= mSize);
-
- *outData = mResolvedData.data();
+ *storageOut = GetAs<SystemMemoryStorage>(memStorageUntyped);
return gl::Error(GL_NO_ERROR);
}
@@ -254,32 +267,46 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
if (data && size > 0)
{
- NativeBuffer11 *stagingBuffer = getStagingBuffer();
+ // Use system memory storage for dynamic buffers.
- if (!stagingBuffer)
+ BufferStorage *writeBuffer = nullptr;
+ if (supportsDirectBinding())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+ writeBuffer = getStagingStorage();
+
+ if (!writeBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+ }
}
+ else
+ {
+ SystemMemoryStorage *systemMemoryStorage = nullptr;
+ gl::Error error = getSystemMemoryStorage(&systemMemoryStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ writeBuffer = systemMemoryStorage;
+ }
+
+ ASSERT(writeBuffer);
// Explicitly resize the staging buffer, preserving data if the new data will not
// completely fill the buffer
- if (stagingBuffer->getSize() < requiredSize)
+ if (writeBuffer->getSize() < requiredSize)
{
bool preserveData = (offset > 0);
- gl::Error error = stagingBuffer->resize(requiredSize, preserveData);
+ gl::Error error = writeBuffer->resize(requiredSize, preserveData);
if (error.isError())
{
return error;
}
}
- gl::Error error = stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset);
- if (error.isError())
- {
- return error;
- }
-
- stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
+ writeBuffer->setData(static_cast<const uint8_t *>(data), offset, size);
+ writeBuffer->setDataRevision(writeBuffer->getDataRevision() + 1);
}
mSize = std::max(mSize, requiredSize);
@@ -293,13 +320,13 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint
Buffer11 *sourceBuffer = makeBuffer11(source);
ASSERT(sourceBuffer != NULL);
- BufferStorage11 *copyDest = getLatestBufferStorage();
+ BufferStorage *copyDest = getLatestBufferStorage();
if (!copyDest)
{
- copyDest = getStagingBuffer();
+ copyDest = getStagingStorage();
}
- BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage();
+ BufferStorage *copySource = sourceBuffer->getLatestBufferStorage();
if (!copySource || !copyDest)
{
@@ -310,11 +337,11 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint
// pack buffer partner, because other native buffers can't be mapped
if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
{
- copySource = sourceBuffer->getStagingBuffer();
+ copySource = sourceBuffer->getStagingStorage();
}
else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
{
- copyDest = getStagingBuffer();
+ copyDest = getStagingStorage();
}
// D3D11 does not allow overlapped copies until 11.1, and only if the
@@ -328,7 +355,7 @@ gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLint
}
else
{
- copySource = getStagingBuffer();
+ copySource = getStagingStorage();
}
}
@@ -345,7 +372,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid
{
ASSERT(!mMappedStorage);
- BufferStorage11 *latestStorage = getLatestBufferStorage();
+ BufferStorage *latestStorage = getLatestBufferStorage();
if (latestStorage &&
(latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
latestStorage->getUsage() == BUFFER_USAGE_STAGING))
@@ -357,7 +384,7 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid
{
// Fall back to using the staging buffer if the latest storage does
// not exist or is not CPU-accessible.
- mMappedStorage = getStagingBuffer();
+ mMappedStorage = getStagingStorage();
}
if (!mMappedStorage)
@@ -371,13 +398,13 @@ gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid
mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
}
- void *mappedBuffer = mMappedStorage->map(offset, length, access);
+ uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access);
if (!mappedBuffer)
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
}
- *mapPtr = mappedBuffer;
+ *mapPtr = static_cast<GLvoid *>(mappedBuffer);
return gl::Error(GL_NO_ERROR);
}
@@ -391,7 +418,7 @@ gl::Error Buffer11::unmap()
void Buffer11::markTransformFeedbackUsage()
{
- BufferStorage11 *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ BufferStorage *transformFeedbackStorage = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
if (transformFeedbackStorage)
{
@@ -405,25 +432,25 @@ void Buffer11::markBufferUsage()
{
mReadUsageCount++;
+ // Free the system memory storage if we decide it isn't being used very often.
const unsigned int usageLimit = 5;
- if (mReadUsageCount > usageLimit && mResolvedData.size() > 0)
+ if (mReadUsageCount > usageLimit && mHasSystemMemoryStorage)
{
- mResolvedData.resize(0);
- mResolvedDataRevision = 0;
- }
-}
+ auto systemMemoryStorageIt = mBufferStorages.find(BUFFER_USAGE_SYSTEM_MEMORY);
+ ASSERT(systemMemoryStorageIt != mBufferStorages.end());
-RendererD3D* Buffer11::getRenderer()
-{
- return mRenderer;
+ SafeDelete(systemMemoryStorageIt->second);
+ mBufferStorages.erase(systemMemoryStorageIt);
+ mHasSystemMemoryStorage = false;
+ }
}
ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage)
{
markBufferUsage();
- BufferStorage11 *bufferStorage = getBufferStorage(usage);
+ BufferStorage *bufferStorage = getBufferStorage(usage);
if (!bufferStorage)
{
@@ -431,14 +458,14 @@ ID3D11Buffer *Buffer11::getBuffer(BufferUsage usage)
return NULL;
}
- ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, bufferStorage));
+ ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, bufferStorage));
- return static_cast<NativeBuffer11*>(bufferStorage)->getNativeBuffer();
+ return static_cast<NativeStorage*>(bufferStorage)->getNativeStorage();
}
ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
{
- BufferStorage11 *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK);
+ BufferStorage *storage = getBufferStorage(BUFFER_USAGE_PIXEL_UNPACK);
if (!storage)
{
@@ -446,8 +473,8 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
return NULL;
}
- ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage));
- ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer();
+ ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, storage));
+ ID3D11Buffer *buffer = static_cast<NativeStorage*>(storage)->getNativeStorage();
auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
@@ -486,9 +513,8 @@ ID3D11ShaderResourceView *Buffer11::getSRV(DXGI_FORMAT srvFormat)
gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
{
- PackStorage11 *packStorage = getPackStorage();
-
- BufferStorage11 *latestStorage = getLatestBufferStorage();
+ PackStorage *packStorage = getPackStorage();
+ BufferStorage *latestStorage = getLatestBufferStorage();
if (packStorage)
{
@@ -503,76 +529,84 @@ gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource,
return gl::Error(GL_NO_ERROR);
}
-Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
+Buffer11::BufferStorage *Buffer11::getBufferStorage(BufferUsage usage)
{
- BufferStorage11 *directBuffer = NULL;
+ BufferStorage *newStorage = NULL;
auto directBufferIt = mBufferStorages.find(usage);
if (directBufferIt != mBufferStorages.end())
{
- directBuffer = directBufferIt->second;
+ newStorage = directBufferIt->second;
}
- if (!directBuffer)
+ if (!newStorage)
{
if (usage == BUFFER_USAGE_PIXEL_PACK)
{
- directBuffer = new PackStorage11(mRenderer);
+ newStorage = new PackStorage(mRenderer);
+ }
+ else if (usage == BUFFER_USAGE_SYSTEM_MEMORY)
+ {
+ newStorage = new SystemMemoryStorage(mRenderer);
+ mHasSystemMemoryStorage = true;
}
else
{
// buffer is not allocated, create it
- directBuffer = new NativeBuffer11(mRenderer, usage);
+ newStorage = new NativeStorage(mRenderer, usage);
}
- mBufferStorages.insert(std::make_pair(usage, directBuffer));
+ mBufferStorages.insert(std::make_pair(usage, newStorage));
}
// resize buffer
- if (directBuffer->getSize() < mSize)
+ if (newStorage->getSize() < mSize)
{
- if (directBuffer->resize(mSize, true).isError())
+ if (newStorage->resize(mSize, true).isError())
{
// Out of memory error
return NULL;
}
}
- BufferStorage11 *latestBuffer = getLatestBufferStorage();
- if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision())
+ BufferStorage *latestBuffer = getLatestBufferStorage();
+ if (latestBuffer && latestBuffer->getDataRevision() > newStorage->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())
+ // Copy through a staging buffer if we're copying from or to a non-staging, mappable
+ // buffer storage. This is because we can't map a GPU buffer, and copy CPU
+ // data directly. If we're already using a staging buffer we're fine.
+ if (latestBuffer->getUsage() != BUFFER_USAGE_STAGING &&
+ newStorage->getUsage() != BUFFER_USAGE_STAGING &&
+ (!latestBuffer->isMappable() || !newStorage->isMappable()))
{
- NativeBuffer11 *stagingBuffer = getStagingBuffer();
+ NativeStorage *stagingBuffer = getStagingStorage();
stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
- directBuffer->setDataRevision(latestBuffer->getDataRevision());
+ stagingBuffer->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))
+ if (newStorage->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0))
{
updateSerial();
}
- directBuffer->setDataRevision(latestBuffer->getDataRevision());
+ newStorage->setDataRevision(latestBuffer->getDataRevision());
}
- return directBuffer;
+ return newStorage;
}
-Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const
+Buffer11::BufferStorage *Buffer11::getLatestBufferStorage() const
{
// Even though we iterate over all the direct buffers, it is expected that only
// 1 or 2 will be present.
- BufferStorage11 *latestStorage = NULL;
+ BufferStorage *latestStorage = NULL;
DataRevision latestRevision = 0;
for (auto it = mBufferStorages.begin(); it != mBufferStorages.end(); it++)
{
- BufferStorage11 *storage = it->second;
+ BufferStorage *storage = it->second;
if (!latestStorage || storage->getDataRevision() > latestRevision)
{
latestStorage = storage;
@@ -580,12 +614,22 @@ Buffer11::BufferStorage11 *Buffer11::getLatestBufferStorage() const
}
}
+ // resize buffer
+ if (latestStorage && latestStorage->getSize() < mSize)
+ {
+ if (latestStorage->resize(mSize, true).isError())
+ {
+ // Out of memory error
+ return NULL;
+ }
+ }
+
return latestStorage;
}
-Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer()
+Buffer11::NativeStorage *Buffer11::getStagingStorage()
{
- BufferStorage11 *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING);
+ BufferStorage *stagingStorage = getBufferStorage(BUFFER_USAGE_STAGING);
if (!stagingStorage)
{
@@ -593,13 +637,13 @@ Buffer11::NativeBuffer11 *Buffer11::getStagingBuffer()
return NULL;
}
- ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage));
- return static_cast<NativeBuffer11*>(stagingStorage);
+ ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, stagingStorage));
+ return static_cast<NativeStorage*>(stagingStorage);
}
-Buffer11::PackStorage11 *Buffer11::getPackStorage()
+Buffer11::PackStorage *Buffer11::getPackStorage()
{
- BufferStorage11 *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK);
+ BufferStorage *packStorage = getBufferStorage(BUFFER_USAGE_PIXEL_PACK);
if (!packStorage)
{
@@ -607,8 +651,8 @@ Buffer11::PackStorage11 *Buffer11::getPackStorage()
return NULL;
}
- ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage));
- return static_cast<PackStorage11*>(packStorage);
+ ASSERT(HAS_DYNAMIC_TYPE(PackStorage*, packStorage));
+ return static_cast<PackStorage*>(packStorage);
}
bool Buffer11::supportsDirectBinding() const
@@ -619,7 +663,7 @@ bool Buffer11::supportsDirectBinding() const
return (mStaticVertexBuffer && mStaticIndexBuffer);
}
-Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage)
+Buffer11::BufferStorage::BufferStorage(Renderer11 *renderer, BufferUsage usage)
: mRenderer(renderer),
mUsage(usage),
mRevision(0),
@@ -627,25 +671,42 @@ Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usa
{
}
-Buffer11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage)
- : BufferStorage11(renderer, usage),
- mNativeBuffer(NULL)
+gl::Error Buffer11::BufferStorage::setData(const uint8_t *data, size_t offset, size_t size)
+{
+ ASSERT(isMappable());
+
+ uint8_t *writePointer = map(offset, size, GL_MAP_WRITE_BIT);
+ if (!writePointer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
+ }
+
+ memcpy(writePointer, data, size);
+
+ unmap();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+Buffer11::NativeStorage::NativeStorage(Renderer11 *renderer, BufferUsage usage)
+ : BufferStorage(renderer, usage),
+ mNativeStorage(NULL)
{
}
-Buffer11::NativeBuffer11::~NativeBuffer11()
+Buffer11::NativeStorage::~NativeStorage()
{
- SafeRelease(mNativeBuffer);
+ SafeRelease(mNativeStorage);
}
// Returns true if it recreates the direct buffer
-bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+bool Buffer11::NativeStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset,
size_t size, size_t destOffset)
{
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
size_t requiredSize = sourceOffset + size;
- bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize;
+ bool createBuffer = !mNativeStorage || mBufferSize < requiredSize;
// (Re)initialize D3D buffer if needed
if (createBuffer)
@@ -654,29 +715,30 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s
resize(source->getSize(), preserveData);
}
- if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK)
+ if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
+ source->getUsage() == BUFFER_USAGE_SYSTEM_MEMORY)
{
- ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source));
+ ASSERT(source->isMappable());
- void *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);
+ uint8_t *sourcePointer = source->map(sourceOffset, size, GL_MAP_READ_BIT);
D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ HRESULT hr = context->Map(mNativeStorage, 0, D3D11_MAP_WRITE, 0, &mappedResource);
UNUSED_ASSERTION_VARIABLE(hr);
ASSERT(SUCCEEDED(hr));
- unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset;
+ uint8_t *destPointer = static_cast<uint8_t *>(mappedResource.pData) + destOffset;
// Offset bounds are validated at the API layer
ASSERT(sourceOffset + size <= destOffset + mBufferSize);
memcpy(destPointer, sourcePointer, size);
- context->Unmap(mNativeBuffer, 0);
+ context->Unmap(mNativeStorage, 0);
source->unmap();
}
else
{
- ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
+ ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));
D3D11_BOX srcBox;
srcBox.left = sourceOffset;
@@ -686,16 +748,16 @@ bool Buffer11::NativeBuffer11::copyFromStorage(BufferStorage11 *source, size_t s
srcBox.front = 0;
srcBox.back = 1;
- ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
- ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer();
+ ASSERT(HAS_DYNAMIC_TYPE(NativeStorage*, source));
+ ID3D11Buffer *sourceBuffer = static_cast<NativeStorage*>(source)->getNativeStorage();
- context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
+ context->CopySubresourceRegion(mNativeStorage, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
}
return createBuffer;
}
-gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
+gl::Error Buffer11::NativeStorage::resize(size_t size, bool preserveData)
{
ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
@@ -711,7 +773,7 @@ gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer, result: 0x%X.", result);
}
- if (mNativeBuffer && preserveData)
+ if (mNativeStorage && preserveData)
{
// We don't call resize if the buffer is big enough already.
ASSERT(mBufferSize <= size);
@@ -724,19 +786,19 @@ gl::Error Buffer11::NativeBuffer11::resize(size_t size, bool preserveData)
srcBox.front = 0;
srcBox.back = 1;
- context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox);
+ context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeStorage, 0, &srcBox);
}
// No longer need the old buffer
- SafeRelease(mNativeBuffer);
- mNativeBuffer = newBuffer;
+ SafeRelease(mNativeStorage);
+ mNativeStorage = newBuffer;
mBufferSize = bufferDesc.ByteWidth;
return gl::Error(GL_NO_ERROR);
}
-void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer,
+void Buffer11::NativeStorage::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer11 *renderer,
BufferUsage usage, unsigned int bufferSize)
{
bufferDesc->ByteWidth = bufferSize;
@@ -754,8 +816,12 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
bufferDesc->Usage = D3D11_USAGE_DEFAULT;
bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
- if (!renderer->isLevel9())
+
+ if (renderer->isES3Capable())
+ {
bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
+ }
+
bufferDesc->CPUAccessFlags = 0;
break;
@@ -782,12 +848,12 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize);
break;
- default:
+ default:
UNREACHABLE();
}
}
-void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield access)
+uint8_t *Buffer11::NativeStorage::map(size_t offset, size_t length, GLbitfield access)
{
ASSERT(mUsage == BUFFER_USAGE_STAGING);
@@ -796,41 +862,22 @@ void *Buffer11::NativeBuffer11::map(size_t offset, size_t length, GLbitfield acc
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);
+ HRESULT result = context->Map(mNativeStorage, 0, d3dMapType, d3dMapFlag, &mappedResource);
UNUSED_ASSERTION_VARIABLE(result);
ASSERT(SUCCEEDED(result));
- return static_cast<GLubyte*>(mappedResource.pData) + offset;
+ return static_cast<uint8_t*>(mappedResource.pData) + offset;
}
-gl::Error Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
-{
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer, result: 0x%X.", result);
- }
-
- uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset;
- memcpy(offsetBufferPointer, data, size);
-
- context->Unmap(mNativeBuffer, 0);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-void Buffer11::NativeBuffer11::unmap()
+void Buffer11::NativeStorage::unmap()
{
ASSERT(mUsage == BUFFER_USAGE_STAGING);
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
- context->Unmap(mNativeBuffer, 0);
+ context->Unmap(mNativeStorage, 0);
}
-Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer)
- : BufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK),
+Buffer11::PackStorage::PackStorage(Renderer11 *renderer)
+ : BufferStorage(renderer, BUFFER_USAGE_PIXEL_PACK),
mStagingTexture(NULL),
mTextureFormat(DXGI_FORMAT_UNKNOWN),
mQueuedPackCommand(NULL),
@@ -838,13 +885,13 @@ Buffer11::PackStorage11::PackStorage11(Renderer11 *renderer)
{
}
-Buffer11::PackStorage11::~PackStorage11()
+Buffer11::PackStorage::~PackStorage()
{
SafeRelease(mStagingTexture);
SafeDelete(mQueuedPackCommand);
}
-bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t sourceOffset,
+bool Buffer11::PackStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset,
size_t size, size_t destOffset)
{
// We copy through a staging buffer when drawing with a pack buffer,
@@ -853,7 +900,7 @@ bool Buffer11::PackStorage11::copyFromStorage(BufferStorage11 *source, size_t so
return false;
}
-gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData)
+gl::Error Buffer11::PackStorage::resize(size_t size, bool preserveData)
{
if (size != mBufferSize)
{
@@ -867,7 +914,7 @@ gl::Error Buffer11::PackStorage11::resize(size_t size, bool preserveData)
return gl::Error(GL_NO_ERROR);
}
-void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield access)
+uint8_t *Buffer11::PackStorage::map(size_t offset, size_t length, GLbitfield access)
{
ASSERT(offset + length <= getSize());
// TODO: fast path
@@ -886,12 +933,12 @@ void *Buffer11::PackStorage11::map(size_t offset, size_t length, GLbitfield acce
return mMemoryBuffer.data() + offset;
}
-void Buffer11::PackStorage11::unmap()
+void Buffer11::PackStorage::unmap()
{
// No-op
}
-gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
+gl::Error Buffer11::PackStorage::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
{
gl::Error error = flushQueuedPackCommand();
if (error.isError())
@@ -963,7 +1010,7 @@ gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT s
return gl::Error(GL_NO_ERROR);
}
-gl::Error Buffer11::PackStorage11::flushQueuedPackCommand()
+gl::Error Buffer11::PackStorage::flushQueuedPackCommand()
{
ASSERT(mMemoryBuffer.size() > 0);
@@ -980,4 +1027,44 @@ gl::Error Buffer11::PackStorage11::flushQueuedPackCommand()
return gl::Error(GL_NO_ERROR);
}
+Buffer11::SystemMemoryStorage::SystemMemoryStorage(Renderer11 *renderer)
+ : Buffer11::BufferStorage(renderer, BUFFER_USAGE_SYSTEM_MEMORY)
+{}
+
+bool Buffer11::SystemMemoryStorage::copyFromStorage(BufferStorage *source, size_t sourceOffset,
+ size_t size, size_t destOffset)
+{
+ ASSERT(source->isMappable());
+ const uint8_t *sourceData = source->map(sourceOffset, size, GL_MAP_READ_BIT);
+ ASSERT(destOffset + size <= mSystemCopy.size());
+ memcpy(mSystemCopy.data() + destOffset, sourceData, size);
+ source->unmap();
+ return true;
+}
+
+gl::Error Buffer11::SystemMemoryStorage::resize(size_t size, bool preserveData)
+{
+ if (mSystemCopy.size() < size)
+ {
+ if (!mSystemCopy.resize(size))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize SystemMemoryStorage");
+ }
+ mBufferSize = size;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+uint8_t *Buffer11::SystemMemoryStorage::map(size_t offset, size_t length, GLbitfield access)
+{
+ ASSERT(!mSystemCopy.empty() && offset + length <= mSystemCopy.size());
+ return mSystemCopy.data() + offset;
+}
+
+void Buffer11::SystemMemoryStorage::unmap()
+{
+ // No-op
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
index 1c06bbf88a..39bafe880e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.h
@@ -6,12 +6,11 @@
// Buffer11.h: Defines the rx::Buffer11 class which implements rx::BufferImpl via rx::BufferD3D.
-#ifndef LIBGLESV2_RENDERER_BUFFER11_H_
-#define LIBGLESV2_RENDERER_BUFFER11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
namespace rx
{
@@ -25,6 +24,7 @@ enum BufferUsage
BUFFER_USAGE_PIXEL_UNPACK,
BUFFER_USAGE_PIXEL_PACK,
BUFFER_USAGE_UNIFORM,
+ BUFFER_USAGE_SYSTEM_MEMORY,
};
struct PackPixelsParams
@@ -60,7 +60,6 @@ class Buffer11 : public BufferD3D
// BufferD3D implementation
virtual size_t getSize() const { return mSize; }
virtual bool supportsDirectBinding() const;
- RendererD3D *getRenderer() override;
// BufferImpl implementation
virtual gl::Error setData(const void* data, size_t size, GLenum usage);
@@ -72,34 +71,33 @@ class Buffer11 : public BufferD3D
virtual void markTransformFeedbackUsage();
private:
- DISALLOW_COPY_AND_ASSIGN(Buffer11);
-
- class BufferStorage11;
- class NativeBuffer11;
- class PackStorage11;
+ class BufferStorage;
+ class NativeStorage;
+ class PackStorage;
+ class SystemMemoryStorage;
Renderer11 *mRenderer;
size_t mSize;
- BufferStorage11 *mMappedStorage;
+ BufferStorage *mMappedStorage;
- std::map<BufferUsage, BufferStorage11*> mBufferStorages;
+ std::map<BufferUsage, BufferStorage*> mBufferStorages;
typedef std::pair<ID3D11Buffer *, ID3D11ShaderResourceView *> BufferSRVPair;
std::map<DXGI_FORMAT, BufferSRVPair> mBufferResourceViews;
- MemoryBuffer mResolvedData;
- DataRevision mResolvedDataRevision;
unsigned int mReadUsageCount;
+ bool mHasSystemMemoryStorage;
void markBufferUsage();
- NativeBuffer11 *getStagingBuffer();
- PackStorage11 *getPackStorage();
+ NativeStorage *getStagingStorage();
+ PackStorage *getPackStorage();
+ gl::Error getSystemMemoryStorage(SystemMemoryStorage **storageOut);
- BufferStorage11 *getBufferStorage(BufferUsage usage);
- BufferStorage11 *getLatestBufferStorage() const;
+ BufferStorage *getBufferStorage(BufferUsage usage);
+ BufferStorage *getLatestBufferStorage() const;
};
}
-#endif // LIBGLESV2_RENDERER_BUFFER11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_BUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
index 7185a05506..057c3bed42 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
@@ -6,23 +6,28 @@
// 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 "libANGLE/renderer/d3d/d3d11/Clear11.h"
+
+#include <algorithm>
+
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
// Precompiled shaders
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearfloat11_fl9ps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
namespace rx
{
@@ -80,7 +85,7 @@ Clear11::ClearShader Clear11::CreateClearShader(ID3D11Device *device, DXGI_FORMA
Clear11::Clear11(Renderer11 *renderer)
: mRenderer(renderer), mClearBlendStates(StructLessThan<ClearBlendInfo>), mClearDepthStencilStates(StructLessThan<ClearDepthStencilInfo>),
- mVertexBuffer(NULL), mRasterizerState(NULL)
+ mVertexBuffer(NULL), mRasterizerState(NULL), mSupportsClearView(false)
{
HRESULT result;
ID3D11Device *device = renderer->getDevice();
@@ -104,7 +109,7 @@ Clear11::Clear11(Renderer11 *renderer)
rsDesc.DepthBias = 0;
rsDesc.DepthBiasClamp = 0.0f;
rsDesc.SlopeScaledDepthBias = 0.0f;
- rsDesc.DepthClipEnable = renderer->isLevel9();
+ rsDesc.DepthClipEnable = TRUE;
rsDesc.ScissorEnable = FALSE;
rsDesc.MultisampleEnable = FALSE;
rsDesc.AntialiasedLineEnable = FALSE;
@@ -113,14 +118,29 @@ Clear11::Clear11(Renderer11 *renderer)
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
- mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
- if (mRenderer->isLevel9()) {
- memset(&mUintClearShader, 0, sizeof(ClearShader));
- memset(&mIntClearShader, 0, sizeof(ClearShader));
- return;
+ if (renderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat_FL9);
+ }
+ else
+ {
+ mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
+ }
+
+ if (renderer->isES3Capable())
+ {
+ mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint );
+ mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint );
+ }
+
+#if defined(ANGLE_ENABLE_D3D11_1)
+ if (renderer->getDeviceContext1IfSupported())
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ mSupportsClearView = (d3d11Options.ClearView != FALSE);
}
- 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 );
+#endif
}
Clear11::~Clear11()
@@ -135,13 +155,16 @@ Clear11::~Clear11()
SafeRelease(mFloatClearShader.vertexShader);
SafeRelease(mFloatClearShader.pixelShader);
- SafeRelease(mUintClearShader.inputLayout);
- SafeRelease(mUintClearShader.vertexShader);
- SafeRelease(mUintClearShader.pixelShader);
+ if (mRenderer->isES3Capable())
+ {
+ SafeRelease(mUintClearShader.inputLayout);
+ SafeRelease(mUintClearShader.vertexShader);
+ SafeRelease(mUintClearShader.pixelShader);
- SafeRelease(mIntClearShader.inputLayout);
- SafeRelease(mIntClearShader.vertexShader);
- SafeRelease(mIntClearShader.pixelShader);
+ SafeRelease(mIntClearShader.inputLayout);
+ SafeRelease(mIntClearShader.vertexShader);
+ SafeRelease(mIntClearShader.pixelShader);
+ }
for (ClearDepthStencilStateMap::iterator i = mClearDepthStencilStates.begin(); i != mClearDepthStencilStates.end(); i++)
{
@@ -153,17 +176,28 @@ Clear11::~Clear11()
SafeRelease(mRasterizerState);
}
-gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
+gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData)
{
- // 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:
+ const auto &colorAttachments = fboData.mColorAttachments;
+ const auto &drawBufferStates = fboData.mDrawBufferStates;
+ const auto *depthAttachment = fboData.mDepthAttachment;
+ const auto *stencilAttachment = fboData.mStencilAttachment;
+
+ ASSERT(colorAttachments.size() == drawBufferStates.size());
+
+ // Iterate over the color buffers which require clearing and determine if they can be
+ // cleared with ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView.
+ // This requires:
// 1) The render target is being cleared to a float value (will be cast to integer when clearing integer
// render targets as expected but does not work the other way around)
// 2) The format of the render target has no color channels that are currently masked out.
// Clear the easy-to-clear buffers on the spot and accumulate the ones that require special work.
//
+ // If these conditions are met, and:
+ // - No scissored clear is needed, then clear using ID3D11DeviceContext::ClearRenderTargetView.
+ // - A scissored clear is needed then clear using ID3D11DeviceContext1::ClearView if available.
+ // Otherwise draw a quad.
+ //
// Also determine if the depth stencil can be cleared with ID3D11DeviceContext::ClearDepthStencilView
// by checking if the stencil write mask covers the entire stencil.
//
@@ -171,18 +205,24 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons
// attribute.
gl::Extents framebufferSize;
- if (frameBuffer->getFirstColorbuffer() != NULL)
+
+ auto iter = std::find_if(colorAttachments.begin(), colorAttachments.end(), [](const gl::FramebufferAttachment *attachment) { return attachment != nullptr; });
+ if (iter != colorAttachments.end())
+ {
+ framebufferSize.width = (*iter)->getWidth();
+ framebufferSize.height = (*iter)->getHeight();
+ framebufferSize.depth = 1;
+ }
+ else if (depthAttachment != nullptr)
{
- gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
- framebufferSize.width = attachment->getWidth();
- framebufferSize.height = attachment->getHeight();
+ framebufferSize.width = depthAttachment->getWidth();
+ framebufferSize.height = depthAttachment->getHeight();
framebufferSize.depth = 1;
}
- else if (frameBuffer->getDepthOrStencilbuffer() != NULL)
+ else if (stencilAttachment != nullptr)
{
- gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
- framebufferSize.width = attachment->getWidth();
- framebufferSize.height = attachment->getHeight();
+ framebufferSize.width = stencilAttachment->getWidth();
+ framebufferSize.height = stencilAttachment->getHeight();
framebufferSize.depth = 1;
}
else
@@ -208,77 +248,96 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons
RenderTarget11* maskedClearDepthStencil = NULL;
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
+ ID3D11DeviceContext1 *deviceContext1 = mRenderer->getDeviceContext1IfSupported();
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ for (size_t colorAttachment = 0; colorAttachment < colorAttachments.size(); colorAttachment++)
{
- if (clearParams.clearColor[colorAttachment] && frameBuffer->isEnabledColorAttachment(colorAttachment))
+ if (clearParams.clearColor[colorAttachment] &&
+ colorAttachments[colorAttachment] != nullptr &&
+ drawBufferStates[colorAttachment] != GL_NONE)
{
- gl::FramebufferAttachment *attachment = frameBuffer->getColorbuffer(colorAttachment);
- if (attachment)
+ const gl::FramebufferAttachment *attachment = colorAttachments[colorAttachment];
+
+ RenderTarget11 *renderTarget = NULL;
+ gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
+ if (error.isError())
{
- RenderTarget11 *renderTarget = NULL;
- gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
- if (error.isError())
- {
- return error;
- }
+ return error;
+ }
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
- if (clearParams.colorClearType == GL_FLOAT &&
- !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
+ if (clearParams.colorClearType == GL_FLOAT &&
+ !(formatInfo.componentType == GL_FLOAT || formatInfo.componentType == GL_UNSIGNED_NORMALIZED || formatInfo.componentType == GL_SIGNED_NORMALIZED))
+ {
+ ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-"
+ "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment,
+ attachment->getInternalFormat());
+ }
+
+ if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
+ (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
+ (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
+ (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
+ {
+ // Every channel either does not exist in the render target or is masked out
+ continue;
+ }
+ else if ((!mSupportsClearView && needScissoredClear) || clearParams.colorClearType != GL_FLOAT ||
+ (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
+ (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
+ (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
+ (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+ {
+ // A masked clear is required, or a scissored clear is required and ID3D11DeviceContext1::ClearView is unavailable
+ MaskedRenderTarget maskAndRt;
+ bool clearColor = clearParams.clearColor[colorAttachment];
+ maskAndRt.colorMask[0] = (clearColor && clearParams.colorMaskRed);
+ maskAndRt.colorMask[1] = (clearColor && clearParams.colorMaskGreen);
+ maskAndRt.colorMask[2] = (clearColor && clearParams.colorMaskBlue);
+ maskAndRt.colorMask[3] = (clearColor && clearParams.colorMaskAlpha);
+ maskAndRt.renderTarget = renderTarget;
+ maskedClearRenderTargets.push_back(maskAndRt);
+ }
+ else
+ {
+ // ID3D11DeviceContext::ClearRenderTargetView or ID3D11DeviceContext1::ClearView is possible
+
+ ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
+ if (!framebufferRTV)
{
- ERR("It is undefined behaviour to clear a render buffer which is not normalized fixed point or floating-"
- "point to floating point values (color attachment %u has internal format 0x%X).", colorAttachment,
- attachment->getInternalFormat());
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
}
- if ((formatInfo.redBits == 0 || !clearParams.colorMaskRed) &&
- (formatInfo.greenBits == 0 || !clearParams.colorMaskGreen) &&
- (formatInfo.blueBits == 0 || !clearParams.colorMaskBlue) &&
- (formatInfo.alphaBits == 0 || !clearParams.colorMaskAlpha))
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat());
+
+ // Check if the actual format has a channel that the internal format does not and set them to the
+ // default values
+ const float clearValues[4] =
{
- // Every channel either does not exist in the render target or is masked out
- continue;
- }
- else if (needScissoredClear || clearParams.colorClearType != GL_FLOAT ||
- (formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
- (formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
- (formatInfo.blueBits > 0 && !clearParams.colorMaskBlue) ||
- (formatInfo.alphaBits > 0 && !clearParams.colorMaskAlpha))
+ ((formatInfo.redBits == 0 && dxgiFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
+ ((formatInfo.greenBits == 0 && dxgiFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+ ((formatInfo.blueBits == 0 && dxgiFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue),
+ ((formatInfo.alphaBits == 0 && dxgiFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+ };
+
+ if (needScissoredClear)
{
- // 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);
+#if defined(ANGLE_ENABLE_D3D11_1)
+ // We shouldn't reach here if deviceContext1 is unavailable.
+ ASSERT(deviceContext1);
+
+ D3D11_RECT rect;
+ rect.left = clearParams.scissor.x;
+ rect.right = clearParams.scissor.x + clearParams.scissor.width;
+ rect.top = clearParams.scissor.y;
+ rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
+
+ deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
+#endif
}
else
{
- // ID3D11DeviceContext::ClearRenderTargetView is possible
-
- ID3D11RenderTargetView *framebufferRTV = renderTarget->getRenderTargetView();
- if (!framebufferRTV)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal render target view pointer unexpectedly null.");
- }
-
- const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
-
- // Check if the actual format has a channel that the internal format does not and set them to the
- // default values
- const float clearValues[4] =
- {
- ((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
- ((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
- ((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue),
- ((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
- };
-
deviceContext->ClearRenderTargetView(framebufferRTV, clearValues);
}
}
@@ -287,40 +346,39 @@ gl::Error Clear11::clearFramebuffer(const gl::ClearParameters &clearParams, cons
if (clearParams.clearDepth || clearParams.clearStencil)
{
- gl::FramebufferAttachment *attachment = frameBuffer->getDepthOrStencilbuffer();
- if (attachment)
+ const gl::FramebufferAttachment *attachment = (depthAttachment != nullptr) ? depthAttachment : stencilAttachment;
+ ASSERT(attachment != nullptr);
+
+ RenderTarget11 *renderTarget = NULL;
+ gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
+ if (error.isError())
{
- RenderTarget11 *renderTarget = NULL;
- gl::Error error = d3d11::GetAttachmentRenderTarget(attachment, &renderTarget);
- if (error.isError())
- {
- return error;
- }
+ return error;
+ }
- const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget->getDXGIFormat());
- unsigned int stencilUnmasked = frameBuffer->hasStencil() ? (1 << actualFormatInfo.stencilBits) - 1 : 0;
- bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
+ unsigned int stencilUnmasked = (stencilAttachment != nullptr) ? (1 << dxgiFormatInfo.stencilBits) - 1 : 0;
+ bool needMaskedStencilClear = clearParams.clearStencil && (clearParams.stencilWriteMask & stencilUnmasked) != stencilUnmasked;
- if (needScissoredClear || needMaskedStencilClear)
+ if (needScissoredClear || needMaskedStencilClear)
+ {
+ maskedClearDepthStencil = renderTarget;
+ }
+ else
+ {
+ ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
+ if (!framebufferDSV)
{
- maskedClearDepthStencil = renderTarget;
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
}
- else
- {
- ID3D11DepthStencilView *framebufferDSV = renderTarget->getDepthStencilView();
- if (!framebufferDSV)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal depth stencil view pointer unexpectedly null.");
- }
- UINT clearFlags = (clearParams.clearDepth ? D3D11_CLEAR_DEPTH : 0) |
- (clearParams.clearStencil ? D3D11_CLEAR_STENCIL : 0);
- FLOAT depthClear = gl::clamp01(clearParams.depthClearValue);
- UINT8 stencilClear = clearParams.stencilClearValue & 0xFF;
+ 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);
- }
+ deviceContext->ClearDepthStencilView(framebufferDSV, clearFlags, depthClear, stencilClear);
}
}
@@ -484,13 +542,13 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>&
blendDesc.AlphaToCoverageEnable = FALSE;
blendDesc.IndependentBlendEnable = (rts.size() > 1) ? TRUE : FALSE;
- for (unsigned int i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; i++)
+ for (unsigned int j = 0; j < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; j++)
{
- 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]);
+ blendDesc.RenderTarget[j].BlendEnable = FALSE;
+ blendDesc.RenderTarget[j].RenderTargetWriteMask = gl_d3d11::ConvertColorMask(blendKey.maskChannels[j][0],
+ blendKey.maskChannels[j][1],
+ blendKey.maskChannels[j][2],
+ blendKey.maskChannels[j][3]);
}
ID3D11Device *device = mRenderer->getDevice();
@@ -508,7 +566,7 @@ ID3D11BlendState *Clear11::getBlendState(const std::vector<MaskedRenderTarget>&
}
}
-ID3D11DepthStencilState *Clear11::getDepthStencilState(const gl::ClearParameters &clearParams)
+ID3D11DepthStencilState *Clear11::getDepthStencilState(const ClearParameters &clearParams)
{
ClearDepthStencilInfo dsKey = { 0 };
dsKey.clearDepth = clearParams.clearDepth;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
index a7e8fea56a..4797ca1aa0 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.h
@@ -6,45 +6,32 @@
// Clear11.h: Framebuffer clear utility class.
-#ifndef LIBGLESV2_RENDERER_CLEAR11_H_
-#define LIBGLESV2_RENDERER_CLEAR11_H_
-
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Error.h"
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
#include <map>
#include <vector>
-namespace gl
-{
-class Framebuffer;
-}
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
namespace rx
{
class Renderer11;
class RenderTarget11;
+struct ClearParameters;
-class Clear11
+class Clear11 : angle::NonCopyable
{
public:
explicit Clear11(Renderer11 *renderer);
~Clear11();
// Clears the framebuffer with the supplied clear parameters, assumes that the framebuffer is currently applied.
- gl::Error clearFramebuffer(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer);
+ gl::Error clearFramebuffer(const ClearParameters &clearParams, const gl::Framebuffer::Data &fboData);
private:
- Renderer11 *mRenderer;
-
- struct ClearBlendInfo
- {
- bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
- };
- typedef bool (*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
- typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
- ClearBlendStateMap mClearBlendStates;
-
struct MaskedRenderTarget
{
bool colorMask[4];
@@ -52,6 +39,7 @@ class Clear11
};
ID3D11BlendState *getBlendState(const std::vector<MaskedRenderTarget> &rts);
+ ID3D11DepthStencilState *getDepthStencilState(const ClearParameters &clearParams);
struct ClearShader
{
@@ -59,13 +47,24 @@ class Clear11
ID3D11VertexShader *vertexShader;
ID3D11PixelShader *pixelShader;
};
+
+ template <unsigned int vsSize, unsigned int psSize>
+ static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE(&vsByteCode)[vsSize], const BYTE(&psByteCode)[psSize]);
+
+ Renderer11 *mRenderer;
+
+ struct ClearBlendInfo
+ {
+ bool maskChannels[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT][4];
+ };
+ typedef bool(*ClearBlendInfoComparisonFunction)(const ClearBlendInfo&, const ClearBlendInfo &);
+ typedef std::map<ClearBlendInfo, ID3D11BlendState*, ClearBlendInfoComparisonFunction> ClearBlendStateMap;
+ ClearBlendStateMap mClearBlendStates;
+
ClearShader mFloatClearShader;
ClearShader mUintClearShader;
ClearShader mIntClearShader;
- template <unsigned int vsSize, unsigned int psSize>
- static ClearShader CreateClearShader(ID3D11Device *device, DXGI_FORMAT colorType, const BYTE (&vsByteCode)[vsSize], const BYTE (&psByteCode)[psSize]);
-
struct ClearDepthStencilInfo
{
bool clearDepth;
@@ -76,12 +75,12 @@ class Clear11
typedef std::map<ClearDepthStencilInfo, ID3D11DepthStencilState*, ClearDepthStencilInfoComparisonFunction> ClearDepthStencilStateMap;
ClearDepthStencilStateMap mClearDepthStencilStates;
- ID3D11DepthStencilState *getDepthStencilState(const gl::ClearParameters &clearParams);
-
ID3D11Buffer *mVertexBuffer;
ID3D11RasterizerState *mRasterizerState;
+
+ bool mSupportsClearView;
};
}
-#endif // LIBGLESV2_RENDERER_CLEAR11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_CLEAR11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
new file mode 100644
index 0000000000..f1fe2bb2c7
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
@@ -0,0 +1,119 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.cpp: D3D11 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+namespace rx
+{
+
+DebugAnnotator11::DebugAnnotator11()
+ : mInitialized(false),
+ mD3d11Module(nullptr),
+ mUserDefinedAnnotation(nullptr)
+{
+ // D3D11 devices can't be created during DllMain.
+ // We defer device creation until the object is actually used.
+}
+
+DebugAnnotator11::~DebugAnnotator11()
+{
+ if (mInitialized)
+ {
+#if defined(ANGLE_ENABLE_D3D11_1)
+ SafeRelease(mUserDefinedAnnotation);
+#endif
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ FreeLibrary(mD3d11Module);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+ }
+}
+
+void DebugAnnotator11::beginEvent(const std::wstring &eventName)
+{
+ initializeDevice();
+
+#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->BeginEvent(eventName.c_str());
+#endif
+}
+
+void DebugAnnotator11::endEvent()
+{
+ initializeDevice();
+
+#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->EndEvent();
+#endif
+}
+
+void DebugAnnotator11::setMarker(const std::wstring &markerName)
+{
+ initializeDevice();
+
+#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->SetMarker(markerName.c_str());
+#endif
+}
+
+bool DebugAnnotator11::getStatus()
+{
+ // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+
+#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+ // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
+ // This should only be called in DEBUG mode.
+ // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
+ IDXGraphicsAnalysis *graphicsAnalysis;
+ DXGIGetDebugInterface1(0, IID_PPV_ARGS(&graphicsAnalysis));
+ bool underCapture = (graphicsAnalysis != nullptr);
+ SafeRelease(graphicsAnalysis);
+ return underCapture;
+#endif // _DEBUG && !ANGLE_ENABLE_WINDOWS_STORE
+
+ // Otherwise, we have to return true here.
+ return true;
+}
+
+void DebugAnnotator11::initializeDevice()
+{
+ if (!mInitialized)
+ {
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ mD3d11Module = LoadLibrary(TEXT("d3d11.dll"));
+ ASSERT(mD3d11Module);
+
+ PFN_D3D11_CREATE_DEVICE D3D11CreateDevice = (PFN_D3D11_CREATE_DEVICE)GetProcAddress(mD3d11Module, "D3D11CreateDevice");
+ ASSERT(D3D11CreateDevice != nullptr);
+#endif // !ANGLE_ENABLE_WINDOWS_STORE
+
+ ID3D11Device *device = nullptr;
+ ID3D11DeviceContext *context = nullptr;
+
+ HRESULT hr = E_FAIL;
+
+ // Create a D3D_DRIVER_TYPE_NULL device, which is much cheaper than other types of device.
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context);
+ ASSERT(SUCCEEDED(hr));
+
+#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
+ ASSERT(mUserDefinedAnnotation != nullptr);
+#endif
+
+ SafeRelease(device);
+ SafeRelease(context);
+
+ mInitialized = true;
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
new file mode 100644
index 0000000000..3df62b015c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
@@ -0,0 +1,39 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator11.h: D3D11 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
+
+#include "common/debug.h"
+
+struct ID3DUserDefinedAnnotation;
+
+namespace rx
+{
+
+class DebugAnnotator11 : public gl::DebugAnnotator
+{
+ public:
+ DebugAnnotator11();
+ ~DebugAnnotator11() override;
+ void beginEvent(const std::wstring &eventName) override;
+ void endEvent() override;
+ void setMarker(const std::wstring &markerName) override;
+ bool getStatus() override;
+
+ private:
+ void initializeDevice();
+
+ bool mInitialized;
+ HMODULE mD3d11Module;
+ ID3DUserDefinedAnnotation *mUserDefinedAnnotation;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_DEBUGANNOTATOR11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
index f44d934056..8552bc2beb 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp
@@ -6,9 +6,8 @@
// Fence11.cpp: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
-#include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "common/utilities.h"
@@ -99,7 +98,7 @@ gl::Error FenceNV11::finishFence(GLboolean *outFinished)
return error;
}
- Sleep(0);
+ ScheduleYield();
}
return gl::Error(GL_NO_ERROR);
@@ -179,8 +178,8 @@ gl::Error FenceSync11::clientWait(GLbitfield flags, GLuint64 timeout, GLenum *ou
while (currentCounter.QuadPart < endCounter && !result)
{
- Sleep(0);
- BOOL success = QueryPerformanceCounter(&currentCounter);
+ ScheduleYield();
+ success = QueryPerformanceCounter(&currentCounter);
UNUSED_ASSERTION_VARIABLE(success);
ASSERT(success);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
index 1223a53b90..2d87f43e76 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Fence11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Fence11.h
@@ -6,10 +6,11 @@
// Fence11.h: Defines the rx::FenceNV11 and rx::FenceSync11 classes which implement rx::FenceNVImpl and rx::FenceSyncImpl.
-#ifndef LIBGLESV2_RENDERER_FENCE11_H_
-#define LIBGLESV2_RENDERER_FENCE11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
-#include "libGLESv2/renderer/FenceImpl.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
namespace rx
{
@@ -26,8 +27,6 @@ class FenceNV11 : public FenceNVImpl
gl::Error finishFence(GLboolean *outFinished);
private:
- DISALLOW_COPY_AND_ASSIGN(FenceNV11);
-
template<class T> friend gl::Error FenceSetHelper(T *fence);
template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
@@ -47,8 +46,6 @@ class FenceSync11 : public FenceSyncImpl
gl::Error getStatus(GLint *outResult);
private:
- DISALLOW_COPY_AND_ASSIGN(FenceSync11);
-
template<class T> friend gl::Error FenceSetHelper(T *fence);
template<class T> friend gl::Error FenceTestHelper(T *fence, bool flushCommandBuffer, GLboolean *outFinished);
@@ -59,4 +56,4 @@ class FenceSync11 : public FenceSyncImpl
}
-#endif // LIBGLESV2_RENDERER_FENCE11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FENCE11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
new file mode 100644
index 0000000000..da01f320c0
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
@@ -0,0 +1,270 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer11.cpp: Implements the Framebuffer11 class.
+
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+
+namespace rx
+{
+
+Framebuffer11::Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer)
+ : FramebufferD3D(data, renderer),
+ mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer11::~Framebuffer11()
+{
+}
+
+static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *attachment)
+{
+ if (attachment && attachment->type() == GL_TEXTURE)
+ {
+ gl::Texture *texture = attachment->getTexture();
+
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = NULL;
+ gl::Error error = textureD3D->getNativeTexture(&texStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (texStorage)
+ {
+ TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage);
+ ASSERT(texStorage11);
+
+ texStorage11->invalidateSwizzleCacheLevel(attachment->mipLevel());
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer11::invalidateSwizzles() const
+{
+ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
+ gl::FramebufferAttachment *colorAttachment = *it;
+ gl::Error error = InvalidateAttachmentSwizzles(colorAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ gl::Error error = InvalidateAttachmentSwizzles(mData.mDepthAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = InvalidateAttachmentSwizzles(mData.mStencilAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer11::clear(const gl::State &state, const ClearParameters &clearParams)
+{
+ Clear11 *clearer = mRenderer->getClearer();
+ gl::Error error = clearer->clearFramebuffer(clearParams, mData);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ error = invalidateSwizzles();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+static gl::Error getRenderTargetResource(const gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut,
+ ID3D11Texture2D **texture2DOut)
+{
+ ASSERT(colorbuffer);
+
+ RenderTarget11 *renderTarget = NULL;
+ gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *renderTargetResource = renderTarget->getTexture();
+ ASSERT(renderTargetResource);
+
+ *subresourceIndexOut = renderTarget->getSubresourceIndex();
+ *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource);
+
+ if (!(*texture2DOut))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget");
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer11::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+{
+ ID3D11Texture2D *colorBufferTexture = NULL;
+ unsigned int subresourceIndex = 0;
+
+ const gl::FramebufferAttachment *colorbuffer = mData.getReadAttachment();
+ ASSERT(colorbuffer);
+
+ gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ gl::Buffer *packBuffer = pack.pixelBuffer.get();
+ if (packBuffer != NULL)
+ {
+ Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
+ PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
+
+ error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
+ if (error.isError())
+ {
+ SafeRelease(colorBufferTexture);
+ return error;
+ }
+
+ packBuffer->getIndexRangeCache()->clear();
+ }
+ else
+ {
+ error = mRenderer->readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
+ if (error.isError())
+ {
+ SafeRelease(colorBufferTexture);
+ return error;
+ }
+ }
+
+ SafeRelease(colorBufferTexture);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer11::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
+ bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
+{
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getReadColorbuffer();
+ ASSERT(readBuffer);
+
+ RenderTargetD3D *readRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readRenderTarget);
+
+ for (size_t colorAttachment = 0; colorAttachment < mData.mColorAttachments.size(); colorAttachment++)
+ {
+ if (mData.mColorAttachments[colorAttachment] != nullptr &&
+ mData.mDrawBufferStates[colorAttachment] != GL_NONE)
+ {
+ const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[colorAttachment];
+
+ RenderTargetD3D *drawRenderTarget = NULL;
+ error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(drawRenderTarget);
+
+ error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget,
+ filter, scissor, blitRenderTarget, false, false);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+ ASSERT(readBuffer);
+
+ RenderTargetD3D *readRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTargetD3D *drawRenderTarget = NULL;
+ error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(drawRenderTarget);
+
+ error = mRenderer->blitRenderbufferRect(sourceArea, destArea, readRenderTarget, drawRenderTarget, filter, scissor,
+ false, blitDepth, blitStencil);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
+ gl::Error error = invalidateSwizzles();
+ if (error.isError())
+ {
+ return error;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum Framebuffer11::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+ RenderTarget11 *renderTarget11 = RenderTarget11::makeRenderTarget11(renderTarget);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(renderTarget11->getDXGIFormat());
+ return dxgiFormatInfo.internalFormat;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
new file mode 100644
index 0000000000..07fa480fa2
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h
@@ -0,0 +1,45 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer11.h: Defines the Framebuffer11 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+namespace rx
+{
+class Renderer11;
+
+class Framebuffer11 : public FramebufferD3D
+{
+ public:
+ Framebuffer11(const gl::Framebuffer::Data &data, Renderer11 *renderer);
+ virtual ~Framebuffer11();
+
+ // Invalidate the cached swizzles of all bound texture attachments.
+ gl::Error invalidateSwizzles() const;
+
+ private:
+ gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
+
+ gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
+ const gl::PixelPackState &pack, uint8_t *pixels) const override;
+
+ gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
+ bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
+
+
+ GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+ Renderer11 *const mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FRAMBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
index e6f3e90683..956b78b5a6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.cpp
@@ -7,23 +7,23 @@
// Image11.h: Implements the rx::Image11 class, which acts as the interface to
// the actual underlying resources of a Texture
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
#include "common/utilities.h"
namespace rx
{
-Image11::Image11()
- : mRenderer(NULL),
+Image11::Image11(Renderer11 *renderer)
+ : mRenderer(renderer),
mDXGIFormat(DXGI_FORMAT_UNKNOWN),
mStagingTexture(NULL),
mStagingSubresource(0),
@@ -31,8 +31,10 @@ Image11::Image11()
mAssociatedStorage(NULL),
mAssociatedImageIndex(gl::ImageIndex::MakeInvalid()),
mRecoveredFromStorageCount(0)
-
{
+ // mRenderer should remain unchanged during the lifetime of the Image11 object.
+ // This lets us safely use mRenderer (and its Feature Level) in Image11's methods.
+ mFeatureLevel = renderer->getFeatureLevel();
}
Image11::~Image11()
@@ -41,7 +43,7 @@ Image11::~Image11()
releaseStagingTexture();
}
-Image11 *Image11::makeImage11(Image *img)
+Image11 *Image11::makeImage11(ImageD3D *img)
{
ASSERT(HAS_DYNAMIC_TYPE(Image11*, img));
return static_cast<Image11*>(img);
@@ -92,7 +94,7 @@ bool Image11::isDirty() const
// AND mStagingTexture doesn't exist AND mStagingTexture doesn't need to be recovered from TextureStorage
// AND the texture doesn't require init data (i.e. a blank new texture will suffice)
// then isDirty should still return false.
- if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL))
+ if (mDirty && !mStagingTexture && !mRecoverFromStorage && !(d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL))
{
return false;
}
@@ -201,10 +203,10 @@ void Image11::disassociateStorage()
}
}
-bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
+bool Image11::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease)
{
- if (mWidth != width ||
- mHeight != height ||
+ if (mWidth != size.width ||
+ mHeight != size.height ||
mInternalFormat != internalformat ||
forceRelease)
{
@@ -213,19 +215,15 @@ bool Image11::redefine(RendererD3D *renderer, GLenum target, GLenum internalform
disassociateStorage();
mRecoveredFromStorageCount = 0;
- mRenderer = Renderer11::makeRenderer11(renderer);
-
- mWidth = width;
- mHeight = height;
- mDepth = depth;
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
mInternalFormat = internalformat;
mTarget = target;
// compute the d3d format that will be used
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(formatInfo.texFormat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, mFeatureLevel);
mDXGIFormat = formatInfo.texFormat;
- mActualFormat = dxgiFormatInfo.internalFormat;
mRenderable = (formatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN);
releaseStagingTexture();
@@ -248,17 +246,16 @@ DXGI_FORMAT Image11::getDXGIFormat() const
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
-gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLint unpackAlignment, GLenum type, const void *input)
+gl::Error Image11::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, width, height, unpackAlignment);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(type, area.width, area.height, unpack.alignment, unpack.rowLength);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel);
LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(type);
D3D11_MAPPED_SUBRESOURCE mappedImage;
@@ -268,8 +265,8 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei
return error;
}
- uint8_t* offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (yoffset * mappedImage.RowPitch + xoffset * outputPixelSize + zoffset * mappedImage.DepthPitch));
- loadFunction(width, height, depth,
+ uint8_t *offsetMappedData = (reinterpret_cast<uint8_t*>(mappedImage.pData) + (area.y * mappedImage.RowPitch + area.x * outputPixelSize + area.z * mappedImage.DepthPitch));
+ loadFunction(area.width, area.height, area.depth,
reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
@@ -278,22 +275,21 @@ gl::Error Image11::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei
return gl::Error(GL_NO_ERROR);
}
-gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- const void *input)
+gl::Error Image11::loadCompressedData(const gl::Box &area, const void *input)
{
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
GLuint outputPixelSize = dxgiFormatInfo.pixelBytes;
GLuint outputBlockWidth = dxgiFormatInfo.blockWidth;
GLuint outputBlockHeight = dxgiFormatInfo.blockHeight;
- ASSERT(xoffset % outputBlockWidth == 0);
- ASSERT(yoffset % outputBlockHeight == 0);
+ ASSERT(area.x % outputBlockWidth == 0);
+ ASSERT(area.y % outputBlockHeight == 0);
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat);
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel);
LoadImageFunction loadFunction = d3dFormatInfo.loadFunctions.at(GL_UNSIGNED_BYTE);
D3D11_MAPPED_SUBRESOURCE mappedImage;
@@ -303,11 +299,11 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse
return error;
}
- uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((yoffset / outputBlockHeight) * mappedImage.RowPitch +
- (xoffset / outputBlockWidth) * outputPixelSize +
- zoffset * mappedImage.DepthPitch);
+ uint8_t* offsetMappedData = reinterpret_cast<uint8_t*>(mappedImage.pData) + ((area.y / outputBlockHeight) * mappedImage.RowPitch +
+ (area.x / outputBlockWidth) * outputPixelSize +
+ area.z * mappedImage.DepthPitch);
- loadFunction(width, height, depth,
+ loadFunction(area.width, area.height, area.depth,
reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
offsetMappedData, mappedImage.RowPitch, mappedImage.DepthPitch);
@@ -316,27 +312,23 @@ gl::Error Image11::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffse
return gl::Error(GL_NO_ERROR);
}
-gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source)
+gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source)
{
RenderTarget11 *sourceRenderTarget = RenderTarget11::makeRenderTarget11(source);
ASSERT(sourceRenderTarget->getTexture());
+ ID3D11Resource *resource = sourceRenderTarget->getTexture();
UINT subresourceIndex = sourceRenderTarget->getSubresourceIndex();
- ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(sourceRenderTarget->getTexture());
-
- if (!sourceTexture2D)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source RenderTarget.");
- }
- gl::Error error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
+ gl::Box sourceBox(sourceArea.x, sourceArea.y, 0, sourceArea.width, sourceArea.height, 1);
+ gl::Error error = copy(destOffset, sourceBox, resource, subresourceIndex);
- SafeRelease(sourceTexture2D);
+ SafeRelease(resource);
return error;
}
-gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source)
+gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, const gl::ImageIndex &sourceIndex, TextureStorage *source)
{
TextureStorage11 *sourceStorage11 = TextureStorage11::makeTextureStorage11(source);
@@ -348,26 +340,52 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
return error;
}
- ID3D11Texture2D *sourceTexture2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(resource);
+ error = copy(destOffset, sourceArea, resource, subresourceIndex);
- if (!sourceTexture2D)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to retrieve the ID3D11Texture2D from the source TextureStorage.");
- }
-
- error = copy(xoffset, yoffset, zoffset, sourceArea, sourceTexture2D, subresourceIndex);
-
- SafeRelease(sourceTexture2D);
+ SafeRelease(resource);
return error;
}
-gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource)
+gl::Error Image11::copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource)
{
- D3D11_TEXTURE2D_DESC textureDesc;
- source->GetDesc(&textureDesc);
+ D3D11_RESOURCE_DIMENSION dim;
+ source->GetType(&dim);
+
+ DXGI_FORMAT format = DXGI_FORMAT_UNKNOWN;
+ gl::Extents extents;
+ UINT sampleCount = 0;
+
+ ID3D11Texture2D *source2D = NULL;
- if (textureDesc.Format == mDXGIFormat)
+ if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D)
+ {
+ D3D11_TEXTURE2D_DESC textureDesc2D;
+ source2D = d3d11::DynamicCastComObject<ID3D11Texture2D>(source);
+ ASSERT(source2D);
+ source2D->GetDesc(&textureDesc2D);
+
+ format = textureDesc2D.Format;
+ extents = gl::Extents(textureDesc2D.Width, textureDesc2D.Height, 1);
+ sampleCount = textureDesc2D.SampleDesc.Count;
+ }
+ else if (dim == D3D11_RESOURCE_DIMENSION_TEXTURE3D)
+ {
+ D3D11_TEXTURE3D_DESC textureDesc3D;
+ ID3D11Texture3D *source3D = d3d11::DynamicCastComObject<ID3D11Texture3D>(source);
+ ASSERT(source3D);
+ source3D->GetDesc(&textureDesc3D);
+
+ format = textureDesc3D.Format;
+ extents = gl::Extents(textureDesc3D.Width, textureDesc3D.Height, textureDesc3D.Depth);
+ sampleCount = 1;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ if (format == mDXGIFormat)
{
// No conversion needed-- use copyback fastpath
ID3D11Resource *stagingTexture = NULL;
@@ -383,15 +401,18 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
UINT subresourceAfterResolve = sourceSubResource;
- ID3D11Texture2D* srcTex = NULL;
- if (textureDesc.SampleDesc.Count > 1)
+ ID3D11Resource *srcTex = NULL;
+
+ bool needResolve = (dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D && sampleCount > 1);
+
+ if (needResolve)
{
D3D11_TEXTURE2D_DESC resolveDesc;
- resolveDesc.Width = textureDesc.Width;
- resolveDesc.Height = textureDesc.Height;
+ resolveDesc.Width = extents.width;
+ resolveDesc.Height = extents.height;
resolveDesc.MipLevels = 1;
resolveDesc.ArraySize = 1;
- resolveDesc.Format = textureDesc.Format;
+ resolveDesc.Format = format;
resolveDesc.SampleDesc.Count = 1;
resolveDesc.SampleDesc.Quality = 0;
resolveDesc.Usage = D3D11_USAGE_DEFAULT;
@@ -399,13 +420,15 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
resolveDesc.CPUAccessFlags = 0;
resolveDesc.MiscFlags = 0;
- HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex);
+ ID3D11Texture2D *srcTex2D = NULL;
+ HRESULT result = device->CreateTexture2D(&resolveDesc, NULL, &srcTex2D);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create resolve texture for Image11::copy, HRESULT: 0x%X.", result);
}
+ srcTex = srcTex2D;
- deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, textureDesc.Format);
+ deviceContext->ResolveSubresource(srcTex, 0, source, sourceSubResource, format);
subresourceAfterResolve = 0;
}
else
@@ -418,12 +441,13 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
srcBox.right = sourceArea.x + sourceArea.width;
srcBox.top = sourceArea.y;
srcBox.bottom = sourceArea.y + sourceArea.height;
- srcBox.front = 0;
- srcBox.back = 1;
+ srcBox.front = sourceArea.z;
+ srcBox.back = sourceArea.z + sourceArea.depth;
- deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, xoffset, yoffset, zoffset, srcTex, subresourceAfterResolve, &srcBox);
+ deviceContext->CopySubresourceRegion(stagingTexture, stagingSubresourceIndex, destOffset.x, destOffset.y,
+ destOffset.z, srcTex, subresourceAfterResolve, &srcBox);
- if (textureDesc.SampleDesc.Count > 1)
+ if (needResolve)
{
SafeRelease(srcTex);
}
@@ -439,12 +463,18 @@ gl::Error Image11::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::R
}
// determine the offset coordinate into the destination buffer
- GLsizei rowOffset = gl::GetInternalFormatInfo(mActualFormat).pixelBytes * xoffset;
- uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * yoffset + rowOffset + zoffset * mappedImage.DepthPitch;
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mDXGIFormat);
+ GLsizei rowOffset = dxgiFormatInfo.pixelBytes * destOffset.x;
+ uint8_t *dataOffset = static_cast<uint8_t*>(mappedImage.pData) + mappedImage.RowPitch * destOffset.y + rowOffset + destOffset.z * mappedImage.DepthPitch;
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- error = mRenderer->readTextureData(source, sourceSubResource, sourceArea, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
+ // Currently in ANGLE, the source data may only need to be converted if the source is the current framebuffer
+ // and OpenGL ES framebuffers must be 2D textures therefore we should not need to convert 3D textures between different formats.
+ ASSERT(dim == D3D11_RESOURCE_DIMENSION_TEXTURE2D);
+ ASSERT(sourceArea.z == 0 && sourceArea.depth == 1);
+ gl::Rectangle sourceRect(sourceArea.x, sourceArea.y, sourceArea.width, sourceArea.height);
+ error = mRenderer->readTextureData(source2D, sourceSubResource, sourceRect, formatInfo.format, formatInfo.type, mappedImage.RowPitch, gl::PixelPackState(), dataOffset);
unmap();
@@ -513,11 +543,11 @@ gl::Error Image11::createStagingTexture()
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
- if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
+ if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
- d3d11::GenerateInitialTextureData(mInternalFormat, width, height, mDepth,
+ d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, mDepth,
lodOffset + 1, &initialData, &textureData);
result = device->CreateTexture3D(&desc, initialData.data(), &newTexture);
@@ -553,11 +583,11 @@ gl::Error Image11::createStagingTexture()
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
desc.MiscFlags = 0;
- if (d3d11::GetTextureFormatInfo(mInternalFormat).dataInitializerFunction != NULL)
+ if (d3d11::GetTextureFormatInfo(mInternalFormat, mFeatureLevel).dataInitializerFunction != NULL)
{
std::vector<D3D11_SUBRESOURCE_DATA> initialData;
std::vector< std::vector<BYTE> > textureData;
- d3d11::GenerateInitialTextureData(mInternalFormat, width, height, 1,
+ d3d11::GenerateInitialTextureData(mInternalFormat, mFeatureLevel, width, height, 1,
lodOffset + 1, &initialData, &textureData);
result = device->CreateTexture2D(&desc, initialData.data(), &newTexture);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
index a936e6d7b2..5734f73b15 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Image11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Image11.h
@@ -7,11 +7,11 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
-#include "libGLESv2/renderer/d3d/ImageD3D.h"
-#include "libGLESv2/ImageIndex.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
+#include "libANGLE/ImageIndex.h"
#include "common/debug.h"
@@ -28,10 +28,10 @@ class TextureStorage11;
class Image11 : public ImageD3D
{
public:
- Image11();
+ Image11(Renderer11 *renderer);
virtual ~Image11();
- static Image11 *makeImage11(Image *img);
+ static Image11 *makeImage11(ImageD3D *img);
static gl::Error generateMipmap(Image11 *dest, Image11 *src);
@@ -39,17 +39,15 @@ class Image11 : public ImageD3D
virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
- bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override;
+ bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
DXGI_FORMAT getDXGIFormat() const;
- virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLint unpackAlignment, GLenum type, const void *input);
- virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- const void *input);
+ virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
+ virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source);
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea,
const gl::ImageIndex &sourceIndex, TextureStorage *source);
gl::Error recoverFromAssociatedStorage();
@@ -61,16 +59,15 @@ class Image11 : public ImageD3D
void unmap();
private:
- DISALLOW_COPY_AND_ASSIGN(Image11);
-
gl::Error copyToStorageImpl(TextureStorage11 *storage11, const gl::ImageIndex &index, const gl::Box &region);
- gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, ID3D11Texture2D *source, UINT sourceSubResource);
+ gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea, ID3D11Resource *source, UINT sourceSubResource);
gl::Error getStagingTexture(ID3D11Resource **outStagingTexture, unsigned int *outSubresourceIndex);
gl::Error createStagingTexture();
void releaseStagingTexture();
Renderer11 *mRenderer;
+ D3D_FEATURE_LEVEL mFeatureLevel;
DXGI_FORMAT mDXGIFormat;
ID3D11Resource *mStagingTexture;
@@ -84,4 +81,4 @@ class Image11 : public ImageD3D
}
-#endif // LIBGLESV2_RENDERER_IMAGE11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_IMAGE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
index 9a61182ee9..99c199f2b9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp
@@ -6,8 +6,8 @@
// IndexBuffer11.cpp: Defines the D3D11 IndexBuffer implementation.
-#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
index 3351df5ec1..eadd03eb76 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h
@@ -6,10 +6,10 @@
// IndexBuffer11.h: Defines the D3D11 IndexBuffer implementation.
-#ifndef LIBGLESV2_RENDERER_INDEXBUFFER11_H_
-#define LIBGLESV2_RENDERER_INDEXBUFFER11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
-#include "libGLESv2/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
namespace rx
{
@@ -38,8 +38,6 @@ class IndexBuffer11 : public IndexBuffer
ID3D11Buffer *getBuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(IndexBuffer11);
-
Renderer11 *const mRenderer;
ID3D11Buffer *mBuffer;
@@ -50,4 +48,4 @@ class IndexBuffer11 : public IndexBuffer
}
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER11_H_ \ No newline at end of file
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INDEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
new file mode 100644
index 0000000000..242c09d6ce
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp
@@ -0,0 +1,430 @@
+//
+// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
+// D3D11 input layouts.
+
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
+
+#include "third_party/murmurhash/MurmurHash3.h"
+
+namespace rx
+{
+
+static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS],
+ gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
+{
+ for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
+ {
+ const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex];
+
+ if (translatedAttributes[attributeIndex].active)
+ {
+ inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute,
+ translatedAttribute.currentValueType);
+ }
+ }
+}
+
+const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
+
+InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
+{
+ mCounter = 0;
+ mDevice = NULL;
+ mDeviceContext = NULL;
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = NULL;
+ mCurrentVertexStrides[i] = static_cast<UINT>(-1);
+ mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
+ }
+ mPointSpriteVertexBuffer = NULL;
+ mPointSpriteIndexBuffer = NULL;
+}
+
+InputLayoutCache::~InputLayoutCache()
+{
+ clear();
+}
+
+void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
+{
+ clear();
+ mDevice = device;
+ mDeviceContext = context;
+ mFeatureLevel = device->GetFeatureLevel();
+}
+
+void InputLayoutCache::clear()
+{
+ for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
+ {
+ SafeRelease(i->second.inputLayout);
+ }
+ mInputLayoutMap.clear();
+ SafeRelease(mPointSpriteVertexBuffer);
+ SafeRelease(mPointSpriteIndexBuffer);
+ markDirty();
+}
+
+void InputLayoutCache::markDirty()
+{
+ mCurrentIL = NULL;
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ mCurrentBuffers[i] = NULL;
+ mCurrentVertexStrides[i] = static_cast<UINT>(-1);
+ mCurrentVertexOffsets[i] = static_cast<UINT>(-1);
+ }
+}
+
+gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
+ GLenum mode, gl::Program *program)
+{
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
+
+ int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
+ programD3D->sortAttributesByLayout(attributes, sortedSemanticIndices);
+ bool programUsesInstancedPointSprites = programD3D->usesPointSize() && programD3D->usesInstancedPointSpriteEmulation();
+ bool instancedPointSpritesActive = programUsesInstancedPointSprites && (mode == GL_POINTS);
+
+ if (!mDevice || !mDeviceContext)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized.");
+ }
+
+ InputLayoutKey ilKey = { 0 };
+
+ static const char* semanticName = "TEXCOORD";
+
+ unsigned int firstIndexedElement = gl::MAX_VERTEX_ATTRIBS;
+ unsigned int firstInstancedElement = gl::MAX_VERTEX_ATTRIBS;
+ unsigned int nextAvailableInputSlot = 0;
+
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ if (attributes[i].active)
+ {
+ D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
+ // If rendering points and instanced pointsprite emulation is being used, the inputClass is required to be configured as per instance data
+ inputClass = instancedPointSpritesActive ? D3D11_INPUT_PER_INSTANCE_DATA : inputClass;
+
+ gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel);
+
+ // Record the type of the associated vertex shader vector in our key
+ // This will prevent mismatched vertex shaders from using the same input layout
+ GLint attributeSize;
+ program->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
+
+ ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
+ ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat;
+ ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
+ ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
+ ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
+ ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = instancedPointSpritesActive ? 1 : attributes[i].divisor;
+
+ if (inputClass == D3D11_INPUT_PER_VERTEX_DATA && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)
+ {
+ firstIndexedElement = ilKey.elementCount;
+ }
+ else if (inputClass == D3D11_INPUT_PER_INSTANCE_DATA && firstInstancedElement == gl::MAX_VERTEX_ATTRIBS)
+ {
+ firstInstancedElement = ilKey.elementCount;
+ }
+
+ ilKey.elementCount++;
+ nextAvailableInputSlot = i + 1;
+ }
+ }
+
+ // Instanced PointSprite emulation requires additional entries in the
+ // inputlayout to support the vertices that make up the pointsprite quad.
+ // We do this even if mode != GL_POINTS, since the shader signature has these inputs, and the input layout must match the shader
+ if (programUsesInstancedPointSprites)
+ {
+ ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITEPOSITION";
+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0;
+ ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32B32_FLOAT;
+ ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot;
+ ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
+ ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0;
+
+ // The new elements are D3D11_INPUT_PER_VERTEX_DATA data so the indexed element
+ // tracking must be applied. This ensures that the instancing specific
+ // buffer swapping logic continues to work.
+ if (firstIndexedElement == gl::MAX_VERTEX_ATTRIBS)
+ {
+ firstIndexedElement = ilKey.elementCount;
+ }
+
+ ilKey.elementCount++;
+
+ ilKey.elements[ilKey.elementCount].desc.SemanticName = "SPRITETEXCOORD";
+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = 0;
+ ilKey.elements[ilKey.elementCount].desc.Format = DXGI_FORMAT_R32G32_FLOAT;
+ ilKey.elements[ilKey.elementCount].desc.InputSlot = nextAvailableInputSlot;
+ ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = sizeof(float) * 3;
+ ilKey.elements[ilKey.elementCount].desc.InputSlotClass = D3D11_INPUT_PER_VERTEX_DATA;
+ ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = 0;
+
+ ilKey.elementCount++;
+ }
+
+ // On 9_3, we must ensure that slot 0 contains non-instanced data.
+ // If slot 0 currently contains instanced data then we swap it with a non-instanced element.
+ // Note that instancing is only available on 9_3 via ANGLE_instanced_arrays, since 9_3 doesn't support OpenGL ES 3.0.
+ // As per the spec for ANGLE_instanced_arrays, not all attributes can be instanced simultaneously, so a non-instanced element must exist.
+ ASSERT(!(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstIndexedElement == gl::MAX_VERTEX_ATTRIBS));
+ bool moveFirstIndexedIntoSlotZero = mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && firstInstancedElement == 0 && firstIndexedElement != gl::MAX_VERTEX_ATTRIBS;
+
+ if (moveFirstIndexedIntoSlotZero)
+ {
+ ilKey.elements[firstInstancedElement].desc.InputSlot = ilKey.elements[firstIndexedElement].desc.InputSlot;
+ ilKey.elements[firstIndexedElement].desc.InputSlot = 0;
+
+ // Instanced PointSprite emulation uses multiple layout entries across a single vertex buffer.
+ // If an index swap is performed, we need to ensure that all elements get the proper InputSlot.
+ if (programUsesInstancedPointSprites)
+ {
+ ilKey.elements[firstIndexedElement + 1].desc.InputSlot = 0;
+ }
+ }
+
+ ID3D11InputLayout *inputLayout = NULL;
+
+ InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey);
+ if (keyIter != mInputLayoutMap.end())
+ {
+ inputLayout = keyIter->second.inputLayout;
+ keyIter->second.lastUsedTime = mCounter++;
+ }
+ else
+ {
+ gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
+ GetInputLayout(attributes, shaderInputLayout);
+
+ ShaderExecutableD3D *shader = NULL;
+ gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader, nullptr);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ShaderExecutableD3D *shader11 = ShaderExecutable11::makeShaderExecutable11(shader);
+
+ D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
+ for (unsigned int j = 0; j < ilKey.elementCount; ++j)
+ {
+ descs[j] = ilKey.elements[j].desc;
+ }
+
+ HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
+ }
+
+ if (mInputLayoutMap.size() >= kMaxInputLayouts)
+ {
+ TRACE("Overflowed the limit of %u input layouts, removing the least recently used "
+ "to make room.", kMaxInputLayouts);
+
+ InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin();
+ for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
+ {
+ if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime)
+ {
+ leastRecentlyUsed = i;
+ }
+ }
+ SafeRelease(leastRecentlyUsed->second.inputLayout);
+ mInputLayoutMap.erase(leastRecentlyUsed);
+ }
+
+ InputLayoutCounterPair inputCounterPair;
+ inputCounterPair.inputLayout = inputLayout;
+ inputCounterPair.lastUsedTime = mCounter++;
+
+ mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
+ }
+
+ if (inputLayout != mCurrentIL)
+ {
+ mDeviceContext->IASetInputLayout(inputLayout);
+ mCurrentIL = inputLayout;
+ }
+
+ bool dirtyBuffers = false;
+ size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
+ size_t maxDiff = 0;
+ unsigned int nextAvailableIndex = 0;
+
+ for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
+ {
+ ID3D11Buffer *buffer = NULL;
+
+ if (attributes[i].active)
+ {
+ VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
+ Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL;
+
+ buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK)
+ : vertexBuffer->getBuffer();
+ }
+
+ UINT vertexStride = attributes[i].stride;
+ UINT vertexOffset = attributes[i].offset;
+
+ if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] ||
+ vertexOffset != mCurrentVertexOffsets[i])
+ {
+ dirtyBuffers = true;
+ minDiff = std::min(minDiff, static_cast<size_t>(i));
+ maxDiff = std::max(maxDiff, static_cast<size_t>(i));
+
+ mCurrentBuffers[i] = buffer;
+ mCurrentVertexStrides[i] = vertexStride;
+ mCurrentVertexOffsets[i] = vertexOffset;
+
+ // If a non null ID3D11Buffer is being assigned to mCurrentBuffers,
+ // then the next available index needs to be tracked to ensure
+ // that any instanced pointsprite emulation buffers will be properly packed.
+ if (buffer)
+ {
+ nextAvailableIndex = i + 1;
+ }
+ }
+ }
+
+ // Instanced PointSprite emulation requires two additional ID3D11Buffers.
+ // A vertex buffer needs to be created and added to the list of current buffers,
+ // strides and offsets collections. This buffer contains the vertices for a single
+ // PointSprite quad.
+ // An index buffer also needs to be created and applied because rendering instanced
+ // data on D3D11 FL9_3 requires DrawIndexedInstanced() to be used.
+ if (instancedPointSpritesActive)
+ {
+ HRESULT result = S_OK;
+ const UINT pointSpriteVertexStride = sizeof(float) * 5;
+
+ if (!mPointSpriteVertexBuffer)
+ {
+ static const float pointSpriteVertices[] =
+ {
+ // Position // TexCoord
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+ -1.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ 1.0f, -1.0f, 0.0f, 1.0f, 1.0f,
+ -1.0f, -1.0f, 0.0f, 0.0f, 1.0f,
+ 1.0f, 1.0f, 0.0f, 1.0f, 0.0f,
+ };
+
+ D3D11_SUBRESOURCE_DATA vertexBufferData = { pointSpriteVertices, 0, 0 };
+ D3D11_BUFFER_DESC vertexBufferDesc;
+ vertexBufferDesc.ByteWidth = sizeof(pointSpriteVertices);
+ vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ vertexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ vertexBufferDesc.CPUAccessFlags = 0;
+ vertexBufferDesc.MiscFlags = 0;
+ vertexBufferDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&vertexBufferDesc, &vertexBufferData, &mPointSpriteVertexBuffer);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation vertex buffer, HRESULT: 0x%08x", result);
+ }
+ }
+
+ mCurrentBuffers[nextAvailableIndex] = mPointSpriteVertexBuffer;
+ mCurrentVertexStrides[nextAvailableIndex] = pointSpriteVertexStride;
+ mCurrentVertexOffsets[nextAvailableIndex] = 0;
+
+ if (!mPointSpriteIndexBuffer)
+ {
+ // Create an index buffer and set it for pointsprite rendering
+ static const unsigned short pointSpriteIndices[] =
+ {
+ 0, 1, 2, 3, 4, 5,
+ };
+
+ D3D11_SUBRESOURCE_DATA indexBufferData = { pointSpriteIndices, 0, 0 };
+ D3D11_BUFFER_DESC indexBufferDesc;
+ indexBufferDesc.ByteWidth = sizeof(pointSpriteIndices);
+ indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
+ indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
+ indexBufferDesc.CPUAccessFlags = 0;
+ indexBufferDesc.MiscFlags = 0;
+ indexBufferDesc.StructureByteStride = 0;
+
+ result = mDevice->CreateBuffer(&indexBufferDesc, &indexBufferData, &mPointSpriteIndexBuffer);
+ if (FAILED(result))
+ {
+ SafeRelease(mPointSpriteVertexBuffer);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create instanced pointsprite emulation index buffer, HRESULT: 0x%08x", result);
+ }
+ }
+
+ // The index buffer is applied here because Instanced PointSprite emulation uses
+ // the a non-indexed rendering path in ANGLE (DrawArrays). This means that applyIndexBuffer()
+ // on the renderer will not be called and setting this buffer here ensures that the rendering
+ // path will contain the correct index buffers.
+ mDeviceContext->IASetIndexBuffer(mPointSpriteIndexBuffer, DXGI_FORMAT_R16_UINT, 0);
+ }
+
+ if (moveFirstIndexedIntoSlotZero)
+ {
+ // In this case, we swapped the slots of the first instanced element and the first indexed element, to ensure
+ // that the first slot contains non-instanced data (required by Feature Level 9_3).
+ // We must also swap the corresponding buffers sent to IASetVertexBuffers so that the correct data is sent to each slot.
+ std::swap(mCurrentBuffers[firstIndexedElement], mCurrentBuffers[firstInstancedElement]);
+ std::swap(mCurrentVertexStrides[firstIndexedElement], mCurrentVertexStrides[firstInstancedElement]);
+ std::swap(mCurrentVertexOffsets[firstIndexedElement], mCurrentVertexOffsets[firstInstancedElement]);
+ }
+
+ if (dirtyBuffers)
+ {
+ ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
+ mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff,
+ mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
+{
+ static const unsigned int seed = 0xDEADBEEF;
+
+ std::size_t hash = 0;
+ MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
+ return hash;
+}
+
+bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
+{
+ if (a.elementCount != b.elementCount)
+ {
+ return false;
+ }
+
+ return std::equal(a.begin(), a.end(), b.begin());
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
index cc71ac3f6f..2c94c57595 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h
@@ -7,11 +7,11 @@
// InputLayoutCache.h: Defines InputLayoutCache, a class that builds and caches
// D3D11 input layouts.
-#ifndef LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
-#define LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Constants.h"
+#include "libANGLE/Error.h"
#include "common/angleutils.h"
#include <GLES2/gl2.h>
@@ -21,14 +21,14 @@
namespace gl
{
-class ProgramBinary;
+class Program;
}
namespace rx
{
struct TranslatedAttribute;
-class InputLayoutCache
+class InputLayoutCache : angle::NonCopyable
{
public:
InputLayoutCache();
@@ -39,11 +39,9 @@ class InputLayoutCache
void markDirty();
gl::Error applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
- gl::ProgramBinary *programBinary);
+ GLenum mode, gl::Program *program);
private:
- DISALLOW_COPY_AND_ASSIGN(InputLayoutCache);
-
struct InputLayoutElement
{
D3D11_INPUT_ELEMENT_DESC desc;
@@ -77,6 +75,9 @@ class InputLayoutCache
UINT mCurrentVertexStrides[gl::MAX_VERTEX_ATTRIBS];
UINT mCurrentVertexOffsets[gl::MAX_VERTEX_ATTRIBS];
+ ID3D11Buffer *mPointSpriteVertexBuffer;
+ ID3D11Buffer *mPointSpriteIndexBuffer;
+
static std::size_t hashInputLayout(const InputLayoutKey &inputLayout);
static bool compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b);
@@ -94,8 +95,9 @@ class InputLayoutCache
ID3D11Device *mDevice;
ID3D11DeviceContext *mDeviceContext;
+ D3D_FEATURE_LEVEL mFeatureLevel;
};
}
-#endif // LIBGLESV2_RENDERER_INPUTLAYOUTCACHE_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_INPUTLAYOUTCACHE_H_
diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
index c4a0e42bcc..81b9ea748d 100644
--- a/src/3rdparty/angle/src/common/NativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
@@ -9,13 +9,14 @@
// It is used for HWND (Desktop Windows) and IInspectable objects
//(Windows Store Applications).
-#ifndef COMMON_NATIVEWINDOW_H_
-#define COMMON_NATIVEWINDOW_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
-#include <EGL/eglplatform.h>
#include "common/debug.h"
#include "common/platform.h"
+#include <EGL/eglplatform.h>
+
// DXGISwapChain and DXGIFactory are typedef'd to specific required
// types. The HWND NativeWindow implementation requires IDXGISwapChain
// and IDXGIFactory and the Windows Store NativeWindow
@@ -47,28 +48,26 @@ namespace rx
class NativeWindow
{
-public:
- explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
+ public:
+ enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 };
+ explicit NativeWindow(EGLNativeWindowType window);
bool initialize();
bool getClientRect(LPRECT rect);
bool isIconic();
-
-# if defined(ANGLE_ENABLE_D3D11)
- typedef ID3D11Device Device;
-#else
- typedef IDirect3DDevice9 Device;
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ RotationFlags rotationFlags() const;
#endif
- HRESULT createSwapChain(Device* device, DXGIFactory* factory,
+ static bool isValidNativeWindow(EGLNativeWindowType window);
+
+ HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, UINT width, UINT height,
DXGISwapChain** swapChain);
inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
- inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
private:
EGLNativeWindowType mWindow;
- EGLNativeDisplayType mDisplay;
#if defined(ANGLE_ENABLE_WINDOWS_STORE)
std::shared_ptr<InspectableNativeWindow> mImpl;
@@ -76,7 +75,6 @@ public:
};
-bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
}
-#endif // COMMON_NATIVEWINDOW_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_NATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
index 6a3d3475ee..5fd5237d90 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp
@@ -9,24 +9,24 @@
// Used to implement pixel transfers from unpack and to pack buffers.
//
-#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Context.h"
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
// Precompiled shaders
-#include "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"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
namespace rx
{
@@ -133,13 +133,10 @@ gl::Error PixelTransfer11::loadResources()
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
}
- if (!mRenderer->isLevel9())
+ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
+ if (!mBufferToTextureGS)
{
- mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
- if (!mBufferToTextureGS)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
- }
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
}
gl::Error error = buildShaderMap();
@@ -167,17 +164,18 @@ void PixelTransfer11::setBufferToTextureCopyParams(const gl::Box &destArea, cons
unsigned int alignmentBytes = static_cast<unsigned int>(unpack.alignment);
unsigned int alignmentPixels = (alignmentBytes <= bytesPerPixel ? 1 : alignmentBytes / bytesPerPixel);
- parametersOut->FirstPixelOffset = offset;
- parametersOut->PixelsPerRow = static_cast<unsigned int>(destArea.width);
+ parametersOut->FirstPixelOffset = offset / bytesPerPixel;
+ parametersOut->PixelsPerRow = static_cast<unsigned int>((unpack.rowLength > 0) ? unpack.rowLength : destArea.width);
parametersOut->RowStride = roundUp(parametersOut->PixelsPerRow, alignmentPixels);
parametersOut->RowsPerSlice = static_cast<unsigned int>(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<float>(destSize.width);
parametersOut->PositionScale[1] = -2.0f / static_cast<float>(destSize.height);
+ parametersOut->FirstSlice = destArea.z;
}
-gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
{
gl::Error error = loadResources();
@@ -202,9 +200,9 @@ gl::Error PixelTransfer11::copyBufferToTexture(const gl::PixelUnpackState &unpac
// The SRV must be in the proper read format, which may be different from the destination format
// EG: for half float data, we can load full precision floats with implicit conversion
GLenum unsizedFormat = gl::GetInternalFormatInfo(destinationFormat).format;
- GLenum sourceFormat = gl::GetFormatTypeInfo(unsizedFormat, sourcePixelsType).internalFormat;
+ GLenum sourceFormat = gl::GetSizedInternalFormat(unsizedFormat, sourcePixelsType);
- const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat);
+ const d3d11::TextureFormat &sourceFormatInfo = d3d11::GetTextureFormatInfo(sourceFormat, mRenderer->getFeatureLevel());
DXGI_FORMAT srvFormat = sourceFormatInfo.srvFormat;
ASSERT(srvFormat != DXGI_FORMAT_UNKNOWN);
Buffer11 *bufferStorage11 = Buffer11::makeBuffer11(sourceBuffer.getImplementation());
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
index 29552140bb..1672121ec7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h
@@ -8,10 +8,10 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include "common/platform.h"
@@ -32,7 +32,7 @@ struct PixelUnpackState;
namespace rx
{
class Renderer11;
-class RenderTarget;
+class RenderTargetD3D;
class PixelTransfer11
{
@@ -45,7 +45,7 @@ class PixelTransfer11
// destRenderTarget: individual slice/layer of a target texture
// destinationFormat/sourcePixelsType: determines shaders + shader parameters
// destArea: the sub-section of destRenderTarget to copy to
- gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ gl::Error copyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
private:
@@ -60,6 +60,7 @@ class PixelTransfer11
float PositionScale[2];
int TexLocationOffset[2];
int TexLocationScale[2];
+ unsigned int FirstSlice;
};
static void setBufferToTextureCopyParams(const gl::Box &destArea, const gl::Extents &destSize, GLenum internalFormat,
@@ -85,4 +86,4 @@ class PixelTransfer11
}
-#endif // LIBGLESV2_PIXELTRANSFER11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_PIXELTRANSFER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
index 17ab1f8ab3..4979ff51a9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
@@ -6,14 +6,20 @@
// Query11.cpp: Defines the rx::Query11 class which implements rx::QueryImpl.
-#include "libGLESv2/renderer/d3d/d3d11/Query11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include "common/utilities.h"
#include <GLES2/gl2ext.h>
+#if defined(ANGLE_MINGW32_COMPAT)
+typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
+ UINT64 NumPrimitivesWritten;
+ UINT64 PrimitivesStorageNeeded;
+} D3D11_QUERY_DATA_SO_STATISTICS;
+#endif
+
namespace rx
{
@@ -73,7 +79,7 @@ gl::Error Query11::getResult(GLuint *params)
if (!mQueryFinished)
{
- Sleep(0);
+ ScheduleYield();
}
}
@@ -145,8 +151,9 @@ gl::Error Query11::testQuery()
break;
}
- if (!mQueryFinished && mRenderer->testDeviceLost(true))
+ if (!mQueryFinished && mRenderer->testDeviceLost())
{
+ mRenderer->notifyDeviceLost();
return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
index f9ff467873..bd53fed250 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Query11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.h
@@ -6,10 +6,10 @@
// Query11.h: Defines the rx::Query11 class which implements rx::QueryImpl.
-#ifndef LIBGLESV2_RENDERER_QUERY11_H_
-#define LIBGLESV2_RENDERER_QUERY11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
-#include "libGLESv2/renderer/QueryImpl.h"
+#include "libANGLE/renderer/QueryImpl.h"
namespace rx
{
@@ -27,8 +27,6 @@ class Query11 : public QueryImpl
virtual gl::Error isResultAvailable(GLuint *available);
private:
- DISALLOW_COPY_AND_ASSIGN(Query11);
-
gl::Error testQuery();
GLuint mResult;
@@ -41,4 +39,4 @@ class Query11 : public QueryImpl
}
-#endif // LIBGLESV2_RENDERER_QUERY11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_QUERY11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
index ab4f60bd98..4990e6bc6e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp
@@ -7,14 +7,16 @@
// 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 "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
-#include "common/debug.h"
+#include <float.h>
+#include "common/debug.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "third_party/murmurhash/MurmurHash3.h"
namespace rx
@@ -92,7 +94,8 @@ gl::Error RenderStateCache::getBlendState(const gl::Framebuffer *framebuffer, co
bool mrt = false;
- const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(mRenderer->getWorkarounds());
+ const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(mRenderer->getWorkarounds());
BlendStateKey key = { 0 };
key.blendState = blendState;
@@ -422,6 +425,16 @@ gl::Error RenderStateCache::getSamplerState(const gl::SamplerState &samplerState
samplerDesc.MinLOD = samplerState.minLod;
samplerDesc.MaxLOD = samplerState.maxLod;
+ if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
+ {
+ // Check that maxLOD is nearly FLT_MAX (1000.0f is the default), since 9_3 doesn't support anything other than FLT_MAX.
+ // Note that Feature Level 9_* only supports GL ES 2.0, so the consumer of ANGLE can't modify the Max LOD themselves.
+ ASSERT(samplerState.maxLod >= 999.9f);
+
+ // Now just set MaxLOD to FLT_MAX. Other parts of the renderer (e.g. the non-zero max LOD workaround) should take account of this.
+ samplerDesc.MaxLOD = FLT_MAX;
+ }
+
ID3D11SamplerState *dx11SamplerState = NULL;
HRESULT result = mDevice->CreateSamplerState(&samplerDesc, &dx11SamplerState);
if (FAILED(result) || !dx11SamplerState)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
index dfd1d84265..0099b94a04 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h
@@ -7,11 +7,11 @@
// RenderStateCache.h: Defines rx::RenderStateCache, a cache of Direct3D render
// state objects.
-#ifndef LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
-#define LIBGLESV2_RENDERER_RENDERSTATECACHE_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
#include "common/angleutils.h"
#include <unordered_map>
@@ -25,7 +25,7 @@ namespace rx
{
class Renderer11;
-class RenderStateCache
+class RenderStateCache : angle::NonCopyable
{
public:
RenderStateCache(Renderer11 *renderer);
@@ -40,8 +40,6 @@ class RenderStateCache
gl::Error getSamplerState(const gl::SamplerState &samplerState, ID3D11SamplerState **outSamplerState);
private:
- DISALLOW_COPY_AND_ASSIGN(RenderStateCache);
-
Renderer11 *mRenderer;
unsigned long long mCounter;
@@ -110,4 +108,4 @@ class RenderStateCache
}
-#endif // LIBGLESV2_RENDERER_RENDERSTATECACHE_H_ \ No newline at end of file
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERSTATECACHE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
index aff3453492..ecd9e13c90 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp
@@ -7,12 +7,11 @@
// RenderTarget11.cpp: Implements a DX11-specific wrapper for ID3D11View pointers
// retained by Renderbuffers.
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
namespace rx
{
@@ -177,24 +176,19 @@ static unsigned int getDSVSubresourceIndex(ID3D11Resource *resource, ID3D11Depth
return D3D11CalcSubresource(mipSlice, arraySlice, mipLevels);
}
-RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTarget *target)
+RenderTarget11 *RenderTarget11::makeRenderTarget11(RenderTargetD3D *target)
{
ASSERT(HAS_DYNAMIC_TYPE(RenderTarget11*, target));
return static_cast<RenderTarget11*>(target);
}
-void RenderTarget11::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
-{
- // Currently a no-op
-}
-
TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11Resource *resource, ID3D11ShaderResourceView *srv,
GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLsizei samples)
: mWidth(width),
mHeight(height),
mDepth(depth),
mInternalFormat(internalFormat),
- mActualFormat(internalFormat),
+ mDXGIFormat(DXGI_FORMAT_UNKNOWN),
mSamples(samples),
mSubresourceIndex(0),
mTexture(resource),
@@ -223,9 +217,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11RenderTargetView *rtv, ID3D11
D3D11_RENDER_TARGET_VIEW_DESC desc;
mRenderTarget->GetDesc(&desc);
-
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
- mActualFormat = dxgiFormatInfo.internalFormat;
+ mDXGIFormat = desc.Format;
}
}
@@ -235,7 +227,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11
mHeight(height),
mDepth(depth),
mInternalFormat(internalFormat),
- mActualFormat(internalFormat),
+ mDXGIFormat(DXGI_FORMAT_UNKNOWN),
mSamples(samples),
mSubresourceIndex(0),
mTexture(resource),
@@ -264,9 +256,7 @@ TextureRenderTarget11::TextureRenderTarget11(ID3D11DepthStencilView *dsv, ID3D11
D3D11_DEPTH_STENCIL_VIEW_DESC desc;
mDepthStencil->GetDesc(&desc);
-
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(desc.Format);
- mActualFormat = dxgiFormatInfo.internalFormat;
+ mDXGIFormat = desc.Format;
}
}
@@ -318,11 +308,6 @@ GLenum TextureRenderTarget11::getInternalFormat() const
return mInternalFormat;
}
-GLenum TextureRenderTarget11::getActualFormat() const
-{
- return mActualFormat;
-}
-
GLsizei TextureRenderTarget11::getSamples() const
{
return mSamples;
@@ -333,9 +318,14 @@ unsigned int TextureRenderTarget11::getSubresourceIndex() const
return mSubresourceIndex;
}
+DXGI_FORMAT TextureRenderTarget11::getDXGIFormat() const
+{
+ return mDXGIFormat;
+}
-SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth)
+SurfaceRenderTarget11::SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth)
: mSwapChain(swapChain),
+ mRenderer(renderer),
mDepth(depth)
{
ASSERT(mSwapChain);
@@ -365,11 +355,6 @@ GLenum SurfaceRenderTarget11::getInternalFormat() const
return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat());
}
-GLenum SurfaceRenderTarget11::getActualFormat() const
-{
- return d3d11::GetDXGIFormatInfo(d3d11::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat;
-}
-
GLsizei SurfaceRenderTarget11::getSamples() const
{
// Our EGL surfaces do not support multisampling.
@@ -401,4 +386,9 @@ unsigned int SurfaceRenderTarget11::getSubresourceIndex() const
return 0;
}
+DXGI_FORMAT SurfaceRenderTarget11::getDXGIFormat() const
+{
+ return d3d11::GetTextureFormatInfo(getInternalFormat(), mRenderer->getFeatureLevel()).texFormat;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
index c7babdda3f..4472a56175 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h
@@ -7,24 +7,23 @@
// RenderTarget11.h: Defines a DX11-specific wrapper for ID3D11View pointers
// retained by Renderbuffers.
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET11_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
namespace rx
{
class SwapChain11;
+class Renderer11;
-class RenderTarget11 : public RenderTarget
+class RenderTarget11 : public RenderTargetD3D
{
public:
RenderTarget11() { }
virtual ~RenderTarget11() { }
- static RenderTarget11 *makeRenderTarget11(RenderTarget *renderTarget);
-
- void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override;
+ static RenderTarget11 *makeRenderTarget11(RenderTargetD3D *renderTarget);
virtual ID3D11Resource *getTexture() const = 0;
virtual ID3D11RenderTargetView *getRenderTargetView() const = 0;
@@ -33,8 +32,10 @@ class RenderTarget11 : public RenderTarget
virtual unsigned int getSubresourceIndex() const = 0;
+ virtual DXGI_FORMAT getDXGIFormat() const = 0;
+
private:
- DISALLOW_COPY_AND_ASSIGN(RenderTarget11);
+ D3D_FEATURE_LEVEL mFeatureLevel;
};
class TextureRenderTarget11 : public RenderTarget11
@@ -51,7 +52,6 @@ class TextureRenderTarget11 : public RenderTarget11
GLsizei getHeight() const override;
GLsizei getDepth() const override;
GLenum getInternalFormat() const override;
- GLenum getActualFormat() const override;
GLsizei getSamples() const override;
ID3D11Resource *getTexture() const override;
@@ -61,14 +61,14 @@ class TextureRenderTarget11 : public RenderTarget11
unsigned int getSubresourceIndex() const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget11);
+ DXGI_FORMAT getDXGIFormat() const override;
+ private:
GLsizei mWidth;
GLsizei mHeight;
GLsizei mDepth;
GLenum mInternalFormat;
- GLenum mActualFormat;
+ DXGI_FORMAT mDXGIFormat;
GLsizei mSamples;
unsigned int mSubresourceIndex;
@@ -81,14 +81,13 @@ class TextureRenderTarget11 : public RenderTarget11
class SurfaceRenderTarget11 : public RenderTarget11
{
public:
- SurfaceRenderTarget11(SwapChain11 *swapChain, bool depth);
+ SurfaceRenderTarget11(SwapChain11 *swapChain, Renderer11 *renderer, bool depth);
virtual ~SurfaceRenderTarget11();
GLsizei getWidth() const override;
GLsizei getHeight() const override;
GLsizei getDepth() const override;
GLenum getInternalFormat() const override;
- GLenum getActualFormat() const override;
GLsizei getSamples() const override;
ID3D11Resource *getTexture() const override;
@@ -98,13 +97,14 @@ class SurfaceRenderTarget11 : public RenderTarget11
unsigned int getSubresourceIndex() const override;
- private:
- DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget11);
+ DXGI_FORMAT getDXGIFormat() const override;
+ private:
SwapChain11 *mSwapChain;
+ Renderer11 *mRenderer;
bool mDepth;
};
}
-#endif // LIBGLESV2_RENDERER_RENDERTARGET11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERTARGET11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
index 777308e6cc..5291a3a086 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
@@ -6,46 +6,49 @@
// Renderer11.cpp: Implements a back-end specific class for the D3D11 renderer.
-#include "libGLESv2/main.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/State.h"
-#include "libGLESv2/renderer/d3d/ProgramD3D.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
-#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
-#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
-#include "libGLESv2/renderer/d3d/IndexDataManager.h"
-#include "libGLESv2/renderer/d3d/d3d11/TextureStorage11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Query11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Fence11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Clear11.h"
-#include "libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/VertexArray11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
-
-#include "libEGL/Display.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
#include "common/utilities.h"
#include "common/tls.h"
-
-#include <EGL/eglext.h>
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Clear11.h"
+#include "libANGLE/renderer/d3d/d3d11/Fence11.h"
+#include "libANGLE/renderer/d3d/d3d11/Framebuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/IndexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/PixelTransfer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Query11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexArray11.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
#include <sstream>
+#include <EGL/eglext.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.
@@ -59,46 +62,174 @@
#define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
#endif
+#ifndef __d3d11sdklayers_h__
+#define D3D11_MESSAGE_CATEGORY UINT
+#define D3D11_MESSAGE_SEVERITY UINT
+#define D3D11_MESSAGE_ID UINT
+struct D3D11_MESSAGE;
+typedef struct D3D11_INFO_QUEUE_FILTER_DESC
+{
+ UINT NumCategories;
+ D3D11_MESSAGE_CATEGORY *pCategoryList;
+ UINT NumSeverities;
+ D3D11_MESSAGE_SEVERITY *pSeverityList;
+ UINT NumIDs;
+ D3D11_MESSAGE_ID *pIDList;
+} D3D11_INFO_QUEUE_FILTER_DESC;
+typedef struct D3D11_INFO_QUEUE_FILTER
+{
+ D3D11_INFO_QUEUE_FILTER_DESC AllowList;
+ D3D11_INFO_QUEUE_FILTER_DESC DenyList;
+} D3D11_INFO_QUEUE_FILTER;
+static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
+MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
+{
+public:
+ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
+ virtual void __stdcall ClearStoredMessages() = 0;
+ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
+ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
+ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
+ virtual UINT64 __stdcall GetNumStoredMessages() = 0;
+ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
+ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
+ virtual UINT64 __stdcall GetMessageCountLimit() = 0;
+ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
+ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
+ virtual void __stdcall ClearStorageFilter() = 0;
+ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
+ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
+ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
+ virtual void __stdcall PopStorageFilter() = 0;
+ virtual UINT __stdcall GetStorageFilterStackSize() = 0;
+ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
+ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
+ virtual void __stdcall ClearRetrievalFilter() = 0;
+ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
+ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
+ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
+ virtual void __stdcall PopRetrievalFilter() = 0;
+ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
+ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
+ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
+ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
+ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
+ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
+ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
+ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
+ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
+ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
+ virtual BOOL __stdcall GetMuteDebugOutput() = 0;
+};
+#endif
+
namespace rx
{
namespace
{
-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
};
+// dirtyPointer is a special value that will make the comparison with any valid pointer fail and force the renderer to re-apply the state.
+static const uintptr_t DirtyPointer = static_cast<uintptr_t>(-1);
+
+static bool ImageIndexConflictsWithSRV(const gl::ImageIndex *index, D3D11_SHADER_RESOURCE_VIEW_DESC desc)
+{
+ unsigned mipLevel = index->mipIndex;
+ unsigned layerIndex = index->layerIndex;
+ GLenum type = index->type;
+
+ switch (desc.ViewDimension)
+ {
+ case D3D11_SRV_DIMENSION_TEXTURE2D:
+ {
+ unsigned maxSrvMip = desc.Texture2D.MipLevels + desc.Texture2D.MostDetailedMip;
+ maxSrvMip = (desc.Texture2D.MipLevels == -1) ? INT_MAX : maxSrvMip;
+
+ unsigned mipMin = index->mipIndex;
+ unsigned mipMax = (layerIndex == -1) ? INT_MAX : layerIndex;
+
+ return type == GL_TEXTURE_2D && RangeUI(mipMin, mipMax).intersects(RangeUI(desc.Texture2D.MostDetailedMip, maxSrvMip));
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURE2DARRAY:
+ {
+ unsigned maxSrvMip = desc.Texture2DArray.MipLevels + desc.Texture2DArray.MostDetailedMip;
+ maxSrvMip = (desc.Texture2DArray.MipLevels == -1) ? INT_MAX : maxSrvMip;
+
+ unsigned maxSlice = desc.Texture2DArray.FirstArraySlice + desc.Texture2DArray.ArraySize;
+
+ // Cube maps can be mapped to Texture2DArray SRVs
+ return (type == GL_TEXTURE_2D_ARRAY || gl::IsCubeMapTextureTarget(type)) &&
+ desc.Texture2DArray.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip &&
+ desc.Texture2DArray.FirstArraySlice <= layerIndex && layerIndex < maxSlice;
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURECUBE:
+ {
+ unsigned maxSrvMip = desc.TextureCube.MipLevels + desc.TextureCube.MostDetailedMip;
+ maxSrvMip = (desc.TextureCube.MipLevels == -1) ? INT_MAX : maxSrvMip;
+
+ return gl::IsCubeMapTextureTarget(type) &&
+ desc.TextureCube.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
+ }
+
+ case D3D11_SRV_DIMENSION_TEXTURE3D:
+ {
+ unsigned maxSrvMip = desc.Texture3D.MipLevels + desc.Texture3D.MostDetailedMip;
+ maxSrvMip = (desc.Texture3D.MipLevels == -1) ? INT_MAX : maxSrvMip;
+
+ return type == GL_TEXTURE_3D &&
+ desc.Texture3D.MostDetailedMip <= mipLevel && mipLevel < maxSrvMip;
+ }
+ default:
+ // We only handle the cases corresponding to valid image indexes
+ UNIMPLEMENTED();
+ }
+
+ return false;
+}
+
// Does *not* increment the resource ref count!!
-ID3D11Resource *GetSRVResource(ID3D11ShaderResourceView *srv)
+ID3D11Resource *GetViewResource(ID3D11View *view)
{
ID3D11Resource *resource = NULL;
- ASSERT(srv);
- srv->GetResource(&resource);
+ ASSERT(view);
+ view->GetResource(&resource);
resource->Release();
return resource;
}
+void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFirstConstant, UINT *outNumConstants)
+{
+ // The offset must be aligned to 256 bytes (should have been enforced by glBindBufferRange).
+ ASSERT(offset % 256 == 0);
+
+ // firstConstant and numConstants are expressed in constants of 16-bytes. Furthermore they must be a multiple of 16 constants.
+ *outFirstConstant = offset / 16;
+
+ // The GL size is not required to be aligned to a 256 bytes boundary.
+ // Round the size up to a 256 bytes boundary then express the results in constants of 16-bytes.
+ *outNumConstants = rx::roundUp(size, static_cast<GLsizeiptr>(256)) / 16;
+
+ // Since the size is rounded up, firstConstant + numConstants may be bigger than the actual size of the buffer.
+ // This behaviour is explictly allowed according to the documentation on ID3D11DeviceContext1::PSSetConstantBuffers1
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
}
-Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes)
+}
+
+Renderer11::Renderer11(egl::Display *display)
: RendererD3D(display),
- mDc(hDc),
mStateCache(this)
{
+ // Initialize global annotator
+ gl::InitializeDebugAnnotations(&mAnnotator);
+
mVertexDataManager = NULL;
mIndexDataManager = NULL;
@@ -110,15 +241,18 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg
mClear = NULL;
+ mTrim = NULL;
+
mSyncQuery = NULL;
+ mSupportsConstantBufferOffsets = false;
+
mD3d11Module = NULL;
mDxgiModule = NULL;
- mDeviceLost = false;
-
mDevice = NULL;
mDeviceContext = NULL;
+ mDeviceContext1 = NULL;
mDxgiAdapter = NULL;
mDxgiFactory = NULL;
@@ -127,9 +261,12 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg
mAppliedVertexShader = NULL;
mAppliedGeometryShader = NULL;
- mCurPointGeometryShader = NULL;
mAppliedPixelShader = NULL;
+ mAppliedNumXFBBindings = static_cast<size_t>(-1);
+
+ const auto &attributes = mDisplay->getAttributeMap();
+
EGLint requestedMajorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE, EGL_DONT_CARE);
EGLint requestedMinorVersion = attributes.get(EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE, EGL_DONT_CARE);
@@ -153,31 +290,45 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg
}
}
-#if !defined(ANGLE_ENABLE_D3D9)
+#if defined(ANGLE_ENABLE_WINDOWS_STORE)
if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
+#else
+ if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
+#endif
{
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
- }
- if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
- {
- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
- }
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
}
-#endif
- mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP
- : D3D_DRIVER_TYPE_HARDWARE;
+ EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+ switch (requestedDeviceType)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_HARDWARE;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_WARP;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_REFERENCE;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDriverType = D3D_DRIVER_TYPE_NULL;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
}
Renderer11::~Renderer11()
{
release();
+
+ gl::UninitializeDebugAnnotations();
}
Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
@@ -190,11 +341,13 @@ Renderer11 *Renderer11::makeRenderer11(Renderer *renderer)
#define D3D11_MESSAGE_ID_DEVICE_DRAW_RENDERTARGETVIEW_NOT_SET ((D3D11_MESSAGE_ID)3146081)
#endif
-EGLint Renderer11::initialize()
+egl::Error Renderer11::initialize()
{
if (!mCompiler.initialize())
{
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_COMPILER_ERROR,
+ "Failed to initialize compiler.");
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
@@ -203,8 +356,9 @@ EGLint Renderer11::initialize()
if (mD3d11Module == NULL || mDxgiModule == NULL)
{
- ERR("Could not load D3D11 or DXGI library - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_MISSING_DEP,
+ "Could not load D3D11 or DXGI library.");
}
// create the D3D11 device
@@ -213,8 +367,9 @@ EGLint Renderer11::initialize()
if (D3D11CreateDevice == NULL)
{
- ERR("Could not retrieve D3D11CreateDevice address - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_MISSING_DEP,
+ "Could not retrieve D3D11CreateDevice address.");
}
#endif
@@ -250,29 +405,29 @@ EGLint Renderer11::initialize()
&mFeatureLevel,
&mDeviceContext);
+ if (result == E_INVALIDARG)
+ {
+ // Cleanup done by destructor through glDestroyRenderer
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_CREATEDEVICE_INVALIDARG,
+ "Could not create D3D11 device.");
+ }
+
if (!mDevice || FAILED(result))
{
- ERR("Could not create D3D11 device - aborting!\n");
- return EGL_NOT_INITIALIZED; // Cleanup done by destructor through glDestroyRenderer
+ // Cleanup done by destructor through glDestroyRenderer
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_CREATEDEVICE_ERROR,
+ "Could not create D3D11 device.");
}
}
#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
- if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
- {
- ID3D10Multithread *multithread;
- result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
- ASSERT(SUCCEEDED(result));
- result = multithread->SetMultithreadProtected(true);
- ASSERT(SUCCEEDED(result));
- multithread->Release();
- }
#if !ANGLE_SKIP_DXGI_1_2_CHECK
// In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
// The easiest way to check is to query for a IDXGIDevice2.
bool requireDXGI1_2 = false;
- HWND hwnd = WindowFromDC(mDc);
+ HWND hwnd = WindowFromDC(mDisplay->getNativeDisplayId());
if (hwnd)
{
DWORD currentProcessId = GetCurrentProcessId();
@@ -291,34 +446,72 @@ EGLint Renderer11::initialize()
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;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_INCOMPATIBLE_DXGI,
+ "DXGI 1.2 required to present to HWNDs owned by another process.");
}
SafeRelease(dxgiDevice2);
}
#endif
#endif
+ // Cast the DeviceContext to a DeviceContext1.
+ // This could fail on Windows 7 without the Platform Update.
+ // Don't error in this case- just don't use mDeviceContext1.
+#if defined(ANGLE_ENABLE_D3D11_1)
+ mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
+#endif
+
IDXGIDevice *dxgiDevice = NULL;
result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
if (FAILED(result))
{
- ERR("Could not query DXGI device - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_OTHER_ERROR,
+ "Could not query DXGI device.");
}
result = dxgiDevice->GetParent(__uuidof(IDXGIAdapter), (void**)&mDxgiAdapter);
if (FAILED(result))
{
- ERR("Could not retrieve DXGI adapter - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_OTHER_ERROR,
+ "Could not retrieve DXGI adapter");
}
SafeRelease(dxgiDevice);
- mDxgiAdapter->GetDesc(&mAdapterDescription);
+#if defined(ANGLE_ENABLE_D3D11_1)
+ IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+
+ // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string.
+ // If DXGI1.2 is available then IDXGIAdapter2::GetDesc2 can be used to get the actual hardware values.
+ if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3 && dxgiAdapter2 != NULL)
+ {
+ DXGI_ADAPTER_DESC2 adapterDesc2 = {0};
+ dxgiAdapter2->GetDesc2(&adapterDesc2);
+
+ // Copy the contents of the DXGI_ADAPTER_DESC2 into mAdapterDescription (a DXGI_ADAPTER_DESC).
+ memcpy(mAdapterDescription.Description, adapterDesc2.Description, sizeof(mAdapterDescription.Description));
+ mAdapterDescription.VendorId = adapterDesc2.VendorId;
+ mAdapterDescription.DeviceId = adapterDesc2.DeviceId;
+ mAdapterDescription.SubSysId = adapterDesc2.SubSysId;
+ mAdapterDescription.Revision = adapterDesc2.Revision;
+ mAdapterDescription.DedicatedVideoMemory = adapterDesc2.DedicatedVideoMemory;
+ mAdapterDescription.DedicatedSystemMemory = adapterDesc2.DedicatedSystemMemory;
+ mAdapterDescription.SharedSystemMemory = adapterDesc2.SharedSystemMemory;
+ mAdapterDescription.AdapterLuid = adapterDesc2.AdapterLuid;
+ }
+ else
+ {
+ mDxgiAdapter->GetDesc(&mAdapterDescription);
+ }
+
+ SafeRelease(dxgiAdapter2);
+#endif
+
memset(mDescription, 0, sizeof(mDescription));
wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
@@ -326,14 +519,15 @@ EGLint Renderer11::initialize()
if (!mDxgiFactory || FAILED(result))
{
- ERR("Could not create DXGI factory - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D11_INIT_OTHER_ERROR,
+ "Could not create DXGI factory.");
}
// Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
#if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
ID3D11InfoQueue *infoQueue;
- result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
+ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
if (SUCCEEDED(result))
{
@@ -353,7 +547,7 @@ EGLint Renderer11::initialize()
initializeDevice();
- return EGL_SUCCESS;
+ return egl::Error(EGL_SUCCESS);
}
// do any one-time device initialization
@@ -366,7 +560,7 @@ void Renderer11::initializeDevice()
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this, getRendererClass());
ASSERT(!mBlit);
mBlit = new Blit11(this);
@@ -374,11 +568,32 @@ void Renderer11::initializeDevice()
ASSERT(!mClear);
mClear = new Clear11(this);
+ const auto &attributes = mDisplay->getAttributeMap();
+ // If automatic trim is enabled, DXGIDevice3::Trim( ) is called for the application
+ // automatically when an application is suspended by the OS. This feature is currently
+ // only supported for Windows Store applications.
+ EGLint enableAutoTrim = attributes.get(EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE, EGL_FALSE);
+
+ if (enableAutoTrim == EGL_TRUE)
+ {
+ ASSERT(!mTrim);
+ mTrim = new Trim11(this);
+ }
+
ASSERT(!mPixelTransfer);
mPixelTransfer = new PixelTransfer11(this);
const gl::Caps &rendererCaps = getRendererCaps();
+#if defined(ANGLE_ENABLE_D3D11_1)
+ if (getDeviceContext1IfSupported())
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE);
+ }
+#endif
+
mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
@@ -391,96 +606,139 @@ void Renderer11::initializeDevice()
markAllStateDirty();
}
-int Renderer11::generateConfigs(ConfigDesc **configDescList)
+egl::ConfigSet Renderer11::generateConfigs() const
{
- unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
- unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
- (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
- int numConfigs = 0;
+ static const GLenum colorBufferFormats[] =
+ {
+ GL_BGRA8_EXT,
+ GL_RGBA8_OES,
+ };
- for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
+ static const GLenum depthStencilBufferFormats[] =
{
- const d3d11::DXGIFormat &renderTargetFormatInfo = d3d11::GetDXGIFormatInfo(RenderTargetFormats[formatIndex]);
- const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat);
- if (renderTargetFormatCaps.renderable)
+ GL_NONE,
+ GL_DEPTH24_STENCIL8_OES,
+ GL_DEPTH_COMPONENT16,
+ };
+
+ const gl::Caps &rendererCaps = getRendererCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+
+ egl::ConfigSet configs;
+ for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
+ {
+ GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
+ const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat);
+ if (colorBufferFormatCaps.renderable)
{
- for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
+ for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
{
- const d3d11::DXGIFormat &depthStencilFormatInfo = d3d11::GetDXGIFormatInfo(DepthStencilFormats[depthStencilIndex]);
- const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat);
- if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == DXGI_FORMAT_UNKNOWN)
+ GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex];
+ const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE)
{
- ConfigDesc newConfig;
- newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat;
- newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat;
- newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
- newConfig.fastConfig = true; // Assume all DX11 format conversions to be fast
- newConfig.es3Capable = true;
-
- (*configDescList)[numConfigs++] = newConfig;
+ const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat);
+
+ egl::Config config;
+ config.renderTargetFormat = colorBufferInternalFormat;
+ config.depthStencilFormat = depthStencilBufferInternalFormat;
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
+ config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT);
+ config.colorBufferType = EGL_RGB_BUFFER;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+ // Can only support a conformant ES2 with feature level greater than 10.0.
+ config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE;
+ config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE;
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = 4;
+ config.minSwapInterval = 0;
+ config.nativeRenderable = EGL_FALSE;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+ // Can't support ES3 at all without feature level 10.0
+ config.renderableType = EGL_OPENGL_ES2_BIT | ((mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? EGL_OPENGL_ES3_BIT_KHR : 0);
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+
+ configs.add(config);
}
}
}
}
- return numConfigs;
+ ASSERT(configs.size() > 0);
+ return configs;
}
-void Renderer11::deleteConfigs(ConfigDesc *configDescList)
+gl::Error Renderer11::flush()
{
- delete [] (configDescList);
+ mDeviceContext->Flush();
+ return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::sync(bool block)
+gl::Error Renderer11::finish()
{
- if (block)
+ HRESULT result;
+
+ if (!mSyncQuery)
{
- HRESULT result;
+ D3D11_QUERY_DESC queryDesc;
+ queryDesc.Query = D3D11_QUERY_EVENT;
+ queryDesc.MiscFlags = 0;
- if (!mSyncQuery)
+ result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
+ ASSERT(SUCCEEDED(result));
+ if (FAILED(result))
{
- D3D11_QUERY_DESC queryDesc;
- queryDesc.Query = D3D11_QUERY_EVENT;
- queryDesc.MiscFlags = 0;
-
- result = mDevice->CreateQuery(&queryDesc, &mSyncQuery);
- ASSERT(SUCCEEDED(result));
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
- }
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create event query, result: 0x%X.", result);
}
+ }
- mDeviceContext->End(mSyncQuery);
- mDeviceContext->Flush();
+ mDeviceContext->End(mSyncQuery);
+ mDeviceContext->Flush();
- do
+ do
+ {
+ result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
+ if (FAILED(result))
{
- result = mDeviceContext->GetData(mSyncQuery, NULL, 0, D3D11_ASYNC_GETDATA_DONOTFLUSH);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
- }
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ }
- // Keep polling, but allow other threads to do something useful first
- Sleep(0);
+ // Keep polling, but allow other threads to do something useful first
+ ScheduleYield();
- if (testDeviceLost(true))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
- }
+ if (testDeviceLost())
+ {
+ mDisplay->notifyDeviceLost();
+ return gl::Error(GL_OUT_OF_MEMORY, "Device was lost while waiting for sync.");
}
- while (result == S_FALSE);
- }
- else
- {
- mDeviceContext->Flush();
}
+ while (result == S_FALSE);
return gl::Error(GL_NO_ERROR);
}
-SwapChain *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer11::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
{
return new SwapChain11(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
}
@@ -489,17 +747,23 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
{
if (texture)
{
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
ASSERT(textureD3D);
- TextureStorage *texStorage = textureD3D->getNativeTexture();
+ TextureStorage *texStorage = nullptr;
+ gl::Error error = textureD3D->getNativeTexture(&texStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
if (texStorage)
{
TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
- gl::Error error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
- texture->getSamplerState().swizzleGreen,
- texture->getSamplerState().swizzleBlue,
- texture->getSamplerState().swizzleAlpha);
+ error = storage11->generateSwizzles(texture->getSamplerState().swizzleRed,
+ texture->getSamplerState().swizzleGreen,
+ texture->getSamplerState().swizzleBlue,
+ texture->getSamplerState().swizzleAlpha);
if (error.isError())
{
return error;
@@ -513,9 +777,20 @@ gl::Error Renderer11::generateSwizzle(gl::Texture *texture)
gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &samplerStateParam)
{
// Make sure to add the level offset for our tiny compressed texture workaround
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
gl::SamplerState samplerStateInternal = samplerStateParam;
- samplerStateInternal.baseLevel += textureD3D->getNativeTexture()->getTopLevel();
+
+ TextureStorage *storage = nullptr;
+ gl::Error error = textureD3D->getNativeTexture(&storage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Storage should exist, texture should be complete
+ ASSERT(storage);
+
+ samplerStateInternal.baseLevel += storage->getTopLevel();
if (type == gl::SAMPLER_PIXEL)
{
@@ -524,7 +799,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu
if (mForceSetPixelSamplerStates[index] || memcmp(&samplerStateInternal, &mCurPixelSamplerStates[index], sizeof(gl::SamplerState)) != 0)
{
ID3D11SamplerState *dxSamplerState = NULL;
- gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
+ error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
if (error.isError())
{
return error;
@@ -545,7 +820,7 @@ gl::Error Renderer11::setSamplerState(gl::SamplerType type, int index, gl::Textu
if (mForceSetVertexSamplerStates[index] || memcmp(&samplerStateInternal, &mCurVertexSamplerStates[index], sizeof(gl::SamplerState)) != 0)
{
ID3D11SamplerState *dxSamplerState = NULL;
- gl::Error error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
+ error = mStateCache.getSamplerState(samplerStateInternal, &dxSamplerState);
if (error.isError())
{
return error;
@@ -570,9 +845,17 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t
if (texture)
{
- TextureD3D *textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
- TextureStorage *texStorage = textureImpl->getNativeTexture();
- ASSERT(texStorage != NULL);
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *texStorage = nullptr;
+ gl::Error error = textureImpl->getNativeTexture(&texStorage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
TextureStorage11 *storage11 = TextureStorage11::makeTextureStorage11(texStorage);
@@ -580,7 +863,7 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t
gl::SamplerState samplerState = texture->getSamplerState();
samplerState.baseLevel += storage11->getTopLevel();
- gl::Error error = storage11->getSRV(samplerState, &textureSRV);
+ error = storage11->getSRV(samplerState, &textureSRV);
if (error.isError())
{
return error;
@@ -601,11 +884,23 @@ gl::Error Renderer11::setTexture(gl::SamplerType type, int index, gl::Texture *t
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[])
+gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
+ const GLint vertexUniformBuffers[],
+ const GLint fragmentUniformBuffers[])
{
- for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
+ for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxVertexUniformBlocks; uniformBufferIndex++)
{
- const gl::Buffer *uniformBuffer = vertexUniformBuffers[uniformBufferIndex];
+ GLint binding = vertexUniformBuffers[uniformBufferIndex];
+
+ if (binding == -1)
+ {
+ continue;
+ }
+
+ gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
+ GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
+
if (uniformBuffer)
{
Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
@@ -616,18 +911,46 @@ gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[]
return gl::Error(GL_OUT_OF_MEMORY);
}
- if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial())
+ if (mCurrentConstantBufferVS[uniformBufferIndex] != bufferStorage->getSerial() ||
+ mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
{
- mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex,
- 1, &constantBuffer);
+#if defined(ANGLE_ENABLE_D3D11_1)
+ if (mSupportsConstantBufferOffsets && uniformBufferSize != 0)
+ {
+ UINT firstConstant = 0, numConstants = 0;
+ CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants);
+ mDeviceContext1->VSSetConstantBuffers1(getReservedVertexUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
+#endif
+ {
+ ASSERT(uniformBufferOffset == 0);
+ mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer);
+ }
+
mCurrentConstantBufferVS[uniformBufferIndex] = bufferStorage->getSerial();
+ mCurrentConstantBufferVSOffset[uniformBufferIndex] = uniformBufferOffset;
+ mCurrentConstantBufferVSSize[uniformBufferIndex] = uniformBufferSize;
}
}
}
- for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS; uniformBufferIndex++)
+ for (unsigned int uniformBufferIndex = 0; uniformBufferIndex < data.caps->maxFragmentUniformBlocks; uniformBufferIndex++)
{
- const gl::Buffer *uniformBuffer = fragmentUniformBuffers[uniformBufferIndex];
+ GLint binding = fragmentUniformBuffers[uniformBufferIndex];
+
+ if (binding == -1)
+ {
+ continue;
+ }
+
+ gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(binding);
+ GLintptr uniformBufferOffset = data.state->getIndexedUniformBufferOffset(binding);
+ GLsizeiptr uniformBufferSize = data.state->getIndexedUniformBufferSize(binding);
+
if (uniformBuffer)
{
Buffer11 *bufferStorage = Buffer11::makeBuffer11(uniformBuffer->getImplementation());
@@ -638,11 +961,29 @@ gl::Error Renderer11::setUniformBuffers(const gl::Buffer *vertexUniformBuffers[]
return gl::Error(GL_OUT_OF_MEMORY);
}
- if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial())
+ if (mCurrentConstantBufferPS[uniformBufferIndex] != bufferStorage->getSerial() ||
+ mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
{
- mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex,
- 1, &constantBuffer);
+#if defined(ANGLE_ENABLE_D3D11_1)
+ if (mSupportsConstantBufferOffsets && uniformBufferSize != 0)
+ {
+ UINT firstConstant = 0, numConstants = 0;
+ CalculateConstantBufferParams(uniformBufferOffset, uniformBufferSize, &firstConstant, &numConstants);
+ mDeviceContext1->PSSetConstantBuffers1(getReservedFragmentUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
+#endif
+ {
+ ASSERT(uniformBufferOffset == 0);
+ mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex,
+ 1, &constantBuffer);
+ }
+
mCurrentConstantBufferPS[uniformBufferIndex] = bufferStorage->getSerial();
+ mCurrentConstantBufferPSOffset[uniformBufferIndex] = uniformBufferOffset;
+ mCurrentConstantBufferPSSize[uniformBufferIndex] = uniformBufferSize;
}
}
}
@@ -739,8 +1080,8 @@ gl::Error Renderer11::setDepthStencilState(const gl::DepthStencilState &depthSte
// 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);
+ static_assert(D3D11_DEFAULT_STENCIL_READ_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_READ_MASK");
+ static_assert(D3D11_DEFAULT_STENCIL_WRITE_MASK == 0xFF, "Unexpected value of D3D11_DEFAULT_STENCIL_WRITE_MASK");
UINT dxStencilRef = std::min<UINT>(stencilRef, 0xFFu);
mDeviceContext->OMSetDepthStencilState(dxDepthStencilState, dxStencilRef);
@@ -799,33 +1140,67 @@ void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z
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<int>(caps.maxViewportWidth), static_cast<int>(caps.maxViewportWidth));
- dxViewport.TopLeftY = gl::clamp(actualViewport.y, -static_cast<int>(caps.maxViewportHeight), static_cast<int>(caps.maxViewportHeight));
- dxViewport.Width = gl::clamp(actualViewport.width, 0, static_cast<int>(caps.maxViewportWidth - dxViewport.TopLeftX));
- dxViewport.Height = gl::clamp(actualViewport.height, 0, static_cast<int>(caps.maxViewportHeight - dxViewport.TopLeftY));
- dxViewport.MinDepth = actualZNear;
- dxViewport.MaxDepth = actualZFar;
-
bool viewportChanged = mForceSetViewport || memcmp(&actualViewport, &mCurViewport, sizeof(gl::Rectangle)) != 0 ||
actualZNear != mCurNear || actualZFar != mCurFar;
if (viewportChanged)
{
+ const gl::Caps& caps = getRendererCaps();
+
+ int dxMaxViewportBoundsX = static_cast<int>(caps.maxViewportWidth);
+ int dxMaxViewportBoundsY = static_cast<int>(caps.maxViewportHeight);
+ int dxMinViewportBoundsX = -dxMaxViewportBoundsX;
+ int dxMinViewportBoundsY = -dxMaxViewportBoundsY;
+
+ if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ // Feature Level 9 viewports shouldn't exceed the dimensions of the rendertarget.
+ dxMaxViewportBoundsX = mRenderTargetDesc.width;
+ dxMaxViewportBoundsY = mRenderTargetDesc.height;
+ dxMinViewportBoundsX = 0;
+ dxMinViewportBoundsY = 0;
+ }
+
+ int dxViewportTopLeftX = gl::clamp(actualViewport.x, dxMinViewportBoundsX, dxMaxViewportBoundsX);
+ int dxViewportTopLeftY = gl::clamp(actualViewport.y, dxMinViewportBoundsY, dxMaxViewportBoundsY);
+ int dxViewportWidth = gl::clamp(actualViewport.width, 0, dxMaxViewportBoundsX - dxViewportTopLeftX);
+ int dxViewportHeight = gl::clamp(actualViewport.height, 0, dxMaxViewportBoundsY - dxViewportTopLeftY);
+
+ D3D11_VIEWPORT dxViewport;
+ dxViewport.TopLeftX = static_cast<float>(dxViewportTopLeftX);
+ dxViewport.TopLeftY = static_cast<float>(dxViewportTopLeftY);
+ dxViewport.Width = static_cast<float>(dxViewportWidth);
+ dxViewport.Height = static_cast<float>(dxViewportHeight);
+ dxViewport.MinDepth = actualZNear;
+ dxViewport.MaxDepth = actualZFar;
+
mDeviceContext->RSSetViewports(1, &dxViewport);
mCurViewport = actualViewport;
mCurNear = actualZNear;
mCurFar = actualZFar;
+ // On Feature Level 9_*, we must emulate large and/or negative viewports in the shaders using viewAdjust (like the D3D9 renderer).
+ if (mFeatureLevel <= D3D_FEATURE_LEVEL_9_3)
+ {
+ mVertexConstants.viewAdjust[0] = static_cast<float>((actualViewport.width - dxViewportWidth) + 2 * (actualViewport.x - dxViewportTopLeftX)) / dxViewport.Width;
+ mVertexConstants.viewAdjust[1] = static_cast<float>((actualViewport.height - dxViewportHeight) + 2 * (actualViewport.y - dxViewportTopLeftY)) / dxViewport.Height;
+ mVertexConstants.viewAdjust[2] = static_cast<float>(actualViewport.width) / dxViewport.Width;
+ mVertexConstants.viewAdjust[3] = static_cast<float>(actualViewport.height) / dxViewport.Height;
+ }
+
mPixelConstants.viewCoords[0] = actualViewport.width * 0.5f;
mPixelConstants.viewCoords[1] = actualViewport.height * 0.5f;
mPixelConstants.viewCoords[2] = actualViewport.x + (actualViewport.width * 0.5f);
mPixelConstants.viewCoords[3] = actualViewport.y + (actualViewport.height * 0.5f);
+ // Instanced pointsprite emulation requires ViewCoords to be defined in the
+ // the vertex shader.
+ mVertexConstants.viewCoords[0] = mPixelConstants.viewCoords[0];
+ mVertexConstants.viewCoords[1] = mPixelConstants.viewCoords[1];
+ mVertexConstants.viewCoords[2] = mPixelConstants.viewCoords[2];
+ mVertexConstants.viewCoords[3] = mPixelConstants.viewCoords[3];
+
mPixelConstants.depthFront[0] = (actualZFar - actualZNear) * 0.5f;
mPixelConstants.depthFront[1] = (actualZNear + actualZFar) * 0.5f;
@@ -841,7 +1216,7 @@ void Renderer11::setViewport(const gl::Rectangle &viewport, float zNear, float z
mForceSetViewport = false;
}
-bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
+bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
{
D3D11_PRIMITIVE_TOPOLOGY primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_UNDEFINED;
@@ -862,6 +1237,14 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
return false;
}
+ // If instanced pointsprite emulation is being used and If gl_PointSize is used in the shader,
+ // GL_POINTS mode is expected to render pointsprites.
+ // Instanced PointSprite emulation requires that the topology to be D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST.
+ if (mode == GL_POINTS && usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation)
+ {
+ primitiveTopology = D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
+ }
+
if (primitiveTopology != mCurrentPrimitiveTopology)
{
mDeviceContext->IASetPrimitiveTopology(primitiveTopology);
@@ -871,15 +1254,15 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
return count >= minCount;
}
-void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource)
+void Renderer11::unsetConflictingSRVs(gl::SamplerType samplerType, uintptr_t resource, const gl::ImageIndex *index)
{
- std::vector<ID3D11ShaderResourceView *> &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
{
- ID3D11ShaderResourceView *srv = currentSRVs[resourceIndex];
+ auto &record = currentSRVs[resourceIndex];
- if (srv && GetSRVResource(srv) == resource)
+ if (record.srv && record.resource == resource && ImageIndexConflictsWithSRV(index, record.desc))
{
setShaderResource(samplerType, static_cast<UINT>(resourceIndex), NULL);
}
@@ -892,12 +1275,12 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
// 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};
+ DXGI_FORMAT renderTargetFormat = DXGI_FORMAT_UNKNOWN;
ID3D11RenderTargetView* framebufferRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
bool missingColorRenderTarget = true;
- const gl::ColorbufferInfo &colorbuffers = framebuffer->getColorbuffersForRender(getWorkarounds());
+ const FramebufferD3D *framebufferD3D = GetImplAs<FramebufferD3D>(framebuffer);
+ const gl::AttachmentList &colorbuffers = framebufferD3D->getColorAttachmentsForRender(getWorkarounds());
for (size_t colorAttachment = 0; colorAttachment < colorbuffers.size(); ++colorAttachment)
{
@@ -915,8 +1298,6 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
return gl::Error(GL_NO_ERROR);
}
- renderTargetSerials[colorAttachment] = GetAttachmentSerial(colorbuffer);
-
// Extract the render target dimensions and view
RenderTarget11 *renderTarget = NULL;
gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
@@ -931,36 +1312,29 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
if (missingColorRenderTarget)
{
- renderTargetWidth = colorbuffer->getWidth();
- renderTargetHeight = colorbuffer->getHeight();
- renderTargetFormat = colorbuffer->getActualFormat();
+ renderTargetWidth = renderTarget->getWidth();
+ renderTargetHeight = renderTarget->getHeight();
+ renderTargetFormat = renderTarget->getDXGIFormat();
missingColorRenderTarget = false;
}
-#if !defined(NDEBUG)
// Unbind render target SRVs from the shader here to prevent D3D11 warnings.
- ID3D11Resource *renderTargetResource = renderTarget->getTexture();
- unsetSRVsWithResource(gl::SAMPLER_VERTEX, renderTargetResource);
- unsetSRVsWithResource(gl::SAMPLER_PIXEL, renderTargetResource);
-#endif
+ if (colorbuffer->type() == GL_TEXTURE)
+ {
+ uintptr_t rtResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferRTVs[colorAttachment]));
+ const gl::ImageIndex *index = colorbuffer->getTextureImageIndex();
+ ASSERT(index);
+ // The index doesn't need to be corrected for the small compressed texture workaround
+ // because a rendertarget is never compressed.
+ unsetConflictingSRVs(gl::SAMPLER_VERTEX, rtResource, index);
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, rtResource, index);
+ }
}
}
- // Get the depth stencil render buffter and serials
- gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer();
- unsigned int depthbufferSerial = 0;
- unsigned int stencilbufferSerial = 0;
- if (depthStencil)
- {
- depthbufferSerial = GetAttachmentSerial(depthStencil);
- }
- else if (framebuffer->getStencilbuffer())
- {
- depthStencil = framebuffer->getStencilbuffer();
- stencilbufferSerial = GetAttachmentSerial(depthStencil);
- }
-
+ // Get the depth stencil buffers
ID3D11DepthStencilView* framebufferDSV = NULL;
+ gl::FramebufferAttachment *depthStencil = framebuffer->getDepthOrStencilbuffer();
if (depthStencil)
{
RenderTarget11 *depthStencilRenderTarget = NULL;
@@ -979,17 +1353,28 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
// the depth stencil
if (missingColorRenderTarget)
{
- renderTargetWidth = depthStencil->getWidth();
- renderTargetHeight = depthStencil->getHeight();
- renderTargetFormat = depthStencil->getActualFormat();
+ renderTargetWidth = depthStencilRenderTarget->getWidth();
+ renderTargetHeight = depthStencilRenderTarget->getHeight();
+ renderTargetFormat = depthStencilRenderTarget->getDXGIFormat();
+ }
+
+ // Unbind render target SRVs from the shader here to prevent D3D11 warnings.
+ if (depthStencil->type() == GL_TEXTURE)
+ {
+ uintptr_t depthStencilResource = reinterpret_cast<uintptr_t>(GetViewResource(framebufferDSV));
+ const gl::ImageIndex *index = depthStencil->getTextureImageIndex();
+ ASSERT(index);
+ // The index doesn't need to be corrected for the small compressed texture workaround
+ // because a rendertarget is never compressed.
+ unsetConflictingSRVs(gl::SAMPLER_VERTEX, depthStencilResource, index);
+ unsetConflictingSRVs(gl::SAMPLER_PIXEL, depthStencilResource, index);
}
}
// Apply the render target and depth stencil
if (!mRenderTargetDescInitialized || !mDepthStencilInitialized ||
- memcmp(renderTargetSerials, mAppliedRenderTargetSerials, sizeof(renderTargetSerials)) != 0 ||
- depthbufferSerial != mAppliedDepthbufferSerial ||
- stencilbufferSerial != mAppliedStencilbufferSerial)
+ memcmp(framebufferRTVs, mAppliedRTVs, sizeof(framebufferRTVs)) != 0 ||
+ reinterpret_cast<uintptr_t>(framebufferDSV) != mAppliedDSV)
{
mDeviceContext->OMSetRenderTargets(getRendererCaps().maxDrawBuffers, framebufferRTVs, framebufferDSV);
@@ -1005,22 +1390,26 @@ gl::Error Renderer11::applyRenderTarget(const gl::Framebuffer *framebuffer)
mForceSetRasterState = true;
}
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ for (size_t rtIndex = 0; rtIndex < ArraySize(framebufferRTVs); rtIndex++)
{
- mAppliedRenderTargetSerials[rtIndex] = renderTargetSerials[rtIndex];
+ mAppliedRTVs[rtIndex] = reinterpret_cast<uintptr_t>(framebufferRTVs[rtIndex]);
}
- mAppliedDepthbufferSerial = depthbufferSerial;
- mAppliedStencilbufferSerial = stencilbufferSerial;
+ mAppliedDSV = reinterpret_cast<uintptr_t>(framebufferDSV);
mRenderTargetDescInitialized = true;
mDepthStencilInitialized = true;
}
- invalidateFramebufferSwizzles(framebuffer);
+ const Framebuffer11 *framebuffer11 = GetImplAs<Framebuffer11>(framebuffer);
+ gl::Error error = framebuffer11->invalidateSwizzles();
+ if (error.isError())
+ {
+ return error;
+ }
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
@@ -1029,7 +1418,7 @@ gl::Error Renderer11::applyVertexBuffer(const gl::State &state, GLint first, GLs
return error;
}
- return mInputLayoutCache.applyVertexBuffers(attributes, state.getCurrentProgramBinary());
+ return mInputLayoutCache.applyVertexBuffers(attributes, mode, state.getProgram());
}
gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo)
@@ -1066,31 +1455,36 @@ gl::Error Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elemen
return gl::Error(GL_NO_ERROR);
}
-void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
+void Renderer11::applyTransformFeedbackBuffers(const gl::State &state)
{
- size_t numXFBBindings = state.getTransformFeedbackBufferIndexRange();
- ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
-
+ size_t numXFBBindings = 0;
bool requiresUpdate = false;
- for (size_t i = 0; i < numXFBBindings; i++)
+
+ if (state.isTransformFeedbackActiveUnpaused())
{
- gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
- GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
- ID3D11Buffer *d3dBuffer = NULL;
- if (curXFBBuffer)
- {
- Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
- d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- }
+ numXFBBindings = state.getTransformFeedbackBufferIndexRange();
+ ASSERT(numXFBBindings <= gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS);
- // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
- if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
+ for (size_t i = 0; i < numXFBBindings; i++)
{
- requiresUpdate = true;
+ gl::Buffer *curXFBBuffer = state.getIndexedTransformFeedbackBuffer(i);
+ GLintptr curXFBOffset = state.getIndexedTransformFeedbackBufferOffset(i);
+ ID3D11Buffer *d3dBuffer = NULL;
+ if (curXFBBuffer)
+ {
+ Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
+ d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ }
+
+ // TODO: mAppliedTFBuffers and friends should also be kept in a vector.
+ if (d3dBuffer != mAppliedTFBuffers[i] || curXFBOffset != mAppliedTFOffsets[i])
+ {
+ requiresUpdate = true;
+ }
}
}
- if (requiresUpdate)
+ if (requiresUpdate || numXFBBindings != mAppliedNumXFBBindings)
{
for (size_t i = 0; i < numXFBBindings; ++i)
{
@@ -1102,7 +1496,7 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
Buffer11 *storage = Buffer11::makeBuffer11(curXFBBuffer->getImplementation());
ID3D11Buffer *d3dBuffer = storage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer && mAppliedTFOffsets[i] != curXFBOffset) ?
+ mCurrentD3DOffsets[i] = (mAppliedTFBuffers[i] != d3dBuffer || mAppliedTFOffsets[i] != curXFBOffset) ?
static_cast<UINT>(curXFBOffset) : -1;
mAppliedTFBuffers[i] = d3dBuffer;
}
@@ -1114,13 +1508,16 @@ void Renderer11::applyTransformFeedbackBuffers(const gl::State& state)
mAppliedTFOffsets[i] = curXFBOffset;
}
+ mAppliedNumXFBBindings = numXFBBindings;
+
mDeviceContext->SOSetTargets(numXFBBindings, mAppliedTFBuffers, mCurrentD3DOffsets);
}
}
-gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
+gl::Error Renderer11::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize)
{
- if (mode == GL_POINTS && transformFeedbackActive)
+ bool useInstancedPointSpriteEmulation = usesPointSize && getWorkarounds().useInstancedPointSpriteEmulation;
+ if (mode == GL_POINTS && data.state->isTransformFeedbackActiveUnpaused())
{
// Since point sprites are generated with a geometry shader, too many vertices will
// be written if transform feedback is active. To work around this, draw only the points
@@ -1138,19 +1535,38 @@ gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances,
mDeviceContext->Draw(count, 0);
}
- mDeviceContext->GSSetShader(mCurPointGeometryShader, NULL, 0);
- mDeviceContext->PSSetShader(mAppliedPixelShader, NULL, 0);
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(data.state->getProgram());
- if (instances > 0)
+ rx::ShaderExecutableD3D *pixelExe = NULL;
+ gl::Error error = programD3D->getPixelExecutableForFramebuffer(data.state->getDrawFramebuffer(), &pixelExe);
+ if (error.isError())
{
- mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ return error;
}
- else
+
+ // Skip this step if we're doing rasterizer discard.
+ if (pixelExe && !data.state->getRasterizerState().rasterizerDiscard && usesPointSize)
{
- mDeviceContext->Draw(count, 0);
- }
+ ID3D11PixelShader *pixelShader = ShaderExecutable11::makeShaderExecutable11(pixelExe)->getPixelShader();
+ ASSERT(reinterpret_cast<uintptr_t>(pixelShader) == mAppliedPixelShader);
+ mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- mDeviceContext->GSSetShader(mAppliedGeometryShader, NULL, 0);
+ // Retrieve the point sprite geometry shader
+ rx::ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
+ ID3D11GeometryShader *geometryShader = (geometryExe ? ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader() : NULL);
+ mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
+ ASSERT(geometryShader);
+ mDeviceContext->GSSetShader(geometryShader, NULL, 0);
+
+ if (instances > 0)
+ {
+ mDeviceContext->DrawInstanced(count, instances, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
+ }
return gl::Error(GL_NO_ERROR);
}
@@ -1169,7 +1585,17 @@ gl::Error Renderer11::drawArrays(GLenum mode, GLsizei count, GLsizei instances,
}
else
{
- mDeviceContext->Draw(count, 0);
+ // If gl_PointSize is used and GL_POINTS is specified, then it is expected to render pointsprites.
+ // If instanced pointsprite emulation is being used the topology is expexted to be
+ // D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST and DrawIndexedInstanced must be used.
+ if (mode == GL_POINTS && useInstancedPointSpriteEmulation)
+ {
+ mDeviceContext->DrawIndexedInstanced(6, count, 0, 0, 0);
+ }
+ else
+ {
+ mDeviceContext->Draw(count, 0);
+ }
return gl::Error(GL_NO_ERROR);
}
}
@@ -1198,90 +1624,13 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons
return gl::Error(GL_NO_ERROR);
}
}
-template<typename T>
-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<const GLubyte*>(indices)[i];
- }
- data[count] = static_cast<const GLubyte*>(indices)[0];
- break;
- case GL_UNSIGNED_SHORT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLushort*>(indices)[i];
- }
- data[count] = static_cast<const GLushort*>(indices)[0];
- break;
- case GL_UNSIGNED_INT:
- for (int i = 0; i < count; i++)
- {
- data[i] = static_cast<const GLuint*>(indices)[i];
- }
- data[count] = static_cast<const GLuint*>(indices)[0];
- break;
- default: UNREACHABLE();
- }
-}
-
-template<typename T>
-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<const GLubyte*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_SHORT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
- }
- break;
- case GL_UNSIGNED_INT:
- for (unsigned int i = 0; i < numTris; i++)
- {
- data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
- data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
- data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
- }
- break;
- default: UNREACHABLE();
- }
-}
gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
{
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
intptr_t offset = reinterpret_cast<intptr_t>(indices);
const uint8_t *bufferData = NULL;
@@ -1294,13 +1643,10 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
indices = bufferData + offset;
}
- // TODO: some level 9 hardware supports 32-bit indices; test and store support instead
- const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-
if (!mLineLoopIB)
{
mLineLoopIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
SafeDelete(mLineLoopIB);
@@ -1311,8 +1657,7 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
// Checked by Renderer11::applyPrimitiveType
ASSERT(count >= 0);
- int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / indexTypeSize))
+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
}
@@ -1332,12 +1677,42 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
return error;
}
- if (indexType == GL_UNSIGNED_SHORT)
- fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
- else
- fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
unsigned int indexBufferOffset = offset;
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = i;
+ }
+ data[count] = 0;
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLubyte*>(indices)[i];
+ }
+ data[count] = static_cast<const GLubyte*>(indices)[0];
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLushort*>(indices)[i];
+ }
+ data[count] = static_cast<const GLushort*>(indices)[0];
+ break;
+ case GL_UNSIGNED_INT:
+ for (int i = 0; i < count; i++)
+ {
+ data[i] = static_cast<const GLuint*>(indices)[i];
+ }
+ data[count] = static_cast<const GLuint*>(indices)[0];
+ break;
+ default: UNREACHABLE();
+ }
+
error = mLineLoopIB->unmapBuffer();
if (error.isError())
{
@@ -1366,7 +1741,7 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
intptr_t offset = reinterpret_cast<intptr_t>(indices);
const uint8_t *bufferData = NULL;
@@ -1379,12 +1754,10 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
indices = bufferData + offset;
}
- const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-
if (!mTriangleFanIB)
{
mTriangleFanIB = new StreamingIndexBufferInterface(this);
- gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
+ gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
if (error.isError())
{
SafeDelete(mTriangleFanIB);
@@ -1397,14 +1770,13 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
const unsigned int numTris = count - 2;
- int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
- if (numTris > (std::numeric_limits<unsigned int>::max() / (indexTypeSize * 3)))
+ if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
}
- const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize;
- gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType);
+ const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
+ gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
if (error.isError())
{
return error;
@@ -1418,13 +1790,46 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return error;
}
- if (indexType == GL_UNSIGNED_SHORT)
- fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
- else
- fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
-
+ unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
unsigned int indexBufferOffset = offset;
+ switch (type)
+ {
+ case GL_NONE: // Non-indexed draw
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = 0;
+ data[i*3 + 1] = i + 1;
+ data[i*3 + 2] = i + 2;
+ }
+ break;
+ case GL_UNSIGNED_BYTE:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_SHORT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
+ }
+ break;
+ case GL_UNSIGNED_INT:
+ for (unsigned int i = 0; i < numTris; i++)
+ {
+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
+ data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
+ }
+ break;
+ default: UNREACHABLE();
+ }
+
error = mTriangleFanIB->unmapBuffer();
if (error.isError())
{
@@ -1455,26 +1860,26 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+gl::Error Renderer11::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive)
{
- ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- ShaderExecutable *vertexExe = NULL;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
+ ShaderExecutableD3D *vertexExe = NULL;
+ gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr);
if (error.isError())
{
return error;
}
- ShaderExecutable *pixelExe = NULL;
+ ShaderExecutableD3D *pixelExe = NULL;
error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
if (error.isError())
{
return error;
}
- ShaderExecutable *geometryExe = programD3D->getGeometryExecutable();
+ ShaderExecutableD3D *geometryExe = programD3D->getGeometryExecutable();
ID3D11VertexShader *vertexShader = (vertexExe ? ShaderExecutable11::makeShaderExecutable11(vertexExe)->getVertexShader() : NULL);
@@ -1497,33 +1902,24 @@ gl::Error Renderer11::applyShaders(gl::ProgramBinary *programBinary, const gl::V
bool dirtyUniforms = false;
- if (vertexShader != mAppliedVertexShader)
+ if (reinterpret_cast<uintptr_t>(vertexShader) != mAppliedVertexShader)
{
mDeviceContext->VSSetShader(vertexShader, NULL, 0);
- mAppliedVertexShader = vertexShader;
+ mAppliedVertexShader = reinterpret_cast<uintptr_t>(vertexShader);
dirtyUniforms = true;
}
- if (geometryShader != mAppliedGeometryShader)
+ if (reinterpret_cast<uintptr_t>(geometryShader) != mAppliedGeometryShader)
{
mDeviceContext->GSSetShader(geometryShader, NULL, 0);
- mAppliedGeometryShader = geometryShader;
+ mAppliedGeometryShader = reinterpret_cast<uintptr_t>(geometryShader);
dirtyUniforms = true;
}
- if (geometryExe && mCurRasterState.pointDrawMode)
- {
- mCurPointGeometryShader = ShaderExecutable11::makeShaderExecutable11(geometryExe)->getGeometryShader();
- }
- else
- {
- mCurPointGeometryShader = NULL;
- }
-
- if (pixelShader != mAppliedPixelShader)
+ if (reinterpret_cast<uintptr_t>(pixelShader) != mAppliedPixelShader)
{
mDeviceContext->PSSetShader(pixelShader, NULL, 0);
- mAppliedPixelShader = pixelShader;
+ mAppliedPixelShader = reinterpret_cast<uintptr_t>(pixelShader);
dirtyUniforms = true;
}
@@ -1560,7 +1956,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
}
}
- const ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(&program);
+ const ProgramD3D *programD3D = GetAs<ProgramD3D>(&program);
const UniformStorage11 *vertexUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getVertexUniformStorage());
const UniformStorage11 *fragmentUniformStorage = UniformStorage11::makeUniformStorage11(&programD3D->getFragmentUniformStorage());
ASSERT(vertexUniformStorage);
@@ -1682,40 +2078,36 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
memcpy(&mAppliedPixelConstants, &mPixelConstants, sizeof(dx_PixelConstants));
}
- // needed for the point sprite geometry shader
- if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ // GSSetConstantBuffers triggers device removal on 9_3, so we should only call it if necessary
+ if (programD3D->usesGeometryShader())
{
- mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
- mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
-{
- gl::Error error = mClear->clearFramebuffer(clearParams, frameBuffer);
- if (error.isError())
- {
- return error;
+ // needed for the point sprite geometry shader
+ if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
+ {
+ mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
+ mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
+ }
}
- invalidateFramebufferSwizzles(frameBuffer);
-
return gl::Error(GL_NO_ERROR);
}
void Renderer11::markAllStateDirty()
{
- for (unsigned int rtIndex = 0; rtIndex < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; rtIndex++)
+ for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
{
- mAppliedRenderTargetSerials[rtIndex] = 0;
+ mAppliedRTVs[rtIndex] = DirtyPointer;
}
- mAppliedDepthbufferSerial = 0;
- mAppliedStencilbufferSerial = 0;
+ mAppliedDSV = DirtyPointer;
mDepthStencilInitialized = false;
mRenderTargetDescInitialized = false;
+ // We reset the current SRV data because it might not be in sync with D3D's state
+ // anymore. For example when a currently used SRV is used as an RTV, D3D silently
+ // remove it from its state.
+ memset(mCurVertexSRVs.data(), 0, sizeof(SRVRecord) * mCurVertexSRVs.size());
+ memset(mCurPixelSRVs.data(), 0, sizeof(SRVRecord) * mCurPixelSRVs.size());
+
ASSERT(mForceSetVertexSamplerStates.size() == mCurVertexSRVs.size());
for (size_t vsamplerId = 0; vsamplerId < mForceSetVertexSamplerStates.size(); ++vsamplerId)
{
@@ -1738,10 +2130,11 @@ void Renderer11::markAllStateDirty()
mAppliedIBFormat = DXGI_FORMAT_UNKNOWN;
mAppliedIBOffset = 0;
- mAppliedVertexShader = NULL;
- mAppliedGeometryShader = NULL;
- mCurPointGeometryShader = NULL;
- mAppliedPixelShader = NULL;
+ mAppliedVertexShader = DirtyPointer;
+ mAppliedGeometryShader = DirtyPointer;
+ mAppliedPixelShader = DirtyPointer;
+
+ mAppliedNumXFBBindings = static_cast<size_t>(-1);
for (size_t i = 0; i < gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS; i++)
{
@@ -1756,8 +2149,12 @@ void Renderer11::markAllStateDirty()
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS; i++)
{
- mCurrentConstantBufferVS[i] = -1;
- mCurrentConstantBufferPS[i] = -1;
+ mCurrentConstantBufferVS[i] = static_cast<unsigned int>(-1);
+ mCurrentConstantBufferVSOffset[i] = 0;
+ mCurrentConstantBufferVSSize[i] = 0;
+ mCurrentConstantBufferPS[i] = static_cast<unsigned int>(-1);
+ mCurrentConstantBufferPSOffset[i] = 0;
+ mCurrentConstantBufferPSSize[i] = 0;
}
mCurrentVertexConstantBuffer = NULL;
@@ -1778,6 +2175,7 @@ void Renderer11::releaseDeviceResources()
SafeDelete(mTriangleFanIB);
SafeDelete(mBlit);
SafeDelete(mClear);
+ SafeDelete(mTrim);
SafeDelete(mPixelTransfer);
SafeRelease(mDriverConstantBufferVS);
@@ -1785,19 +2183,8 @@ void Renderer11::releaseDeviceResources()
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 Renderer11::testDeviceLost()
{
bool isLost = false;
@@ -1819,10 +2206,6 @@ bool Renderer11::testDeviceLost(bool notify)
// 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;
@@ -1872,12 +2255,15 @@ void Renderer11::release()
{
RendererD3D::cleanup();
- releaseShaderCompiler();
releaseDeviceResources();
SafeRelease(mDxgiFactory);
SafeRelease(mDxgiAdapter);
+#if defined(ANGLE_ENABLE_D3D11_1)
+ SafeRelease(mDeviceContext1);
+#endif
+
if (mDeviceContext)
{
mDeviceContext->ClearState();
@@ -1906,11 +2292,11 @@ bool Renderer11::resetDevice()
{
// recreate everything
release();
- EGLint result = initialize();
+ egl::Error result = initialize();
- if (result != EGL_SUCCESS)
+ if (result.isError())
{
- ERR("Could not reinitialize D3D11 device: %08X", result);
+ ERR("Could not reinitialize D3D11 device: %08X", result.getCode());
return false;
}
@@ -1919,9 +2305,9 @@ bool Renderer11::resetDevice()
return true;
}
-DWORD Renderer11::getAdapterVendor() const
+VendorID Renderer11::getVendorId() const
{
- return mAdapterDescription.VendorId;
+ return static_cast<VendorID>(mAdapterDescription.VendorId);
}
std::string Renderer11::getRendererDescription() const
@@ -1931,8 +2317,8 @@ std::string Renderer11::getRendererDescription() const
rendererString << mDescription;
rendererString << " Direct3D11";
- rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel();
- rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel();
+ rendererString << " vs_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix();
+ rendererString << " ps_" << getMajorShaderModel() << "_" << getMinorShaderModel() << getShaderModelSuffix();
return rendererString.str();
}
@@ -1941,7 +2327,7 @@ 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));
+ static_assert(sizeof(LUID) <= sizeof(GUID), "Size of GUID must be at least as large as LUID.");
GUID adapterId = {0};
memcpy(&adapterId, &mAdapterDescription.AdapterLuid, sizeof(LUID));
return adapterId;
@@ -1974,7 +2360,8 @@ 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();
+ // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains.
+ return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation
}
bool Renderer11::getPostSubBufferSupport() const
@@ -1989,10 +2376,8 @@ int Renderer11::getMajorShaderModel() const
{
case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
- case D3D_FEATURE_LEVEL_10_0:
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
+ case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MAJOR_VERSION; // 4
default: UNREACHABLE(); return 0;
}
}
@@ -2003,26 +2388,26 @@ int Renderer11::getMinorShaderModel() const
{
case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
- case D3D_FEATURE_LEVEL_10_0:
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
+ case D3D_FEATURE_LEVEL_9_3: return D3D10_SHADER_MINOR_VERSION; // 0
default: UNREACHABLE(); return 0;
}
}
-int Renderer11::getMinSwapInterval() const
+std::string Renderer11::getShaderModelSuffix() const
{
- return 0;
-}
-
-int Renderer11::getMaxSwapInterval() const
-{
- return 4;
+ switch (mFeatureLevel)
+ {
+ case D3D_FEATURE_LEVEL_11_0: return "";
+ case D3D_FEATURE_LEVEL_10_1: return "";
+ case D3D_FEATURE_LEVEL_10_0: return "";
+ case D3D_FEATURE_LEVEL_9_3: return "_level_9_3";
+ default: UNREACHABLE(); return "";
+ }
}
-gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
ASSERT(colorbuffer);
@@ -2042,7 +2427,7 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan
ASSERT(storage11);
gl::ImageIndex index = gl::ImageIndex::Make2D(level);
- RenderTarget *destRenderTarget = NULL;
+ RenderTargetD3D *destRenderTarget = NULL;
error = storage11->getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -2056,7 +2441,7 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan
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::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
// Use nearest filtering because source and destination are the same size for the direct
@@ -2072,8 +2457,8 @@ gl::Error Renderer11::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectan
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer11::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
{
gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
ASSERT(colorbuffer);
@@ -2093,7 +2478,7 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect
ASSERT(storage11);
gl::ImageIndex index = gl::ImageIndex::MakeCube(target, level);
- RenderTarget *destRenderTarget = NULL;
+ RenderTargetD3D *destRenderTarget = NULL;
error = storage11->getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -2107,7 +2492,7 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect
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::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
// Use nearest filtering because source and destination are the same size for the direct
@@ -2123,8 +2508,8 @@ gl::Error Renderer11::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rect
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
ASSERT(colorbuffer);
@@ -2143,8 +2528,8 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan
TextureStorage11_3D *storage11 = TextureStorage11_3D::makeTextureStorage11_3D(storage);
ASSERT(storage11);
- gl::ImageIndex index = gl::ImageIndex::Make3D(level, zOffset);
- RenderTarget *destRenderTarget = NULL;
+ gl::ImageIndex index = gl::ImageIndex::Make3D(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = NULL;
error = storage11->getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -2158,7 +2543,7 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan
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::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
// Use nearest filtering because source and destination are the same size for the direct
@@ -2174,8 +2559,8 @@ gl::Error Renderer11::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectan
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer11::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
ASSERT(colorbuffer);
@@ -2194,8 +2579,8 @@ gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::R
TextureStorage11_2DArray *storage11 = TextureStorage11_2DArray::makeTextureStorage11_2DArray(storage);
ASSERT(storage11);
- gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, zOffset);
- RenderTarget *destRenderTarget = NULL;
+ gl::ImageIndex index = gl::ImageIndex::Make2DArray(level, destOffset.z);
+ RenderTargetD3D *destRenderTarget = NULL;
error = storage11->getRenderTarget(index, &destRenderTarget);
if (error.isError())
{
@@ -2209,7 +2594,7 @@ gl::Error Renderer11::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::R
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::Box destArea(destOffset.x, destOffset.y, 0, sourceRect.width, sourceRect.height, 1);
gl::Extents destSize(destRenderTarget->getWidth(), destRenderTarget->getHeight(), 1);
// Use nearest filtering because source and destination are the same size for the direct
@@ -2230,6 +2615,7 @@ void Renderer11::unapplyRenderTargets()
setOneTimeRenderTarget(NULL);
}
+// When finished with this rendertarget, markAllStateDirty must be called.
void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView)
{
ID3D11RenderTargetView *rtvArray[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS] = {NULL};
@@ -2239,22 +2625,16 @@ void Renderer11::setOneTimeRenderTarget(ID3D11RenderTargetView *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++)
+ for (size_t rtIndex = 0; rtIndex < ArraySize(mAppliedRTVs); rtIndex++)
{
- mAppliedRenderTargetSerials[rtIndex] = 0;
+ mAppliedRTVs[rtIndex] = DirtyPointer;
}
+ mAppliedDSV = DirtyPointer;
}
-gl::Error Renderer11::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
-{
- SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
- *outRT = new SurfaceRenderTarget11(swapChain11, depth);
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
+gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
{
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(format, mFeatureLevel);
const gl::TextureCaps &textureCaps = getRendererTextureCaps().get(format);
GLuint supportedSamples = textureCaps.getNearestSamples(samples);
@@ -2386,24 +2766,34 @@ gl::Error Renderer11::createRenderTarget(int width, int height, GLenum format, G
return gl::Error(GL_NO_ERROR);
}
-ShaderImpl *Renderer11::createShader(const gl::Data &data, GLenum type)
+FramebufferImpl *Renderer11::createDefaultFramebuffer(const gl::Framebuffer::Data &data)
{
- return new ShaderD3D(data, type, this);
+ return createFramebuffer(data);
}
-ProgramImpl *Renderer11::createProgram()
+FramebufferImpl *Renderer11::createFramebuffer(const gl::Framebuffer::Data &data)
{
- return new ProgramD3D(this);
+ return new Framebuffer11(data, this);
}
-void Renderer11::releaseShaderCompiler()
+CompilerImpl *Renderer11::createCompiler(const gl::Data &data)
{
- ShaderD3D::releaseCompiler();
+ return new CompilerD3D(data, SH_HLSL11_OUTPUT);
+}
+
+ShaderImpl *Renderer11::createShader(GLenum type)
+{
+ return new ShaderD3D(type);
+}
+
+ProgramImpl *Renderer11::createProgram()
+{
+ return new ProgramD3D(this);
}
gl::Error Renderer11::loadExecutable(const void *function, size_t length, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutable **outExecutable)
+ bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable)
{
switch (type)
{
@@ -2490,8 +2880,8 @@ gl::Error Renderer11::loadExecutable(const void *function, size_t length, Shader
gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, D3DWorkaroundType workaround,
- ShaderExecutable **outExectuable)
+ bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable)
{
const char *profileType = NULL;
switch (type)
@@ -2510,51 +2900,11 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
return gl::Error(GL_INVALID_OPERATION);
}
- unsigned int profileMajorVersion = 0;
- unsigned int profileMinorVersion = 0;
- const char *profileSuffix = NULL;
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
- profileMajorVersion = 5;
- profileMinorVersion = 0;
- break;
- case D3D_FEATURE_LEVEL_10_1:
- profileMajorVersion = 4;
- profileMinorVersion = 1;
- break;
- case D3D_FEATURE_LEVEL_10_0:
- profileMajorVersion = 4;
- profileMinorVersion = 0;
- break;
- case D3D_FEATURE_LEVEL_9_3:
- profileMajorVersion = 4;
- profileMinorVersion = 0;
- profileSuffix = "_level_9_3";
- break;
- case D3D_FEATURE_LEVEL_9_2:
- profileMajorVersion = 4;
- profileMinorVersion = 0;
- profileSuffix = "_level_9_2";
- break;
- case D3D_FEATURE_LEVEL_9_1:
- profileMajorVersion = 4;
- profileMinorVersion = 0;
- profileSuffix = "_level_9_1";
- break;
- break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
- }
-
- std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
- if (profileSuffix)
- profile += profileSuffix;
+ std::string profile = FormatString("%s_%d_%d%s", profileType, getMajorShaderModel(), getMinorShaderModel(), getShaderModelSuffix().c_str());
UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
- if (gl::perfActive())
+ if (gl::DebugAnnotationsActive())
{
#ifndef NDEBUG
flags = D3DCOMPILE_SKIP_OPTIMIZATION;
@@ -2563,6 +2913,9 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
flags |= D3DCOMPILE_DEBUG;
}
+ if (workarounds.enableIEEEStrictness)
+ flags |= D3DCOMPILE_IEEE_STRICTNESS;
+
// Sometimes D3DCompile will fail with the default compilation flags for complicated shaders when it would otherwise pass with alternative options.
// Try the default flags first and if compilation fails, try some alternatives.
std::vector<CompileConfig> configs;
@@ -2605,7 +2958,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
return gl::Error(GL_NO_ERROR);
}
-UniformStorage *Renderer11::createUniformStorage(size_t storageSize)
+UniformStorageD3D *Renderer11::createUniformStorage(size_t storageSize)
{
return new UniformStorage11(this, storageSize);
}
@@ -2655,7 +3008,7 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
ASSERT(getRendererExtensions().pixelBufferObject);
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
- const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::TextureFormat &d3d11FormatInfo = d3d11::GetTextureFormatInfo(internalFormat, mFeatureLevel);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11FormatInfo.texFormat);
// sRGB formats do not work with D3D11 buffer SRVs
@@ -2665,7 +3018,7 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
}
// We cannot support direct copies to non-color-renderable formats
- if (d3d11FormatInfo.rtvFormat != DXGI_FORMAT_UNKNOWN)
+ if (d3d11FormatInfo.rtvFormat == DXGI_FORMAT_UNKNOWN)
{
return false;
}
@@ -2685,196 +3038,39 @@ bool Renderer11::supportsFastCopyBufferToTexture(GLenum internalFormat) const
return true;
}
-gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+gl::Error Renderer11::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
{
ASSERT(supportsFastCopyBufferToTexture(destinationFormat));
return mPixelTransfer->copyBufferToTexture(unpack, offset, destRenderTarget, destinationFormat, sourcePixelsType, destArea);
}
-gl::Error Renderer11::getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut)
-
+ImageD3D *Renderer11::createImage()
{
- ASSERT(colorbuffer);
-
- RenderTarget11 *renderTarget = NULL;
- gl::Error error = d3d11::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- ID3D11Resource *renderTargetResource = renderTarget->getTexture();
- ASSERT(renderTargetResource);
-
- *subresourceIndexOut = renderTarget->getSubresourceIndex();
- *texture2DOut = d3d11::DynamicCastComObject<ID3D11Texture2D>(renderTargetResource);
-
- if (!(*texture2DOut))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to query the ID3D11Texture2D from a RenderTarget");
- }
-
- return gl::Error(GL_NO_ERROR);
+ return new Image11(this);
}
-gl::Error Renderer11::blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
- const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- const gl::Rectangle *scissor, bool blitRenderTarget,
- bool blitDepth, bool blitStencil, GLenum filter)
-{
- if (blitRenderTarget)
- {
- gl::FramebufferAttachment *readBuffer = readTarget->getReadColorbuffer();
- ASSERT(readBuffer);
-
- RenderTarget *readRenderTarget = NULL;
- gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(readRenderTarget);
-
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (drawTarget->isEnabledColorAttachment(colorAttachment))
- {
- gl::FramebufferAttachment *drawBuffer = drawTarget->getColorbuffer(colorAttachment);
- ASSERT(drawBuffer);
-
- RenderTarget *drawRenderTarget = NULL;
- error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(drawRenderTarget);
-
- error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, blitRenderTarget,
- false, false);
- if (error.isError())
- {
- return error;
- }
- }
- }
- }
-
- if (blitDepth || blitStencil)
- {
- gl::FramebufferAttachment *readBuffer = readTarget->getDepthOrStencilbuffer();
- ASSERT(readBuffer);
-
- RenderTarget *readRenderTarget = NULL;
- gl::Error error = GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(readRenderTarget);
-
- gl::FramebufferAttachment *drawBuffer = drawTarget->getDepthOrStencilbuffer();
- ASSERT(drawBuffer);
-
- RenderTarget *drawRenderTarget = NULL;
- error = GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(drawRenderTarget);
-
- error = blitRenderbufferRect(readRect, drawRect, readRenderTarget, drawRenderTarget, filter, scissor, false,
- blitDepth, blitStencil);
- if (error.isError())
- {
- return error;
- }
- }
-
- invalidateFramebufferSwizzles(drawTarget);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer11::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
-{
- ID3D11Texture2D *colorBufferTexture = NULL;
- unsigned int subresourceIndex = 0;
-
- gl::FramebufferAttachment *colorbuffer = framebuffer->getReadColorbuffer();
- ASSERT(colorbuffer);
-
- gl::Error error = getRenderTargetResource(colorbuffer, &subresourceIndex, &colorBufferTexture);
- if (error.isError())
- {
- return error;
- }
-
- gl::Rectangle area;
- area.x = x;
- area.y = y;
- area.width = width;
- area.height = height;
-
- gl::Buffer *packBuffer = pack.pixelBuffer.get();
- if (packBuffer != NULL)
- {
- Buffer11 *packBufferStorage = Buffer11::makeBuffer11(packBuffer->getImplementation());
- PackPixelsParams packParams(area, format, type, outputPitch, pack, reinterpret_cast<ptrdiff_t>(pixels));
-
- error = packBufferStorage->packPixels(colorBufferTexture, subresourceIndex, packParams);
- if (error.isError())
- {
- SafeRelease(colorBufferTexture);
- return error;
- }
-
- packBuffer->getIndexRangeCache()->clear();
- }
- else
- {
- error = readTextureData(colorBufferTexture, subresourceIndex, area, format, type, outputPitch, pack, pixels);
- if (error.isError())
- {
- SafeRelease(colorBufferTexture);
- return error;
- }
- }
-
- SafeRelease(colorBufferTexture);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-Image *Renderer11::createImage()
-{
- return new Image11();
-}
-
-gl::Error Renderer11::generateMipmap(Image *dest, Image *src)
+gl::Error Renderer11::generateMipmap(ImageD3D *dest, ImageD3D *src)
{
Image11 *dest11 = Image11::makeImage11(dest);
Image11 *src11 = Image11::makeImage11(src);
return Image11::generateMipmap(dest11, src11);
}
-TextureStorage *Renderer11::createTextureStorage2D(SwapChain *swapChain)
+TextureStorage *Renderer11::createTextureStorage2D(SwapChainD3D *swapChain)
{
SwapChain11 *swapChain11 = SwapChain11::makeSwapChain11(swapChain);
return new TextureStorage11_2D(this, swapChain11);
}
-TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+TextureStorage *Renderer11::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
{
- return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels);
+ return new TextureStorage11_2D(this, internalformat, renderTarget, width, height, levels, hintLevelZeroOnly);
}
-TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
+TextureStorage *Renderer11::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
{
- return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels);
+ return new TextureStorage11_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
}
TextureStorage *Renderer11::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
@@ -2908,13 +3104,6 @@ RenderbufferImpl *Renderer11::createRenderbuffer()
return renderbuffer;
}
-RenderbufferImpl *Renderer11::createRenderbuffer(SwapChain *swapChain, bool depth)
-{
- RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
- renderbuffer->setStorage(swapChain, depth);
- return renderbuffer;
-}
-
gl::Error Renderer11::readTextureData(ID3D11Texture2D *texture, unsigned int subResource, const gl::Rectangle &area, GLenum format,
GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
{
@@ -3057,8 +3246,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
const d3d11::DXGIFormat &sourceDXGIFormatInfo = d3d11::GetDXGIFormatInfo(textureDesc.Format);
ColorCopyFunction fastCopyFunc = sourceDXGIFormatInfo.getFastCopyFunction(params.format, params.type);
- const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(params.format, params.type);
- const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
+ GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(params.format, params.type);
+ const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
if (fastCopyFunc)
{
@@ -3076,10 +3265,14 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
}
else
{
+ ColorReadFunction colorReadFunction = sourceDXGIFormatInfo.colorReadFunction;
+ ColorWriteFunction colorWriteFunction = GetColorWriteFunction(params.format, params.type);
+
uint8_t temp[16]; // Maximum size of any Color<T> type used.
- META_ASSERT(sizeof(temp) >= sizeof(gl::ColorF) &&
- sizeof(temp) >= sizeof(gl::ColorUI) &&
- sizeof(temp) >= sizeof(gl::ColorI));
+ static_assert(sizeof(temp) >= sizeof(gl::ColorF) &&
+ sizeof(temp) >= sizeof(gl::ColorUI) &&
+ sizeof(temp) >= sizeof(gl::ColorI),
+ "Unexpected size of gl::Color struct.");
for (int y = 0; y < params.area.height; y++)
{
@@ -3090,8 +3283,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
// readFunc and writeFunc will be using the same type of color, CopyTexImage
// will not allow the copy otherwise.
- sourceDXGIFormatInfo.colorReadFunction(src, temp);
- destFormatTypeInfo.colorWriteFunction(temp, dest);
+ colorReadFunction(src, temp);
+ colorWriteFunction(temp, dest);
}
}
}
@@ -3102,8 +3295,8 @@ gl::Error Renderer11::packPixels(ID3D11Texture2D *readTexture, const PackPixelsP
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
bool colorBlit, bool depthBlit, bool stencilBlit)
{
// Since blitRenderbufferRect is called for each render buffer that needs to be blitted,
@@ -3187,12 +3380,12 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
drawRect.x < 0 || drawRect.x + drawRect.width > drawSize.width ||
drawRect.y < 0 || drawRect.y + drawRect.height > drawSize.height;
- const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(drawRenderTarget->getActualFormat());
- bool partialDSBlit = (actualFormatInfo.depthBits > 0 && depthBlit) != (actualFormatInfo.stencilBits > 0 && stencilBlit);
+ const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(drawRenderTarget11->getDXGIFormat());
+ bool partialDSBlit = (dxgiFormatInfo.depthBits > 0 && depthBlit) != (dxgiFormatInfo.stencilBits > 0 && stencilBlit);
gl::Error result(GL_NO_ERROR);
- if (readRenderTarget11->getActualFormat() == drawRenderTarget->getActualFormat() &&
+ if (readRenderTarget11->getDXGIFormat() == drawRenderTarget11->getDXGIFormat() &&
!stretchRequired && !outOfBounds && !flipRequired && !partialDSBlit &&
(!(depthBlit || stencilBlit) || wholeBufferCopy))
{
@@ -3276,6 +3469,11 @@ gl::Error Renderer11::blitRenderbufferRect(const gl::Rectangle &readRect, const
return result;
}
+bool Renderer11::isES3Capable() const
+{
+ return (d3d11_gl::GetMaximumClientVersion(mFeatureLevel) > 2);
+};
+
ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource)
{
D3D11_TEXTURE2D_DESC textureDesc;
@@ -3314,50 +3512,6 @@ ID3D11Texture2D *Renderer11::resolveMultisampledTexture(ID3D11Texture2D *source,
}
}
-void Renderer11::invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel)
-{
- ASSERT(attachment->isTexture());
- gl::Texture *texture = attachment->getTexture();
-
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- TextureStorage *texStorage = textureD3D->getNativeTexture();
- if (texStorage)
- {
- TextureStorage11 *texStorage11 = TextureStorage11::makeTextureStorage11(texStorage);
- if (!texStorage11)
- {
- ERR("texture storage pointer unexpectedly null.");
- return;
- }
-
- texStorage11->invalidateSwizzleCacheLevel(mipLevel);
- }
-}
-
-void Renderer11::invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer)
-{
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(colorAttachment);
- if (attachment && attachment->isTexture())
- {
- invalidateFBOAttachmentSwizzles(attachment, attachment->mipLevel());
- }
- }
-
- gl::FramebufferAttachment *depthAttachment = framebuffer->getDepthbuffer();
- if (depthAttachment && depthAttachment->isTexture())
- {
- invalidateFBOAttachmentSwizzles(depthAttachment, depthAttachment->mipLevel());
- }
-
- gl::FramebufferAttachment *stencilAttachment = framebuffer->getStencilbuffer();
- if (stencilAttachment && stencilAttachment->isTexture())
- {
- invalidateFBOAttachmentSwizzles(stencilAttachment, stencilAttachment->mipLevel());
- }
-}
-
bool Renderer11::getLUID(LUID *adapterLuid) const
{
adapterLuid->HighPart = 0;
@@ -3380,31 +3534,32 @@ bool Renderer11::getLUID(LUID *adapterLuid) const
VertexConversionType Renderer11::getVertexConversionType(const gl::VertexFormat &vertexFormat) const
{
- return d3d11::GetVertexFormatInfo(vertexFormat).conversionType;
+ return d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).conversionType;
}
GLenum Renderer11::getVertexComponentType(const gl::VertexFormat &vertexFormat) const
{
- return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat).nativeFormat).componentType;
+ return d3d11::GetDXGIFormatInfo(d3d11::GetVertexFormatInfo(vertexFormat, mFeatureLevel).nativeFormat).componentType;
}
void Renderer11::generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const
{
- d3d11_gl::GenerateCaps(mDevice, outCaps, outTextureCaps, outExtensions);
+ d3d11_gl::GenerateCaps(mDevice, mDeviceContext, outCaps, outTextureCaps, outExtensions);
}
Workarounds Renderer11::generateWorkarounds() const
{
- return d3d11::GenerateWorkarounds();
+ return d3d11::GenerateWorkarounds(mFeatureLevel);
}
void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
{
- std::vector<ID3D11ShaderResourceView *> &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
+ auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
+ auto &record = currentSRVs[resourceSlot];
- if (currentSRVs[resourceSlot] != srv)
+ if (record.srv != reinterpret_cast<uintptr_t>(srv))
{
if (shaderType == gl::SAMPLER_VERTEX)
{
@@ -3415,8 +3570,16 @@ void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot
mDeviceContext->PSSetShaderResources(resourceSlot, 1, &srv);
}
- currentSRVs[resourceSlot] = srv;
+ record.srv = reinterpret_cast<uintptr_t>(srv);
+ if (srv)
+ {
+ record.resource = reinterpret_cast<uintptr_t>(GetViewResource(srv));
+ srv->GetDesc(&record.desc);
+ }
+ else
+ {
+ record.resource = 0;
+ }
}
}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
index d44bd2fd30..cc7d6c237b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
@@ -6,24 +6,26 @@
// Renderer11.h: Defines a back-end specific class for the D3D11 renderer.
-#ifndef LIBGLESV2_RENDERER_RENDERER11_H_
-#define LIBGLESV2_RENDERER_RENDERER11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
#include "common/mathutil.h"
+#include "libANGLE/AttributeMap.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h"
+#include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderStateCache.h"
-#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h"
-#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-
-#include "libEGL/AttributeMap.h"
+struct ID3D11DeviceContext1;
namespace gl
{
class FramebufferAttachment;
+struct ImageIndex;
}
namespace rx
@@ -36,6 +38,7 @@ class Blit11;
class Clear11;
class PixelTransfer11;
class RenderTarget11;
+class Trim11;
struct PackPixelsParams;
enum
@@ -44,29 +47,51 @@ enum
MAX_FRAGMENT_UNIFORM_VECTORS_D3D11 = 1024
};
+// Possible reasons RendererD3D initialize can fail
+enum D3D11InitError
+{
+ // The renderer loaded successfully
+ D3D11_INIT_SUCCESS = 0,
+ // Failed to load the ANGLE & D3D compiler libraries
+ D3D11_INIT_COMPILER_ERROR,
+ // Failed to load a necessary DLL (non-compiler)
+ D3D11_INIT_MISSING_DEP,
+ // CreateDevice returned E_INVALIDARG
+ D3D11_INIT_CREATEDEVICE_INVALIDARG,
+ // CreateDevice failed with an error other than invalid arg
+ D3D11_INIT_CREATEDEVICE_ERROR,
+ // DXGI 1.2 required but not found
+ D3D11_INIT_INCOMPATIBLE_DXGI,
+ // Other initialization error
+ D3D11_INIT_OTHER_ERROR,
+ NUM_D3D11_INIT_ERRORS
+};
+
class Renderer11 : public RendererD3D
{
public:
- Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes);
+ explicit Renderer11(egl::Display *display);
virtual ~Renderer11();
static Renderer11 *makeRenderer11(Renderer *renderer);
- virtual EGLint initialize();
+ egl::Error initialize() override;
virtual bool resetDevice();
- virtual int generateConfigs(ConfigDesc **configDescList);
- virtual void deleteConfigs(ConfigDesc *configDescList);
+ egl::ConfigSet generateConfigs() const override;
- virtual gl::Error sync(bool block);
+ gl::Error flush() override;
+ gl::Error finish() override;
- virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
virtual gl::Error generateSwizzle(gl::Texture *texture);
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
- virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
+ gl::Error setUniformBuffers(const gl::Data &data,
+ const GLint vertexUniformBuffers[],
+ const GLint fragmentUniformBuffers[]) override;
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
@@ -78,31 +103,27 @@ class Renderer11 : public RendererD3D
virtual void setViewport(const gl::Rectangle &viewport, float zNear, float zFar, GLenum drawMode, GLenum frontFace,
bool ignoreViewport);
- virtual bool applyPrimitiveType(GLenum mode, GLsizei count);
+ virtual bool applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize);
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
- virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive);
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
- virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
+ virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
- virtual void applyTransformFeedbackBuffers(const gl::State &state);
+ void applyTransformFeedbackBuffers(const gl::State &state) override;
- virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
+ gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
- gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override;
-
virtual void markAllStateDirty();
// lost device
- void notifyDeviceLost() override;
- bool isDeviceLost() override;
- bool testDeviceLost(bool notify) override;
+ bool testDeviceLost() override;
bool testDeviceResettable() override;
- DWORD getAdapterVendor() const override;
+ VendorID getVendorId() const override;
std::string getRendererDescription() const override;
GUID getAdapterIdentifier() const override;
@@ -114,50 +135,47 @@ class Renderer11 : public RendererD3D
virtual bool getPostSubBufferSupport() const;
virtual int getMajorShaderModel() const;
- virtual int getMinSwapInterval() const;
- virtual int getMaxSwapInterval() const;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
// Pixel operations
- virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
- virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
-
- gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect, const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- const gl::Rectangle *scissor, bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter) override;
-
- virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+ virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
+ virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
// RenderTarget creation
- virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
- virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
+ virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT);
+
+ // Framebuffer creation
+ FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override;
+ FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override;
// Shader creation
- virtual ShaderImpl *createShader(const gl::Data &data, GLenum type);
+ virtual CompilerImpl *createCompiler(const gl::Data &data);
+ virtual ShaderImpl *createShader(GLenum type);
virtual ProgramImpl *createProgram();
// Shader operations
- void releaseShaderCompiler() override;
virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutable **outExecutable);
+ bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, D3DWorkaroundType workaround,
- ShaderExecutable **outExectuable);
- virtual UniformStorage *createUniformStorage(size_t storageSize);
+ bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable);
+ virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
// Image operations
- virtual Image *createImage();
- gl::Error generateMipmap(Image *dest, Image *source) override;
- virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
- virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
- virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
+ virtual ImageD3D *createImage();
+ gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+ virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
@@ -166,7 +184,6 @@ class Renderer11 : public RendererD3D
// Renderbuffer creation
virtual RenderbufferImpl *createRenderbuffer();
- virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth);
// Buffer creation
virtual BufferImpl *createBuffer();
@@ -187,23 +204,22 @@ class Renderer11 : public RendererD3D
// D3D11-renderer specific methods
ID3D11Device *getDevice() { return mDevice; }
ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
+ ID3D11DeviceContext1 *getDeviceContext1IfSupported() { return mDeviceContext1; };
DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
- bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; }
Blit11 *getBlitter() { return mBlit; }
+ Clear11 *getClearer() { return mClear; }
// Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
- gl::Error getRenderTargetResource(gl::FramebufferAttachment *colorbuffer, unsigned int *subresourceIndexOut, ID3D11Texture2D **texture2DOut);
-
void unapplyRenderTargets();
void setOneTimeRenderTarget(ID3D11RenderTargetView *renderTargetView);
gl::Error packPixels(ID3D11Texture2D *readTexture, const PackPixelsParams &params, uint8_t *pixelsOut);
- virtual bool getLUID(LUID *adapterLuid) const;
+ bool getLUID(LUID *adapterLuid) const override;
virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
@@ -212,48 +228,51 @@ class Renderer11 : public RendererD3D
void setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv);
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderer11);
+ gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTargetD3D *readRenderTarget,
+ RenderTargetD3D *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
+ bool colorBlit, bool depthBlit, bool stencilBlit);
+ bool isES3Capable() const;
+ D3D_FEATURE_LEVEL getFeatureLevel() const { return mFeatureLevel; };
+
+ RendererClass getRendererClass() const override { return RENDERER_D3D11; }
+
+ private:
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override;
Workarounds generateWorkarounds() const override;
gl::Error drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer);
gl::Error drawTriangleFan(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer, int instances);
- gl::Error blitRenderbufferRect(const gl::Rectangle &readRect, const gl::Rectangle &drawRect, RenderTarget *readRenderTarget,
- RenderTarget *drawRenderTarget, GLenum filter, const gl::Rectangle *scissor,
- bool colorBlit, bool depthBlit, bool stencilBlit);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
- void unsetSRVsWithResource(gl::SamplerType shaderType, const ID3D11Resource *resource);
-
- static void invalidateFBOAttachmentSwizzles(gl::FramebufferAttachment *attachment, int mipLevel);
- static void invalidateFramebufferSwizzles(const gl::Framebuffer *framebuffer);
+ void unsetConflictingSRVs(gl::SamplerType shaderType, uintptr_t resource, const gl::ImageIndex *index);
HMODULE mD3d11Module;
HMODULE mDxgiModule;
- EGLNativeDisplayType mDc;
std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
D3D_DRIVER_TYPE mDriverType;
HLSLCompiler mCompiler;
- bool mDeviceLost;
-
void initializeDevice();
void releaseDeviceResources();
- int getMinorShaderModel() const;
void release();
RenderStateCache mStateCache;
// current render target states
- unsigned int mAppliedRenderTargetSerials[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
- unsigned int mAppliedDepthbufferSerial;
- unsigned int mAppliedStencilbufferSerial;
+ uintptr_t mAppliedRTVs[gl::IMPLEMENTATION_MAX_DRAW_BUFFERS];
+ uintptr_t mAppliedDSV;
bool mDepthStencilInitialized;
bool mRenderTargetDescInitialized;
- RenderTarget::Desc mRenderTargetDesc;
+
+ struct RenderTargetDesc
+ {
+ size_t width;
+ size_t height;
+ DXGI_FORMAT format;
+ };
+ RenderTargetDesc mRenderTargetDesc;
// Currently applied sampler states
std::vector<bool> mForceSetVertexSamplerStates;
@@ -263,8 +282,14 @@ class Renderer11 : public RendererD3D
std::vector<gl::SamplerState> mCurPixelSamplerStates;
// Currently applied textures
- std::vector<ID3D11ShaderResourceView*> mCurVertexSRVs;
- std::vector<ID3D11ShaderResourceView*> mCurPixelSRVs;
+ struct SRVRecord
+ {
+ uintptr_t srv;
+ uintptr_t resource;
+ D3D11_SHADER_RESOURCE_VIEW_DESC desc;
+ };
+ std::vector<SRVRecord> mCurVertexSRVs;
+ std::vector<SRVRecord> mCurPixelSRVs;
// Currently applied blend state
bool mForceSetBlendState;
@@ -302,6 +327,7 @@ class Renderer11 : public RendererD3D
unsigned int mAppliedIBOffset;
// Currently applied transform feedback buffers
+ size_t mAppliedNumXFBBindings;
ID3D11Buffer *mAppliedTFBuffers[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current D3D buffers
// in use for streamout
GLintptr mAppliedTFOffsets[gl::IMPLEMENTATION_MAX_TRANSFORM_FEEDBACK_BUFFERS]; // Tracks the current GL-specified
@@ -312,22 +338,25 @@ class Renderer11 : public RendererD3D
// to different append behavior
// Currently applied shaders
- ID3D11VertexShader *mAppliedVertexShader;
- ID3D11GeometryShader *mAppliedGeometryShader;
- ID3D11GeometryShader *mCurPointGeometryShader;
- ID3D11PixelShader *mAppliedPixelShader;
+ uintptr_t mAppliedVertexShader;
+ uintptr_t mAppliedGeometryShader;
+ uintptr_t mAppliedPixelShader;
dx_VertexConstants mVertexConstants;
dx_VertexConstants mAppliedVertexConstants;
ID3D11Buffer *mDriverConstantBufferVS;
ID3D11Buffer *mCurrentVertexConstantBuffer;
unsigned int mCurrentConstantBufferVS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ GLintptr mCurrentConstantBufferVSOffset[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ GLsizeiptr mCurrentConstantBufferVSSize[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
dx_PixelConstants mPixelConstants;
dx_PixelConstants mAppliedPixelConstants;
ID3D11Buffer *mDriverConstantBufferPS;
ID3D11Buffer *mCurrentPixelConstantBuffer;
- unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_VERTEX_SHADER_UNIFORM_BUFFERS];
+ unsigned int mCurrentConstantBufferPS[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+ GLintptr mCurrentConstantBufferPSOffset[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
+ GLsizeiptr mCurrentConstantBufferPSSize[gl::IMPLEMENTATION_MAX_FRAGMENT_SHADER_UNIFORM_BUFFERS];
ID3D11Buffer *mCurrentGeometryConstantBuffer;
@@ -346,17 +375,26 @@ class Renderer11 : public RendererD3D
// Masked clear resources
Clear11 *mClear;
+ // Perform trim for D3D resources
+ Trim11 *mTrim;
+
// Sync query
ID3D11Query *mSyncQuery;
+ // Constant buffer offset support
+ bool mSupportsConstantBufferOffsets;
+
ID3D11Device *mDevice;
D3D_FEATURE_LEVEL mFeatureLevel;
ID3D11DeviceContext *mDeviceContext;
+ ID3D11DeviceContext1 *mDeviceContext1;
IDXGIAdapter *mDxgiAdapter;
DXGI_ADAPTER_DESC mAdapterDescription;
char mDescription[128];
DXGIFactory *mDxgiFactory;
+
+ DebugAnnotator11 mAnnotator;
};
}
-#endif // LIBGLESV2_RENDERER_RENDERER11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
index 52f34887fb..7e64c3183d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp
@@ -7,14 +7,14 @@
// 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"
+#include "libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
namespace rx
{
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable)
- : ShaderExecutable(function, length)
+ : ShaderExecutableD3D(function, length)
{
mPixelExecutable = executable;
mVertexExecutable = NULL;
@@ -23,7 +23,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
}
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11VertexShader *executable, ID3D11GeometryShader *streamOut)
- : ShaderExecutable(function, length)
+ : ShaderExecutableD3D(function, length)
{
mVertexExecutable = executable;
mPixelExecutable = NULL;
@@ -32,7 +32,7 @@ ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D
}
ShaderExecutable11::ShaderExecutable11(const void *function, size_t length, ID3D11GeometryShader *executable)
- : ShaderExecutable(function, length)
+ : ShaderExecutableD3D(function, length)
{
mGeometryExecutable = executable;
mVertexExecutable = NULL;
@@ -48,7 +48,7 @@ ShaderExecutable11::~ShaderExecutable11()
SafeRelease(mStreamOutExecutable);
}
-ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutable *executable)
+ShaderExecutable11 *ShaderExecutable11::makeShaderExecutable11(ShaderExecutableD3D *executable)
{
ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable11*, executable));
return static_cast<ShaderExecutable11*>(executable);
@@ -75,7 +75,7 @@ ID3D11GeometryShader *ShaderExecutable11::getStreamOutShader() const
}
UniformStorage11::UniformStorage11(Renderer11 *renderer, size_t initialSize)
- : UniformStorage(initialSize),
+ : UniformStorageD3D(initialSize),
mConstantBuffer(NULL)
{
ID3D11Device *d3d11Device = renderer->getDevice();
@@ -101,7 +101,7 @@ UniformStorage11::~UniformStorage11()
SafeRelease(mConstantBuffer);
}
-const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorage *uniformStorage)
+const UniformStorage11 *UniformStorage11::makeUniformStorage11(const UniformStorageD3D *uniformStorage)
{
ASSERT(HAS_DYNAMIC_TYPE(const UniformStorage11*, uniformStorage));
return static_cast<const UniformStorage11*>(uniformStorage);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
index 74a1e03915..02558ee4dc 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h
@@ -7,17 +7,17 @@
// ShaderExecutable11.h: Defines a D3D11-specific class to contain shader
// executable implementation details.
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
-#include "libGLESv2/renderer/ShaderExecutable.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
namespace rx
{
class Renderer11;
class UniformStorage11;
-class ShaderExecutable11 : public ShaderExecutable
+class ShaderExecutable11 : public ShaderExecutableD3D
{
public:
ShaderExecutable11(const void *function, size_t length, ID3D11PixelShader *executable);
@@ -26,7 +26,7 @@ class ShaderExecutable11 : public ShaderExecutable
virtual ~ShaderExecutable11();
- static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutable *executable);
+ static ShaderExecutable11 *makeShaderExecutable11(ShaderExecutableD3D *executable);
ID3D11PixelShader *getPixelShader() const;
ID3D11VertexShader *getVertexShader() const;
@@ -34,21 +34,19 @@ class ShaderExecutable11 : public ShaderExecutable
ID3D11GeometryShader *getStreamOutShader() const;
private:
- DISALLOW_COPY_AND_ASSIGN(ShaderExecutable11);
-
ID3D11PixelShader *mPixelExecutable;
ID3D11VertexShader *mVertexExecutable;
ID3D11GeometryShader *mGeometryExecutable;
ID3D11GeometryShader *mStreamOutExecutable;
};
-class UniformStorage11 : public UniformStorage
+class UniformStorage11 : public UniformStorageD3D
{
public:
UniformStorage11(Renderer11 *renderer, size_t initialSize);
virtual ~UniformStorage11();
- static const UniformStorage11 *makeUniformStorage11(const UniformStorage *uniformStorage);
+ static const UniformStorage11 *makeUniformStorage11(const UniformStorageD3D *uniformStorage);
ID3D11Buffer *getConstantBuffer() const { return mConstantBuffer; }
@@ -58,4 +56,4 @@ class UniformStorage11 : public UniformStorage
}
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SHADEREXECUTABLE11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
index 52c8a81633..298f3ccbd2 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
@@ -6,17 +6,17 @@
// SwapChain11.cpp: Implements a back-end specific class for the D3D11 swap chain.
-#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+#include "libANGLE/features.h"
// Precompiled shaders
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
-#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
+#include "libANGLE/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
-#include "common/features.h"
-#include "common/NativeWindow.h"
namespace rx
{
@@ -24,7 +24,9 @@ namespace rx
SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat)
: mRenderer(renderer),
- SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat)
+ SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
+ mColorRenderTarget(this, renderer, false),
+ mDepthStencilRenderTarget(this, renderer, true)
{
mSwapChain = NULL;
mBackBufferTexture = NULL;
@@ -42,8 +44,6 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE
mPassThroughPS = NULL;
mWidth = -1;
mHeight = -1;
- mRotateL = false;
- mRotateR = false;
mSwapInterval = 0;
mAppCreatedShareHandle = mShareHandle != NULL;
mPassThroughResourcesInit = false;
@@ -94,11 +94,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
ASSERT(device != NULL);
// D3D11 does not allow zero size textures
- ASSERT(backbufferWidth != 0);
- ASSERT(backbufferHeight != 0);
+ ASSERT(backbufferWidth >= 1);
+ ASSERT(backbufferHeight >= 1);
// Preserve the render target content
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
if (previousOffscreenTexture)
{
@@ -106,11 +105,10 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
}
const int previousWidth = mWidth;
const int previousHeight = mHeight;
-#endif
releaseOffscreenTexture();
- const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel());
// If the app passed in a share handle, open the resource
// See EGL_ANGLE_d3d_share_handle_client_buffer
@@ -140,8 +138,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
mOffscreenTexture->GetDesc(&offscreenTextureDesc);
- if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) ||
- offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) ||
+ if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
+ offscreenTextureDesc.Height != (UINT)backbufferHeight ||
offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
offscreenTextureDesc.MipLevels != 1 ||
offscreenTextureDesc.ArraySize != 1)
@@ -156,8 +154,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
- offscreenTextureDesc.Width = abs(backbufferWidth);
- offscreenTextureDesc.Height = abs(backbufferHeight);
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ const int textureLength = std::max(backbufferWidth, backbufferHeight);
+ offscreenTextureDesc.Width = textureLength;
+ offscreenTextureDesc.Height = textureLength;
+#else
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
+#endif
offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
offscreenTextureDesc.MipLevels = 1;
offscreenTextureDesc.ArraySize = 1;
@@ -226,26 +230,38 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
offscreenSRVDesc.Format = backbufferFormatInfo.srvFormat;
offscreenSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
offscreenSRVDesc.Texture2D.MostDetailedMip = 0;
- offscreenSRVDesc.Texture2D.MipLevels = -1;
+ offscreenSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
result = device->CreateShaderResourceView(mOffscreenTexture, &offscreenSRVDesc, &mOffscreenSRView);
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mOffscreenSRView, "Offscreen back buffer shader resource");
- const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat);
+ const d3d11::TextureFormat &depthBufferFormatInfo = d3d11::GetTextureFormatInfo(mDepthBufferFormat, mRenderer->getFeatureLevel());
if (mDepthBufferFormat != GL_NONE)
{
D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
- depthStencilTextureDesc.Width = abs(backbufferWidth);
- depthStencilTextureDesc.Height = abs(backbufferHeight);
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ const int textureLength = std::max(backbufferWidth, backbufferHeight);
+ depthStencilTextureDesc.Width = textureLength;
+ depthStencilTextureDesc.Height = textureLength;
+#else
+ depthStencilTextureDesc.Width = backbufferWidth;
+ depthStencilTextureDesc.Height = backbufferHeight;
+#endif
depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
depthStencilTextureDesc.MipLevels = 1;
depthStencilTextureDesc.ArraySize = 1;
depthStencilTextureDesc.SampleDesc.Count = 1;
depthStencilTextureDesc.SampleDesc.Quality = 0;
depthStencilTextureDesc.Usage = D3D11_USAGE_DEFAULT;
- depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE;
+ depthStencilTextureDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL;
+
+ if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ depthStencilTextureDesc.BindFlags |= D3D11_BIND_SHADER_RESOURCE;
+ }
+
depthStencilTextureDesc.CPUAccessFlags = 0;
depthStencilTextureDesc.MiscFlags = 0;
@@ -276,21 +292,23 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
ASSERT(SUCCEEDED(result));
d3d11::SetDebugName(mDepthStencilDSView, "Offscreen depth stencil view");
- D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
- depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
- depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
- depthStencilSRVDesc.Texture2D.MipLevels = -1;
-
- result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
+ if (depthBufferFormatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
+ {
+ D3D11_SHADER_RESOURCE_VIEW_DESC depthStencilSRVDesc;
+ depthStencilSRVDesc.Format = depthBufferFormatInfo.srvFormat;
+ depthStencilSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
+ depthStencilSRVDesc.Texture2D.MostDetailedMip = 0;
+ depthStencilSRVDesc.Texture2D.MipLevels = static_cast<UINT>(-1);
+
+ result = device->CreateShaderResourceView(mDepthStencilTexture, &depthStencilSRVDesc, &mDepthStencilSRView);
+ ASSERT(SUCCEEDED(result));
+ d3d11::SetDebugName(mDepthStencilSRView, "Offscreen depth stencil shader resource");
+ }
}
mWidth = backbufferWidth;
mHeight = backbufferHeight;
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
if (previousOffscreenTexture != NULL)
{
D3D11_BOX sourceBox = {0};
@@ -312,7 +330,6 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
swapRect(0, 0, mWidth, mHeight);
}
}
-#endif
return EGL_SUCCESS;
}
@@ -326,31 +343,23 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
return EGL_BAD_ACCESS;
}
- // Windows Phone works around the rotation limitation by using negative values for the swap chain size
-#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape
- mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape
- backbufferWidth = abs(backbufferWidth);
- backbufferHeight = abs(backbufferHeight);
-#endif
-
// EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
- if (backbufferWidth == 0 || backbufferHeight == 0)
+ if (backbufferWidth < 1 || backbufferHeight < 1)
{
return EGL_SUCCESS;
}
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
// Can only call resize if we have already created our swap buffer and resources
ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone
SafeRelease(mBackBufferTexture);
SafeRelease(mBackBufferRTView);
// Resize swap chain
DXGI_SWAP_CHAIN_DESC desc;
mSwapChain->GetDesc(&desc);
- const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel());
HRESULT result = mSwapChain->ResizeBuffers(desc.BufferCount, backbufferWidth, backbufferHeight, backbufferFormatInfo.texFormat, 0);
if (FAILED(result))
@@ -381,9 +390,14 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
{
d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
}
-#endif
return resetOffscreenTexture(backbufferWidth, backbufferHeight);
+#else
+ // Do nothing on Windows Phone apart from updating the internal buffer/width height
+ mWidth = backbufferWidth;
+ mHeight = backbufferHeight;
+ return EGL_SUCCESS;
+#endif
}
EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
@@ -417,7 +431,7 @@ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swap
if (mNativeWindow.getNativeWindow())
{
- const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat);
+ const d3d11::TextureFormat &backbufferFormatInfo = d3d11::GetTextureFormatInfo(mBackBufferFormat, mRenderer->getFeatureLevel());
HRESULT result = mNativeWindow.createSwapChain(device, mRenderer->getDxgiFactory(),
backbufferFormatInfo.texFormat,
@@ -528,20 +542,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
- // Create a quad in homogeneous coordinates
- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
- float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
- float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
-
- float u1 = x / float(mWidth);
- float v1 = y / float(mHeight);
- float u2 = (x + width) / float(mWidth);
- float v2 = (y + height) / float(mHeight);
-
- const bool rotateL = mRotateL;
- const bool rotateR = mRotateR;
-
// Set vertices
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
@@ -552,10 +552,37 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
+ // Create a quad in homogeneous coordinates
+ float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
+ float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
+ float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+ float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ const float dim = std::max(mWidth, mHeight);
+ float u1 = x / dim;
+ float v1 = y / dim;
+ float u2 = (x + width) / dim;
+ float v2 = (y + height) / dim;
+
+ const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
+ const bool rotateL = flags == NativeWindow::RotateLeft;
+ const bool rotateR = flags == NativeWindow::RotateRight;
d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
+#else
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+ float v2 = (y + height) / float(mHeight);
+
+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
+#endif
deviceContext->Unmap(mQuadVB, 0);
@@ -583,11 +610,15 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
// Set the viewport
D3D11_VIEWPORT viewport;
- viewport.TopLeftX = 0.0f;
- viewport.TopLeftY = 0.0f;
- const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR);
- viewport.Width = FLOAT(invertViewport ? mHeight : mWidth);
- viewport.Height = FLOAT(invertViewport ? mWidth : mHeight);
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
+ viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
+#else
+ viewport.Width = mWidth;
+ viewport.Height = mHeight;
+#endif
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
deviceContext->RSSetViewports(1, &viewport);
@@ -661,7 +692,7 @@ ID3D11Texture2D *SwapChain11::getDepthStencilTexture()
return mDepthStencilTexture;
}
-SwapChain11 *SwapChain11::makeSwapChain11(SwapChain *swapChain)
+SwapChain11 *SwapChain11::makeSwapChain11(SwapChainD3D *swapChain)
{
ASSERT(HAS_DYNAMIC_TYPE(SwapChain11*, swapChain));
return static_cast<SwapChain11*>(swapChain);
@@ -672,4 +703,9 @@ void SwapChain11::recreate()
// possibly should use this method instead of reset
}
+void *rx::SwapChain11::getDevice()
+{
+ return mRenderer->getDevice();
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
index 77509edcd3..48c808a261 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
@@ -6,17 +6,18 @@
// SwapChain11.h: Defines a back-end specific class for the D3D11 swap chain.
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN11_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
#include "common/angleutils.h"
-#include "libGLESv2/renderer/SwapChain.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
namespace rx
{
class Renderer11;
-class SwapChain11 : public SwapChain
+class SwapChain11 : public SwapChainD3D
{
public:
SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
@@ -28,6 +29,9 @@ class SwapChain11 : public SwapChain
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
virtual void recreate();
+ RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+ RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
virtual ID3D11Texture2D *getOffscreenTexture();
virtual ID3D11RenderTargetView *getRenderTarget();
virtual ID3D11ShaderResourceView *getRenderTargetShaderResource();
@@ -39,11 +43,11 @@ class SwapChain11 : public SwapChain
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
- static SwapChain11 *makeSwapChain11(SwapChain *swapChain);
+ virtual void *getDevice();
- private:
- DISALLOW_COPY_AND_ASSIGN(SwapChain11);
+ static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain);
+ private:
void release();
void initPassThroughResources();
void releaseOffscreenTexture();
@@ -52,8 +56,6 @@ class SwapChain11 : public SwapChain
Renderer11 *mRenderer;
EGLint mHeight;
EGLint mWidth;
- bool mRotateL;
- bool mRotateR;
bool mAppCreatedShareHandle;
unsigned int mSwapInterval;
bool mPassThroughResourcesInit;
@@ -76,7 +78,10 @@ class SwapChain11 : public SwapChain
ID3D11InputLayout *mPassThroughIL;
ID3D11VertexShader *mPassThroughVS;
ID3D11PixelShader *mPassThroughPS;
+
+ SurfaceRenderTarget11 mColorRenderTarget;
+ SurfaceRenderTarget11 mDepthStencilRenderTarget;
};
}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_SWAPCHAIN11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
index 74af27e8b3..103e90fed3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
@@ -7,23 +7,22 @@
// 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 "libANGLE/renderer/d3d/d3d11/TextureStorage11.h"
#include <tuple>
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/d3d/d3d11/SwapChain11.h"
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/Blit11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Image11.h"
-#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/ImageIndex.h"
-
+#include "common/MemoryBuffer.h"
#include "common/utilities.h"
+#include "libANGLE/ImageIndex.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/d3d11/Blit11.h"
+#include "libANGLE/renderer/d3d/d3d11/Image11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/SwapChain11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
namespace rx
{
@@ -102,11 +101,11 @@ TextureStorage11 *TextureStorage11::makeTextureStorage11(TextureStorage *storage
return static_cast<TextureStorage11*>(storage);
}
-DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, bool renderTarget)
+DWORD TextureStorage11::GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget)
{
UINT bindFlags = 0;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel);
if (formatInfo.srvFormat != DXGI_FORMAT_UNKNOWN)
{
bindFlags |= D3D11_BIND_SHADER_RESOURCE;
@@ -176,11 +175,27 @@ gl::Error TextureStorage11::getSRV(const gl::SamplerState &samplerState, ID3D11S
{
bool swizzleRequired = samplerState.swizzleRequired();
bool mipmapping = gl::IsMipmapFiltered(samplerState);
- unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel) : 1;
+ unsigned int mipLevels = mipmapping ? (samplerState.maxLevel - samplerState.baseLevel + 1) : 1;
// Make sure there's 'mipLevels' mipmap levels below the base level (offset by the top level, which corresponds to GL level 0)
mipLevels = std::min(mipLevels, mMipLevels - mTopLevel - samplerState.baseLevel);
+ if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
+ {
+ ASSERT(!swizzleRequired);
+ ASSERT(mipLevels == 1 || mipLevels == mMipLevels);
+ }
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ // We must ensure that the level zero texture is in sync with mipped texture.
+ gl::Error error = useLevelZeroWorkaroundTexture(mipLevels == 1);
+ if (error.isError())
+ {
+ return error;
+ }
+ }
+
if (swizzleRequired)
{
verifySwizzleExists(samplerState.swizzleRed, samplerState.swizzleGreen, samplerState.swizzleBlue, samplerState.swizzleAlpha);
@@ -329,7 +344,19 @@ gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, u
copyArea.depth == texSize.depth;
ID3D11Resource *dstTexture = NULL;
- gl::Error error = getResource(&dstTexture);
+ gl::Error error(GL_NO_ERROR);
+
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should
+ // update the mipmapped texture, even if mapmaps are currently disabled.
+ if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ error = getMippedResource(&dstTexture);
+ }
+ else
+ {
+ error = getResource(&dstTexture);
+ }
+
if (error.isError())
{
return error;
@@ -351,8 +378,6 @@ gl::Error TextureStorage11::updateSubresourceLevel(ID3D11Resource *srcTexture, u
}
else
{
- const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
-
D3D11_BOX srcBox;
srcBox.left = copyArea.x;
srcBox.top = copyArea.y;
@@ -375,7 +400,19 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, uns
ASSERT(dstTexture);
ID3D11Resource *srcTexture = NULL;
- gl::Error error = getResource(&srcTexture);
+ gl::Error error(GL_NO_ERROR);
+
+ // If the zero-LOD workaround is active and we want to update a level greater than zero, then we should
+ // update the mipmapped texture, even if mapmaps are currently disabled.
+ if (index.mipIndex > 0 && mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ error = getMippedResource(&srcTexture);
+ }
+ else
+ {
+ error = getResource(&srcTexture);
+ }
+
if (error.isError())
{
return error;
@@ -386,8 +423,28 @@ gl::Error TextureStorage11::copySubresourceLevel(ID3D11Resource* dstTexture, uns
unsigned int srcSubresource = getSubresourceIndex(index);
ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ // D3D11 can't perform partial CopySubresourceRegion on depth/stencil textures, so pSrcBox should be NULL.
+ D3D11_BOX srcBox;
+ D3D11_BOX *pSrcBox = NULL;
+ if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
+ {
+ // However, D3D10Level9 doesn't always perform CopySubresourceRegion correctly unless the source box
+ // is specified. This is okay, since we don't perform CopySubresourceRegion on depth/stencil
+ // textures on 9_3.
+ ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).depthBits == 0);
+ ASSERT(d3d11::GetDXGIFormatInfo(mTextureFormat).stencilBits == 0);
+ srcBox.left = region.x;
+ srcBox.right = region.x + region.width;
+ srcBox.top = region.y;
+ srcBox.bottom = region.y + region.height;
+ srcBox.front = region.z;
+ srcBox.back = region.z + region.depth;
+ pSrcBox = &srcBox;
+ }
+
context->CopySubresourceRegion(dstTexture, dstSubresource, region.x, region.y, region.z,
- srcTexture, srcSubresource, NULL);
+ srcTexture, srcSubresource, pSrcBox);
return gl::Error(GL_NO_ERROR);
}
@@ -398,14 +455,14 @@ gl::Error TextureStorage11::generateMipmap(const gl::ImageIndex &sourceIndex, co
invalidateSwizzleCacheLevel(destIndex.mipIndex);
- RenderTarget *source = NULL;
+ RenderTargetD3D *source = NULL;
gl::Error error = getRenderTarget(sourceIndex, &source);
if (error.isError())
{
return error;
}
- RenderTarget *dest = NULL;
+ RenderTargetD3D *dest = NULL;
error = getRenderTarget(destIndex, &dest);
if (error.isError())
{
@@ -462,9 +519,11 @@ gl::Error TextureStorage11::copyToStorage(TextureStorage *destStorage)
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+gl::Error TextureStorage11::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
{
+ ASSERT(!image->isDirty());
+
ID3D11Resource *resource = NULL;
gl::Error error = getResource(&resource);
if (error.isError())
@@ -477,7 +536,8 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(image->getInternalFormat());
- bool fullUpdate = (destBox == NULL || *destBox == gl::Box(0, 0, 0, mTextureWidth, mTextureHeight, mTextureDepth));
+ gl::Box levelBox(0, 0, 0, getLevelWidth(index.mipIndex), getLevelHeight(index.mipIndex), getLevelDepth(index.mipIndex));
+ bool fullUpdate = (destBox == NULL || *destBox == levelBox);
ASSERT(internalFormatInfo.depthBits == 0 || fullUpdate);
// TODO(jmadill): Handle compressed formats
@@ -489,10 +549,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
int width = destBox ? destBox->width : static_cast<int>(image->getWidth());
int height = destBox ? destBox->height : static_cast<int>(image->getHeight());
int depth = destBox ? destBox->depth : static_cast<int>(image->getDepth());
- UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment);
- UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment);
+ UINT srcRowPitch = internalFormatInfo.computeRowPitch(type, width, unpack.alignment, unpack.rowLength);
+ UINT srcDepthPitch = internalFormatInfo.computeDepthPitch(type, width, height, unpack.alignment, unpack.rowLength);
- const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat());
+ const d3d11::TextureFormat &d3d11Format = d3d11::GetTextureFormatInfo(image->getInternalFormat(), mRenderer->getFeatureLevel());
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3d11Format.texFormat);
size_t outputPixelSize = dxgiFormatInfo.pixelBytes;
@@ -500,17 +560,19 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
UINT bufferRowPitch = outputPixelSize * width;
UINT bufferDepthPitch = bufferRowPitch * height;
- MemoryBuffer conversionBuffer;
- if (!conversionBuffer.resize(bufferDepthPitch * depth))
+ size_t neededSize = bufferDepthPitch * depth;
+ MemoryBuffer *conversionBuffer = NULL;
+ error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer);
+ if (error.isError())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
+ return error;
}
// TODO: fast path
LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type);
loadFunction(width, height, depth,
pixelData, srcRowPitch, srcDepthPitch,
- conversionBuffer.data(), bufferRowPitch, bufferDepthPitch);
+ conversionBuffer->data(), bufferRowPitch, bufferDepthPitch);
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
@@ -523,17 +585,17 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
destD3DBox.right = destBox->x + destBox->width;
destD3DBox.top = destBox->y;
destD3DBox.bottom = destBox->y + destBox->height;
- destD3DBox.front = 0;
- destD3DBox.back = 1;
+ destD3DBox.front = destBox->z;
+ destD3DBox.back = destBox->z + destBox->depth;
immediateContext->UpdateSubresource(resource, destSubresource,
- &destD3DBox, conversionBuffer.data(),
+ &destD3DBox, conversionBuffer->data(),
bufferRowPitch, bufferDepthPitch);
}
else
{
immediateContext->UpdateSubresource(resource, destSubresource,
- NULL, conversionBuffer.data(),
+ NULL, conversionBuffer->data(),
bufferRowPitch, bufferDepthPitch);
}
@@ -543,7 +605,10 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain)
: TextureStorage11(renderer, D3D11_BIND_RENDER_TARGET | D3D11_BIND_SHADER_RESOURCE),
mTexture(swapchain->getOffscreenTexture()),
- mSwizzleTexture(NULL)
+ mSwizzleTexture(NULL),
+ mLevelZeroTexture(NULL),
+ mLevelZeroRenderTarget(NULL),
+ mUseLevelZeroTexture(false)
{
mTexture->AddRef();
@@ -575,7 +640,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap
mRenderTargetFormat = rtvDesc.Format;
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(mTextureFormat);
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(dxgiFormatInfo.internalFormat, mRenderer->getFeatureLevel());
mSwizzleTextureFormat = formatInfo.swizzleTexFormat;
mSwizzleShaderResourceFormat = formatInfo.swizzleSRVFormat;
mSwizzleRenderTargetFormat = formatInfo.swizzleRTVFormat;
@@ -585,10 +650,13 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swap
initializeSerials(1, 1);
}
-TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
- : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget)),
+TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget)),
mTexture(NULL),
- mSwizzleTexture(NULL)
+ mSwizzleTexture(NULL),
+ mLevelZeroTexture(NULL),
+ mLevelZeroRenderTarget(NULL),
+ mUseLevelZeroTexture(false)
{
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
@@ -599,7 +667,7 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo
mInternalFormat = internalformat;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel());
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
mDepthStencilFormat = formatInfo.dsvFormat;
@@ -614,6 +682,13 @@ TextureStorage11_2D::TextureStorage11_2D(Renderer11 *renderer, GLenum internalfo
mTextureHeight = height;
mTextureDepth = 1;
+ if (hintLevelZeroOnly && levels > 1)
+ {
+ //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+ mUseLevelZeroTexture = true;
+ }
+
initializeSerials(getLevelCount(), 1);
}
@@ -641,6 +716,9 @@ TextureStorage11_2D::~TextureStorage11_2D()
SafeRelease(mTexture);
SafeRelease(mSwizzleTexture);
+ SafeRelease(mLevelZeroTexture);
+ SafeDelete(mLevelZeroRenderTarget);
+
for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; i++)
{
SafeDelete(mRenderTarget[i]);
@@ -654,6 +732,120 @@ TextureStorage11_2D *TextureStorage11_2D::makeTextureStorage11_2D(TextureStorage
return static_cast<TextureStorage11_2D*>(storage);
}
+gl::Error TextureStorage11_2D::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_2D *dest11 = TextureStorage11_2D::makeTextureStorage11_2D(destStorage);
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage.
+ if (mTexture)
+ {
+ gl::Error error = dest11->useLevelZeroWorkaroundTexture(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ immediateContext->CopyResource(destResource, mTexture);
+ }
+
+ if (mLevelZeroTexture)
+ {
+ gl::Error error = dest11->useLevelZeroWorkaroundTexture(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ }
+ }
+ else
+ {
+ ID3D11Resource *sourceResouce = NULL;
+ gl::Error error = getResource(&sourceResouce);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource, sourceResouce);
+ }
+
+ dest11->invalidateSwizzleCache();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2D::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture)
+ {
+ gl::Error error = ensureTextureExists(1);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->CopySubresourceRegion(mLevelZeroTexture, 0, 0, 0, 0, mTexture, 0, NULL);
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture)
+ {
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ context->CopySubresourceRegion(mTexture, 0, 0, 0, 0, mLevelZeroTexture, 0, NULL);
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
void TextureStorage11_2D::associateImage(Image11* image, const gl::ImageIndex &index)
{
GLint level = index.mipIndex;
@@ -733,18 +925,63 @@ gl::Error TextureStorage11_2D::releaseAssociatedImage(const gl::ImageIndex &inde
gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ gl::Error error = ensureTextureExists(1);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mLevelZeroTexture;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error TextureStorage11_2D::getMippedResource(ID3D11Resource **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_2D::ensureTextureExists(int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false;
+ ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
// if the width or height is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
{
- ASSERT(mMipLevels > 0);
+ ASSERT(mipLevels > 0);
ID3D11Device *device = mRenderer->getDevice();
D3D11_TEXTURE2D_DESC desc;
desc.Width = mTextureWidth; // Compressed texture size constraints?
desc.Height = mTextureHeight;
- desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels;
+ desc.MipLevels = mipLevels;
desc.ArraySize = 1;
desc.Format = mTextureFormat;
desc.SampleDesc.Count = 1;
@@ -754,7 +991,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+ HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
// this can happen from windows TDR
if (d3d11::isDeviceLostError(result))
@@ -769,17 +1006,23 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
}
}
- *outResource = mTexture;
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
ASSERT(!index.hasLayer());
int level = index.mipIndex;
ASSERT(level >= 0 && level < getLevelCount());
+ // In GL ES 2.0, the application can only render to level zero of the texture (Section 4.4.3 of the GLES 2.0 spec, page 113 of version 2.0.25).
+ // Other parts of TextureStorage11_2D could create RTVs on non-zero levels of the texture (e.g. generateMipmap).
+ // On Feature Level 9_3, this is unlikely to be useful. The renderer can't create SRVs on the individual levels of the texture,
+ // so methods like generateMipmap can't do anything useful with non-zero-level RTVs.
+ // Therefore if level > 0 on 9_3 then there's almost certainly something wrong.
+ ASSERT(!(mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3 && level > 0));
+
if (!mRenderTarget[level])
{
ID3D11Resource *texture = NULL;
@@ -796,6 +1039,37 @@ gl::Error TextureStorage11_2D::getRenderTarget(const gl::ImageIndex &index, Rend
return error;
}
+ if (mUseLevelZeroTexture)
+ {
+ if (!mLevelZeroRenderTarget)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+ rtvDesc.Texture2D.MipSlice = mTopLevel + level;
+
+ ID3D11RenderTargetView *rtv;
+ HRESULT result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelZeroRenderTarget = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelZeroRenderTarget;
+ return gl::Error(GL_NO_ERROR);
+ }
+
if (mRenderTargetFormat != DXGI_FORMAT_UNKNOWN)
{
ID3D11Device *device = mRenderer->getDevice();
@@ -863,10 +1137,32 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM
srvDesc.Format = format;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
- srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels;
+ srvDesc.Texture2D.MipLevels = mipLevels;
+
+ ID3D11Resource *srvTexture = texture;
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ASSERT(mTopLevel == 0);
+ ASSERT(baseLevel == 0);
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture.
+
+ if (mipLevels == 1 && mMipLevels > 1)
+ {
+ // We must use a SRV on the level-zero-only texture.
+ ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture);
+ srvTexture = mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture != NULL && texture == mTexture);
+ srvTexture = mTexture;
+ }
+ }
ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+ HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
if (FAILED(result))
@@ -945,8 +1241,8 @@ gl::Error TextureStorage11_2D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
return gl::Error(GL_NO_ERROR);
}
-TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
- : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
{
mTexture = NULL;
mSwizzleTexture = NULL;
@@ -961,9 +1257,17 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern
}
}
+ mLevelZeroTexture = NULL;
+ mUseLevelZeroTexture = false;
+
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ mLevelZeroRenderTarget[face] = NULL;
+ }
+
mInternalFormat = internalformat;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel());
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
mDepthStencilFormat = formatInfo.dsvFormat;
@@ -981,6 +1285,13 @@ TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer, GLenum intern
mTextureHeight = size;
mTextureDepth = 1;
+ if (hintLevelZeroOnly && levels > 1)
+ {
+ //The LevelZeroOnly hint should only be true if the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+ mUseLevelZeroTexture = true;
+ }
+
initializeSerials(getLevelCount() * CUBE_FACE_COUNT, CUBE_FACE_COUNT);
}
@@ -1006,6 +1317,12 @@ TextureStorage11_Cube::~TextureStorage11_Cube()
SafeRelease(mTexture);
SafeRelease(mSwizzleTexture);
+ SafeRelease(mLevelZeroTexture);
+
+ for (unsigned int face = 0; face < CUBE_FACE_COUNT; face++)
+ {
+ SafeDelete(mLevelZeroRenderTarget[face]);
+ }
for (unsigned int level = 0; level < gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS; level++)
{
@@ -1023,6 +1340,147 @@ TextureStorage11_Cube *TextureStorage11_Cube::makeTextureStorage11_Cube(TextureS
return static_cast<TextureStorage11_Cube*>(storage);
}
+UINT TextureStorage11_Cube::getSubresourceIndex(const gl::ImageIndex &index) const
+{
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround && mUseLevelZeroTexture && index.mipIndex == 0)
+ {
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT subresource = D3D11CalcSubresource(0, arraySlice, 1);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ return subresource;
+ }
+ else
+ {
+ UINT mipSlice = static_cast<UINT>(index.mipIndex + mTopLevel);
+ UINT arraySlice = static_cast<UINT>(index.hasLayer() ? index.layerIndex : 0);
+ UINT subresource = D3D11CalcSubresource(mipSlice, arraySlice, mMipLevels);
+ ASSERT(subresource != std::numeric_limits<UINT>::max());
+ return subresource;
+ }
+}
+
+gl::Error TextureStorage11_Cube::copyToStorage(TextureStorage *destStorage)
+{
+ ASSERT(destStorage);
+
+ TextureStorage11_Cube *dest11 = TextureStorage11_Cube::makeTextureStorage11_Cube(destStorage);
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+
+ // If either mTexture or mLevelZeroTexture exist, then we need to copy them into the corresponding textures in destStorage.
+ if (mTexture)
+ {
+ gl::Error error = dest11->useLevelZeroWorkaroundTexture(false);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ immediateContext->CopyResource(destResource, mTexture);
+ }
+
+ if (mLevelZeroTexture)
+ {
+ gl::Error error = dest11->useLevelZeroWorkaroundTexture(true);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ immediateContext->CopyResource(destResource, mLevelZeroTexture);
+ }
+ }
+ else
+ {
+ ID3D11Resource *sourceResouce = NULL;
+ gl::Error error = getResource(&sourceResouce);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11Resource *destResource = NULL;
+ error = dest11->getResource(&destResource);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
+ immediateContext->CopyResource(destResource, sourceResouce);
+ }
+
+ dest11->invalidateSwizzleCache();
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::useLevelZeroWorkaroundTexture(bool useLevelZeroTexture)
+{
+ if (useLevelZeroTexture && mMipLevels > 1)
+ {
+ if (!mUseLevelZeroTexture && mTexture)
+ {
+ gl::Error error = ensureTextureExists(1);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Pull data back from the mipped texture if necessary.
+ ASSERT(mLevelZeroTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ context->CopySubresourceRegion(mLevelZeroTexture, D3D11CalcSubresource(0, face, 1), 0, 0, 0, mTexture, face * mMipLevels, NULL);
+ }
+ }
+
+ mUseLevelZeroTexture = true;
+ }
+ else
+ {
+ if (mUseLevelZeroTexture && mLevelZeroTexture)
+ {
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Pull data back from the level zero texture if necessary.
+ ASSERT(mTexture);
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ for (int face = 0; face < 6; face++)
+ {
+ context->CopySubresourceRegion(mTexture, D3D11CalcSubresource(0, face, mMipLevels), 0, 0, 0, mLevelZeroTexture, face, NULL);
+ }
+ }
+
+ mUseLevelZeroTexture = false;
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
void TextureStorage11_Cube::associateImage(Image11* image, const gl::ImageIndex &index)
{
GLint level = index.mipIndex;
@@ -1121,9 +1579,54 @@ gl::Error TextureStorage11_Cube::releaseAssociatedImage(const gl::ImageIndex &in
gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
{
+ if (mUseLevelZeroTexture && mMipLevels > 1)
+ {
+ gl::Error error = ensureTextureExists(1);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mLevelZeroTexture;
+ return gl::Error(GL_NO_ERROR);
+ }
+ else
+ {
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+ }
+}
+
+gl::Error TextureStorage11_Cube::getMippedResource(ID3D11Resource **outResource)
+{
+ // This shouldn't be called unless the zero max LOD workaround is active.
+ ASSERT(mRenderer->getWorkarounds().zeroMaxLodWorkaround);
+
+ gl::Error error = ensureTextureExists(mMipLevels);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ *outResource = mTexture;
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error TextureStorage11_Cube::ensureTextureExists(int mipLevels)
+{
+ // If mMipLevels = 1 then always use mTexture rather than mLevelZeroTexture.
+ bool useLevelZeroTexture = mRenderer->getWorkarounds().zeroMaxLodWorkaround ? (mipLevels == 1) && (mMipLevels > 1) : false;
+ ID3D11Texture2D **outputTexture = useLevelZeroTexture ? &mLevelZeroTexture : &mTexture;
+
// if the size is not positive this should be treated as an incomplete texture
// we handle that here by skipping the d3d texture creation
- if (mTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
+ if (*outputTexture == NULL && mTextureWidth > 0 && mTextureHeight > 0)
{
ASSERT(mMipLevels > 0);
@@ -1132,7 +1635,7 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
D3D11_TEXTURE2D_DESC desc;
desc.Width = mTextureWidth;
desc.Height = mTextureHeight;
- desc.MipLevels = mMipLevels;
+ desc.MipLevels = mipLevels;
desc.ArraySize = CUBE_FACE_COUNT;
desc.Format = mTextureFormat;
desc.SampleDesc.Count = 1;
@@ -1142,7 +1645,7 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
desc.CPUAccessFlags = 0;
desc.MiscFlags = D3D11_RESOURCE_MISC_TEXTURECUBE;
- HRESULT result = device->CreateTexture2D(&desc, NULL, &mTexture);
+ HRESULT result = device->CreateTexture2D(&desc, NULL, outputTexture);
// this can happen from windows TDR
if (d3d11::isDeviceLostError(result))
@@ -1157,11 +1660,10 @@ gl::Error TextureStorage11_Cube::getResource(ID3D11Resource **outResource)
}
}
- *outResource = mTexture;
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
int faceIndex = index.layerIndex;
int level = index.mipIndex;
@@ -1181,14 +1683,53 @@ gl::Error TextureStorage11_Cube::getRenderTarget(const gl::ImageIndex &index, Re
return error;
}
+ if (mUseLevelZeroTexture)
+ {
+ if (!mLevelZeroRenderTarget[faceIndex])
+ {
+ D3D11_RENDER_TARGET_VIEW_DESC rtvDesc;
+ rtvDesc.Format = mRenderTargetFormat;
+ rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DARRAY;
+ rtvDesc.Texture2DArray.MipSlice = mTopLevel + level;
+ rtvDesc.Texture2DArray.FirstArraySlice = faceIndex;
+ rtvDesc.Texture2DArray.ArraySize = 1;
+
+ ID3D11RenderTargetView *rtv;
+ result = device->CreateRenderTargetView(mLevelZeroTexture, &rtvDesc, &rtv);
+
+ if (result == E_OUTOFMEMORY)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal render target view for texture storage, result: 0x%X.", result);
+ }
+ ASSERT(SUCCEEDED(result));
+
+ mLevelZeroRenderTarget[faceIndex] = new TextureRenderTarget11(rtv, mLevelZeroTexture, NULL, mInternalFormat, getLevelWidth(level), getLevelHeight(level), 1, 0);
+
+ // RenderTarget will take ownership of these resources
+ SafeRelease(rtv);
+ }
+
+ ASSERT(outRT);
+ *outRT = mLevelZeroRenderTarget[faceIndex];
+ return gl::Error(GL_NO_ERROR);
+ }
+
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
srvDesc.Format = mShaderResourceFormat;
- srvDesc.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;
+ if (mRenderer->getFeatureLevel() <= D3D_FEATURE_LEVEL_9_3)
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE;
+ }
+ else
+ {
+ srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2DARRAY; // Will be used with Texture2D sampler, not TextureCube
+ }
+
ID3D11ShaderResourceView *srv;
result = device->CreateShaderResourceView(texture, &srvDesc, &srv);
@@ -1285,8 +1826,30 @@ gl::Error TextureStorage11_Cube::createSRV(int baseLevel, int mipLevels, DXGI_FO
srvDesc.TextureCube.MostDetailedMip = mTopLevel + baseLevel;
}
+ ID3D11Resource *srvTexture = texture;
+
+ if (mRenderer->getWorkarounds().zeroMaxLodWorkaround)
+ {
+ ASSERT(mTopLevel == 0);
+ ASSERT(baseLevel == 0);
+ // This code also assumes that the incoming texture equals either mLevelZeroTexture or mTexture.
+
+ if (mipLevels == 1 && mMipLevels > 1)
+ {
+ // We must use a SRV on the level-zero-only texture.
+ ASSERT(mLevelZeroTexture != NULL && texture == mLevelZeroTexture);
+ srvTexture = mLevelZeroTexture;
+ }
+ else
+ {
+ ASSERT(mipLevels == static_cast<int>(mMipLevels));
+ ASSERT(mTexture != NULL && texture == mTexture);
+ srvTexture = mTexture;
+ }
+ }
+
ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
+ HRESULT result = device->CreateShaderResourceView(srvTexture, &srvDesc, outSRV);
ASSERT(result == E_OUTOFMEMORY || SUCCEEDED(result));
if (FAILED(result))
@@ -1369,7 +1932,7 @@ gl::Error TextureStorage11_Cube::getSwizzleRenderTarget(int mipLevel, ID3D11Rend
TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels)
- : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
{
mTexture = NULL;
mSwizzleTexture = NULL;
@@ -1383,7 +1946,7 @@ TextureStorage11_3D::TextureStorage11_3D(Renderer11 *renderer, GLenum internalfo
mInternalFormat = internalformat;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel());
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
mDepthStencilFormat = formatInfo.dsvFormat;
@@ -1582,7 +2145,7 @@ gl::Error TextureStorage11_3D::createSRV(int baseLevel, int mipLevels, DXGI_FORM
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
int mipLevel = index.mipIndex;
ASSERT(mipLevel >= 0 && mipLevel < getLevelCount());
@@ -1614,7 +2177,7 @@ gl::Error TextureStorage11_3D::getRenderTarget(const gl::ImageIndex &index, Rend
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture3D.FirstWSlice = 0;
- rtvDesc.Texture3D.WSize = -1;
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
ID3D11RenderTargetView *rtv;
HRESULT result = device->CreateRenderTargetView(texture, &rtvDesc, &rtv);
@@ -1738,7 +2301,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
rtvDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE3D;
rtvDesc.Texture3D.MipSlice = mTopLevel + mipLevel;
rtvDesc.Texture3D.FirstWSlice = 0;
- rtvDesc.Texture3D.WSize = -1;
+ rtvDesc.Texture3D.WSize = static_cast<UINT>(-1);
HRESULT result = device->CreateRenderTargetView(mSwizzleTexture, &rtvDesc, &mSwizzleRenderTargets[mipLevel]);
@@ -1755,7 +2318,7 @@ gl::Error TextureStorage11_3D::getSwizzleRenderTarget(int mipLevel, ID3D11Render
TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum internalformat, bool renderTarget,
GLsizei width, GLsizei height, GLsizei depth, int levels)
- : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderTarget))
+ : TextureStorage11(renderer, GetTextureBindFlags(internalformat, renderer->getFeatureLevel(), renderTarget))
{
mTexture = NULL;
mSwizzleTexture = NULL;
@@ -1767,7 +2330,7 @@ TextureStorage11_2DArray::TextureStorage11_2DArray(Renderer11 *renderer, GLenum
mInternalFormat = internalformat;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalformat, renderer->getFeatureLevel());
mTextureFormat = formatInfo.texFormat;
mShaderResourceFormat = formatInfo.srvFormat;
mDepthStencilFormat = formatInfo.dsvFormat;
@@ -1791,13 +2354,16 @@ TextureStorage11_2DArray::~TextureStorage11_2DArray()
{
for (ImageMap::iterator i = mAssociatedImages.begin(); i != mAssociatedImages.end(); i++)
{
- bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this);
- ASSERT(imageAssociationCorrect);
-
- if (imageAssociationCorrect)
+ if (i->second)
{
- // We must let the Images recover their data before we delete it from the TextureStorage.
- i->second->recoverFromAssociatedStorage();
+ bool imageAssociationCorrect = i->second->isAssociatedStorageValid(this);
+ ASSERT(imageAssociationCorrect);
+
+ if (imageAssociationCorrect)
+ {
+ // We must let the Images recover their data before we delete it from the TextureStorage.
+ i->second->recoverFromAssociatedStorage();
+ }
}
}
mAssociatedImages.clear();
@@ -1875,8 +2441,6 @@ gl::Error TextureStorage11_2DArray::releaseAssociatedImage(const gl::ImageIndex
LevelLayerKey key(level, layerTarget);
- ASSERT(mAssociatedImages.find(key) != mAssociatedImages.end());
-
if (mAssociatedImages.find(key) != mAssociatedImages.end())
{
if (mAssociatedImages[key] != NULL && mAssociatedImages[key] != incomingImage)
@@ -1966,7 +2530,7 @@ gl::Error TextureStorage11_2DArray::createSRV(int baseLevel, int mipLevels, DXGI
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureStorage11_2DArray::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
ASSERT(index.hasLayer());
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
index 930300a63d..456e2660f9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
@@ -7,12 +7,12 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Error.h"
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
#include <map>
@@ -23,7 +23,7 @@ struct ImageIndex;
namespace rx
{
-class RenderTarget;
+class RenderTargetD3D;
class RenderTarget11;
class Renderer11;
class SwapChain11;
@@ -36,13 +36,13 @@ class TextureStorage11 : public TextureStorage
static TextureStorage11 *makeTextureStorage11(TextureStorage *storage);
- static DWORD GetTextureBindFlags(GLenum internalFormat, bool renderTarget);
+ static DWORD GetTextureBindFlags(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel, bool renderTarget);
UINT getBindFlags() const;
virtual gl::Error getResource(ID3D11Resource **outResource) = 0;
virtual gl::Error getSRV(const gl::SamplerState &samplerState, ID3D11ShaderResourceView **outSRV);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
@@ -50,7 +50,7 @@ class TextureStorage11 : public TextureStorage
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
virtual int getLevelCount() const;
- UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+ virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
gl::Error generateSwizzles(GLenum swizzleRed, GLenum swizzleGreen, GLenum swizzleBlue, GLenum swizzleAlpha);
void invalidateSwizzleCacheLevel(int mipLevel);
@@ -68,7 +68,7 @@ class TextureStorage11 : public TextureStorage
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage) = 0;
virtual gl::Error copyToStorage(TextureStorage *destStorage);
- virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+ virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
protected:
@@ -77,6 +77,9 @@ class TextureStorage11 : public TextureStorage
int getLevelHeight(int mipLevel) const;
int getLevelDepth(int mipLevel) const;
+ // Some classes (e.g. TextureStorage11_2D) will override getMippedResource.
+ virtual gl::Error getMippedResource(ID3D11Resource **outResource) { return getResource(outResource); }
+
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture) = 0;
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV) = 0;
gl::Error getSRVLevel(int mipLevel, ID3D11ShaderResourceView **outSRV);
@@ -118,8 +121,6 @@ class TextureStorage11 : public TextureStorage
SwizzleCacheValue mSwizzleCache[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11);
-
const UINT mBindFlags;
struct SRVKey
@@ -142,32 +143,51 @@ class TextureStorage11_2D : public TextureStorage11
{
public:
TextureStorage11_2D(Renderer11 *renderer, SwapChain11 *swapchain);
- TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
+ TextureStorage11_2D(Renderer11 *renderer, GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly = false);
virtual ~TextureStorage11_2D();
static TextureStorage11_2D *makeTextureStorage11_2D(TextureStorage *storage);
virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getMippedResource(ID3D11Resource **outResource);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
+
protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2D);
+ gl::Error ensureTextureExists(int mipLevels);
+ private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ // These are members related to the zero max-LOD workaround.
+ // D3D11 Feature Level 9_3 can't disable mipmaps on a mipmapped texture (i.e. solely sample from level zero).
+ // These members are used to work around this limitation.
+ // Usually only mTexture XOR mLevelZeroTexture will exist.
+ // For example, if an app creates a texture with only one level, then 9_3 will only create mLevelZeroTexture.
+ // However, in some scenarios, both textures have to be created. This incurs additional memory overhead.
+ // One example of this is an application that creates a texture, calls glGenerateMipmap, and then disables mipmaps on the texture.
+ // A more likely example is an app that creates an empty texture, renders to it, and then calls glGenerateMipmap
+ // TODO: In this rendering scenario, release the mLevelZeroTexture after mTexture has been created to save memory.
+ ID3D11Texture2D *mLevelZeroTexture;
+ RenderTarget11 *mLevelZeroRenderTarget;
+ bool mUseLevelZeroTexture;
+
+ // Swizzle-related variables
ID3D11Texture2D *mSwizzleTexture;
ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
@@ -177,26 +197,33 @@ class TextureStorage11_2D : public TextureStorage11
class TextureStorage11_Cube : public TextureStorage11
{
public:
- TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
+ TextureStorage11_Cube(Renderer11 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual ~TextureStorage11_Cube();
static TextureStorage11_Cube *makeTextureStorage11_Cube(TextureStorage *storage);
+ virtual UINT getSubresourceIndex(const gl::ImageIndex &index) const;
+
virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getMippedResource(ID3D11Resource **outResource);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
+
+ virtual gl::Error copyToStorage(TextureStorage *destStorage);
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
virtual bool isAssociatedImageValid(const gl::ImageIndex &index, Image11* expectedImage);
virtual gl::Error releaseAssociatedImage(const gl::ImageIndex &index, Image11* incomingImage);
+ virtual gl::Error useLevelZeroWorkaroundTexture(bool useLevelZeroTexture);
+
protected:
virtual gl::Error getSwizzleTexture(ID3D11Resource **outTexture);
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_Cube);
+ gl::Error ensureTextureExists(int mipLevels);
+ private:
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
@@ -205,6 +232,11 @@ class TextureStorage11_Cube : public TextureStorage11
ID3D11Texture2D *mTexture;
RenderTarget11 *mRenderTarget[CUBE_FACE_COUNT][gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
+ // Level-zero workaround members. See TextureStorage11_2D's workaround members for a description.
+ ID3D11Texture2D *mLevelZeroTexture;
+ RenderTarget11 *mLevelZeroRenderTarget[CUBE_FACE_COUNT];
+ bool mUseLevelZeroTexture;
+
ID3D11Texture2D *mSwizzleTexture;
ID3D11RenderTargetView *mSwizzleRenderTargets[gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS];
@@ -223,7 +255,7 @@ class TextureStorage11_3D : public TextureStorage11
virtual gl::Error getResource(ID3D11Resource **outResource);
// Handles both layer and non-layer RTs
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
@@ -235,8 +267,6 @@ class TextureStorage11_3D : public TextureStorage11
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_3D);
-
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
@@ -263,7 +293,7 @@ class TextureStorage11_2DArray : public TextureStorage11
static TextureStorage11_2DArray *makeTextureStorage11_2DArray(TextureStorage *storage);
virtual gl::Error getResource(ID3D11Resource **outResource);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual void associateImage(Image11* image, const gl::ImageIndex &index);
virtual void disassociateImage(const gl::ImageIndex &index, Image11* expectedImage);
@@ -275,8 +305,6 @@ class TextureStorage11_2DArray : public TextureStorage11
virtual gl::Error getSwizzleRenderTarget(int mipLevel, ID3D11RenderTargetView **outRTV);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage11_2DArray);
-
virtual gl::Error createSRV(int baseLevel, int mipLevels, DXGI_FORMAT format, ID3D11Resource *texture,
ID3D11ShaderResourceView **outSRV) const;
@@ -295,4 +323,4 @@ class TextureStorage11_2DArray : public TextureStorage11
}
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TEXTURESTORAGE11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
new file mode 100644
index 0000000000..213ce31817
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp
@@ -0,0 +1,95 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.cpp: Trim support utility class.
+
+#include "libANGLE/renderer/d3d/d3d11/Trim11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+using namespace ABI::Windows::Foundation;
+using namespace ABI::Windows::ApplicationModel;
+using namespace ABI::Windows::ApplicationModel::Core;
+#endif
+
+namespace rx
+{
+
+Trim11::Trim11(rx::Renderer11 *renderer)
+ : mRenderer(renderer)
+{
+ bool result = true;
+ result = registerForRendererTrimRequest();
+ ASSERT(result);
+}
+
+Trim11::~Trim11()
+{
+ unregisterForRendererTrimRequest();
+}
+
+void Trim11::trim()
+{
+ if (!mRenderer)
+ {
+ return;
+ }
+
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+ ID3D11Device* device = mRenderer->getDevice();
+ // IDXGIDevice3 is only supported on Windows 8.1 and Windows Phone 8.1 and above.
+ IDXGIDevice3 *dxgiDevice3 = d3d11::DynamicCastComObject<IDXGIDevice3>(device);
+ if (dxgiDevice3)
+ {
+ dxgiDevice3->Trim();
+ }
+ SafeRelease(dxgiDevice3);
+#endif
+}
+
+bool Trim11::registerForRendererTrimRequest()
+{
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+ ICoreApplication* coreApplication = nullptr;
+ HRESULT result = GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication);
+ if (SUCCEEDED(result))
+ {
+ auto suspendHandler = Callback<IEventHandler<SuspendingEventArgs*>>(
+ [this](IInspectable*, ISuspendingEventArgs*) -> HRESULT
+ {
+ trim();
+ return S_OK;
+ });
+ result = coreApplication->add_Suspending(suspendHandler.Get(), &mApplicationSuspendedEventToken);
+ }
+ SafeRelease(coreApplication);
+
+ if (FAILED(result))
+ {
+ return false;
+ }
+#endif
+ return true;
+}
+
+void Trim11::unregisterForRendererTrimRequest()
+{
+#if defined (ANGLE_ENABLE_WINDOWS_STORE)
+ if (mApplicationSuspendedEventToken.value != 0)
+ {
+ ICoreApplication* coreApplication = nullptr;
+ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(), &coreApplication)))
+ {
+ coreApplication->remove_Suspending(mApplicationSuspendedEventToken);
+ }
+ mApplicationSuspendedEventToken.value = 0;
+ SafeRelease(coreApplication);
+ }
+#endif
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
new file mode 100644
index 0000000000..f232ad7e8e
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Trim11.h
@@ -0,0 +1,43 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Trim11.h: Trim support utility class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
+
+#include "common/angleutils.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Error.h"
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+typedef void* EventRegistrationToken;
+#else
+#include <EventToken.h>
+#endif
+
+namespace rx
+{
+class Renderer11;
+
+class Trim11 : angle::NonCopyable
+{
+ public:
+ explicit Trim11(Renderer11 *renderer);
+ ~Trim11();
+
+ private:
+ Renderer11 *mRenderer;
+ EventRegistrationToken mApplicationSuspendedEventToken;
+
+ void trim();
+ bool registerForRendererTrimRequest();
+ void unregisterForRendererTrimRequest();
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_TRIM11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
index 70bc3bb26f..78aad7d106 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexArray11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexArray11.h
@@ -6,11 +6,11 @@
// VertexArray11.h: Defines the rx::VertexArray11 class which implements rx::VertexArrayImpl.
-#ifndef LIBGLESV2_RENDERER_VERTEXARRAY11_H_
-#define LIBGLESV2_RENDERER_VERTEXARRAY11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
-#include "libGLESv2/renderer/VertexArrayImpl.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
namespace rx
{
@@ -32,11 +32,9 @@ class VertexArray11 : public VertexArrayImpl
virtual void enableAttribute(size_t idx, bool enabledState) { }
private:
- DISALLOW_COPY_AND_ASSIGN(VertexArray11);
-
Renderer11 *mRenderer;
};
}
-#endif // LIBGLESV2_RENDERER_VERTEXARRAY11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXARRAY11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
index a9d6fa2ca4..adc64cef5e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
@@ -6,12 +6,12 @@
// VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
-#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/d3d11/VertexBuffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Buffer11.h"
+#include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/VertexAttribute.h"
namespace rx
{
@@ -21,10 +21,12 @@ VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
mBuffer = NULL;
mBufferSize = 0;
mDynamicUsage = false;
+ mMappedResourceData = NULL;
}
VertexBuffer11::~VertexBuffer11()
{
+ ASSERT(mMappedResourceData == NULL);
SafeRelease(mBuffer);
}
@@ -65,6 +67,37 @@ VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
return static_cast<VertexBuffer11*>(vetexBuffer);
}
+gl::Error VertexBuffer11::mapResource()
+{
+ if (mMappedResourceData == NULL)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+
+ HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
+ }
+
+ mMappedResourceData = reinterpret_cast<uint8_t*>(mappedResource.pData);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+void VertexBuffer11::hintUnmapResource()
+{
+ if (mMappedResourceData != NULL)
+ {
+ ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
+ dxContext->Unmap(mBuffer, 0);
+
+ mMappedResourceData = NULL;
+ }
+}
+
gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
GLint start, GLsizei count, GLsizei instances, unsigned int offset)
{
@@ -75,24 +108,23 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
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))
+ // This will map the resource if it isn't already mapped.
+ gl::Error error = mapResource();
+ if (error.isError())
{
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
+ return error;
}
- uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset;
+ uint8_t *output = mMappedResourceData + offset;
const uint8_t *input = NULL;
if (attrib.enabled)
{
if (buffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(buffer);
- gl::Error error = storage->getData(&input);
+ BufferD3D *storage = GetImplAs<BufferD3D>(buffer);
+ error = storage->getData(&input);
if (error.isError())
{
return error;
@@ -115,12 +147,10 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
}
gl::VertexFormat vertexFormat(attrib, currentValue.Type);
- const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel());
ASSERT(vertexFormatInfo.copyFunction != NULL);
vertexFormatInfo.copyFunction(input, inputStride, count, output);
- dxContext->Unmap(mBuffer, 0);
-
return gl::Error(GL_NO_ERROR);
}
@@ -141,7 +171,7 @@ gl::Error VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GL
}
gl::VertexFormat vertexFormat(attrib);
- const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
+ const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat, mRenderer->getFeatureLevel());
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(vertexFormatInfo.nativeFormat);
unsigned int elementSize = dxgiFormatInfo.pixelBytes;
if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
index a9bbac98fa..2450e8955c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
@@ -6,10 +6,12 @@
// VertexBuffer11.h: Defines the D3D11 VertexBuffer implementation.
-#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
-#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+#include <stdint.h>
+
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
namespace rx
{
@@ -35,18 +37,22 @@ class VertexBuffer11 : public VertexBuffer
virtual gl::Error setBufferSize(unsigned int size);
virtual gl::Error discard();
+ virtual void hintUnmapResource();
+
ID3D11Buffer *getBuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
+ gl::Error mapResource();
Renderer11 *const mRenderer;
ID3D11Buffer *mBuffer;
unsigned int mBufferSize;
bool mDynamicUsage;
+
+ uint8_t *mMappedResourceData;
};
}
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
new file mode 100644
index 0000000000..5501e361f1
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.h
@@ -0,0 +1,40 @@
+//
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// copyvertex.h: Defines D3D11 vertex buffer copying and conversion functions
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
+
+#include "common/mathutil.h"
+
+namespace rx
+{
+
+// 'alphaDefaultValueBits' gives the default value for the alpha channel (4th component)
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits>
+inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t componentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized>
+inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+template <bool isSigned, bool normalized, bool toFloat>
+inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+}
+
+#include "copyvertex.inl"
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_COPYVERTEX_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
index 7eef17b22b..60678d7b9f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.inl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/copyvertex.inl
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -7,40 +7,111 @@
namespace rx
{
-template <typename T, size_t componentCount, uint32_t widenDefaultValueBits>
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, uint32_t alphaDefaultValueBits>
inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
{
- const size_t attribSize = sizeof(T)* componentCount;
- const T defaultValue = gl::bitCast<T>(widenDefaultValueBits);
- const bool widen = (widenDefaultValueBits != 0);
+ const size_t attribSize = sizeof(T)* inputComponentCount;
- if (attribSize == stride && !widen)
+ if (attribSize == stride && inputComponentCount == outputComponentCount)
{
memcpy(output, input, count * attribSize);
}
else
{
- size_t outputStride = widen ? 4 : componentCount;
+ const T defaultAlphaValue = gl::bitCast<T>(alphaDefaultValueBits);
+ const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
for (size_t i = 0; i < count; i++)
{
const T *offsetInput = reinterpret_cast<const T*>(input + (i * stride));
- T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
+ T *offsetOutput = reinterpret_cast<T*>(output) + i * outputComponentCount;
- for (size_t j = 0; j < componentCount; j++)
+ for (size_t j = 0; j < inputComponentCount; j++)
{
offsetOutput[j] = offsetInput[j];
}
- if (widen)
+ for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
{
- offsetOutput[3] = defaultValue;
+ // Set the remaining G/B channels to 0.
+ offsetOutput[j] = 0;
}
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // Set the remaining alpha channel to the defaultAlphaValue.
+ offsetOutput[3] = defaultAlphaValue;
+ }
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SintTo16SintVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ const size_t lastNonAlphaOutputComponent = std::min<size_t>(outputComponentCount, 3);
+
+ for (size_t i = 0; i < count; i++)
+ {
+ const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride);
+ GLshort *offsetOutput = reinterpret_cast<GLshort*>(output)+i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ offsetOutput[j] = static_cast<GLshort>(offsetInput[j]);
+ }
+
+ for (size_t j = inputComponentCount; j < lastNonAlphaOutputComponent; j++)
+ {
+ // Set remaining G/B channels to 0.
+ offsetOutput[j] = 0;
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // On integer formats, we must set the Alpha channel to 1 if it's unused.
+ offsetOutput[3] = 1;
}
}
}
-template <size_t componentCount>
+template <size_t inputComponentCount, size_t outputComponentCount>
+inline void Copy8SnormTo16SnormVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
+{
+ for (size_t i = 0; i < count; i++)
+ {
+ const GLbyte *offsetInput = reinterpret_cast<const GLbyte*>(input + i * stride);
+ GLshort *offsetOutput = reinterpret_cast<GLshort*>(output) + i * outputComponentCount;
+
+ for (size_t j = 0; j < inputComponentCount; j++)
+ {
+ // The original GLbyte value ranges from -128 to +127 (INT8_MAX).
+ // When converted to GLshort, the value must be scaled to between -32768 and +32767 (INT16_MAX).
+ if (offsetInput[j] > 0)
+ {
+ offsetOutput[j] = offsetInput[j] << 8 | offsetInput[j] << 1 | ((offsetInput[j] & 0x40) >> 6);
+ }
+ else
+ {
+ offsetOutput[j] = offsetInput[j] << 8;
+ }
+ }
+
+ for (size_t j = inputComponentCount; j < std::min<size_t>(outputComponentCount, 3); j++)
+ {
+ // Set remaining G/B channels to 0.
+ offsetOutput[j] = 0;
+ }
+
+ if (inputComponentCount < outputComponentCount && outputComponentCount == 4)
+ {
+ // On normalized formats, we must set the Alpha channel to the max value if it's unused.
+ offsetOutput[3] = INT16_MAX;
+ }
+ }
+}
+
+template <size_t inputComponentCount, size_t outputComponentCount>
inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
{
static const float divisor = 1.0f / (1 << 16);
@@ -48,16 +119,25 @@ inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size
for (size_t i = 0; i < count; i++)
{
const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(input + (stride * i));
- float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
+ float* offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
- for (size_t j = 0; j < componentCount; j++)
+ for (size_t j = 0; j < inputComponentCount; j++)
{
offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
}
+
+ // 4-component output formats would need special padding in the alpha channel.
+ static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
+ "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported.");
+
+ for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+ {
+ offsetOutput[j] = 0.0f;
+ }
}
}
-template <typename T, size_t componentCount, bool normalized>
+template <typename T, size_t inputComponentCount, size_t outputComponentCount, bool normalized>
inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output)
{
typedef std::numeric_limits<T> NL;
@@ -65,9 +145,9 @@ inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t coun
for (size_t i = 0; i < count; i++)
{
const T *offsetInput = reinterpret_cast<const T*>(input + (stride * i));
- float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
+ float *offsetOutput = reinterpret_cast<float*>(output) + i * outputComponentCount;
- for (size_t j = 0; j < componentCount; j++)
+ for (size_t j = 0; j < inputComponentCount; j++)
{
if (normalized)
{
@@ -86,6 +166,15 @@ inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t coun
offsetOutput[j] = static_cast<float>(offsetInput[j]);
}
}
+
+ // This would require special padding.
+ static_assert(!(inputComponentCount < 4 && outputComponentCount == 4),
+ "An inputComponentCount less than 4 and an outputComponentCount equal to 4 is not supported.");
+
+ for (size_t j = inputComponentCount; j < outputComponentCount; j++)
+ {
+ offsetOutput[j] = 0.0f;
+ }
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
index 90a879e170..2f81d6d608 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp
@@ -7,12 +7,14 @@
// 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"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/Renderer.h"
+#include "libANGLE/renderer/d3d/copyimage.h"
+#include "libANGLE/renderer/d3d/generatemip.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
+#include "libANGLE/renderer/d3d/d3d11/copyvertex.h"
namespace rx
{
@@ -127,6 +129,90 @@ static D3D11FastCopyMap BuildFastCopyMap()
return map;
}
+struct DXGIColorFormatInfo
+{
+ size_t redBits;
+ size_t greenBits;
+ size_t blueBits;
+
+ size_t luminanceBits;
+
+ size_t alphaBits;
+ size_t sharedBits;
+};
+
+typedef std::map<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoMap;
+typedef std::pair<DXGI_FORMAT, DXGIColorFormatInfo> ColorFormatInfoPair;
+
+static inline void InsertDXGIColorFormatInfo(ColorFormatInfoMap *map, DXGI_FORMAT format, size_t redBits, size_t greenBits,
+ size_t blueBits, size_t alphaBits, size_t sharedBits)
+{
+ DXGIColorFormatInfo info;
+ info.redBits = redBits;
+ info.greenBits = greenBits;
+ info.blueBits = blueBits;
+ info.alphaBits = alphaBits;
+ info.sharedBits = sharedBits;
+
+ map->insert(std::make_pair(format, info));
+}
+
+static ColorFormatInfoMap BuildColorFormatInfoMap()
+{
+ ColorFormatInfoMap map;
+
+ // | DXGI format | R | G | B | A | S |
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_A8_UNORM, 0, 0, 0, 8, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UNORM, 8, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UNORM, 8, 8, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, 8, 8, 8, 8, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_B8G8R8A8_UNORM, 8, 8, 8, 8, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SNORM, 8, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SNORM, 8, 8, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_UINT, 8, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_UINT, 16, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_UINT, 32, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_UINT, 8, 8, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_UINT, 16, 16, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_UINT, 32, 32, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_UINT, 32, 32, 32, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_UINT, 8, 8, 8, 8, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_UINT, 16, 16, 16, 16, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_UINT, 32, 32, 32, 32, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8_SINT, 8, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_SINT, 16, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_SINT, 32, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8_SINT, 8, 8, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_SINT, 16, 16, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_SINT, 32, 32, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_SINT, 32, 32, 32, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R8G8B8A8_SINT, 8, 8, 8, 8, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_SINT, 16, 16, 16, 16, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_SINT, 32, 32, 32, 32, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R10G10B10A2_UINT, 10, 10, 10, 2, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16_FLOAT, 16, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16_FLOAT, 16, 16, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32_FLOAT, 32, 0, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32_FLOAT, 32, 32, 0, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32_FLOAT, 32, 32, 32, 0, 0);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0);
+
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R9G9B9E5_SHAREDEXP, 9, 9, 9, 0, 5);
+ InsertDXGIColorFormatInfo(&map, DXGI_FORMAT_R11G11B10_FLOAT, 11, 11, 10, 0, 0);
+
+ return map;
+}
+
struct DXGIDepthStencilInfo
{
unsigned int depthBits;
@@ -179,6 +265,11 @@ DXGIFormat::DXGIFormat()
: pixelBytes(0),
blockWidth(0),
blockHeight(0),
+ redBits(0),
+ greenBits(0),
+ blueBits(0),
+ alphaBits(0),
+ sharedBits(0),
depthBits(0),
depthOffset(0),
stencilBits(0),
@@ -205,21 +296,27 @@ void AddDXGIFormat(DXGIFormatInfoMap *map, DXGI_FORMAT dxgiFormat, GLuint pixelB
info.blockWidth = blockWidth;
info.blockHeight = blockHeight;
+ static const ColorFormatInfoMap colorInfoMap = BuildColorFormatInfoMap();
+ ColorFormatInfoMap::const_iterator colorInfoIter = colorInfoMap.find(dxgiFormat);
+ if (colorInfoIter != colorInfoMap.end())
+ {
+ const DXGIColorFormatInfo &colorInfo = colorInfoIter->second;
+ info.redBits = colorInfo.redBits;
+ info.greenBits = colorInfo.greenBits;
+ info.blueBits = colorInfo.blueBits;
+ info.alphaBits = colorInfo.alphaBits;
+ info.sharedBits = colorInfo.sharedBits;
+ }
+
static const DepthStencilInfoMap dsInfoMap = BuildDepthStencilInfoMap();
DepthStencilInfoMap::const_iterator dsInfoIter = dsInfoMap.find(dxgiFormat);
if (dsInfoIter != dsInfoMap.end())
{
- info.depthBits = dsInfoIter->second.depthBits;
- info.depthOffset = dsInfoIter->second.depthOffset;
- info.stencilBits = dsInfoIter->second.stencilBits;
- info.stencilOffset = dsInfoIter->second.stencilOffset;
- }
- else
- {
- info.depthBits = 0;
- info.depthOffset = 0;
- info.stencilBits = 0;
- info.stencilOffset = 0;
+ const DXGIDepthStencilInfo &dsInfo = dsInfoIter->second;
+ info.depthBits = dsInfo.depthBits;
+ info.depthOffset = dsInfo.depthOffset;
+ info.stencilBits = dsInfo.stencilBits;
+ info.stencilOffset = dsInfo.stencilOffset;
}
static const DXGIToESFormatMap dxgiToESMap = BuildDXGIToESFormatMap();
@@ -452,7 +549,28 @@ static inline void InsertLoadFunction(D3D11LoadFunctionMap *map, GLenum internal
(*map)[internalFormat].push_back(TypeLoadFunctionPair(type, loadFunc));
}
-D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
+D3D11LoadFunctionMap BuildD3D11_FL9_3_LoadFunctionMap()
+{
+ D3D11LoadFunctionMap map;
+
+ // From GL_EXT_texture_storage. Also used by GL_ALPHA8
+ // On feature level 9_3, A8_UNORM doesn't support mipmaps, so we must use RGBA8 instead
+ InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8);
+
+ return map;
+}
+
+D3D11LoadFunctionMap BuildD3D11_FL10_0Plus_LoadFunctionMap()
+{
+ D3D11LoadFunctionMap map;
+
+ // From GL_EXT_texture_storage. Also used by GL_ALPHA8
+ InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1>);
+
+ return map;
+}
+
+D3D11LoadFunctionMap BuildBaseD3D11LoadFunctionMap()
{
D3D11LoadFunctionMap map;
@@ -557,7 +675,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F );
// From GL_EXT_texture_storage
- InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 );
+ // GL_ALPHA8_EXT GL_UNSIGNED_BYTE is in the feature-level-specific load function maps, due to differences between 9_3 and 10_0+
InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 );
InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 );
InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F );
@@ -627,8 +745,8 @@ TextureFormat::TextureFormat()
{
}
-static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat,
- DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat)
+static inline void InsertD3D11FormatInfoBase(D3D11ES3FormatMap *formatMap, const D3D11LoadFunctionMap &flLoadFunctions, GLenum internalFormat, DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat)
{
TextureFormat info;
info.texFormat = texFormat;
@@ -712,8 +830,8 @@ static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internal
InternalFormatInitializerMap::const_iterator initializerIter = initializerMap.find(internalFormat);
info.dataInitializerFunction = (initializerIter != initializerMap.end()) ? initializerIter->second : NULL;
- // Gather all the load functions for this internal format
- static const D3D11LoadFunctionMap loadFunctions = BuildD3D11LoadFunctionMap();
+ // Gather all the load functions for this internal format from the base list
+ static const D3D11LoadFunctionMap loadFunctions = BuildBaseD3D11LoadFunctionMap();
D3D11LoadFunctionMap::const_iterator loadFunctionIter = loadFunctions.find(internalFormat);
if (loadFunctionIter != loadFunctions.end())
{
@@ -726,7 +844,57 @@ static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internal
}
}
- map->insert(std::make_pair(internalFormat, info));
+ // Gather load functions for this internal format from the feature-level-specific list
+ D3D11LoadFunctionMap::const_iterator flLoadFunctionIter = flLoadFunctions.find(internalFormat);
+ if (flLoadFunctionIter != flLoadFunctions.end())
+ {
+ const std::vector<TypeLoadFunctionPair> &flLoadFunctionVector = flLoadFunctionIter->second;
+ for (size_t i = 0; i < flLoadFunctionVector.size(); i++)
+ {
+ GLenum type = flLoadFunctionVector[i].first;
+ LoadImageFunction function = flLoadFunctionVector[i].second;
+ info.loadFunctions.insert(std::make_pair(type, function));
+ }
+ }
+
+ formatMap->insert(std::make_pair(internalFormat, info));
+}
+
+static inline void InsertD3D11_FL9_3_FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat)
+{
+ static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL9_3_LoadFunctionMap();
+ InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat);
+}
+
+static inline void InsertD3D11FormatInfo(D3D11ES3FormatMap *map, GLenum internalFormat, DXGI_FORMAT texFormat,
+ DXGI_FORMAT srvFormat, DXGI_FORMAT rtvFormat, DXGI_FORMAT dsvFormat)
+{
+ static const D3D11LoadFunctionMap flLoadFunctions = BuildD3D11_FL10_0Plus_LoadFunctionMap();
+ InsertD3D11FormatInfoBase(map, flLoadFunctions, internalFormat, texFormat, srvFormat, rtvFormat, dsvFormat);
+}
+
+static D3D11ES3FormatMap BuildD3D11_FL9_3FormatOverrideMap()
+{
+ // D3D11 Feature Level 9_3 doesn't support as many texture formats as Feature Level 10_0+.
+ // In particular, it doesn't support:
+ // - mipmaps on DXGI_FORMAT_A8_NORM
+ // - *_TYPELESS formats
+ // - DXGI_FORMAT_D32_FLOAT_S8X24_UINT or DXGI_FORMAT_D32_FLOAT
+
+ D3D11ES3FormatMap map;
+
+ // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT16, DXGI_FORMAT_D16_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D16_UNORM);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT24, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH_COMPONENT32F, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH24_STENCIL8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_DEPTH32F_STENCIL8, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN);
+ InsertD3D11_FL9_3_FormatInfo(&map, GL_STENCIL_INDEX8, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_D24_UNORM_S8_UINT);
+
+ return map;
}
static D3D11ES3FormatMap BuildD3D11FormatMap()
@@ -795,7 +963,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap()
// From GL_EXT_texture_storage
// | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format |
- InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
+ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN );
InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
@@ -846,9 +1014,21 @@ static D3D11ES3FormatMap BuildD3D11FormatMap()
return map;
}
-const TextureFormat &GetTextureFormatInfo(GLenum internalFormat)
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel)
{
static const D3D11ES3FormatMap formatMap = BuildD3D11FormatMap();
+ static const D3D11ES3FormatMap formatMapFL9_3Override = BuildD3D11_FL9_3FormatOverrideMap();
+
+ if (featureLevel == D3D_FEATURE_LEVEL_9_3)
+ {
+ // First see if the internalFormat has a special map for FL9_3
+ D3D11ES3FormatMap::const_iterator fl9_3Iter = formatMapFL9_3Override.find(internalFormat);
+ if (fl9_3Iter != formatMapFL9_3Override.end())
+ {
+ return fl9_3Iter->second;
+ }
+ }
+
D3D11ES3FormatMap::const_iterator iter = formatMap.find(internalFormat);
if (iter != formatMap.end())
{
@@ -897,6 +1077,68 @@ static void AddIntegerVertexFormatInfo(D3D11VertexFormatInfoMap *map, GLenum inp
map->insert(D3D11VertexFormatPair(inputFormat, info));
}
+static D3D11VertexFormatInfoMap BuildD3D11_FL9_3VertexFormatInfoOverrideMap()
+{
+ // D3D11 Feature Level 9_3 doesn't support as many formats for vertex buffer resource as Feature Level 10_0+.
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/ff471324(v=vs.85).aspx
+
+ D3D11VertexFormatInfoMap map;
+
+ // GL_BYTE -- unnormalized
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<1, 2>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &Copy8SintTo16SintVertexData<2, 2>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<3, 4>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &Copy8SintTo16SintVertexData<4, 4>);
+
+ // GL_BYTE -- normalized
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<1, 2>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &Copy8SnormTo16SnormVertexData<2, 2>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<3, 4>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &Copy8SnormTo16SnormVertexData<4, 4>);
+
+ // GL_UNSIGNED_BYTE -- unnormalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 1, 4, 1>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 2, 4, 1>);
+ // NOTE: 3 and 4 component unnormalized GL_UNSIGNED_BYTE should use the default format table.
+
+ // GL_UNSIGNED_BYTE -- normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 1, 4, UINT8_MAX>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 2, 4, UINT8_MAX>);
+ // NOTE: 3 and 4 component normalized GL_UNSIGNED_BYTE should use the default format table.
+
+ // GL_SHORT -- unnormalized
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ // NOTE: 2, 3 and 4 component unnormalized GL_SHORT should use the default format table.
+
+ // GL_SHORT -- normalized
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 1, 2, 0>);
+ // NOTE: 2, 3 and 4 component normalized GL_SHORT should use the default format table.
+
+ // GL_UNSIGNED_SHORT -- unnormalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, false>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, false>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, false>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, false>);
+
+ // GL_UNSIGNED_SHORT -- normalized
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 1, 2, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLushort, 2, 2, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLushort, 3, 3, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLushort, 4, 4, true>);
+
+ // GL_FIXED
+ // TODO: Add test to verify that this works correctly.
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<1, 2>);
+ // NOTE: 2, 3 and 4 component GL_FIXED should use the default format table.
+
+ // GL_FLOAT
+ // TODO: Add test to verify that this works correctly.
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 2, 0>);
+ // NOTE: 2, 3 and 4 component GL_FLOAT should use the default format table.
+
+ return map;
+}
+
static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap()
{
D3D11VertexFormatInfoMap map;
@@ -908,94 +1150,94 @@ static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap()
//
// GL_BYTE -- un-normalized
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
// GL_BYTE -- normalized
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 0>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 0>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, INT8_MAX>);
- AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SNORM, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SNORM, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 3, 4, INT8_MAX>);
+ AddVertexFormatInfo(&map, GL_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SNORM, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
// GL_UNSIGNED_BYTE -- un-normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
// GL_UNSIGNED_BYTE -- normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, UINT8_MAX>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UNORM, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UNORM, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 3, 4, UINT8_MAX>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_BYTE, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UNORM, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
// GL_SHORT -- un-normalized
- AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 1>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>);
// GL_SHORT -- normalized
- AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 0>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 0>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, INT16_MAX>);
- AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SNORM, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SNORM, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 3, 4, INT16_MAX>);
+ AddVertexFormatInfo(&map, GL_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SNORM, &CopyNativeVertexData<GLshort, 4, 4, 0>);
// GL_UNSIGNED_SHORT -- un-normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 3, VERTEX_CONVERT_BOTH, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>);
// GL_UNSIGNED_SHORT -- normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, UINT16_MAX>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UNORM, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UNORM, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 3, 4, UINT16_MAX>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_SHORT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UNORM, &CopyNativeVertexData<GLushort, 4, 4, 0>);
// GL_INT -- un-normalized
- AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>);
- AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>);
- AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>);
- AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>);
+ AddVertexFormatInfo(&map, GL_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>);
// GL_INT -- normalized
- AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, true>);
- AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, true>);
- AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, true>);
- AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLint, 1, 1, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLint, 2, 2, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLint, 3, 3, true>);
+ AddVertexFormatInfo(&map, GL_INT, GL_TRUE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLint, 4, 4, true>);
// GL_UNSIGNED_INT -- un-normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 0>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 1, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 2, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32_UINT, &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 3, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32_UINT, &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_FALSE, 4, VERTEX_CONVERT_GPU, DXGI_FORMAT_R32G32B32A32_UINT, &CopyNativeVertexData<GLuint, 4, 4, 0>);
// GL_UNSIGNED_INT -- normalized
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyTo32FVertexData<GLuint, 1, 1, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyTo32FVertexData<GLuint, 2, 2, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &CopyTo32FVertexData<GLuint, 3, 3, true>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyTo32FVertexData<GLuint, 4, 4, true>);
// GL_FIXED
- AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1>);
- AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2>);
- AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3>);
- AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 1, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32_FLOAT, &Copy32FixedTo32FVertexData<1, 1>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 2, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32_FLOAT, &Copy32FixedTo32FVertexData<2, 2>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32_FLOAT, &Copy32FixedTo32FVertexData<3, 3>);
+ AddVertexFormatInfo(&map, GL_FIXED, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &Copy32FixedTo32FVertexData<4, 4>);
// GL_HALF_FLOAT
- AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 0>);
- AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 0>);
- AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, gl::Float16One>);
- AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 0>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_FLOAT, &CopyNativeVertexData<GLhalf, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_FLOAT, &CopyNativeVertexData<GLhalf, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 3, 4, gl::Float16One>);
+ AddVertexFormatInfo(&map, GL_HALF_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_FLOAT, &CopyNativeVertexData<GLhalf, 4, 4, 0>);
// GL_FLOAT
- AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 0>);
- AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 0>);
- AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 0>);
- AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_FLOAT, &CopyNativeVertexData<GLfloat, 1, 1, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_FLOAT, &CopyNativeVertexData<GLfloat, 2, 2, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_FLOAT, &CopyNativeVertexData<GLfloat, 3, 3, 0>);
+ AddVertexFormatInfo(&map, GL_FLOAT, GL_FALSE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyNativeVertexData<GLfloat, 4, 4, 0>);
// GL_INT_2_10_10_10_REV
AddVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<true, false, true>);
@@ -1003,60 +1245,71 @@ static D3D11VertexFormatInfoMap BuildD3D11VertexFormatInfoMap()
// GL_UNSIGNED_INT_2_10_10_10_REV
AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_FALSE, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R32G32B32A32_FLOAT, &CopyXYZ10W2ToXYZW32FVertexData<false, false, true>);
- AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 0>);
+ AddVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UNORM, &CopyNativeVertexData<GLuint, 1, 1, 0>);
//
// Integer Formats
//
// GL_BYTE
- AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 1>);
- AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_SINT, &CopyNativeVertexData<GLbyte, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_SINT, &CopyNativeVertexData<GLbyte, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 3, 4, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_SINT, &CopyNativeVertexData<GLbyte, 4, 4, 0>);
// GL_UNSIGNED_BYTE
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 1>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8_UINT, &CopyNativeVertexData<GLubyte, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8_UINT, &CopyNativeVertexData<GLubyte, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 3, 4, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_BYTE, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R8G8B8A8_UINT, &CopyNativeVertexData<GLubyte, 4, 4, 0>);
// GL_SHORT
- AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 1>);
- AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_SINT, &CopyNativeVertexData<GLshort, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_SINT, &CopyNativeVertexData<GLshort, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 3, 4, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_SINT, &CopyNativeVertexData<GLshort, 4, 4, 0>);
// GL_UNSIGNED_SHORT
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 1>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16_UINT, &CopyNativeVertexData<GLushort, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16_UINT, &CopyNativeVertexData<GLushort, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 3, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 3, 4, 1>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_SHORT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R16G16B16A16_UINT, &CopyNativeVertexData<GLushort, 4, 4, 0>);
// GL_INT
- AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 0>);
- AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLint, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLint, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLint, 3, 3, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLint, 4, 4, 0>);
// GL_UNSIGNED_INT
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 0>);
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 1, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32_SINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 2, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32_SINT, &CopyNativeVertexData<GLuint, 2, 2, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 3, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32_SINT, &CopyNativeVertexData<GLuint, 3, 3, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R32G32B32A32_SINT, &CopyNativeVertexData<GLuint, 4, 4, 0>);
// GL_INT_2_10_10_10_REV
AddIntegerVertexFormatInfo(&map, GL_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_CPU, DXGI_FORMAT_R16G16B16A16_SINT, &CopyXYZ10W2ToXYZW32FVertexData<true, true, false>);
// GL_UNSIGNED_INT_2_10_10_10_REV
- AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 0>);
+ AddIntegerVertexFormatInfo(&map, GL_UNSIGNED_INT_2_10_10_10_REV, 4, VERTEX_CONVERT_NONE, DXGI_FORMAT_R10G10B10A2_UINT, &CopyNativeVertexData<GLuint, 1, 1, 0>);
return map;
}
-const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat)
+const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel)
{
static const D3D11VertexFormatInfoMap vertexFormatMap = BuildD3D11VertexFormatInfoMap();
+ static const D3D11VertexFormatInfoMap vertexFormatMapFL9_3Override = BuildD3D11_FL9_3VertexFormatInfoOverrideMap();
+
+ if (featureLevel == D3D_FEATURE_LEVEL_9_3)
+ {
+ // First see if the format has a special mapping for FL9_3
+ D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMapFL9_3Override.find(vertexFormat);
+ if (iter != vertexFormatMapFL9_3Override.end())
+ {
+ return iter->second;
+ }
+ }
D3D11VertexFormatInfoMap::const_iterator iter = vertexFormatMap.find(vertexFormat);
if (iter != vertexFormatMap.end())
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
index ea11aaa74c..33fe29dc39 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/formatutils11.h
@@ -7,10 +7,13 @@
// formatutils11.h: Queries for GL image formats and their translations to D3D11
// formats.
-#ifndef LIBGLESV2_RENDERER_FORMATUTILS11_H_
-#define LIBGLESV2_RENDERER_FORMATUTILS11_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
-#include "libGLESv2/formatutils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/angletypes.h"
+
+#include "common/platform.h"
#include <map>
@@ -30,6 +33,12 @@ struct DXGIFormat
GLuint blockWidth;
GLuint blockHeight;
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+ GLuint alphaBits;
+ GLuint sharedBits;
+
GLuint depthBits;
GLuint depthOffset;
GLuint stencilBits;
@@ -65,7 +74,7 @@ struct TextureFormat
typedef std::map<GLenum, LoadImageFunction> LoadFunctionMap;
LoadFunctionMap loadFunctions;
};
-const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
+const TextureFormat &GetTextureFormatInfo(GLenum internalFormat, D3D_FEATURE_LEVEL featureLevel);
struct VertexFormat
{
@@ -75,10 +84,10 @@ struct VertexFormat
DXGI_FORMAT nativeFormat;
VertexCopyFunction copyFunction;
};
-const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat);
+const VertexFormat &GetVertexFormatInfo(const gl::VertexFormat &vertexFormat, D3D_FEATURE_LEVEL featureLevel);
}
}
-#endif // LIBGLESV2_RENDERER_FORMATUTILS11_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_FORMATUTILS11_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
index 121aa3bbad..63085f497f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
@@ -7,12 +7,14 @@
// renderer11_utils.cpp: Conversion functions and other utility routines
// specific to the D3D11 renderer.
-#include "libGLESv2/renderer/d3d/d3d11/renderer11_utils.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/d3d11/RenderTarget11.h"
-#include "libGLESv2/renderer/Workarounds.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d11/renderer11_utils.h"
+#include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+#include "libANGLE/renderer/d3d/d3d11/RenderTarget11.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/Workarounds.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Framebuffer.h"
#include "common/debug.h"
@@ -96,6 +98,9 @@
#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
#endif
+#if defined(ANGLE_MINGW32_COMPAT)
+static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 };
+#endif
namespace rx
{
@@ -305,25 +310,47 @@ D3D11_QUERY ConvertQueryType(GLenum queryType)
namespace d3d11_gl
{
-static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, ID3D11Device *device)
+GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return 3;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 2;
+
+ default: UNREACHABLE(); return 0;
+ }
+}
+
+static gl::TextureCaps GenerateTextureFormatCaps(GLint maxClientVersion, GLenum internalFormat, ID3D11Device *device)
{
gl::TextureCaps textureCaps;
- const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::TextureFormat &formatInfo = d3d11::GetTextureFormatInfo(internalFormat, device->GetFeatureLevel());
UINT formatSupport;
if (SUCCEEDED(device->CheckFormatSupport(formatInfo.texFormat, &formatSupport)))
{
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(internalFormat);
+ if (internalFormatInfo.depthBits > 0 || internalFormatInfo.stencilBits > 0)
{
textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0);
}
else
{
- textureCaps.texturable = ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D) != 0) &&
- ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURECUBE) != 0) &&
- ((formatSupport & D3D11_FORMAT_SUPPORT_TEXTURE3D) != 0);
+ UINT formatSupportMask = D3D11_FORMAT_SUPPORT_TEXTURE2D | D3D11_FORMAT_SUPPORT_TEXTURECUBE;
+ if (maxClientVersion > 2)
+ {
+ formatSupportMask |= D3D11_FORMAT_SUPPORT_TEXTURE3D;
+ }
+ textureCaps.texturable = ((formatSupport & formatSupportMask) == formatSupportMask);
}
}
@@ -355,7 +382,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -365,7 +392,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
case D3D_FEATURE_LEVEL_9_3:
case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return true; // Provided that mipmaps & wrap modes are not used
+ case D3D_FEATURE_LEVEL_9_1: return false;
default: UNREACHABLE(); return false;
}
@@ -375,7 +402,7 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
@@ -397,7 +424,7 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -419,7 +446,7 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -439,12 +466,18 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+
+ // Feature Level 9_3 supports instancing, but slot 0 in the input layout must not be instanced.
+ // D3D9 has a similar restriction, where stream 0 must not be instanced.
+ // This restriction can be worked around by remapping any non-instanced slot to slot 0.
+ // This works because HLSL uses shader semantics to match the vertex inputs to the elements in the input layout, rather than the slots.
+ // Note that we only support instancing via ANGLE_instanced_array on 9_3, since 9_3 doesn't support OpenGL ES 3.0
case D3D_FEATURE_LEVEL_9_3: return true;
case D3D_FEATURE_LEVEL_9_2:
@@ -454,6 +487,44 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
}
}
+static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return false;
+
+ default: UNREACHABLE(); return false;
+ }
+}
+
+static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return false;
+
+ default: UNREACHABLE(); return false;
+ }
+}
+
static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
{
// http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588.aspx states that shader model
@@ -464,7 +535,7 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -478,13 +549,32 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
}
}
+static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
+{
+ switch (featureLevel)
+ {
+#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return false;
+
+ default: UNREACHABLE(); return false;
+ }
+}
+
static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel)
{
// From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476150.aspx ID3D11Device::CreateInputLayout
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
@@ -504,7 +594,7 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
@@ -524,7 +614,7 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
@@ -544,7 +634,7 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
@@ -564,7 +654,7 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
@@ -584,7 +674,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
@@ -592,7 +682,7 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
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
+ // No constants for D3D11 Feature Level 9 viewport size limits, use the maximum texture sizes
case D3D_FEATURE_LEVEL_9_3: return D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION;
case D3D_FEATURE_LEVEL_9_2:
case D3D_FEATURE_LEVEL_9_1: return D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION;
@@ -605,12 +695,12 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
{
// D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's
// returned from glGetInteger
- META_ASSERT(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32);
- META_ASSERT(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32);
+ static_assert(D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+ static_assert(D3D10_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -629,12 +719,12 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
{
// D3D11 allows up to 2^32 elements, but we report max signed int for convenience since that's what's
// returned from glGetInteger
- META_ASSERT(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32);
- META_ASSERT(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32);
+ static_assert(D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
+ static_assert(D3D10_REQ_DRAW_VERTEX_COUNT_2_TO_EXP == 32, "Unexpected D3D11 constant value.");
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -653,7 +743,7 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
@@ -675,7 +765,7 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
// TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
@@ -702,7 +792,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
@@ -710,7 +800,7 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
- // Uniform blocks not supported in D3D9 feature levels
+ // Uniform blocks not supported on D3D11 Feature Level 9
case D3D_FEATURE_LEVEL_9_3:
case D3D_FEATURE_LEVEL_9_2:
case D3D_FEATURE_LEVEL_9_1: return 0;
@@ -719,30 +809,55 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
}
}
-static size_t GetReservedVertexOutputVectors()
+static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
{
- // We potentially reserve varyings for gl_Position, dx_Position, gl_FragCoord and gl_PointSize
- return 4;
+ // According to The OpenGL ES Shading Language specifications
+ // (Language Version 1.00 section 10.16, Language Version 3.10 section 12.21)
+ // built-in special variables (e.g. gl_FragCoord, or gl_PointCoord)
+ // which are statically used in the shader should be included in the variable packing algorithm.
+ // Therefore, we should not reserve output vectors for them.
+
+ switch (featureLevel)
+ {
+ // We must reserve one output vector for dx_Position.
+ // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+,
+ // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved.
+#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
+#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return 2;
+
+ // Just reserve dx_Position on Feature Level 9, since we don't ever need to output gl_Position.
+ case D3D_FEATURE_LEVEL_9_3:
+ case D3D_FEATURE_LEVEL_9_2:
+ case D3D_FEATURE_LEVEL_9_1: return 1;
+
+ default: UNREACHABLE(); return 0;
+ }
+
+ return 1;
}
static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
{
- META_ASSERT(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT);
+ static_assert(gl::IMPLEMENTATION_MAX_VARYING_VECTORS == D3D11_VS_OUTPUT_REGISTER_COUNT, "Unexpected D3D11 constant value.");
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
- case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- // Use D3D9 SM3 and SM2 limits
- case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors();
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3:
case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel);
default: UNREACHABLE(); return 0;
}
@@ -752,7 +867,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
@@ -760,7 +875,7 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_SAMPLER_SLOT_COUNT;
- // Vertex textures not supported in D3D9 feature levels according to
+ // Vertex textures not supported on D3D11 Feature Level 9 according to
// http://msdn.microsoft.com/en-us/library/windows/desktop/ff476149.aspx
// ID3D11DeviceContext::VSSetSamplers and ID3D11DeviceContext::VSSetShaderResources
case D3D_FEATURE_LEVEL_9_3:
@@ -776,7 +891,7 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
// TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
@@ -803,7 +918,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
@@ -811,7 +926,7 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
case D3D_FEATURE_LEVEL_10_1:
case D3D_FEATURE_LEVEL_10_0: return D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
- // Uniform blocks not supported in D3D9 feature levels
+ // Uniform blocks not supported on D3D11 Feature Level 9
case D3D_FEATURE_LEVEL_9_3:
case D3D_FEATURE_LEVEL_9_2:
case D3D_FEATURE_LEVEL_9_1: return 0;
@@ -824,18 +939,18 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_10_0: return D3D10_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
- // Use D3D9 SM3 and SM2 limits
- case D3D_FEATURE_LEVEL_9_3: return 10 - GetReservedVertexOutputVectors();
+ // Use Shader Model 2.X limits
+ case D3D_FEATURE_LEVEL_9_3: return 8 - GetReservedVertexOutputVectors(featureLevel);
case D3D_FEATURE_LEVEL_9_2:
- case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors();
+ case D3D_FEATURE_LEVEL_9_1: return 8 - GetReservedVertexOutputVectors(featureLevel);
default: UNREACHABLE(); return 0;
}
@@ -845,7 +960,7 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
@@ -866,7 +981,7 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
@@ -887,7 +1002,7 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
@@ -912,7 +1027,7 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
@@ -933,7 +1048,7 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
@@ -953,7 +1068,7 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0:
@@ -973,7 +1088,7 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature
{
switch (featureLevel)
{
-#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+#if defined(ANGLE_ENABLE_D3D11_1)
case D3D_FEATURE_LEVEL_11_1:
#endif
case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
@@ -992,13 +1107,15 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature
}
}
-void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions)
{
+ D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel();
+
GLuint maxSamples = 0;
const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
for (gl::FormatSet::const_iterator internalFormat = allFormats.begin(); internalFormat != allFormats.end(); ++internalFormat)
{
- gl::TextureCaps textureCaps = GenerateTextureFormatCaps(*internalFormat, device);
+ gl::TextureCaps textureCaps = GenerateTextureFormatCaps(GetMaximumClientVersion(featureLevel), *internalFormat, device);
textureCapsMap->insert(*internalFormat, textureCaps);
maxSamples = std::max(maxSamples, textureCaps.getMaxSamples());
@@ -1009,8 +1126,6 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
}
}
- D3D_FEATURE_LEVEL featureLevel = device->GetFeatureLevel();
-
// GL core feature limits
caps->maxElementIndex = static_cast<GLint64>(std::numeric_limits<unsigned int>::max());
caps->max3DTextureSize = GetMaximum3DTextureSize(featureLevel);
@@ -1048,6 +1163,21 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
// Program and shader binary formats (no supported shader binary formats)
caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+ caps->vertexHighpFloat.setIEEEFloat();
+ caps->vertexMediumpFloat.setIEEEFloat();
+ caps->vertexLowpFloat.setIEEEFloat();
+ caps->fragmentHighpFloat.setIEEEFloat();
+ caps->fragmentMediumpFloat.setIEEEFloat();
+ caps->fragmentLowpFloat.setIEEEFloat();
+
+ // 32-bit integers are natively supported
+ caps->vertexHighpInt.setTwosComplementInt(32);
+ caps->vertexMediumpInt.setTwosComplementInt(32);
+ caps->vertexLowpInt.setTwosComplementInt(32);
+ caps->fragmentHighpInt.setTwosComplementInt(32);
+ caps->fragmentMediumpInt.setTwosComplementInt(32);
+ caps->fragmentLowpInt.setTwosComplementInt(32);
+
// We do not wait for server fence objects internally, so report a max timeout of zero.
caps->maxServerWaitTimeout = 0;
@@ -1074,6 +1204,24 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
// Setting a large alignment forces uniform buffers to bind with zero offset
caps->uniformBufferOffsetAlignment = static_cast<GLuint>(std::numeric_limits<GLint>::max());
+#if defined(ANGLE_ENABLE_D3D11_1)
+ ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(deviceContext);
+
+ if (deviceContext1)
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+
+ if (d3d11Options.ConstantBufferOffsetting)
+ {
+ // With DirectX 11.1, constant buffer offset and size must be a multiple of 16 constants of 16 bytes each.
+ // https://msdn.microsoft.com/en-us/library/windows/desktop/hh404649%28v=vs.85%29.aspx
+ caps->uniformBufferOffsetAlignment = 256;
+ }
+
+ SafeRelease(deviceContext1);
+ }
+#endif
caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
@@ -1109,13 +1257,13 @@ void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *text
extensions->timerQuery = false; // Unimplemented
extensions->robustness = true;
extensions->blendMinMax = true;
- extensions->framebufferBlit = true;
- extensions->framebufferMultisample = true;
+ extensions->framebufferBlit = GetFramebufferBlitSupport(featureLevel);
+ extensions->framebufferMultisample = GetFramebufferMultisampleSupport(featureLevel);
extensions->maxSamples = maxSamples;
extensions->instancedArrays = GetInstancingSupport(featureLevel);
extensions->packReverseRowOrder = true;
extensions->standardDerivatives = GetDerivativeInstructionSupport(featureLevel);
- extensions->shaderTextureLOD = true;
+ extensions->shaderTextureLOD = GetShaderTextureLODSupport(featureLevel);
extensions->fragDepth = true;
extensions->textureUsage = true; // This could be false since it has no effect in D3D11
extensions->translatedShaderSource = true;
@@ -1145,11 +1293,11 @@ void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsi
*levelOffset = upsampleCount;
}
-void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth,
+void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth,
GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
std::vector< std::vector<BYTE> > *outData)
{
- const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat);
+ const d3d11::TextureFormat &d3dFormatInfo = d3d11::GetTextureFormatInfo(internalFormat, featureLevel);
ASSERT(d3dFormatInfo.dataInitializerFunction != NULL);
const d3d11::DXGIFormat &dxgiFormatInfo = d3d11::GetDXGIFormatInfo(d3dFormatInfo.texFormat);
@@ -1196,16 +1344,16 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
{
-#if defined(_DEBUG) && !defined(__MINGW32__)
+#if defined(_DEBUG)
return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
#else
return S_OK;
#endif
}
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT)
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT)
{
- RenderTarget *renderTarget = NULL;
+ RenderTargetD3D *renderTarget = NULL;
gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
if (error.isError())
{
@@ -1215,11 +1363,13 @@ gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, Rende
return gl::Error(GL_NO_ERROR);
}
-Workarounds GenerateWorkarounds()
+Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel)
{
Workarounds workarounds;
workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = true;
+ workarounds.zeroMaxLodWorkaround = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
+ workarounds.useInstancedPointSpriteEmulation = (featureLevel <= D3D_FEATURE_LEVEL_9_3);
return workarounds;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
index 9df9c95763..207e6b5404 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h
@@ -7,12 +7,12 @@
// 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
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
#include <vector>
@@ -50,7 +50,8 @@ D3D11_QUERY ConvertQueryType(GLenum queryType);
namespace d3d11_gl
{
-void GenerateCaps(ID3D11Device *device, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
+GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel);
+void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::Caps *caps, gl::TextureCapsMap *textureCapsMap, gl::Extensions *extensions);
}
@@ -59,7 +60,7 @@ namespace d3d11
void MakeValidSize(bool isImage, DXGI_FORMAT format, GLsizei *requestWidth, GLsizei *requestHeight, int *levelOffset);
-void GenerateInitialTextureData(GLint internalFormat, GLuint width, GLuint height, GLuint depth,
+void GenerateInitialTextureData(GLint internalFormat, D3D_FEATURE_LEVEL featureLevel, GLuint width, GLuint height, GLuint depth,
GLuint mipLevels, std::vector<D3D11_SUBRESOURCE_DATA> *outSubresourceData,
std::vector< std::vector<BYTE> > *outData);
@@ -178,12 +179,12 @@ inline void SetBufferData(ID3D11DeviceContext *context, ID3D11Buffer *constantBu
context->Unmap(constantBuffer, 0);
}
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget11 **outRT);
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget11 **outRT);
-Workarounds GenerateWorkarounds();
+Workarounds GenerateWorkarounds(D3D_FEATURE_LEVEL featureLevel);
}
}
-#endif // LIBGLESV2_RENDERER_RENDERER11_UTILS_H
+#endif // LIBANGLE_RENDERER_D3D_D3D11_RENDERER11_UTILS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
index 20e6623a30..c43734f6a3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
@@ -26,6 +26,7 @@ cbuffer BufferCopyParams : register(b0)
float2 PositionScale;
int2 TexLocationOffset;
int2 TexLocationScale;
+ uint FirstSlice;
}
void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex)
@@ -42,7 +43,7 @@ void ComputePositionAndIndex(uint vertexID, out VS_OUTPUT outVertex)
outVertex.position = float4(PositionOffset + PositionScale * coords, 0.0f, 1.0f);
outVertex.index = FirstPixelOffset + slice * SliceStride + row * RowStride + col;
- outVertex.slice = slice;
+ outVertex.slice = FirstSlice + slice;
}
void VS_BufferToTexture(in uint vertexID : SV_VertexID, out VS_OUTPUT outVertex)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
index b4cf38076e..2b3e1ebe4c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
@@ -13,12 +13,10 @@ struct PS_OutputFloat
float4 color1 : SV_TARGET1;
float4 color2 : SV_TARGET2;
float4 color3 : SV_TARGET3;
-#if SM4
float4 color4 : SV_TARGET4;
float4 color5 : SV_TARGET5;
float4 color6 : SV_TARGET6;
float4 color7 : SV_TARGET7;
-#endif
};
PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
@@ -28,15 +26,30 @@ PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inCol
outColor.color1 = inColor;
outColor.color2 = inColor;
outColor.color3 = inColor;
-#if SM4
outColor.color4 = inColor;
outColor.color5 = inColor;
outColor.color6 = inColor;
outColor.color7 = inColor;
-#endif
return outColor;
}
+struct PS_OutputFloat_FL9
+{
+ float4 color0 : SV_TARGET0;
+ float4 color1 : SV_TARGET1;
+ float4 color2 : SV_TARGET2;
+ float4 color3 : SV_TARGET3;
+};
+
+PS_OutputFloat_FL9 PS_ClearFloat_FL9(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
+{
+ PS_OutputFloat_FL9 outColor;
+ outColor.color0 = inColor;
+ outColor.color1 = inColor;
+ outColor.color2 = inColor;
+ outColor.color3 = inColor;
+ return outColor;
+}
void VS_ClearUint( in float3 inPosition : POSITION, in uint4 inColor : COLOR,
out float4 outPosition : SV_POSITION, out uint4 outColor : COLOR)
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
index 8671c39fb7..8671c39fb7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
index c23c9032ec..c23c9032ec 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
index 505e222137..505e222137 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
index 46082a2e28..9d8f0bb96c 100644
--- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp
@@ -6,17 +6,14 @@
// NativeWindow.cpp: Handler for managing HWND native window types.
-#include "common/NativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
+
#include "common/debug.h"
namespace rx
{
-bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
-{
- return (IsWindow(window) == TRUE);
-}
-NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
+NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window)
{
}
@@ -35,7 +32,12 @@ bool NativeWindow::isIconic()
return IsIconic(mWindow) == TRUE;
}
-HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory,
+bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsWindow(window) == TRUE;
+}
+
+HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
DXGI_FORMAT format, unsigned int width, unsigned int height,
DXGISwapChain** swapChain)
{
diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
index 9b65c15625..350526c867 100644
--- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
@@ -6,25 +6,22 @@
// CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
-#include <algorithm>
-#include "common/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+
using namespace ABI::Windows::Foundation::Collections;
namespace rx
{
-
-typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
-
CoreWindowNativeWindow::~CoreWindowNativeWindow()
{
unregisterForSizeChangeEvents();
}
-bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
{
+ mOrientationChangedEventToken.value = 0;
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
- ComPtr<IInspectable> displayInformation = display;
SIZE swapChainSize = {};
bool swapChainSizeSpecified = false;
HRESULT result = S_OK;
@@ -51,29 +48,6 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis
if (SUCCEEDED(result))
{
- result = displayInformation.As(&mDisplayInformation);
- }
-
- if (SUCCEEDED(result))
- {
-#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
- ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
- result = mDisplayInformation.As(&displayInformation2);
- ASSERT(SUCCEEDED(result));
-
- result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
- ASSERT(SUCCEEDED(result));
-#else
- ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
- result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
- ASSERT(SUCCEEDED(result));
-
- mScaleFactor = DOUBLE(resolutionScale) / 100.0;
-#endif
- }
-
- if (SUCCEEDED(result))
- {
// If a swapchain size is specfied, then the automatic resize
// behaviors implemented by the host should be disabled. The swapchain
// will be still be scaled when being rendered to fit the bounds
@@ -87,14 +61,17 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis
}
else
{
- ABI::Windows::Foundation::Rect rect;
- HRESULT result = mCoreWindow->get_Bounds(&rect);
- if (SUCCEEDED(result))
- {
- LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
- LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
- mClientRect = { 0, 0, width, height };
- }
+ result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect);
+ }
+ }
+
+ if (SUCCEEDED(result))
+ {
+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation;
+ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation);
+ if (SUCCEEDED(result))
+ {
+ result = displayInformation->GetForCurrentView(&mDisplayInformation);
}
}
@@ -110,8 +87,21 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDis
bool CoreWindowNativeWindow::registerForSizeChangeEvents()
{
- HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
- &mSizeChangedEventToken);
+ ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler;
+ HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
+ if (SUCCEEDED(result))
+ {
+ result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+ }
+
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler;
+ result = sizeChangedHandler.As(&orientationChangedHandler);
+ if (SUCCEEDED(result))
+ {
+ result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
+ }
+#endif
if (SUCCEEDED(result))
{
@@ -127,7 +117,14 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
{
(void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
}
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ if (mDisplayInformation)
+ {
+ (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken);
+ }
+#endif
mSizeChangedEventToken.value = 0;
+ mOrientationChangedEventToken.value = 0;
}
HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
@@ -156,7 +153,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
if (SUCCEEDED(result))
{
-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
+#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain.
// Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
// other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
// (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
@@ -182,19 +179,36 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
return result;
}
-// Basically, this shouldn't be used on Phone
-HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize)
{
- ABI::Windows::Foundation::Size size;
- if (SUCCEEDED(e->get_Size(&size)))
+ ABI::Windows::Foundation::Rect bounds;
+ HRESULT result = coreWindow->get_Bounds(&bounds);
+ if (SUCCEEDED(result))
{
- SIZE windowSizeInPixels = {
- std::floor(size.Width * mScaleFactor + 0.5),
- std::floor(size.Height * mScaleFactor + 0.5)
- };
- setNewClientSize(windowSizeInPixels);
+ *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) };
}
- return S_OK;
+ return result;
+}
+
+static float GetLogicalDpi()
+{
+ ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
+ float dpi = 96.0f;
+
+ if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
+ {
+ if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
+ {
+ return dpi;
+ }
+ }
+ return dpi;
+}
+
+long ConvertDipsToPixels(float dips)
+{
+ static const float dipsPerInch = 96.0f;
+ return lround((dips * GetLogicalDpi() / dipsPerInch));
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
new file mode 100644
index 0000000000..59df9d5a6c
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
@@ -0,0 +1,110 @@
+//
+// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// CoreWindowNativeWindow.h: NativeWindow for managing ICoreWindow native window types.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+#include <memory>
+#include <windows.graphics.display.h>
+
+typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
+typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler;
+
+namespace rx
+{
+long ConvertDipsToPixels(float dips);
+
+class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
+{
+ public:
+ ~CoreWindowNativeWindow();
+
+ bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
+ bool registerForSizeChangeEvents();
+ void unregisterForSizeChangeEvents();
+ HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
+
+ private:
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
+ EventRegistrationToken mOrientationChangedEventToken;
+};
+
+[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
+class CoreWindowSizeChangedHandler :
+ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler>
+{
+ public:
+ CoreWindowSizeChangedHandler() { }
+ HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
+ {
+ if (!host)
+ {
+ return E_INVALIDARG;
+ }
+
+ mHost = host;
+ return S_OK;
+ }
+
+ // IWindowSizeChangedEventHandler
+ IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs)
+ {
+ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+ if (host)
+ {
+ ABI::Windows::Foundation::Size windowSize;
+ if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
+ {
+ SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
+ host->setNewClientSize(windowSizeInPixels);
+ }
+ }
+
+ return S_OK;
+ }
+
+ IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *)
+ {
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+ NativeWindow::RotationFlags flags = NativeWindow::RotateNone;
+ ABI::Windows::Graphics::Display::DisplayOrientations orientation;
+ if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation)))
+ {
+ switch (orientation)
+ {
+ case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape:
+ flags = NativeWindow::RotateLeft;
+ break;
+ case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped:
+ flags = NativeWindow::RotateRight;
+ break;
+ default:
+ break;
+ }
+ }
+ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
+ if (host)
+ {
+ host->setRotationFlags(flags);
+ }
+#endif
+ return S_OK;
+ }
+
+ private:
+ std::weak_ptr<InspectableNativeWindow> mHost;
+};
+
+HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize);
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_COREWINDOWNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
index 0589f6dce5..2bf48c5d94 100644
--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
@@ -6,14 +6,14 @@
// InspectableNativeWindow.cpp: NativeWindow base class for managing IInspectable native window types.
-#include "common/winrt/CoreWindowNativeWindow.h"
-#include "common/winrt/SwapChainPanelNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
namespace rx
{
-NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
- : mWindow(window), mDisplay(display)
+NativeWindow::NativeWindow(EGLNativeWindowType window)
{
+ mWindow = window;
}
bool NativeWindow::initialize()
@@ -40,7 +40,7 @@ bool NativeWindow::initialize()
mImpl = std::make_shared<CoreWindowNativeWindow>();
if (mImpl)
{
- return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+ return mImpl->initialize(mWindow, propertySet.Get());
}
}
else if (IsSwapChainPanel(mWindow, &swapChainPanel))
@@ -48,7 +48,7 @@ bool NativeWindow::initialize()
mImpl = std::make_shared<SwapChainPanelNativeWindow>();
if (mImpl)
{
- return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
+ return mImpl->initialize(mWindow, propertySet.Get());
}
}
else
@@ -69,11 +69,28 @@ bool NativeWindow::getClientRect(RECT *rect)
return false;
}
+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
+NativeWindow::RotationFlags NativeWindow::rotationFlags() const
+{
+ if (mImpl)
+ {
+ return mImpl->rotationFlags();
+ }
+
+ return NativeWindow::RotateNone;
+}
+#endif
+
bool NativeWindow::isIconic()
{
return false;
}
+bool NativeWindow::isValidNativeWindow(EGLNativeWindowType window)
+{
+ return IsValidEGLNativeWindowType(window);
+}
+
HRESULT NativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
{
if (mImpl)
diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
index 402941a788..575bdf8a58 100644
--- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
@@ -7,11 +7,13 @@
// InspectableNativeWindow.h: Host specific implementation interface for
// managing IInspectable native window types.
-#ifndef COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
-#define COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
+
+#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
#include "common/platform.h"
-#include "common/NativeWindow.h"
+
#include "angle_windowsstore.h"
#include <windows.ui.xaml.h>
@@ -33,13 +35,13 @@ class InspectableNativeWindow
mClientRectChanged(false),
mClientRect({0,0,0,0}),
mNewClientRect({0,0,0,0}),
- mScaleFactor(1.0)
+ mRotationFlags(NativeWindow::RotateNone)
{
mSizeChangedEventToken.value = 0;
}
virtual ~InspectableNativeWindow(){}
- virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
+ virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
virtual bool registerForSizeChangeEvents() = 0;
virtual void unregisterForSizeChangeEvents() = 0;
@@ -50,7 +52,6 @@ class InspectableNativeWindow
if (mClientRectChanged && mSupportsSwapChainResize)
{
mClientRect = mNewClientRect;
- mClientRectChanged = false;
}
*rect = mClientRect;
@@ -72,20 +73,33 @@ class InspectableNativeWindow
}
}
+ NativeWindow::RotationFlags rotationFlags() const
+ {
+ return mRotationFlags;
+ }
+
+ void setRotationFlags(NativeWindow::RotationFlags flags)
+ {
+ mRotationFlags = flags;
+ }
+
protected:
bool mSupportsSwapChainResize;
bool mRequiresSwapChainScaling;
RECT mClientRect;
RECT mNewClientRect;
bool mClientRectChanged;
- DOUBLE mScaleFactor;
+ NativeWindow::RotationFlags mRotationFlags;
EventRegistrationToken mSizeChangedEventToken;
};
+bool IsValidEGLNativeWindowType(EGLNativeWindowType window);
bool IsCoreWindow(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Core::ICoreWindow> *coreWindow = nullptr);
bool IsSwapChainPanel(EGLNativeWindowType window, ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> *swapChainPanel = nullptr);
bool IsEGLConfiguredPropertySet(EGLNativeWindowType window, ABI::Windows::Foundation::Collections::IPropertySet **propertySet = nullptr, IInspectable **inspectable = nullptr);
HRESULT GetOptionalSizePropertyValue(const ComPtr<ABI::Windows::Foundation::Collections::IMap<HSTRING, IInspectable*>>& propertyMap, const wchar_t *propertyName, SIZE *value, bool *valueExists);
+
}
-#endif // COMMON_WINRT_INSPECTABLENATIVEWINDOW_H_
+
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_INSPECTABLENATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
index 268dfbd8f0..53899dbb30 100644
--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
@@ -6,9 +6,11 @@
// SwapChainPanelNativeWindow.cpp: NativeWindow for managing ISwapChainPanel native window types.
-#include "common/winrt/SwapChainPanelNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h"
+
#include <algorithm>
#include <math.h>
+
using namespace ABI::Windows::Foundation::Collections;
namespace rx
@@ -18,7 +20,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
unregisterForSizeChangeEvents();
}
-bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
{
ComPtr<IPropertySet> props = propertySet;
ComPtr<IInspectable> win = window;
diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
index 5bbf274e64..caf327d913 100644
--- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
@@ -6,10 +6,10 @@
// SwapChainPanelNativeWindow.h: NativeWindow for managing ISwapChainPanel native window types.
-#ifndef COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
-#define COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#define LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
-#include "common/winrt/InspectableNativeWindow.h"
+#include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
namespace rx
{
@@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
public:
~SwapChainPanelNativeWindow();
- bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
+ bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
bool registerForSizeChangeEvents();
void unregisterForSizeChangeEvents();
HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
@@ -76,4 +76,4 @@ class SwapChainPanelSizeChangedHandler :
HRESULT GetSwapChainPanelSize(const ComPtr<ABI::Windows::UI::Xaml::Controls::ISwapChainPanel> &swapChainPanel, RECT *windowSize);
}
-#endif // COMMON_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D11_WINRT_SWAPCHAINPANELNATIVEWINDOW_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
index 2ca7a9cf8a..a0bc2960b7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp
@@ -6,41 +6,41 @@
// Blit9.cpp: Surface copy utility class.
-#include "libGLESv2/renderer/d3d/d3d9/Blit9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
namespace
{
// Precompiled shaders
-#include "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"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/standardvs.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/flipyvs.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/passthroughps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/luminanceps.h"
+#include "libANGLE/renderer/d3d/d3d9/shaders/compiled/componentmaskps.h"
const BYTE* const g_shaderCode[] =
{
- g_vs20_VS_standard,
- g_vs20_VS_flipy,
- g_ps20_PS_passthrough,
- g_ps20_PS_luminance,
- g_ps20_PS_componentmask
+ g_vs20_standardvs,
+ g_vs20_flipyvs,
+ g_ps20_passthroughps,
+ g_ps20_luminanceps,
+ g_ps20_componentmaskps
};
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)
+ sizeof(g_vs20_standardvs),
+ sizeof(g_vs20_flipyvs),
+ sizeof(g_ps20_passthroughps),
+ sizeof(g_ps20_luminanceps),
+ sizeof(g_ps20_componentmaskps)
};
}
@@ -217,7 +217,7 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
device->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
device->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
- setViewport(getSurfaceRect(dest), 0, 0);
+ setViewport(getSurfaceRect(dest), gl::Offset(0, 0, 0));
render();
@@ -228,7 +228,7 @@ gl::Error Blit9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
return gl::Error(GL_NO_ERROR);
}
-gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Blit9::copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
gl::Error error = initialize();
if (error.isError())
@@ -259,7 +259,7 @@ gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GL
}
ASSERT(destSurface);
- gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
+ gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
SafeRelease(destSurface);
SafeRelease(source);
@@ -267,7 +267,7 @@ gl::Error Blit9::copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GL
return result;
}
-gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Blit9::copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
{
gl::Error error = initialize();
if (error.isError())
@@ -298,7 +298,7 @@ gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect,
}
ASSERT(destSurface);
- gl::Error result = copy(source, sourceRect, destFormat, xoffset, yoffset, destSurface);
+ gl::Error result = copy(source, sourceRect, destFormat, destOffset, destSurface);
SafeRelease(destSurface);
SafeRelease(source);
@@ -306,7 +306,7 @@ gl::Error Blit9::copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect,
return result;
}
-gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
{
ASSERT(source != NULL && dest != NULL);
@@ -320,7 +320,7 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum
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)};
+ RECT destRect = { destOffset.x, destOffset.y, destOffset.x + (sourceRect.right - sourceRect.left), destOffset.y + (sourceRect.bottom - sourceRect.top)};
HRESULT result = device->StretchRect(source, &sourceRect, dest, &destRect, D3DTEXF_POINT);
if (FAILED(result))
@@ -333,11 +333,11 @@ gl::Error Blit9::copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum
}
else
{
- return formatConvert(source, sourceRect, destFormat, xoffset, yoffset, dest);
+ return formatConvert(source, sourceRect, destFormat, destOffset, dest);
}
}
-gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest)
+gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest)
{
gl::Error error = initialize();
if (error.isError())
@@ -359,7 +359,7 @@ gl::Error Blit9::formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect
device->SetTexture(0, texture);
device->SetRenderTarget(0, dest);
- setViewport(sourceRect, xoffset, yoffset);
+ setViewport(sourceRect, destOffset);
setCommonBlitState();
@@ -548,13 +548,13 @@ gl::Error Blit9::copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &so
return gl::Error(GL_NO_ERROR);
}
-void Blit9::setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset)
+void Blit9::setViewport(const RECT &sourceRect, const gl::Offset &offset)
{
IDirect3DDevice9 *device = mRenderer->getDevice();
D3DVIEWPORT9 vp;
- vp.X = xoffset;
- vp.Y = yoffset;
+ vp.X = offset.x;
+ vp.Y = offset.y;
vp.Width = sourceRect.right - sourceRect.left;
vp.Height = sourceRect.bottom - sourceRect.top;
vp.MinZ = 0.0f;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
index 5c7a76ce05..586abd2580 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Blit9.h
@@ -6,17 +6,18 @@
// Blit9.cpp: Surface copy utility class.
-#ifndef LIBGLESV2_BLIT9_H_
-#define LIBGLESV2_BLIT9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
#include "common/angleutils.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include <GLES2/gl2.h>
namespace gl
{
class Framebuffer;
+struct Offset;
}
namespace rx
@@ -24,7 +25,7 @@ namespace rx
class Renderer9;
class TextureStorage;
-class Blit9
+class Blit9 : angle::NonCopyable
{
public:
explicit Blit9(Renderer9 *renderer);
@@ -34,13 +35,13 @@ class Blit9
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
- gl::Error copy2D(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
- gl::Error copyCube(gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
+ gl::Error copy2D(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ gl::Error copyCube(const gl::Framebuffer *framebuffer, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
// Copy from source surface to dest surface.
// sourceRect, xoffset, yoffset are in D3D coordinates (0,0 in upper-left)
// source is interpreted as RGBA and destFormat specifies the desired result format. For example, if destFormat = GL_RGB, the alpha channel will be forced to 0.
- gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+ gl::Error formatConvert(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
// 2x2 box filter sample from source to dest.
// Requires that source is RGB(A) and dest has the same format as source.
@@ -55,9 +56,9 @@ class Blit9
gl::Error setFormatConvertShaders(GLenum destFormat);
- gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, GLint xoffset, GLint yoffset, IDirect3DSurface9 *dest);
+ gl::Error copy(IDirect3DSurface9 *source, const RECT &sourceRect, GLenum destFormat, const gl::Offset &destOffset, IDirect3DSurface9 *dest);
gl::Error copySurfaceToTexture(IDirect3DSurface9 *surface, const RECT &sourceRect, IDirect3DTexture9 **outTexture);
- void setViewport(const RECT &sourceRect, GLint xoffset, GLint yoffset);
+ void setViewport(const RECT &sourceRect, const gl::Offset &offset);
void setCommonBlitState();
RECT getSurfaceRect(IDirect3DSurface9 *surface) const;
@@ -89,9 +90,8 @@ class Blit9
IDirect3DStateBlock9 *mSavedStateBlock;
IDirect3DSurface9 *mSavedRenderTarget;
IDirect3DSurface9 *mSavedDepthStencil;
-
- DISALLOW_COPY_AND_ASSIGN(Blit9);
};
+
}
-#endif // LIBGLESV2_BLIT9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BLIT9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
index 430fe81e50..b051c81aa8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp
@@ -6,15 +6,14 @@
// Buffer9.cpp Defines the Buffer9 class.
-#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
Buffer9::Buffer9(Renderer9 *renderer)
- : BufferD3D(),
+ : BufferD3D(renderer),
mRenderer(renderer),
mSize(0)
{}
@@ -114,9 +113,4 @@ void Buffer9::markTransformFeedbackUsage()
UNREACHABLE();
}
-RendererD3D *Buffer9::getRenderer()
-{
- return mRenderer;
-}
-
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
index c80b009738..c1984146fc 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Buffer9.h
@@ -6,12 +6,12 @@
// Buffer9.h: Defines the rx::Buffer9 class which implements rx::BufferImpl via rx::BufferD3D.
-#ifndef LIBGLESV2_RENDERER_BUFFER9_H_
-#define LIBGLESV2_RENDERER_BUFFER9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/renderer/d3d/MemoryBuffer.h"
-#include "libGLESv2/angletypes.h"
+#include "common/MemoryBuffer.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
namespace rx
{
@@ -28,7 +28,6 @@ class Buffer9 : public BufferD3D
// BufferD3D implementation
virtual size_t getSize() const { return mSize; }
virtual bool supportsDirectBinding() const { return false; }
- RendererD3D *getRenderer() override;
// BufferImpl implementation
virtual gl::Error setData(const void* data, size_t size, GLenum usage);
@@ -40,8 +39,6 @@ class Buffer9 : public BufferD3D
virtual void markTransformFeedbackUsage();
private:
- DISALLOW_COPY_AND_ASSIGN(Buffer9);
-
Renderer9 *mRenderer;
MemoryBuffer mMemory;
size_t mSize;
@@ -49,4 +46,4 @@ class Buffer9 : public BufferD3D
}
-#endif // LIBGLESV2_RENDERER_BUFFER9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_BUFFER9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
new file mode 100644
index 0000000000..09b229bcb1
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp
@@ -0,0 +1,36 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+
+#include "common/platform.h"
+
+namespace rx
+{
+
+void DebugAnnotator9::beginEvent(const std::wstring &eventName)
+{
+ D3DPERF_BeginEvent(0, eventName.c_str());
+}
+
+void DebugAnnotator9::endEvent()
+{
+ D3DPERF_EndEvent();
+}
+
+void DebugAnnotator9::setMarker(const std::wstring &markerName)
+{
+ D3DPERF_SetMarker(0, markerName.c_str());
+}
+
+bool DebugAnnotator9::getStatus()
+{
+ return !!D3DPERF_GetStatus();
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
new file mode 100644
index 0000000000..02956f7183
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h
@@ -0,0 +1,29 @@
+//
+// Copyright 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// DebugAnnotator9.h: D3D9 helpers for adding trace annotations.
+//
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
+
+#include "common/debug.h"
+
+namespace rx
+{
+
+class DebugAnnotator9 : public gl::DebugAnnotator
+{
+ public:
+ DebugAnnotator9() {}
+ void beginEvent(const std::wstring &eventName) override;
+ void endEvent() override;
+ void setMarker(const std::wstring &markerName) override;
+ bool getStatus() override;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_DEBUGANNOTATOR9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
index 66263fe110..27c265e28d 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp
@@ -6,10 +6,9 @@
// Fence9.cpp: Defines the rx::FenceNV9 class.
-#include "libGLESv2/renderer/d3d/d3d9/Fence9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
index d7873d5264..4b86747396 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Fence9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Fence9.h
@@ -6,10 +6,11 @@
// Fence9.h: Defines the rx::FenceNV9 class which implements rx::FenceNVImpl.
-#ifndef LIBGLESV2_RENDERER_FENCE9_H_
-#define LIBGLESV2_RENDERER_FENCE9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
-#include "libGLESv2/renderer/FenceImpl.h"
+#include "libANGLE/renderer/FenceNVImpl.h"
+#include "libANGLE/renderer/FenceSyncImpl.h"
namespace rx
{
@@ -26,12 +27,10 @@ class FenceNV9 : public FenceNVImpl
gl::Error finishFence(GLboolean *outFinished);
private:
- DISALLOW_COPY_AND_ASSIGN(FenceNV9);
-
Renderer9 *mRenderer;
IDirect3DQuery9 *mQuery;
};
}
-#endif // LIBGLESV2_RENDERER_FENCE9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FENCE9_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
new file mode 100644
index 0000000000..dbdfc6d6de
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp
@@ -0,0 +1,422 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer9.cpp: Implements the Framebuffer9 class.
+
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Texture.h"
+
+namespace rx
+{
+
+Framebuffer9::Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer)
+ : FramebufferD3D(data, renderer),
+ mRenderer(renderer)
+{
+ ASSERT(mRenderer != nullptr);
+}
+
+Framebuffer9::~Framebuffer9()
+{
+}
+
+gl::Error Framebuffer9::clear(const gl::State &state, const ClearParameters &clearParams)
+{
+ const gl::FramebufferAttachment *colorAttachment = mData.mColorAttachments[0];
+ const gl::FramebufferAttachment *depthStencilAttachment = mData.getDepthOrStencilAttachment();
+
+ gl::Error error = mRenderer->applyRenderTarget(colorAttachment, depthStencilAttachment);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ float nearZ, farZ;
+ state.getDepthRange(&nearZ, &farZ);
+ mRenderer->setViewport(state.getViewport(), nearZ, farZ, GL_TRIANGLES, state.getRasterizerState().frontFace, true);
+
+ mRenderer->setScissorRectangle(state.getScissor(), state.isScissorTestEnabled());
+
+ return mRenderer->clear(clearParams, colorAttachment, depthStencilAttachment);
+}
+
+gl::Error Framebuffer9::readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch, const gl::PixelPackState &pack, uint8_t *pixels) const
+{
+ ASSERT(pack.pixelBuffer.get() == NULL);
+
+ const gl::FramebufferAttachment *colorbuffer = mData.mColorAttachments[0];
+ ASSERT(colorbuffer);
+
+ RenderTarget9 *renderTarget = NULL;
+ gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(renderTarget);
+
+ IDirect3DSurface9 *surface = renderTarget->getSurface();
+ ASSERT(surface);
+
+ D3DSURFACE_DESC desc;
+ surface->GetDesc(&desc);
+
+ if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
+ {
+ UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
+ }
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ HRESULT result;
+ IDirect3DSurface9 *systemSurface = NULL;
+ bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && mRenderer->getShareHandleSupport() &&
+ area.x == 0 && area.y == 0 &&
+ static_cast<UINT>(area.width) == desc.Width && static_cast<UINT>(area.height) == desc.Height &&
+ desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
+ if (directToPixels)
+ {
+ // Use the pixels ptr as a shared handle to write directly into client's memory
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels));
+ if (FAILED(result))
+ {
+ // Try again without the shared handle
+ directToPixels = false;
+ }
+ }
+
+ if (!directToPixels)
+ {
+ result = device->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
+ D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ SafeRelease(surface);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
+ }
+ }
+
+ result = device->GetRenderTargetData(surface, systemSurface);
+ SafeRelease(surface);
+
+ if (FAILED(result))
+ {
+ SafeRelease(systemSurface);
+
+ // It turns out that D3D will sometimes produce more error
+ // codes than those documented.
+ if (d3d9::isDeviceLostError(result))
+ {
+ mRenderer->notifyDeviceLost();
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
+ }
+
+ if (directToPixels)
+ {
+ SafeRelease(systemSurface);
+ return gl::Error(GL_NO_ERROR);
+ }
+
+ RECT rect;
+ rect.left = gl::clamp(area.x, 0L, static_cast<LONG>(desc.Width));
+ rect.top = gl::clamp(area.y, 0L, static_cast<LONG>(desc.Height));
+ rect.right = gl::clamp(area.x + area.width, 0L, static_cast<LONG>(desc.Width));
+ rect.bottom = gl::clamp(area.y + area.height, 0L, static_cast<LONG>(desc.Height));
+
+ D3DLOCKED_RECT lock;
+ result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
+
+ if (FAILED(result))
+ {
+ UNREACHABLE();
+ SafeRelease(systemSurface);
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
+ }
+
+ uint8_t *source;
+ int inputPitch;
+ if (pack.reverseRowOrder)
+ {
+ source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
+ inputPitch = -lock.Pitch;
+ }
+ else
+ {
+ source = reinterpret_cast<uint8_t*>(lock.pBits);
+ inputPitch = lock.Pitch;
+ }
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat);
+ if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
+ {
+ // Direct copy possible
+ for (int y = 0; y < rect.bottom - rect.top; y++)
+ {
+ memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
+ }
+ }
+ else
+ {
+ const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
+ ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type);
+
+ GLenum sizedDestInternalFormat = gl::GetSizedInternalFormat(format, type);
+ const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(sizedDestInternalFormat);
+
+ if (fastCopyFunc)
+ {
+ // Fast copy is possible through some special function
+ for (int y = 0; y < rect.bottom - rect.top; y++)
+ {
+ for (int x = 0; x < rect.right - rect.left; x++)
+ {
+ uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+
+ fastCopyFunc(src, dest);
+ }
+ }
+ }
+ else
+ {
+ ColorReadFunction colorReadFunction = sourceD3DFormatInfo.colorReadFunction;
+ ColorWriteFunction colorWriteFunction = GetColorWriteFunction(format, type);
+
+ uint8_t temp[sizeof(gl::ColorF)];
+ for (int y = 0; y < rect.bottom - rect.top; y++)
+ {
+ for (int x = 0; x < rect.right - rect.left; x++)
+ {
+ uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
+ const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
+
+ // readFunc and writeFunc will be using the same type of color, CopyTexImage
+ // will not allow the copy otherwise.
+ colorReadFunction(src, temp);
+ colorWriteFunction(temp, dest);
+ }
+ }
+ }
+ }
+
+ systemSurface->UnlockRect();
+ SafeRelease(systemSurface);
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Framebuffer9::blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
+ bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer)
+{
+ ASSERT(filter == GL_NEAREST);
+
+ IDirect3DDevice9 *device = mRenderer->getDevice();
+ ASSERT(device);
+
+ mRenderer->endScene();
+
+ if (blitRenderTarget)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getColorbuffer(0);
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readRenderTarget = NULL;
+ gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readRenderTarget);
+
+ const gl::FramebufferAttachment *drawBuffer = mData.mColorAttachments[0];
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawRenderTarget = NULL;
+ error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(drawRenderTarget);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9* readSurface = readRenderTarget->getSurface();
+ ASSERT(readSurface);
+
+ IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface();
+ ASSERT(drawSurface);
+
+ gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
+ gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
+
+ RECT srcRect;
+ srcRect.left = sourceArea.x;
+ srcRect.right = sourceArea.x + sourceArea.width;
+ srcRect.top = sourceArea.y;
+ srcRect.bottom = sourceArea.y + sourceArea.height;
+
+ RECT dstRect;
+ dstRect.left = destArea.x;
+ dstRect.right = destArea.x + destArea.width;
+ dstRect.top = destArea.y;
+ dstRect.bottom = destArea.y + destArea.height;
+
+ // Clip the rectangles to the scissor rectangle
+ if (scissor)
+ {
+ if (dstRect.left < scissor->x)
+ {
+ srcRect.left += (scissor->x - dstRect.left);
+ dstRect.left = scissor->x;
+ }
+ if (dstRect.top < scissor->y)
+ {
+ srcRect.top += (scissor->y - dstRect.top);
+ dstRect.top = scissor->y;
+ }
+ if (dstRect.right > scissor->x + scissor->width)
+ {
+ srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
+ dstRect.right = scissor->x + scissor->width;
+ }
+ if (dstRect.bottom > scissor->y + scissor->height)
+ {
+ srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
+ dstRect.bottom = scissor->y + scissor->height;
+ }
+ }
+
+ // Clip the rectangles to the destination size
+ if (dstRect.left < 0)
+ {
+ srcRect.left += -dstRect.left;
+ dstRect.left = 0;
+ }
+ if (dstRect.right > dstSize.width)
+ {
+ srcRect.right -= (dstRect.right - dstSize.width);
+ dstRect.right = dstSize.width;
+ }
+ if (dstRect.top < 0)
+ {
+ srcRect.top += -dstRect.top;
+ dstRect.top = 0;
+ }
+ if (dstRect.bottom > dstSize.height)
+ {
+ srcRect.bottom -= (dstRect.bottom - dstSize.height);
+ dstRect.bottom = dstSize.height;
+ }
+
+ // Clip the rectangles to the source size
+ if (srcRect.left < 0)
+ {
+ dstRect.left += -srcRect.left;
+ srcRect.left = 0;
+ }
+ if (srcRect.right > srcSize.width)
+ {
+ dstRect.right -= (srcRect.right - srcSize.width);
+ srcRect.right = srcSize.width;
+ }
+ if (srcRect.top < 0)
+ {
+ dstRect.top += -srcRect.top;
+ srcRect.top = 0;
+ }
+ if (srcRect.bottom > srcSize.height)
+ {
+ dstRect.bottom -= (srcRect.bottom - srcSize.height);
+ srcRect.bottom = srcSize.height;
+ }
+
+ HRESULT result = device->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ }
+ }
+
+ if (blitDepth || blitStencil)
+ {
+ const gl::FramebufferAttachment *readBuffer = sourceFramebuffer->getDepthOrStencilbuffer();
+ ASSERT(readBuffer);
+
+ RenderTarget9 *readDepthStencil = NULL;
+ gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(readDepthStencil);
+
+ const gl::FramebufferAttachment *drawBuffer = mData.getDepthOrStencilAttachment();
+ ASSERT(drawBuffer);
+
+ RenderTarget9 *drawDepthStencil = NULL;
+ error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil);
+ if (error.isError())
+ {
+ return error;
+ }
+ ASSERT(drawDepthStencil);
+
+ // The getSurface calls do an AddRef so save them until after no errors are possible
+ IDirect3DSurface9* readSurface = readDepthStencil->getSurface();
+ ASSERT(readDepthStencil);
+
+ IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface();
+ ASSERT(drawDepthStencil);
+
+ HRESULT result = device->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
+
+ SafeRelease(readSurface);
+ SafeRelease(drawSurface);
+
+ if (FAILED(result))
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
+ }
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+GLenum Framebuffer9::getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const
+{
+ RenderTarget9 *renderTarget9 = RenderTarget9::makeRenderTarget9(renderTarget);
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(renderTarget9->getD3DFormat());
+ return d3dFormatInfo.internalFormat;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
new file mode 100644
index 0000000000..292118e6db
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h
@@ -0,0 +1,41 @@
+//
+// Copyright 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// Framebuffer9.h: Defines the Framebuffer9 class.
+
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
+
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+
+namespace rx
+{
+class Renderer9;
+
+class Framebuffer9 : public FramebufferD3D
+{
+ public:
+ Framebuffer9(const gl::Framebuffer::Data &data, Renderer9 *renderer);
+ virtual ~Framebuffer9();
+
+ private:
+ gl::Error clear(const gl::State &state, const ClearParameters &clearParams) override;
+
+ gl::Error readPixels(const gl::Rectangle &area, GLenum format, GLenum type, size_t outputPitch,
+ const gl::PixelPackState &pack, uint8_t *pixels) const override;
+
+ gl::Error blit(const gl::Rectangle &sourceArea, const gl::Rectangle &destArea, const gl::Rectangle *scissor,
+ bool blitRenderTarget, bool blitDepth, bool blitStencil, GLenum filter,
+ const gl::Framebuffer *sourceFramebuffer) override;
+
+ GLenum getRenderTargetImplementationFormat(RenderTargetD3D *renderTarget) const override;
+
+ Renderer9 *const mRenderer;
+};
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FRAMBUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
index 2a06d12942..d149f7a806 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.cpp
@@ -7,28 +7,30 @@
// Image9.cpp: Implements the rx::Image9 class, which acts as the interface to
// the actual underlying surfaces of a Texture.
-#include "libGLESv2/renderer/d3d/d3d9/Image9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Renderbuffer.h"
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Renderbuffer.h"
#include "common/utilities.h"
namespace rx
{
-Image9::Image9()
+Image9::Image9(Renderer9 *renderer)
{
mSurface = NULL;
mRenderer = NULL;
mD3DPool = D3DPOOL_SYSTEMMEM;
mD3DFormat = D3DFMT_UNKNOWN;
+
+ mRenderer = renderer;
}
Image9::~Image9()
@@ -92,7 +94,7 @@ gl::Error Image9::generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9
return gl::Error(GL_NO_ERROR);
}
-Image9 *Image9::makeImage9(Image *img)
+Image9 *Image9::makeImage9(ImageD3D *img)
{
ASSERT(HAS_DYNAMIC_TYPE(Image9*, img));
return static_cast<Image9*>(img);
@@ -168,32 +170,28 @@ gl::Error Image9::copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface
return gl::Error(GL_NO_ERROR);
}
-bool Image9::redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease)
+bool Image9::redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease)
{
// 3D textures are not supported by the D3D9 backend.
- ASSERT(depth <= 1);
+ ASSERT(size.depth <= 1);
// Only 2D and cube texture are supported by the D3D9 backend.
ASSERT(target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP);
- if (mWidth != width ||
- mHeight != height ||
- mDepth != depth ||
+ if (mWidth != size.width ||
+ mHeight != size.height ||
+ mDepth != size.depth ||
mInternalFormat != internalformat ||
forceRelease)
{
- mRenderer = Renderer9::makeRenderer9(renderer);
-
- mWidth = width;
- mHeight = height;
- mDepth = depth;
+ mWidth = size.width;
+ mHeight = size.height;
+ mDepth = size.depth;
mInternalFormat = internalformat;
// compute the d3d format that will be used
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(internalformat);
- const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat);
mD3DFormat = d3d9FormatInfo.texFormat;
- mActualFormat = d3dFormatInfo.internalFormat;
mRenderable = (d3d9FormatInfo.renderFormat != D3DFMT_UNKNOWN);
SafeRelease(mSurface);
@@ -397,7 +395,7 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i
if (index.type == GL_TEXTURE_2D)
{
TextureStorage9_2D *storage9 = TextureStorage9_2D::makeTextureStorage9_2D(storage);
- gl::Error error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface);
+ error = storage9->getSurfaceLevel(index.mipIndex, true, &destSurface);
if (error.isError())
{
return error;
@@ -405,23 +403,23 @@ gl::Error Image9::copyToStorage(TextureStorage *storage, const gl::ImageIndex &i
}
else
{
- ASSERT(gl::IsCubemapTextureTarget(index.type));
+ ASSERT(gl::IsCubeMapTextureTarget(index.type));
TextureStorage9_Cube *storage9 = TextureStorage9_Cube::makeTextureStorage9_Cube(storage);
- gl::Error error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface);
+ error = storage9->getCubeMapSurface(index.type, index.mipIndex, true, &destSurface);
if (error.isError())
{
return error;
}
}
- error = copyToSurface(destSurface, region.x, region.y, region.width, region.height);
+ error = copyToSurface(destSurface, region);
SafeRelease(destSurface);
return error;
}
-gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height)
+gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, const gl::Box &area)
{
- ASSERT(width > 0 && height > 0);
+ ASSERT(area.width > 0 && area.height > 0 && area.depth == 1);
ASSERT(destSurface);
IDirect3DSurface9 *sourceSurface = NULL;
@@ -434,10 +432,10 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, G
ASSERT(sourceSurface && sourceSurface != destSurface);
RECT rect;
- rect.left = xoffset;
- rect.top = yoffset;
- rect.right = xoffset + width;
- rect.bottom = yoffset + height;
+ rect.left = area.x;
+ rect.top = area.y;
+ rect.right = area.x + area.width;
+ rect.bottom = area.y + area.height;
POINT point = {rect.left, rect.top};
@@ -480,22 +478,21 @@ gl::Error Image9::copyToSurface(IDirect3DSurface9 *destSurface, GLint xoffset, G
// Store the pixel rectangle designated by xoffset,yoffset,width,height with pixels stored as format/type at input
// into the target pixel rectangle.
-gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLint unpackAlignment, GLenum type, const void *input)
+gl::Error Image9::loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input)
{
// 3D textures are not supported by the D3D9 backend.
- ASSERT(zoffset == 0 && depth == 1);
+ ASSERT(area.z == 0 && area.depth == 1);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(type, width, unpackAlignment);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(type, area.width, unpack.alignment, unpack.rowLength);
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
ASSERT(d3dFormatInfo.loadFunction != NULL);
RECT lockRect =
{
- xoffset, yoffset,
- xoffset + width, yoffset + height
+ area.x, area.y,
+ area.x + area.width, area.y + area.height
};
D3DLOCKED_RECT locked;
@@ -505,7 +502,7 @@ gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei
return error;
}
- d3dFormatInfo.loadFunction(width, height, depth,
+ d3dFormatInfo.loadFunction(area.width, area.height, area.depth,
reinterpret_cast<const uint8_t*>(input), inputRowPitch, 0,
reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
@@ -514,27 +511,26 @@ gl::Error Image9::loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei
return gl::Error(GL_NO_ERROR);
}
-gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- const void *input)
+gl::Error Image9::loadCompressedData(const gl::Box &area, const void *input)
{
// 3D textures are not supported by the D3D9 backend.
- ASSERT(zoffset == 0 && depth == 1);
+ ASSERT(area.z == 0 && area.depth == 1);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(mInternalFormat);
- GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, width, 1);
- GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, width, height, 1);
+ GLsizei inputRowPitch = formatInfo.computeRowPitch(GL_UNSIGNED_BYTE, area.width, 1, 0);
+ GLsizei inputDepthPitch = formatInfo.computeDepthPitch(GL_UNSIGNED_BYTE, area.width, area.height, 1, 0);
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(mInternalFormat);
- ASSERT(xoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
- ASSERT(yoffset % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
+ ASSERT(area.x % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockWidth == 0);
+ ASSERT(area.y % d3d9::GetD3DFormatInfo(d3d9FormatInfo.texFormat).blockHeight == 0);
ASSERT(d3d9FormatInfo.loadFunction != NULL);
RECT lockRect =
{
- xoffset, yoffset,
- xoffset + width, yoffset + height
+ area.x, area.y,
+ area.x + area.width, area.y + area.height
};
D3DLOCKED_RECT locked;
@@ -544,7 +540,7 @@ gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset
return error;
}
- d3d9FormatInfo.loadFunction(width, height, depth,
+ d3d9FormatInfo.loadFunction(area.width, area.height, area.depth,
reinterpret_cast<const uint8_t*>(input), inputRowPitch, inputDepthPitch,
reinterpret_cast<uint8_t*>(locked.pBits), locked.Pitch, 0);
@@ -554,12 +550,12 @@ gl::Error Image9::loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset
}
// This implements glCopyTex[Sub]Image2D for non-renderable internal texture formats and incomplete textures
-gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source)
+gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source)
{
ASSERT(source);
// ES3.0 only behaviour to copy into a 3d texture
- ASSERT(zoffset == 0);
+ ASSERT(destOffset.z == 0);
RenderTarget9 *renderTarget = RenderTarget9::makeRenderTarget9(source);
@@ -593,7 +589,7 @@ gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Re
int height = sourceArea.height;
RECT sourceRect = { sourceArea.x, sourceArea.y, sourceArea.x + width, sourceArea.y + height };
- RECT destRect = { xoffset, yoffset, xoffset + width, yoffset + height };
+ RECT destRect = { destOffset.x, destOffset.y, destOffset.x + width, destOffset.y + height };
D3DLOCKED_RECT sourceLock = {0};
result = renderTargetData->LockRect(&sourceLock, &sourceRect, 0);
@@ -782,7 +778,7 @@ gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Re
return gl::Error(GL_NO_ERROR);
}
-gl::Error Image9::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage)
+gl::Error Image9::copy(const gl::Offset &destOffset, const gl::Box &area, const gl::ImageIndex &srcIndex, TextureStorage *srcStorage)
{
// Currently unreachable, due to only being used in a D3D11-only workaround
UNIMPLEMENTED();
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
index 8cc2258859..8cbfbbebf6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Image9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Image9.h
@@ -7,10 +7,10 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
-#include "libGLESv2/renderer/d3d/ImageD3D.h"
+#include "libANGLE/renderer/d3d/ImageD3D.h"
#include "common/debug.h"
namespace gl
@@ -25,16 +25,16 @@ class Renderer9;
class Image9 : public ImageD3D
{
public:
- Image9();
+ Image9(Renderer9 *renderer);
~Image9();
- static Image9 *makeImage9(Image *img);
+ static Image9 *makeImage9(ImageD3D *img);
static gl::Error generateMipmap(Image9 *dest, Image9 *source);
static gl::Error generateMip(IDirect3DSurface9 *destSurface, IDirect3DSurface9 *sourceSurface);
static gl::Error copyLockableSurfaces(IDirect3DSurface9 *dest, IDirect3DSurface9 *source);
- bool redefine(RendererD3D *renderer, GLenum target, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, bool forceRelease) override;
+ bool redefine(GLenum target, GLenum internalformat, const gl::Extents &size, bool forceRelease) override;
D3DFORMAT getD3DFormat() const;
@@ -44,23 +44,19 @@ class Image9 : public ImageD3D
virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level);
virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region);
- virtual gl::Error loadData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- GLint unpackAlignment, GLenum type, const void *input);
- virtual gl::Error loadCompressedData(GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth,
- const void *input);
+ virtual gl::Error loadData(const gl::Box &area, const gl::PixelUnpackState &unpack, GLenum type, const void *input);
+ virtual gl::Error loadCompressedData(const gl::Box &area, const void *input);
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea, RenderTarget *source);
- virtual gl::Error copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &sourceArea,
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Rectangle &sourceArea, RenderTargetD3D *source);
+ virtual gl::Error copy(const gl::Offset &destOffset, const gl::Box &sourceArea,
const gl::ImageIndex &sourceIndex, TextureStorage *source);
private:
- DISALLOW_COPY_AND_ASSIGN(Image9);
-
gl::Error getSurface(IDirect3DSurface9 **outSurface);
gl::Error createSurface();
gl::Error setManagedSurface(IDirect3DSurface9 *surface);
- gl::Error copyToSurface(IDirect3DSurface9 *dest, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height);
+ gl::Error copyToSurface(IDirect3DSurface9 *dest, const gl::Box &area);
gl::Error lock(D3DLOCKED_RECT *lockedRect, const RECT &rect);
void unlock();
@@ -74,4 +70,4 @@ class Image9 : public ImageD3D
};
}
-#endif // LIBGLESV2_RENDERER_IMAGE9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_IMAGE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
index 1c51b9e985..c5d72e6a50 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp
@@ -6,8 +6,8 @@
// Indexffer9.cpp: Defines the D3D9 IndexBuffer implementation.
-#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
index 2375fcf4b0..61f8b11566 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h
@@ -6,10 +6,10 @@
// Indexffer9.h: Defines the D3D9 IndexBuffer implementation.
-#ifndef LIBGLESV2_RENDERER_INDEXBUFFER9_H_
-#define LIBGLESV2_RENDERER_INDEXBUFFER9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
-#include "libGLESv2/renderer/d3d/IndexBuffer.h"
+#include "libANGLE/renderer/d3d/IndexBuffer.h"
namespace rx
{
@@ -38,8 +38,6 @@ class IndexBuffer9 : public IndexBuffer
IDirect3DIndexBuffer9 *getBuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(IndexBuffer9);
-
Renderer9 *const mRenderer;
IDirect3DIndexBuffer9 *mIndexBuffer;
@@ -50,4 +48,4 @@ class IndexBuffer9 : public IndexBuffer
}
-#endif // LIBGLESV2_RENDERER_INDEXBUFFER9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_INDEXBUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
index a3cab578be..96f12d7868 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.cpp
@@ -6,10 +6,9 @@
// Query9.cpp: Defines the rx::Query9 class which implements rx::QueryImpl.
-#include "libGLESv2/renderer/d3d/d3d9/Query9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
#include <GLES2/gl2ext.h>
@@ -132,8 +131,9 @@ gl::Error Query9::testQuery()
mRenderer->notifyDeviceLost();
return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
}
- else if (mRenderer->testDeviceLost(true))
+ else if (mRenderer->testDeviceLost())
{
+ mRenderer->notifyDeviceLost();
return gl::Error(GL_OUT_OF_MEMORY, "Failed to test get query result, device is lost.");
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
index 36851c6c6c..399da2ed83 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Query9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Query9.h
@@ -6,10 +6,10 @@
// Query9.h: Defines the rx::Query9 class which implements rx::QueryImpl.
-#ifndef LIBGLESV2_RENDERER_QUERY9_H_
-#define LIBGLESV2_RENDERER_QUERY9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
-#include "libGLESv2/renderer/QueryImpl.h"
+#include "libANGLE/renderer/QueryImpl.h"
namespace rx
{
@@ -27,8 +27,6 @@ class Query9 : public QueryImpl
virtual gl::Error isResultAvailable(GLuint *available);
private:
- DISALLOW_COPY_AND_ASSIGN(Query9);
-
gl::Error testQuery();
GLuint mResult;
@@ -40,4 +38,4 @@ class Query9 : public QueryImpl
}
-#endif // LIBGLESV2_RENDERER_QUERY9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_QUERY9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
index 53d1f752fa..412c0109f5 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp
@@ -7,27 +7,21 @@
// RenderTarget9.cpp: Implements a D3D9-specific wrapper for IDirect3DSurface9
// pointers retained by renderbuffers.
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
namespace rx
{
-RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTarget *target)
+RenderTarget9 *RenderTarget9::makeRenderTarget9(RenderTargetD3D *target)
{
ASSERT(HAS_DYNAMIC_TYPE(RenderTarget9*, target));
return static_cast<RenderTarget9*>(target);
}
-void RenderTarget9::invalidate(GLint x, GLint y, GLsizei width, GLsizei height)
-{
- // Currently a no-op
-}
-
// TODO: AddRef the incoming surface to take ownership instead of expecting that its ref is being given.
TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum internalFormat, GLsizei width, GLsizei height, GLsizei depth,
GLsizei samples)
@@ -35,7 +29,7 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in
mHeight(height),
mDepth(depth),
mInternalFormat(internalFormat),
- mActualFormat(internalFormat),
+ mD3DFormat(D3DFMT_UNKNOWN),
mSamples(samples),
mRenderTarget(surface)
{
@@ -45,9 +39,7 @@ TextureRenderTarget9::TextureRenderTarget9(IDirect3DSurface9 *surface, GLenum in
{
D3DSURFACE_DESC description;
mRenderTarget->GetDesc(&description);
-
- const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(description.Format);
- mActualFormat = d3dFormatInfo.internalFormat;
+ mD3DFormat = description.Format;
}
}
@@ -76,11 +68,6 @@ GLenum TextureRenderTarget9::getInternalFormat() const
return mInternalFormat;
}
-GLenum TextureRenderTarget9::getActualFormat() const
-{
- return mActualFormat;
-}
-
GLsizei TextureRenderTarget9::getSamples() const
{
return mSamples;
@@ -98,6 +85,10 @@ IDirect3DSurface9 *TextureRenderTarget9::getSurface()
return mRenderTarget;
}
+D3DFORMAT TextureRenderTarget9::getD3DFormat() const
+{
+ return mD3DFormat;
+}
SurfaceRenderTarget9::SurfaceRenderTarget9(SwapChain9 *swapChain, bool depth)
: mSwapChain(swapChain),
@@ -129,11 +120,6 @@ GLenum SurfaceRenderTarget9::getInternalFormat() const
return (mDepth ? mSwapChain->GetDepthBufferInternalFormat() : mSwapChain->GetBackBufferInternalFormat());
}
-GLenum SurfaceRenderTarget9::getActualFormat() const
-{
- return d3d9::GetD3DFormatInfo(d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat).internalFormat;
-}
-
GLsizei SurfaceRenderTarget9::getSamples() const
{
// Our EGL surfaces do not support multisampling.
@@ -145,4 +131,9 @@ IDirect3DSurface9 *SurfaceRenderTarget9::getSurface()
return (mDepth ? mSwapChain->getDepthStencil() : mSwapChain->getRenderTarget());
}
+D3DFORMAT SurfaceRenderTarget9::getD3DFormat() const
+{
+ return d3d9::GetTextureFormatInfo(getInternalFormat()).texFormat;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
index 4585697f4c..32c7dfa09c 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h
@@ -7,30 +7,27 @@
// RenderTarget9.h: Defines a D3D9-specific wrapper for IDirect3DSurface9 pointers
// retained by Renderbuffers.
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET9_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
namespace rx
{
class Renderer9;
class SwapChain9;
-class RenderTarget9 : public RenderTarget
+class RenderTarget9 : public RenderTargetD3D
{
public:
RenderTarget9() { }
virtual ~RenderTarget9() { }
- static RenderTarget9 *makeRenderTarget9(RenderTarget *renderTarget);
-
- void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) override;
+ static RenderTarget9 *makeRenderTarget9(RenderTargetD3D *renderTarget);
virtual IDirect3DSurface9 *getSurface() = 0;
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderTarget9);
+ virtual D3DFORMAT getD3DFormat() const = 0;
};
class TextureRenderTarget9 : public RenderTarget9
@@ -44,19 +41,18 @@ class TextureRenderTarget9 : public RenderTarget9
GLsizei getHeight() const override;
GLsizei getDepth() const override;
GLenum getInternalFormat() const override;
- GLenum getActualFormat() const override;
GLsizei getSamples() const override;
IDirect3DSurface9 *getSurface() override;
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureRenderTarget9);
+ D3DFORMAT getD3DFormat() const override;
+ private:
GLsizei mWidth;
GLsizei mHeight;
GLsizei mDepth;
GLenum mInternalFormat;
- GLenum mActualFormat;
+ D3DFORMAT mD3DFormat;
GLsizei mSamples;
IDirect3DSurface9 *mRenderTarget;
@@ -72,18 +68,17 @@ class SurfaceRenderTarget9 : public RenderTarget9
GLsizei getHeight() const override;
GLsizei getDepth() const override;
GLenum getInternalFormat() const override;
- GLenum getActualFormat() const override;
GLsizei getSamples() const override;
IDirect3DSurface9 *getSurface() override;
- private:
- DISALLOW_COPY_AND_ASSIGN(SurfaceRenderTarget9);
+ D3DFORMAT getD3DFormat() const override;
+ private:
SwapChain9 *mSwapChain;
bool mDepth;
};
}
-#endif // LIBGLESV2_RENDERER_RENDERTARGET9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERTARGET9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 18e6e2d7f0..bf1c367693 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -6,79 +6,64 @@
// Renderer9.cpp: Implements a back-end specific class for the D3D9 renderer.
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h"
-#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Image9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Blit9.h"
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Buffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Query9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Fence9.h"
-#include "libGLESv2/renderer/d3d/d3d9/VertexArray9.h"
-#include "libGLESv2/renderer/d3d/IndexDataManager.h"
-#include "libGLESv2/renderer/d3d/ProgramD3D.h"
-#include "libGLESv2/renderer/d3d/ShaderD3D.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/TransformFeedbackD3D.h"
-#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/State.h"
-#include "libGLESv2/angletypes.h"
-
-#include "libEGL/Display.h"
-
-#include "common/features.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+
#include "common/utilities.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/State.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/features.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/renderer/d3d/CompilerD3D.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/d3d/IndexDataManager.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/RenderbufferD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+#include "libANGLE/renderer/d3d/SurfaceD3D.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/renderer/d3d/TransformFeedbackD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/Blit9.h"
+#include "libANGLE/renderer/d3d/d3d9/Buffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Fence9.h"
+#include "libANGLE/renderer/d3d/d3d9/Framebuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Image9.h"
+#include "libANGLE/renderer/d3d/d3d9/IndexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Query9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexArray9.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+
+#include "third_party/trace_event/trace_event.h"
#include <sstream>
-// Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
-#define REF_RAST 0
+#include <EGL/eglext.h>
#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')));
+// Enable ANGLE_SUPPORT_SHADER_MODEL_2 if you wish devices with only shader model 2.
+// Such a device would not be conformant.
+#ifndef ANGLE_SUPPORT_SHADER_MODEL_2
+#define ANGLE_SUPPORT_SHADER_MODEL_2 0
+#endif
namespace rx
{
-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
{
@@ -91,10 +76,12 @@ enum
MAX_TEXTURE_IMAGE_UNITS_VTF_SM3 = 4
};
-Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes)
- : RendererD3D(display),
- mDc(hDc)
+Renderer9::Renderer9(egl::Display *display)
+ : RendererD3D(display)
{
+ // Initialize global annotator
+ gl::InitializeDebugAnnotations(&mAnnotator);
+
mD3d9Module = NULL;
mD3d9 = NULL;
@@ -106,13 +93,26 @@ Renderer9::Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl:
mAdapter = D3DADAPTER_DEFAULT;
- #if REF_RAST == 1 || defined(FORCE_REF_RAST)
- mDeviceType = D3DDEVTYPE_REF;
- #else
+ const egl::AttributeMap &attributes = display->getAttributeMap();
+ EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE);
+ switch (requestedDeviceType)
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
mDeviceType = D3DDEVTYPE_HAL;
- #endif
+ break;
- mDeviceLost = false;
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ mDeviceType = D3DDEVTYPE_REF;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ mDeviceType = D3DDEVTYPE_NULLREF;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
mMaskedClearSavedState = NULL;
@@ -140,20 +140,21 @@ Renderer9::~Renderer9()
if (mDevice)
{
// If the device is lost, reset it first to prevent leaving the driver in an unstable state
- if (testDeviceLost(false))
+ if (testDeviceLost())
{
resetDevice();
}
}
release();
+
+ gl::UninitializeDebugAnnotations();
}
void Renderer9::release()
{
RendererD3D::cleanup();
- releaseShaderCompiler();
releaseDeviceResources();
SafeRelease(mDevice);
@@ -178,19 +179,21 @@ Renderer9 *Renderer9::makeRenderer9(Renderer *renderer)
return static_cast<Renderer9*>(renderer);
}
-EGLint Renderer9::initialize()
+egl::Error Renderer9::initialize()
{
if (!mCompiler.initialize())
{
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_COMPILER_ERROR,
+ "Compiler failed to initialize.");
}
+ TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
if (mD3d9Module == NULL)
{
- ERR("No D3D9 module found - aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "No D3D9 module found.");
}
typedef HRESULT (WINAPI *Direct3DCreate9ExFunc)(UINT, IDirect3D9Ex**);
@@ -201,22 +204,23 @@ EGLint Renderer9::initialize()
// desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
{
+ TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
ASSERT(mD3d9Ex);
mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&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;
+ return egl::Error(EGL_NOT_INITIALIZED, D3D9_INIT_MISSING_DEP, "Could not create D3D9 device.");
}
- if (mDc != NULL)
+ if (mDisplay->getNativeDisplayId() != nullptr)
{
// UNIMPLEMENTED(); // FIXME: Determine which adapter index the device context corresponds to
}
@@ -225,6 +229,7 @@ EGLint Renderer9::initialize()
// Give up on getting device caps after about one second.
{
+ TRACE_EVENT0("gpu", "GetDeviceCaps");
for (int i = 0; i < 10; ++i)
{
result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
@@ -238,99 +243,83 @@ EGLint Renderer9::initialize()
}
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;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_OTHER_ERROR,
+ "Failed to get device caps: Error code 0x%x\n", result);
}
}
}
- if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(2, 0))
+#if ANGLE_SUPPORT_SHADER_MODEL_2
+ size_t minShaderModel = 2;
+#else
+ size_t minShaderModel = 3;
+#endif
+
+ if (mDeviceCaps.PixelShaderVersion < D3DPS_VERSION(minShaderModel, 0))
{
- ERR("Renderer does not support PS 2.0. aborting!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_UNSUPPORTED_VERSION,
+ "Renderer does not support PS %u.%u.aborting!", minShaderModel, 0);
}
// When DirectX9 is running with an older DirectX8 driver, a StretchRect from a regular texture to a render target texture is not supported.
// This is required by Texture2D::ensureRenderTarget.
if ((mDeviceCaps.DevCaps2 & D3DDEVCAPS2_CAN_STRETCHRECT_FROM_TEXTURES) == 0)
{
- ERR("Renderer does not support stretctrect from textures!\n");
- return EGL_NOT_INITIALIZED;
+ return egl::Error(EGL_NOT_INITIALIZED,
+ D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+ "Renderer does not support StretctRect from textures.");
}
{
+ TRACE_EVENT0("gpu", "GetAdapterIdentifier");
mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
}
- mMinSwapInterval = 4;
- mMaxSwapInterval = 0;
-
- if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
- {
- mMinSwapInterval = std::min(mMinSwapInterval, 0);
- mMaxSwapInterval = std::max(mMaxSwapInterval, 0);
- }
- if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
- {
- mMinSwapInterval = std::min(mMinSwapInterval, 1);
- mMaxSwapInterval = std::max(mMaxSwapInterval, 1);
- }
- if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
- {
- mMinSwapInterval = std::min(mMinSwapInterval, 2);
- mMaxSwapInterval = std::max(mMaxSwapInterval, 2);
- }
- if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
- {
- mMinSwapInterval = std::min(mMinSwapInterval, 3);
- mMaxSwapInterval = std::max(mMaxSwapInterval, 3);
- }
- if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
- {
- mMinSwapInterval = std::min(mMinSwapInterval, 4);
- mMaxSwapInterval = std::max(mMaxSwapInterval, 4);
- }
-
static const TCHAR windowName[] = TEXT("AngleHiddenWindow");
static const TCHAR className[] = TEXT("STATIC");
{
+ 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;
-
- static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
- if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
- behaviorFlags |= D3DCREATE_MULTITHREADED;
+ DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES | D3DCREATE_MULTITHREADED;
{
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice");
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
}
if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
{
- return EGL_BAD_ALLOC;
+ return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+ "CreateDevice failed: device lost of out of memory");
}
if (FAILED(result))
{
+ TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
if (FAILED(result))
{
ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_NOTAVAILABLE || result == D3DERR_DEVICELOST);
- return EGL_BAD_ALLOC;
+ return egl::Error(EGL_BAD_ALLOC, D3D9_INIT_OUT_OF_MEMORY,
+ "CreateDevice2 failed: device lost, not available, or of out of memory");
}
}
if (mD3d9Ex)
{
+ TRACE_EVENT0("gpu", "mDevice_QueryInterface");
result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
ASSERT(SUCCEEDED(result));
}
{
+ TRACE_EVENT0("gpu", "ShaderCache initialize");
mVertexShaderCache.initialize(mDevice);
mPixelShaderCache.initialize(mDevice);
}
@@ -347,7 +336,7 @@ EGLint Renderer9::initialize()
initializeDevice();
- return EGL_SUCCESS;
+ return egl::Error(EGL_SUCCESS);
}
// do any one-time device initialization
@@ -389,7 +378,7 @@ void Renderer9::initializeDevice()
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
- mIndexDataManager = new IndexDataManager(this);
+ mIndexDataManager = new IndexDataManager(this, getRendererClass());
}
D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
@@ -414,47 +403,124 @@ D3DPRESENT_PARAMETERS Renderer9::getDefaultPresentParameters()
return presentParameters;
}
-int Renderer9::generateConfigs(ConfigDesc **configDescList)
+egl::ConfigSet Renderer9::generateConfigs() const
{
+ static const GLenum colorBufferFormats[] =
+ {
+ GL_BGR5_A1_ANGLEX,
+ GL_BGRA8_EXT,
+ GL_RGB565,
+
+ };
+
+ static const GLenum depthStencilBufferFormats[] =
+ {
+ GL_NONE,
+ GL_DEPTH_COMPONENT32_OES,
+ GL_DEPTH24_STENCIL8_OES,
+ GL_DEPTH_COMPONENT24_OES,
+ GL_DEPTH_COMPONENT16,
+ };
+
+ const gl::Caps &rendererCaps = getRendererCaps();
+ const gl::TextureCapsMap &rendererTextureCaps = getRendererTextureCaps();
+
D3DDISPLAYMODE currentDisplayMode;
mD3d9->GetAdapterDisplayMode(mAdapter, &currentDisplayMode);
- unsigned int numRenderFormats = ArraySize(RenderTargetFormats);
- unsigned int numDepthFormats = ArraySize(DepthStencilFormats);
- (*configDescList) = new ConfigDesc[numRenderFormats * numDepthFormats];
- int numConfigs = 0;
+ // Determine the min and max swap intervals
+ int minSwapInterval = 4;
+ int maxSwapInterval = 0;
+
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 0);
+ maxSwapInterval = std::max(maxSwapInterval, 0);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 1);
+ maxSwapInterval = std::max(maxSwapInterval, 1);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_TWO)
+ {
+ minSwapInterval = std::min(minSwapInterval, 2);
+ maxSwapInterval = std::max(maxSwapInterval, 2);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_THREE)
+ {
+ minSwapInterval = std::min(minSwapInterval, 3);
+ maxSwapInterval = std::max(maxSwapInterval, 3);
+ }
+ if (mDeviceCaps.PresentationIntervals & D3DPRESENT_INTERVAL_FOUR)
+ {
+ minSwapInterval = std::min(minSwapInterval, 4);
+ maxSwapInterval = std::max(maxSwapInterval, 4);
+ }
- for (unsigned int formatIndex = 0; formatIndex < numRenderFormats; formatIndex++)
+ egl::ConfigSet configs;
+ for (size_t formatIndex = 0; formatIndex < ArraySize(colorBufferFormats); formatIndex++)
{
- const d3d9::D3DFormat &renderTargetFormatInfo = d3d9::GetD3DFormatInfo(RenderTargetFormats[formatIndex]);
- const gl::TextureCaps &renderTargetFormatCaps = getRendererTextureCaps().get(renderTargetFormatInfo.internalFormat);
- if (renderTargetFormatCaps.renderable)
+ GLenum colorBufferInternalFormat = colorBufferFormats[formatIndex];
+ const gl::TextureCaps &colorBufferFormatCaps = rendererTextureCaps.get(colorBufferInternalFormat);
+ if (colorBufferFormatCaps.renderable)
{
- for (unsigned int depthStencilIndex = 0; depthStencilIndex < numDepthFormats; depthStencilIndex++)
+ for (size_t depthStencilIndex = 0; depthStencilIndex < ArraySize(depthStencilBufferFormats); depthStencilIndex++)
{
- const d3d9::D3DFormat &depthStencilFormatInfo = d3d9::GetD3DFormatInfo(DepthStencilFormats[depthStencilIndex]);
- const gl::TextureCaps &depthStencilFormatCaps = getRendererTextureCaps().get(depthStencilFormatInfo.internalFormat);
- if (depthStencilFormatCaps.renderable || DepthStencilFormats[depthStencilIndex] == D3DFMT_UNKNOWN)
+ GLenum depthStencilBufferInternalFormat = depthStencilBufferFormats[depthStencilIndex];
+ const gl::TextureCaps &depthStencilBufferFormatCaps = rendererTextureCaps.get(depthStencilBufferInternalFormat);
+ if (depthStencilBufferFormatCaps.renderable || depthStencilBufferInternalFormat == GL_NONE)
{
- ConfigDesc newConfig;
- newConfig.renderTargetFormat = renderTargetFormatInfo.internalFormat;
- newConfig.depthStencilFormat = depthStencilFormatInfo.internalFormat;
- newConfig.multiSample = 0; // FIXME: enumerate multi-sampling
- newConfig.fastConfig = (currentDisplayMode.Format == RenderTargetFormats[formatIndex]);
- newConfig.es3Capable = false;
-
- (*configDescList)[numConfigs++] = newConfig;
+ const gl::InternalFormat &colorBufferFormatInfo = gl::GetInternalFormatInfo(colorBufferInternalFormat);
+ const gl::InternalFormat &depthStencilBufferFormatInfo = gl::GetInternalFormatInfo(depthStencilBufferInternalFormat);
+ const d3d9::TextureFormat &d3d9ColorBufferFormatInfo = d3d9::GetTextureFormatInfo(colorBufferInternalFormat);
+
+ egl::Config config;
+ config.renderTargetFormat = colorBufferInternalFormat;
+ config.depthStencilFormat = depthStencilBufferInternalFormat;
+ config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
+ config.redSize = colorBufferFormatInfo.redBits;
+ config.greenSize = colorBufferFormatInfo.greenBits;
+ config.blueSize = colorBufferFormatInfo.blueBits;
+ config.luminanceSize = colorBufferFormatInfo.luminanceBits;
+ config.alphaSize = colorBufferFormatInfo.alphaBits;
+ config.alphaMaskSize = 0;
+ config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
+ config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT);
+ config.colorBufferType = EGL_RGB_BUFFER;
+ // Mark as slow if blits to the back-buffer won't be straight forward
+ config.configCaveat = (currentDisplayMode.Format == d3d9ColorBufferFormatInfo.renderFormat) ? EGL_NONE : EGL_SLOW_CONFIG;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+ config.conformant = EGL_OPENGL_ES2_BIT;
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+ config.maxPBufferWidth = rendererCaps.max2DTextureSize;
+ config.maxPBufferHeight = rendererCaps.max2DTextureSize;
+ config.maxPBufferPixels = rendererCaps.max2DTextureSize * rendererCaps.max2DTextureSize;
+ config.maxSwapInterval = maxSwapInterval;
+ config.minSwapInterval = minSwapInterval;
+ config.nativeRenderable = EGL_FALSE;
+ config.nativeVisualID = 0;
+ config.nativeVisualType = EGL_NONE;
+ config.renderableType = EGL_OPENGL_ES2_BIT;
+ config.sampleBuffers = 0; // FIXME: enumerate multi-sampling
+ config.samples = 0;
+ config.stencilSize = depthStencilBufferFormatInfo.stencilBits;
+ config.surfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
+ config.transparentType = EGL_NONE;
+ config.transparentRedValue = 0;
+ config.transparentGreenValue = 0;
+ config.transparentBlueValue = 0;
+
+ configs.add(config);
}
}
}
}
- return numConfigs;
-}
-
-void Renderer9::deleteConfigs(ConfigDesc *configDescList)
-{
- delete [] (configDescList);
+ ASSERT(configs.size() > 0);
+ return configs;
}
void Renderer9::startScene()
@@ -481,7 +547,39 @@ void Renderer9::endScene()
}
}
-gl::Error Renderer9::sync(bool block)
+gl::Error Renderer9::flush()
+{
+ IDirect3DQuery9* query = NULL;
+ gl::Error error = allocateEventQuery(&query);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ HRESULT result = query->Issue(D3DISSUE_END);
+ if (FAILED(result))
+ {
+ ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
+ }
+
+ // Grab the query data once
+ result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
+ freeEventQuery(query);
+ if (FAILED(result))
+ {
+ if (d3d9::isDeviceLostError(result))
+ {
+ notifyDeviceLost();
+ }
+
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
+ }
+
+ return gl::Error(GL_NO_ERROR);
+}
+
+gl::Error Renderer9::finish()
{
IDirect3DQuery9* query = NULL;
gl::Error error = allocateEventQuery(&query);
@@ -497,7 +595,7 @@ gl::Error Renderer9::sync(bool block)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to issue event query, result: 0x%X.", result);
}
- // Grab the query data once in blocking and non-blocking case
+ // Grab the query data once
result = query->GetData(NULL, 0, D3DGETDATA_FLUSH);
if (FAILED(result))
{
@@ -510,8 +608,8 @@ gl::Error Renderer9::sync(bool block)
return gl::Error(GL_OUT_OF_MEMORY, "Failed to get event query data, result: 0x%X.", result);
}
- // If blocking, loop until the query completes
- while (block && result == S_FALSE)
+ // Loop until the query completes
+ while (result == S_FALSE)
{
// Keep polling, but allow other threads to do something useful first
Sleep(0);
@@ -521,7 +619,7 @@ gl::Error Renderer9::sync(bool block)
// explicitly check for device loss
// some drivers seem to return S_FALSE even if the device is lost
// instead of D3DERR_DEVICELOST like they should
- if (result == S_FALSE && testDeviceLost(false))
+ if (result == S_FALSE && testDeviceLost())
{
result = D3DERR_DEVICELOST;
}
@@ -544,7 +642,7 @@ gl::Error Renderer9::sync(bool block)
return gl::Error(GL_NO_ERROR);
}
-SwapChain *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
+SwapChainD3D *Renderer9::createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat)
{
return new SwapChain9(this, nativeWindow, shareHandle, backBufferFormat, depthBufferFormat);
}
@@ -651,7 +749,7 @@ bool Renderer9::supportsFastCopyBufferToTexture(GLenum internalFormat) const
return false;
}
-gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+gl::Error Renderer9::fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea)
{
// Pixel buffer objects are not supported in D3D9, since D3D9 is ES2-only and PBOs are ES3.
@@ -677,8 +775,19 @@ gl::Error Renderer9::setSamplerState(gl::SamplerType type, int index, gl::Textur
int d3dSampler = index + d3dSamplerOffset;
// Make sure to add the level offset for our tiny compressed texture workaround
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- DWORD baseLevel = samplerState.baseLevel + textureD3D->getNativeTexture()->getTopLevel();
+ TextureD3D *textureD3D = GetImplAs<TextureD3D>(texture);
+
+ TextureStorage *storage = nullptr;
+ gl::Error error = textureD3D->getNativeTexture(&storage);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Storage should exist, texture should be complete
+ ASSERT(storage);
+
+ DWORD baseLevel = samplerState.baseLevel + storage->getTopLevel();
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSU, gl_d3d9::ConvertTextureWrap(samplerState.wrapS));
mDevice->SetSamplerState(d3dSampler, D3DSAMP_ADDRESSV, gl_d3d9::ConvertTextureWrap(samplerState.wrapT));
@@ -713,19 +822,25 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te
if (texture)
{
- TextureD3D* textureImpl = TextureD3D::makeTextureD3D(texture->getImplementation());
+ TextureD3D *textureImpl = GetImplAs<TextureD3D>(texture);
- TextureStorage *texStorage = textureImpl->getNativeTexture();
- if (texStorage)
+ TextureStorage *texStorage = nullptr;
+ gl::Error error = textureImpl->getNativeTexture(&texStorage);
+ if (error.isError())
{
- TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage);
+ return error;
+ }
- gl::Error error = storage9->getBaseTexture(&d3dTexture);
- if (error.isError())
- {
- return error;
- }
+ // Texture should be complete and have a storage
+ ASSERT(texStorage);
+
+ TextureStorage9 *storage9 = TextureStorage9::makeTextureStorage9(texStorage);
+ error = storage9->getBaseTexture(&d3dTexture);
+ if (error.isError())
+ {
+ return error;
}
+
// If we get NULL back from getBaseTexture here, something went wrong
// in the texture class and we're unexpectedly missing the d3d texture
ASSERT(d3dTexture != NULL);
@@ -745,7 +860,9 @@ gl::Error Renderer9::setTexture(gl::SamplerType type, int index, gl::Texture *te
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::setUniformBuffers(const gl::Buffer* /*vertexUniformBuffers*/[], const gl::Buffer* /*fragmentUniformBuffers*/[])
+gl::Error Renderer9::setUniformBuffers(const gl::Data &/*data*/,
+ const GLint /*vertexUniformBuffers*/[],
+ const GLint /*fragmentUniformBuffers*/[])
{
// No effect in ES2/D3D9
return gl::Error(GL_NO_ERROR);
@@ -850,7 +967,7 @@ gl::Error Renderer9::setBlendState(const gl::Framebuffer *framebuffer, const gl:
GLenum internalFormat = attachment ? attachment->getInternalFormat() : GL_NONE;
// Set the color mask
- bool zeroColorMaskAllowed = getAdapterVendor() != VENDOR_ID_AMD;
+ bool zeroColorMaskAllowed = getVendorId() != VENDOR_ID_AMD;
// Apparently some ATI cards have a bug where a draw with a zero color
// write mask can cause later draws to have incorrect results. Instead,
// set a nonzero color write mask but modify the blend state so that no
@@ -1096,7 +1213,7 @@ void Renderer9::setViewport(const gl::Rectangle &viewport, float zNear, float zF
mForceSetViewport = false;
}
-bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
+bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count, bool usesPointSize)
{
switch (mode)
{
@@ -1137,7 +1254,7 @@ bool Renderer9::applyPrimitiveType(GLenum mode, GLsizei count)
}
-gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer)
+gl::Error Renderer9::getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer)
{
ASSERT(depthbuffer);
@@ -1158,7 +1275,7 @@ gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer,
}
gl::Renderbuffer *nullRenderbuffer = new gl::Renderbuffer(createRenderbuffer(), 0);
- gl::Error error = nullRenderbuffer->setStorage(width, height, GL_NONE, 0);
+ gl::Error error = nullRenderbuffer->setStorage(GL_NONE, width, height);
if (error.isError())
{
SafeDelete(nullRenderbuffer);
@@ -1187,28 +1304,31 @@ gl::Error Renderer9::getNullColorbuffer(gl::FramebufferAttachment *depthbuffer,
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
+gl::Error Renderer9::applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer)
{
// if there is no color attachment we must synthesize a NULL colorattachment
// to keep the D3D runtime happy. This should only be possible if depth texturing.
- gl::FramebufferAttachment *attachment = framebuffer->getColorbuffer(0);
- if (!attachment)
+ if (!colorBuffer)
{
- gl::Error error = getNullColorbuffer(framebuffer->getDepthbuffer(), &attachment);
+ gl::Error error = getNullColorbuffer(depthStencilBuffer, &colorBuffer);
if (error.isError())
{
return error;
}
}
- ASSERT(attachment);
+ ASSERT(colorBuffer);
+
+ size_t renderTargetWidth = 0;
+ size_t renderTargetHeight = 0;
+ D3DFORMAT renderTargetFormat = D3DFMT_UNKNOWN;
bool renderTargetChanged = false;
- unsigned int renderTargetSerial = GetAttachmentSerial(attachment);
+ unsigned int renderTargetSerial = GetAttachmentSerial(colorBuffer);
if (renderTargetSerial != mAppliedRenderTargetSerial)
{
// Apply the render target on the device
RenderTarget9 *renderTarget = NULL;
- gl::Error error = d3d9::GetAttachmentRenderTarget(attachment, &renderTarget);
+ gl::Error error = d3d9::GetAttachmentRenderTarget(colorBuffer, &renderTarget);
if (error.isError())
{
return error;
@@ -1221,35 +1341,25 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
mDevice->SetRenderTarget(0, renderTargetSurface);
SafeRelease(renderTargetSurface);
+ renderTargetWidth = renderTarget->getWidth();
+ renderTargetHeight = renderTarget->getHeight();
+ renderTargetFormat = renderTarget->getD3DFormat();
+
mAppliedRenderTargetSerial = renderTargetSerial;
renderTargetChanged = true;
}
- gl::FramebufferAttachment *depthStencil = framebuffer->getDepthbuffer();
- unsigned int depthbufferSerial = 0;
- unsigned int stencilbufferSerial = 0;
- if (depthStencil)
- {
- depthbufferSerial = GetAttachmentSerial(depthStencil);
- }
- else if (framebuffer->getStencilbuffer())
- {
- depthStencil = framebuffer->getStencilbuffer();
- stencilbufferSerial = GetAttachmentSerial(depthStencil);
- }
-
- if (depthbufferSerial != mAppliedDepthbufferSerial ||
- stencilbufferSerial != mAppliedStencilbufferSerial ||
- !mDepthStencilInitialized)
+ unsigned int depthStencilSerial = (depthStencilBuffer != nullptr) ? GetAttachmentSerial(depthStencilBuffer) : 0;
+ if (depthStencilSerial != mAppliedDepthStencilSerial || !mDepthStencilInitialized)
{
unsigned int depthSize = 0;
unsigned int stencilSize = 0;
// Apply the depth stencil on the device
- if (depthStencil)
+ if (depthStencilBuffer)
{
RenderTarget9 *depthStencilRenderTarget = NULL;
- gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencil, &depthStencilRenderTarget);
+ gl::Error error = d3d9::GetAttachmentRenderTarget(depthStencilBuffer, &depthStencilRenderTarget);
if (error.isError())
{
return error;
@@ -1262,8 +1372,8 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
mDevice->SetDepthStencilSurface(depthStencilSurface);
SafeRelease(depthStencilSurface);
- depthSize = depthStencil->getDepthSize();
- stencilSize = depthStencil->getStencilSize();
+ depthSize = depthStencilBuffer->getDepthSize();
+ stencilSize = depthStencilBuffer->getStencilSize();
}
else
{
@@ -1282,8 +1392,7 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
mForceSetDepthStencilState = true;
}
- mAppliedDepthbufferSerial = depthbufferSerial;
- mAppliedStencilbufferSerial = stencilbufferSerial;
+ mAppliedDepthStencilSerial = depthStencilSerial;
mDepthStencilInitialized = true;
}
@@ -1293,16 +1402,21 @@ gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
mForceSetViewport = true;
mForceSetBlendState = true;
- mRenderTargetDesc.width = attachment->getWidth();
- mRenderTargetDesc.height = attachment->getHeight();
- mRenderTargetDesc.format = attachment->getActualFormat();
+ mRenderTargetDesc.width = renderTargetWidth;
+ mRenderTargetDesc.height = renderTargetHeight;
+ mRenderTargetDesc.format = renderTargetFormat;
mRenderTargetDescInitialized = true;
}
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances)
+gl::Error Renderer9::applyRenderTarget(const gl::Framebuffer *framebuffer)
+{
+ return applyRenderTarget(framebuffer->getColorbuffer(0), framebuffer->getDepthOrStencilbuffer());
+}
+
+gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances)
{
TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS];
gl::Error error = mVertexDataManager->prepareVertexData(state, first, count, attributes, instances);
@@ -1311,7 +1425,7 @@ gl::Error Renderer9::applyVertexBuffer(const gl::State &state, GLint first, GLsi
return error;
}
- return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getCurrentProgramBinary(), instances, &mRepeatDraw);
+ return mVertexDeclarationCache.applyDeclaration(mDevice, attributes, state.getProgram(), instances, &mRepeatDraw);
}
// Applies the indices and element array bindings to the Direct3D 9 device
@@ -1339,12 +1453,12 @@ gl::Error Renderer9::applyIndexBuffer(const GLvoid *indices, gl::Buffer *element
void Renderer9::applyTransformFeedbackBuffers(const gl::State& state)
{
- UNREACHABLE();
+ ASSERT(!state.isTransformFeedbackActiveUnpaused());
}
-gl::Error Renderer9::drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive)
+gl::Error Renderer9::drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize)
{
- ASSERT(!transformFeedbackActive);
+ ASSERT(!data.state->isTransformFeedbackActiveUnpaused());
startScene();
@@ -1414,7 +1528,7 @@ gl::Error Renderer9::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indi
// Get the raw indices for an indexed draw
if (type != GL_NONE && elementArrayBuffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
intptr_t offset = reinterpret_cast<intptr_t>(indices);
const uint8_t *bufferData = NULL;
gl::Error error = storage->getData(&bufferData);
@@ -1616,7 +1730,7 @@ gl::Error Renderer9::drawIndexedPoints(GLsizei count, GLenum type, const GLvoid
if (elementArrayBuffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(elementArrayBuffer);
+ BufferD3D *storage = GetImplAs<BufferD3D>(elementArrayBuffer);
intptr_t offset = reinterpret_cast<intptr_t>(indices);
const uint8_t *bufferData = NULL;
@@ -1710,22 +1824,22 @@ gl::Error Renderer9::getCountingIB(size_t count, StaticIndexBufferInterface **ou
return gl::Error(GL_NO_ERROR);
}
-gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+gl::Error Renderer9::applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive)
{
ASSERT(!transformFeedbackActive);
ASSERT(!rasterizerDiscard);
- ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
+ ProgramD3D *programD3D = GetImplAs<ProgramD3D>(program);
- ShaderExecutable *vertexExe = NULL;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe);
+ ShaderExecutableD3D *vertexExe = NULL;
+ gl::Error error = programD3D->getVertexExecutableForInputLayout(inputLayout, &vertexExe, nullptr);
if (error.isError())
{
return error;
}
- ShaderExecutable *pixelExe = NULL;
+ ShaderExecutableD3D *pixelExe = NULL;
error = programD3D->getPixelExecutableForFramebuffer(framebuffer, &pixelExe);
if (error.isError())
{
@@ -1752,7 +1866,7 @@ gl::Error Renderer9::applyShaders(gl::ProgramBinary *programBinary, const gl::Ve
// 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();
+ unsigned int programSerial = programD3D->getSerial();
if (programSerial != mAppliedProgramSerial)
{
programD3D->dirtyAllUniforms();
@@ -1862,7 +1976,9 @@ void Renderer9::applyUniformnbv(gl::LinkedUniform *targetUniform, const GLint *v
applyUniformnfv(targetUniform, (GLfloat*)vector);
}
-gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer)
+gl::Error Renderer9::clear(const ClearParameters &clearParams,
+ const gl::FramebufferAttachment *colorBuffer,
+ const gl::FramebufferAttachment *depthStencilBuffer)
{
if (clearParams.colorClearType != GL_FLOAT)
{
@@ -1886,10 +2002,20 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra
DWORD stencil = clearParams.stencilClearValue & 0x000000FF;
unsigned int stencilUnmasked = 0x0;
- if (clearParams.clearStencil && frameBuffer->hasStencil())
+ if (clearParams.clearStencil && depthStencilBuffer->getStencilSize() > 0)
{
- unsigned int stencilSize = gl::GetInternalFormatInfo((frameBuffer->getStencilbuffer()->getActualFormat())).stencilBits;
- stencilUnmasked = (0x1 << stencilSize) - 1;
+ RenderTargetD3D *stencilRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(depthStencilBuffer, &stencilRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ RenderTarget9 *stencilRenderTarget9 = RenderTarget9::makeRenderTarget9(stencilRenderTarget);
+ ASSERT(stencilRenderTarget9);
+
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(stencilRenderTarget9->getD3DFormat());
+ stencilUnmasked = (0x1 << d3dFormatInfo.stencilBits) - 1;
}
const bool needMaskedStencilClear = clearParams.clearStencil &&
@@ -1899,14 +2025,23 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra
D3DCOLOR color = D3DCOLOR_ARGB(255, 0, 0, 0);
if (clearColor)
{
- const gl::FramebufferAttachment *attachment = frameBuffer->getFirstColorbuffer();
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(attachment->getInternalFormat());
- const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(attachment->getActualFormat());
+ RenderTargetD3D *colorRenderTarget = NULL;
+ gl::Error error = GetAttachmentRenderTarget(colorBuffer, &colorRenderTarget);
+ if (error.isError())
+ {
+ return error;
+ }
- color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && actualFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
- gl::unorm<8>((formatInfo.redBits == 0 && actualFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
- gl::unorm<8>((formatInfo.greenBits == 0 && actualFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
- gl::unorm<8>((formatInfo.blueBits == 0 && actualFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue));
+ RenderTarget9 *colorRenderTarget9 = RenderTarget9::makeRenderTarget9(colorRenderTarget);
+ ASSERT(colorRenderTarget9);
+
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(colorBuffer->getInternalFormat());
+ const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(colorRenderTarget9->getD3DFormat());
+
+ color = D3DCOLOR_ARGB(gl::unorm<8>((formatInfo.alphaBits == 0 && d3dFormatInfo.alphaBits > 0) ? 1.0f : clearParams.colorFClearValue.alpha),
+ gl::unorm<8>((formatInfo.redBits == 0 && d3dFormatInfo.redBits > 0) ? 0.0f : clearParams.colorFClearValue.red),
+ gl::unorm<8>((formatInfo.greenBits == 0 && d3dFormatInfo.greenBits > 0) ? 0.0f : clearParams.colorFClearValue.green),
+ gl::unorm<8>((formatInfo.blueBits == 0 && d3dFormatInfo.blueBits > 0) ? 0.0f : clearParams.colorFClearValue.blue));
if ((formatInfo.redBits > 0 && !clearParams.colorMaskRed) ||
(formatInfo.greenBits > 0 && !clearParams.colorMaskGreen) ||
@@ -2082,8 +2217,7 @@ gl::Error Renderer9::clear(const gl::ClearParameters &clearParams, const gl::Fra
void Renderer9::markAllStateDirty()
{
mAppliedRenderTargetSerial = 0;
- mAppliedDepthbufferSerial = 0;
- mAppliedStencilbufferSerial = 0;
+ mAppliedDepthStencilSerial = 0;
mDepthStencilInitialized = false;
mRenderTargetDescInitialized = false;
@@ -2141,19 +2275,8 @@ void Renderer9::releaseDeviceResources()
}
}
-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)
+bool Renderer9::testDeviceLost()
{
HRESULT status = getDeviceStatusCode();
bool isLost = FAILED(status);
@@ -2166,10 +2289,6 @@ bool Renderer9::testDeviceLost(bool notify)
// 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;
@@ -2217,7 +2336,7 @@ bool Renderer9::resetDevice()
D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
HRESULT result = D3D_OK;
- bool lost = testDeviceLost(false);
+ bool lost = testDeviceLost();
bool removedDevice = (getDeviceStatusCode() == D3DERR_DEVICEREMOVED);
// Device Removed is a feature which is only present with D3D9Ex
@@ -2237,7 +2356,7 @@ bool Renderer9::resetDevice()
{
Sleep(500); // Give the graphics driver some CPU time
result = mDeviceEx->ResetEx(&presentParameters, NULL);
- lost = testDeviceLost(false);
+ lost = testDeviceLost();
}
else
{
@@ -2252,7 +2371,7 @@ bool Renderer9::resetDevice()
{
result = mDevice->Reset(&presentParameters);
}
- lost = testDeviceLost(false);
+ lost = testDeviceLost();
}
}
@@ -2311,12 +2430,12 @@ bool Renderer9::resetRemovedDevice()
// 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);
+ return !initialize().isError();
}
-DWORD Renderer9::getAdapterVendor() const
+VendorID Renderer9::getVendorId() const
{
- return mAdapterIdentifier.VendorId;
+ return static_cast<VendorID>(mAdapterIdentifier.VendorId);
}
std::string Renderer9::getRendererDescription() const
@@ -2367,7 +2486,7 @@ unsigned int Renderer9::getReservedFragmentUniformBuffers() const
bool Renderer9::getShareHandleSupport() const
{
// PIX doesn't seem to support using share handles, so disable them.
- return (mD3d9Ex != NULL) && !gl::perfActive();
+ return (mD3d9Ex != NULL) && !gl::DebugAnnotationsActive();
}
bool Renderer9::getPostSubBufferSupport() const
@@ -2380,19 +2499,19 @@ int Renderer9::getMajorShaderModel() const
return D3DSHADER_VERSION_MAJOR(mDeviceCaps.PixelShaderVersion);
}
-DWORD Renderer9::getCapsDeclTypes() const
+int Renderer9::getMinorShaderModel() const
{
- return mDeviceCaps.DeclTypes;
+ return D3DSHADER_VERSION_MINOR(mDeviceCaps.PixelShaderVersion);
}
-int Renderer9::getMinSwapInterval() const
+std::string Renderer9::getShaderModelSuffix() const
{
- return mMinSwapInterval;
+ return "";
}
-int Renderer9::getMaxSwapInterval() const
+DWORD Renderer9::getCapsDeclTypes() const
{
- return mMaxSwapInterval;
+ return mDeviceCaps.DeclTypes;
}
D3DPOOL Renderer9::getBufferPool(DWORD usage) const
@@ -2412,8 +2531,8 @@ D3DPOOL Renderer9::getBufferPool(DWORD usage) const
return D3DPOOL_DEFAULT;
}
-gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
RECT rect;
rect.left = sourceRect.x;
@@ -2421,11 +2540,11 @@ gl::Error Renderer9::copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectang
rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copy2D(framebuffer, rect, destFormat, xoffset, yoffset, storage, level);
+ return mBlit->copy2D(framebuffer, rect, destFormat, destOffset, storage, level);
}
-gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level)
+gl::Error Renderer9::copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level)
{
RECT rect;
rect.left = sourceRect.x;
@@ -2433,385 +2552,26 @@ gl::Error Renderer9::copyImageCube(gl::Framebuffer *framebuffer, const gl::Recta
rect.right = sourceRect.x + sourceRect.width;
rect.bottom = sourceRect.y + sourceRect.height;
- return mBlit->copyCube(framebuffer, rect, destFormat, xoffset, yoffset, storage, target, level);
+ return mBlit->copyCube(framebuffer, rect, destFormat, destOffset, storage, target, level);
}
-gl::Error Renderer9::copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
// 3D textures are not available in the D3D9 backend.
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION);
}
-gl::Error Renderer9::copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level)
+gl::Error Renderer9::copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level)
{
// 2D array textures are not available in the D3D9 backend.
UNREACHABLE();
return gl::Error(GL_INVALID_OPERATION);
}
-gl::Error Renderer9::blitRect(const gl::Framebuffer *readFramebuffer, const gl::Rectangle &readRect,
- const gl::Framebuffer *drawFramebuffer, const gl::Rectangle &drawRect,
- const gl::Rectangle *scissor, bool blitRenderTarget,
- bool blitDepth, bool blitStencil, GLenum filter)
-{
- ASSERT(filter == GL_NEAREST);
-
- endScene();
-
- if (blitRenderTarget)
- {
- gl::FramebufferAttachment *readBuffer = readFramebuffer->getColorbuffer(0);
- ASSERT(readBuffer);
-
- RenderTarget9 *readRenderTarget = NULL;
- gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(readRenderTarget);
-
- gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getColorbuffer(0);
- ASSERT(drawBuffer);
-
- RenderTarget9 *drawRenderTarget = NULL;
- error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawRenderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(drawRenderTarget);
-
- // The getSurface calls do an AddRef so save them until after no errors are possible
- IDirect3DSurface9* readSurface = readRenderTarget->getSurface();
- ASSERT(readSurface);
-
- IDirect3DSurface9* drawSurface = drawRenderTarget->getSurface();
- ASSERT(drawSurface);
-
- gl::Extents srcSize(readRenderTarget->getWidth(), readRenderTarget->getHeight(), 1);
- gl::Extents dstSize(drawRenderTarget->getWidth(), drawRenderTarget->getHeight(), 1);
-
- RECT srcRect;
- srcRect.left = readRect.x;
- srcRect.right = readRect.x + readRect.width;
- srcRect.top = readRect.y;
- srcRect.bottom = readRect.y + readRect.height;
-
- RECT dstRect;
- dstRect.left = drawRect.x;
- dstRect.right = drawRect.x + drawRect.width;
- dstRect.top = drawRect.y;
- dstRect.bottom = drawRect.y + drawRect.height;
-
- // Clip the rectangles to the scissor rectangle
- if (scissor)
- {
- if (dstRect.left < scissor->x)
- {
- srcRect.left += (scissor->x - dstRect.left);
- dstRect.left = scissor->x;
- }
- if (dstRect.top < scissor->y)
- {
- srcRect.top += (scissor->y - dstRect.top);
- dstRect.top = scissor->y;
- }
- if (dstRect.right > scissor->x + scissor->width)
- {
- srcRect.right -= (dstRect.right - (scissor->x + scissor->width));
- dstRect.right = scissor->x + scissor->width;
- }
- if (dstRect.bottom > scissor->y + scissor->height)
- {
- srcRect.bottom -= (dstRect.bottom - (scissor->y + scissor->height));
- dstRect.bottom = scissor->y + scissor->height;
- }
- }
-
- // Clip the rectangles to the destination size
- if (dstRect.left < 0)
- {
- srcRect.left += -dstRect.left;
- dstRect.left = 0;
- }
- if (dstRect.right > dstSize.width)
- {
- srcRect.right -= (dstRect.right - dstSize.width);
- dstRect.right = dstSize.width;
- }
- if (dstRect.top < 0)
- {
- srcRect.top += -dstRect.top;
- dstRect.top = 0;
- }
- if (dstRect.bottom > dstSize.height)
- {
- srcRect.bottom -= (dstRect.bottom - dstSize.height);
- dstRect.bottom = dstSize.height;
- }
-
- // Clip the rectangles to the source size
- if (srcRect.left < 0)
- {
- dstRect.left += -srcRect.left;
- srcRect.left = 0;
- }
- if (srcRect.right > srcSize.width)
- {
- dstRect.right -= (srcRect.right - srcSize.width);
- srcRect.right = srcSize.width;
- }
- if (srcRect.top < 0)
- {
- dstRect.top += -srcRect.top;
- srcRect.top = 0;
- }
- if (srcRect.bottom > srcSize.height)
- {
- dstRect.bottom -= (srcRect.bottom - srcSize.height);
- srcRect.bottom = srcSize.height;
- }
-
- HRESULT result = mDevice->StretchRect(readSurface, &srcRect, drawSurface, &dstRect, D3DTEXF_NONE);
-
- SafeRelease(readSurface);
- SafeRelease(drawSurface);
-
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
- }
- }
-
- if (blitDepth || blitStencil)
- {
- gl::FramebufferAttachment *readBuffer = readFramebuffer->getDepthOrStencilbuffer();
- ASSERT(readBuffer);
-
- RenderTarget9 *readDepthStencil = NULL;
- gl::Error error = d3d9::GetAttachmentRenderTarget(readBuffer, &readDepthStencil);
- if (error.isError())
- {
- return error;
- }
- ASSERT(readDepthStencil);
-
- gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getDepthOrStencilbuffer();
- ASSERT(drawBuffer);
-
- RenderTarget9 *drawDepthStencil = NULL;
- error = d3d9::GetAttachmentRenderTarget(drawBuffer, &drawDepthStencil);
- if (error.isError())
- {
- return error;
- }
- ASSERT(drawDepthStencil);
-
- // The getSurface calls do an AddRef so save them until after no errors are possible
- IDirect3DSurface9* readSurface = readDepthStencil->getSurface();
- ASSERT(readDepthStencil);
-
- IDirect3DSurface9* drawSurface = drawDepthStencil->getSurface();
- ASSERT(drawDepthStencil);
-
- HRESULT result = mDevice->StretchRect(readSurface, NULL, drawSurface, NULL, D3DTEXF_NONE);
-
- SafeRelease(readSurface);
- SafeRelease(drawSurface);
-
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal blit failed, StretchRect returned 0x%X.", result);
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer9::readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels)
-{
- ASSERT(pack.pixelBuffer.get() == NULL);
-
- gl::FramebufferAttachment *colorbuffer = framebuffer->getColorbuffer(0);
- ASSERT(colorbuffer);
-
- RenderTarget9 *renderTarget = NULL;
- gl::Error error = d3d9::GetAttachmentRenderTarget(colorbuffer, &renderTarget);
- if (error.isError())
- {
- return error;
- }
- ASSERT(renderTarget);
-
- IDirect3DSurface9 *surface = renderTarget->getSurface();
- ASSERT(surface);
-
- D3DSURFACE_DESC desc;
- surface->GetDesc(&desc);
-
- if (desc.MultiSampleType != D3DMULTISAMPLE_NONE)
- {
- UNIMPLEMENTED(); // FIXME: Requires resolve using StretchRect into non-multisampled render target
- SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "ReadPixels is unimplemented for multisampled framebuffer attachments.");
- }
-
- HRESULT result;
- IDirect3DSurface9 *systemSurface = NULL;
- bool directToPixels = !pack.reverseRowOrder && pack.alignment <= 4 && getShareHandleSupport() &&
- x == 0 && y == 0 && UINT(width) == desc.Width && UINT(height) == desc.Height &&
- desc.Format == D3DFMT_A8R8G8B8 && format == GL_BGRA_EXT && type == GL_UNSIGNED_BYTE;
- if (directToPixels)
- {
- // Use the pixels ptr as a shared handle to write directly into client's memory
- result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
- D3DPOOL_SYSTEMMEM, &systemSurface, reinterpret_cast<void**>(&pixels));
- if (FAILED(result))
- {
- // Try again without the shared handle
- directToPixels = false;
- }
- }
-
- if (!directToPixels)
- {
- result = mDevice->CreateOffscreenPlainSurface(desc.Width, desc.Height, desc.Format,
- D3DPOOL_SYSTEMMEM, &systemSurface, NULL);
- if (FAILED(result))
- {
- ASSERT(result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY);
- SafeRelease(surface);
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal texture for ReadPixels.");
- }
- }
-
- result = mDevice->GetRenderTargetData(surface, systemSurface);
- SafeRelease(surface);
-
- if (FAILED(result))
- {
- SafeRelease(systemSurface);
-
- // It turns out that D3D will sometimes produce more error
- // codes than those documented.
- if (d3d9::isDeviceLostError(result))
- {
- notifyDeviceLost();
- }
- else
- {
- UNREACHABLE();
- }
-
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to read internal render target data.");
- }
-
- if (directToPixels)
- {
- SafeRelease(systemSurface);
- return gl::Error(GL_NO_ERROR);
- }
-
- RECT rect;
- rect.left = gl::clamp(x, 0L, static_cast<LONG>(desc.Width));
- rect.top = gl::clamp(y, 0L, static_cast<LONG>(desc.Height));
- rect.right = gl::clamp(x + width, 0L, static_cast<LONG>(desc.Width));
- rect.bottom = gl::clamp(y + height, 0L, static_cast<LONG>(desc.Height));
-
- D3DLOCKED_RECT lock;
- result = systemSurface->LockRect(&lock, &rect, D3DLOCK_READONLY);
-
- if (FAILED(result))
- {
- UNREACHABLE();
- SafeRelease(systemSurface);
-
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to lock internal render target.");
- }
-
- uint8_t *source;
- int inputPitch;
- if (pack.reverseRowOrder)
- {
- source = reinterpret_cast<uint8_t*>(lock.pBits) + lock.Pitch * (rect.bottom - rect.top - 1);
- inputPitch = -lock.Pitch;
- }
- else
- {
- source = reinterpret_cast<uint8_t*>(lock.pBits);
- inputPitch = lock.Pitch;
- }
-
- const d3d9::D3DFormat &d3dFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
- const gl::InternalFormat &sourceFormatInfo = gl::GetInternalFormatInfo(d3dFormatInfo.internalFormat);
- if (sourceFormatInfo.format == format && sourceFormatInfo.type == type)
- {
- // Direct copy possible
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- memcpy(pixels + y * outputPitch, source + y * inputPitch, (rect.right - rect.left) * sourceFormatInfo.pixelBytes);
- }
- }
- else
- {
- const d3d9::D3DFormat &sourceD3DFormatInfo = d3d9::GetD3DFormatInfo(desc.Format);
- ColorCopyFunction fastCopyFunc = sourceD3DFormatInfo.getFastCopyFunction(format, type);
-
- const gl::FormatType &destFormatTypeInfo = gl::GetFormatTypeInfo(format, type);
- const gl::InternalFormat &destFormatInfo = gl::GetInternalFormatInfo(destFormatTypeInfo.internalFormat);
-
- if (fastCopyFunc)
- {
- // Fast copy is possible through some special function
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- for (int x = 0; x < rect.right - rect.left; x++)
- {
- uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
-
- fastCopyFunc(src, dest);
- }
- }
- }
- else
- {
- uint8_t temp[sizeof(gl::ColorF)];
- for (int y = 0; y < rect.bottom - rect.top; y++)
- {
- for (int x = 0; x < rect.right - rect.left; x++)
- {
- uint8_t *dest = pixels + y * outputPitch + x * destFormatInfo.pixelBytes;
- const uint8_t *src = source + y * inputPitch + x * sourceFormatInfo.pixelBytes;
-
- // readFunc and writeFunc will be using the same type of color, CopyTexImage
- // will not allow the copy otherwise.
- sourceD3DFormatInfo.colorReadFunction(src, temp);
- destFormatTypeInfo.colorWriteFunction(temp, dest);
- }
- }
- }
- }
-
- systemSurface->UnlockRect();
- SafeRelease(systemSurface);
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer9::createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT)
-{
- SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
- *outRT = new SurfaceRenderTarget9(swapChain9, depth);
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT)
+gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT)
{
const d3d9::TextureFormat &d3d9FormatInfo = d3d9::GetTextureFormatInfo(format);
@@ -2862,24 +2622,34 @@ gl::Error Renderer9::createRenderTarget(int width, int height, GLenum format, GL
return gl::Error(GL_NO_ERROR);
}
-ShaderImpl *Renderer9::createShader(const gl::Data &data, GLenum type)
+FramebufferImpl *Renderer9::createDefaultFramebuffer(const gl::Framebuffer::Data &data)
{
- return new ShaderD3D(data, type, this);
+ return createFramebuffer(data);
}
-ProgramImpl *Renderer9::createProgram()
+FramebufferImpl *Renderer9::createFramebuffer(const gl::Framebuffer::Data &data)
{
- return new ProgramD3D(this);
+ return new Framebuffer9(data, this);
+}
+
+CompilerImpl *Renderer9::createCompiler(const gl::Data &data)
+{
+ return new CompilerD3D(data, SH_HLSL9_OUTPUT);
}
-void Renderer9::releaseShaderCompiler()
+ShaderImpl *Renderer9::createShader(GLenum type)
{
- ShaderD3D::releaseCompiler();
+ return new ShaderD3D(type);
+}
+
+ProgramImpl *Renderer9::createProgram()
+{
+ return new ProgramD3D(this);
}
gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutable **outExecutable)
+ bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
@@ -2918,8 +2688,8 @@ gl::Error Renderer9::loadExecutable(const void *function, size_t length, ShaderT
gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, D3DWorkaroundType workaround,
- ShaderExecutable **outExectuable)
+ bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable)
{
// Transform feedback is not supported in ES2 or D3D9
ASSERT(transformFeedbackVaryings.size() == 0);
@@ -2943,17 +2713,16 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string
UINT flags = ANGLE_COMPILE_OPTIMIZATION_LEVEL;
- if (workaround == ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION)
+ if (workarounds.skipOptimization)
{
flags = D3DCOMPILE_SKIP_OPTIMIZATION;
}
- else if (workaround == ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION)
+ else if (workarounds.useMaxOptimization)
{
flags = D3DCOMPILE_OPTIMIZATION_LEVEL3;
}
- else ASSERT(workaround == ANGLE_D3D_WORKAROUND_NONE);
- if (gl::perfActive())
+ if (gl::DebugAnnotationsActive())
{
#ifndef NDEBUG
flags = D3DCOMPILE_SKIP_OPTIMIZATION;
@@ -3002,9 +2771,9 @@ gl::Error Renderer9::compileToExecutable(gl::InfoLog &infoLog, const std::string
return gl::Error(GL_NO_ERROR);
}
-UniformStorage *Renderer9::createUniformStorage(size_t storageSize)
+UniformStorageD3D *Renderer9::createUniformStorage(size_t storageSize)
{
- return new UniformStorage(storageSize);
+ return new UniformStorageD3D(storageSize);
}
gl::Error Renderer9::boxFilter(IDirect3DSurface9 *source, IDirect3DSurface9 *dest)
@@ -3065,32 +2834,32 @@ gl::Error Renderer9::copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurfac
return gl::Error(GL_NO_ERROR);
}
-Image *Renderer9::createImage()
+ImageD3D *Renderer9::createImage()
{
- return new Image9();
+ return new Image9(this);
}
-gl::Error Renderer9::generateMipmap(Image *dest, Image *src)
+gl::Error Renderer9::generateMipmap(ImageD3D *dest, ImageD3D *src)
{
Image9 *src9 = Image9::makeImage9(src);
Image9 *dst9 = Image9::makeImage9(dest);
return Image9::generateMipmap(dst9, src9);
}
-TextureStorage *Renderer9::createTextureStorage2D(SwapChain *swapChain)
+TextureStorage *Renderer9::createTextureStorage2D(SwapChainD3D *swapChain)
{
SwapChain9 *swapChain9 = SwapChain9::makeSwapChain9(swapChain);
return new TextureStorage9_2D(this, swapChain9);
}
-TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels)
+TextureStorage *Renderer9::createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly)
{
return new TextureStorage9_2D(this, internalformat, renderTarget, width, height, levels);
}
-TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels)
+TextureStorage *Renderer9::createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
{
- return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels);
+ return new TextureStorage9_Cube(this, internalformat, renderTarget, size, levels, hintLevelZeroOnly);
}
TextureStorage *Renderer9::createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels)
@@ -3127,13 +2896,6 @@ RenderbufferImpl *Renderer9::createRenderbuffer()
return renderbuffer;
}
-RenderbufferImpl *Renderer9::createRenderbuffer(SwapChain *swapChain, bool depth)
-{
- RenderbufferD3D *renderbuffer = new RenderbufferD3D(this);
- renderbuffer->setStorage(swapChain, depth);
- return renderbuffer;
-}
-
bool Renderer9::getLUID(LUID *adapterLuid) const
{
adapterLuid->HighPart = 0;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
index 10d2fb11e8..19bea3eb35 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.h
@@ -6,16 +6,17 @@
// Renderer9.h: Defines a back-end specific class for the D3D9 renderer.
-#ifndef LIBGLESV2_RENDERER_RENDERER9_H_
-#define LIBGLESV2_RENDERER_RENDERER9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
#include "common/angleutils.h"
#include "common/mathutil.h"
-#include "libGLESv2/renderer/d3d/d3d9/ShaderCache.h"
-#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
-#include "libGLESv2/renderer/d3d/HLSLCompiler.h"
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-#include "libGLESv2/renderer/RenderTarget.h"
+#include "libANGLE/renderer/d3d/HLSLCompiler.h"
+#include "libANGLE/renderer/d3d/RendererD3D.h"
+#include "libANGLE/renderer/d3d/RenderTargetD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderCache.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
namespace gl
{
@@ -29,33 +30,54 @@ class AttributeMap;
namespace rx
{
-class VertexDataManager;
+class Blit9;
class IndexDataManager;
class StreamingIndexBufferInterface;
class StaticIndexBufferInterface;
+class VertexDataManager;
+struct ClearParameters;
struct TranslatedAttribute;
-class Blit9;
+
+enum D3D9InitError
+{
+ D3D9_INIT_SUCCESS = 0,
+ // Failed to load the D3D or ANGLE compiler
+ D3D9_INIT_COMPILER_ERROR,
+ // Failed to load a necessary DLL
+ D3D9_INIT_MISSING_DEP,
+ // Device creation error
+ D3D9_INIT_CREATE_DEVICE_ERROR,
+ // System does not meet minimum shader spec
+ D3D9_INIT_UNSUPPORTED_VERSION,
+ // System does not support stretchrect from textures
+ D3D9_INIT_UNSUPPORTED_STRETCHRECT,
+ // A call returned out of memory or device lost
+ D3D9_INIT_OUT_OF_MEMORY,
+ // Other unspecified error
+ D3D9_INIT_OTHER_ERROR,
+ NUM_D3D9_INIT_ERRORS
+};
class Renderer9 : public RendererD3D
{
public:
- Renderer9(egl::Display *display, EGLNativeDisplayType hDc, const egl::AttributeMap &attributes);
+ explicit Renderer9(egl::Display *display);
virtual ~Renderer9();
static Renderer9 *makeRenderer9(Renderer *renderer);
- virtual EGLint initialize();
+ egl::Error initialize() override;
virtual bool resetDevice();
- virtual int generateConfigs(ConfigDesc **configDescList);
- virtual void deleteConfigs(ConfigDesc *configDescList);
+ egl::ConfigSet generateConfigs() const override;
void startScene();
void endScene();
- virtual gl::Error sync(bool block);
+ gl::Error flush() override;
+ gl::Error finish() override;
- virtual SwapChain *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
+ virtual SwapChainD3D *createSwapChain(NativeWindow nativeWindow, HANDLE shareHandle, GLenum backBufferFormat, GLenum depthBufferFormat);
gl::Error allocateEventQuery(IDirect3DQuery9 **outQuery);
void freeEventQuery(IDirect3DQuery9* query);
@@ -69,7 +91,9 @@ class Renderer9 : public RendererD3D
virtual gl::Error setSamplerState(gl::SamplerType type, int index, gl::Texture *texture, const gl::SamplerState &sampler);
virtual gl::Error setTexture(gl::SamplerType type, int index, gl::Texture *texture);
- virtual gl::Error setUniformBuffers(const gl::Buffer *vertexUniformBuffers[], const gl::Buffer *fragmentUniformBuffers[]);
+ gl::Error setUniformBuffers(const gl::Data &data,
+ const GLint vertexUniformBuffers[],
+ const GLint fragmentUniformBuffers[]) override;
virtual gl::Error setRasterizerState(const gl::RasterizerState &rasterState);
gl::Error setBlendState(const gl::Framebuffer *framebuffer, const gl::BlendState &blendState, const gl::ColorF &blendColor,
@@ -82,30 +106,31 @@ class Renderer9 : public RendererD3D
bool ignoreViewport);
gl::Error applyRenderTarget(const gl::Framebuffer *frameBuffer) override;
- virtual gl::Error applyShaders(gl::ProgramBinary *programBinary, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
+ gl::Error applyRenderTarget(const gl::FramebufferAttachment *colorBuffer, const gl::FramebufferAttachment *depthStencilBuffer);
+ virtual gl::Error applyShaders(gl::Program *program, const gl::VertexFormat inputLayout[], const gl::Framebuffer *framebuffer,
bool rasterizerDiscard, bool transformFeedbackActive);
virtual gl::Error applyUniforms(const ProgramImpl &program, const std::vector<gl::LinkedUniform*> &uniformArray);
- virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount);
- virtual gl::Error applyVertexBuffer(const gl::State &state, GLint first, GLsizei count, GLsizei instances);
+ virtual bool applyPrimitiveType(GLenum primitiveType, GLsizei elementCount, bool usesPointSize);
+ virtual gl::Error applyVertexBuffer(const gl::State &state, GLenum mode, GLint first, GLsizei count, GLsizei instances);
virtual gl::Error applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementArrayBuffer, GLsizei count, GLenum mode, GLenum type, TranslatedIndexData *indexInfo);
- virtual void applyTransformFeedbackBuffers(const gl::State& state);
+ void applyTransformFeedbackBuffers(const gl::State &state) override;
- virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive);
+ gl::Error drawArrays(const gl::Data &data, GLenum mode, GLsizei count, GLsizei instances, bool usesPointSize) override;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
gl::Buffer *elementArrayBuffer, const TranslatedIndexData &indexInfo, GLsizei instances);
- gl::Error clear(const gl::ClearParameters &clearParams, const gl::Framebuffer *frameBuffer) override;
+ gl::Error clear(const ClearParameters &clearParams,
+ const gl::FramebufferAttachment *colorBuffer,
+ const gl::FramebufferAttachment *depthStencilBuffer);
virtual void markAllStateDirty();
// lost device
- void notifyDeviceLost() override;
- bool isDeviceLost() override;
- bool testDeviceLost(bool notify) override;
+ bool testDeviceLost() override;
bool testDeviceResettable() override;
- DWORD getAdapterVendor() const override;
+ VendorID getVendorId() const override;
std::string getRendererDescription() const override;
GUID getAdapterIdentifier() const override;
@@ -119,53 +144,49 @@ class Renderer9 : public RendererD3D
virtual bool getPostSubBufferSupport() const;
virtual int getMajorShaderModel() const;
+ int getMinorShaderModel() const override;
+ std::string getShaderModelSuffix() const override;
+
DWORD getCapsDeclTypes() const;
- virtual int getMinSwapInterval() const;
- virtual int getMaxSwapInterval() const;
// Pixel operations
- virtual gl::Error copyImage2D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImageCube(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, TextureStorage *storage, GLenum target, GLint level);
- virtual gl::Error copyImage3D(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
- virtual gl::Error copyImage2DArray(gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
- GLint xoffset, GLint yoffset, GLint zOffset, TextureStorage *storage, GLint level);
-
- gl::Error blitRect(const gl::Framebuffer *readTarget, const gl::Rectangle &readRect,
- const gl::Framebuffer *drawTarget, const gl::Rectangle &drawRect,
- const gl::Rectangle *scissor, bool blitRenderTarget,
- bool blitDepth, bool blitStencil, GLenum filter) override;
-
- virtual gl::Error readPixels(const gl::Framebuffer *framebuffer, GLint x, GLint y, GLsizei width, GLsizei height, GLenum format,
- GLenum type, GLuint outputPitch, const gl::PixelPackState &pack, uint8_t *pixels);
+ virtual gl::Error copyImage2D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ virtual gl::Error copyImageCube(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLenum target, GLint level);
+ virtual gl::Error copyImage3D(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
+ virtual gl::Error copyImage2DArray(const gl::Framebuffer *framebuffer, const gl::Rectangle &sourceRect, GLenum destFormat,
+ const gl::Offset &destOffset, TextureStorage *storage, GLint level);
// RenderTarget creation
- virtual gl::Error createRenderTarget(SwapChain *swapChain, bool depth, RenderTarget **outRT);
- virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTarget **outRT);
+ virtual gl::Error createRenderTarget(int width, int height, GLenum format, GLsizei samples, RenderTargetD3D **outRT);
+
+ // Framebuffer creation
+ FramebufferImpl *createDefaultFramebuffer(const gl::Framebuffer::Data &data) override;
+ FramebufferImpl *createFramebuffer(const gl::Framebuffer::Data &data) override;
// Shader creation
- virtual ShaderImpl *createShader(const gl::Data &data, GLenum type);
+ virtual CompilerImpl *createCompiler(const gl::Data &data);
+ virtual ShaderImpl *createShader(GLenum type);
virtual ProgramImpl *createProgram();
// Shader operations
- void releaseShaderCompiler() override;
virtual gl::Error loadExecutable(const void *function, size_t length, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, ShaderExecutable **outExecutable);
+ bool separatedOutputBuffers, ShaderExecutableD3D **outExecutable);
virtual gl::Error compileToExecutable(gl::InfoLog &infoLog, const std::string &shaderHLSL, ShaderType type,
const std::vector<gl::LinkedVarying> &transformFeedbackVaryings,
- bool separatedOutputBuffers, D3DWorkaroundType workaround,
- ShaderExecutable **outExectuable);
- virtual UniformStorage *createUniformStorage(size_t storageSize);
+ bool separatedOutputBuffers, const D3DCompilerWorkarounds &workarounds,
+ ShaderExecutableD3D **outExectuable);
+ virtual UniformStorageD3D *createUniformStorage(size_t storageSize);
// Image operations
- virtual Image *createImage();
- gl::Error generateMipmap(Image *dest, Image *source) override;
- virtual TextureStorage *createTextureStorage2D(SwapChain *swapChain);
- virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels);
- virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels);
+ virtual ImageD3D *createImage();
+ gl::Error generateMipmap(ImageD3D *dest, ImageD3D *source) override;
+ virtual TextureStorage *createTextureStorage2D(SwapChainD3D *swapChain);
+ virtual TextureStorage *createTextureStorage2D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, int levels, bool hintLevelZeroOnly);
+ virtual TextureStorage *createTextureStorageCube(GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual TextureStorage *createTextureStorage3D(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
virtual TextureStorage *createTextureStorage2DArray(GLenum internalformat, bool renderTarget, GLsizei width, GLsizei height, GLsizei depth, int levels);
@@ -174,7 +195,6 @@ class Renderer9 : public RendererD3D
// Renderbuffer creation
virtual RenderbufferImpl *createRenderbuffer();
- virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth);
// Buffer creation
virtual BufferImpl *createBuffer();
@@ -194,7 +214,7 @@ class Renderer9 : public RendererD3D
// Buffer-to-texture and Texture-to-buffer copies
virtual bool supportsFastCopyBufferToTexture(GLenum internalFormat) const;
- virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTarget *destRenderTarget,
+ virtual gl::Error fastCopyBufferToTexture(const gl::PixelUnpackState &unpack, unsigned int offset, RenderTargetD3D *destRenderTarget,
GLenum destinationFormat, GLenum sourcePixelsType, const gl::Box &destArea);
// D3D9-renderer specific methods
@@ -202,15 +222,17 @@ class Renderer9 : public RendererD3D
D3DPOOL getTexturePool(DWORD usage) const;
- virtual bool getLUID(LUID *adapterLuid) const;
+ bool getLUID(LUID *adapterLuid) const override;
virtual VertexConversionType getVertexConversionType(const gl::VertexFormat &vertexFormat) const;
virtual GLenum getVertexComponentType(const gl::VertexFormat &vertexFormat) const;
gl::Error copyToRenderTarget(IDirect3DSurface9 *dest, IDirect3DSurface9 *source, bool fromManaged);
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderer9);
+ RendererClass getRendererClass() const override { return RENDERER_D3D9; }
+
+ D3DDEVTYPE getD3D9DeviceType() const { return mDeviceType; }
+ private:
void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap *outTextureCaps, gl::Extensions *outExtensions) const override;
Workarounds generateWorkarounds() const override;
@@ -225,12 +247,11 @@ class Renderer9 : public RendererD3D
gl::Error getCountingIB(size_t count, StaticIndexBufferInterface **outIB);
- gl::Error getNullColorbuffer(gl::FramebufferAttachment *depthbuffer, gl::FramebufferAttachment **outColorBuffer);
+ gl::Error getNullColorbuffer(const gl::FramebufferAttachment *depthbuffer, const gl::FramebufferAttachment **outColorBuffer);
D3DPOOL getBufferPool(DWORD usage) const;
HMODULE mD3d9Module;
- HDC mDc;
void initializeDevice();
D3DPRESENT_PARAMETERS getDefaultPresentParameters();
@@ -253,7 +274,6 @@ class Renderer9 : public RendererD3D
HWND mDeviceWindow;
- bool mDeviceLost;
D3DCAPS9 mDeviceCaps;
D3DADAPTER_IDENTIFIER9 mAdapterIdentifier;
@@ -262,21 +282,25 @@ class Renderer9 : public RendererD3D
GLsizei mRepeatDraw;
bool mSceneStarted;
- int mMinSwapInterval;
- int mMaxSwapInterval;
bool mVertexTextureSupport;
// current render target states
unsigned int mAppliedRenderTargetSerial;
- unsigned int mAppliedDepthbufferSerial;
- unsigned int mAppliedStencilbufferSerial;
+ unsigned int mAppliedDepthStencilSerial;
bool mDepthStencilInitialized;
bool mRenderTargetDescInitialized;
- RenderTarget::Desc mRenderTargetDesc;
unsigned int mCurStencilSize;
unsigned int mCurDepthSize;
+ struct RenderTargetDesc
+ {
+ size_t width;
+ size_t height;
+ D3DFORMAT format;
+ };
+ RenderTargetDesc mRenderTargetDesc;
+
IDirect3DStateBlock9 *mMaskedClearSavedState;
// previously set render states
@@ -346,7 +370,8 @@ class Renderer9 : public RendererD3D
} mNullColorbufferCache[NUM_NULL_COLORBUFFER_CACHE_ENTRIES];
UINT mMaxNullColorbufferLRU;
+ DebugAnnotator9 mAnnotator;
};
}
-#endif // LIBGLESV2_RENDERER_RENDERER9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
index 6d7d2d648f..cf831c62fa 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderCache.h
@@ -7,10 +7,10 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
-#include "libGLESv2/Error.h"
+#include "libANGLE/Error.h"
#include "common/debug.h"
@@ -21,7 +21,7 @@
namespace rx
{
template <typename ShaderObject>
-class ShaderCache
+class ShaderCache : angle::NonCopyable
{
public:
ShaderCache() : mDevice(NULL)
@@ -82,8 +82,6 @@ class ShaderCache
}
private:
- DISALLOW_COPY_AND_ASSIGN(ShaderCache);
-
const static size_t kMaxMapSize = 100;
HRESULT createShader(const DWORD *function, IDirect3DVertexShader9 **shader)
@@ -107,4 +105,4 @@ typedef ShaderCache<IDirect3DPixelShader9> PixelShaderCache;
}
-#endif // LIBGLESV2_RENDERER_SHADER_CACHE_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADERCACHE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
index bc7120461b..280e80930b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp
@@ -7,7 +7,7 @@
// ShaderExecutable9.cpp: Implements a D3D9-specific class to contain shader
// executable implementation details.
-#include "libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h"
+#include "libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h"
#include "common/debug.h"
@@ -15,14 +15,14 @@ namespace rx
{
ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable)
- : ShaderExecutable(function, length)
+ : ShaderExecutableD3D(function, length)
{
mPixelExecutable = executable;
mVertexExecutable = NULL;
}
ShaderExecutable9::ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable)
- : ShaderExecutable(function, length)
+ : ShaderExecutableD3D(function, length)
{
mVertexExecutable = executable;
mPixelExecutable = NULL;
@@ -34,7 +34,7 @@ ShaderExecutable9::~ShaderExecutable9()
SafeRelease(mPixelExecutable);
}
-ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutable *executable)
+ShaderExecutable9 *ShaderExecutable9::makeShaderExecutable9(ShaderExecutableD3D *executable)
{
ASSERT(HAS_DYNAMIC_TYPE(ShaderExecutable9*, executable));
return static_cast<ShaderExecutable9*>(executable);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
index fa1e6c2844..561f7defc8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h
@@ -7,33 +7,31 @@
// ShaderExecutable9.h: Defines a D3D9-specific class to contain shader
// executable implementation details.
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
-#include "libGLESv2/renderer/ShaderExecutable.h"
+#include "libANGLE/renderer/d3d/ShaderExecutableD3D.h"
namespace rx
{
-class ShaderExecutable9 : public ShaderExecutable
+class ShaderExecutable9 : public ShaderExecutableD3D
{
public:
ShaderExecutable9(const void *function, size_t length, IDirect3DPixelShader9 *executable);
ShaderExecutable9(const void *function, size_t length, IDirect3DVertexShader9 *executable);
virtual ~ShaderExecutable9();
- static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutable *executable);
+ static ShaderExecutable9 *makeShaderExecutable9(ShaderExecutableD3D *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
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SHADEREXECUTABLE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
index 95eb1a4371..1620668166 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp
@@ -6,12 +6,11 @@
// SwapChain9.cpp: Implements a back-end specific class for the D3D9 swap chain.
-#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-
-#include "common/features.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/features.h"
namespace rx
{
@@ -19,7 +18,9 @@ namespace rx
SwapChain9::SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
GLenum backBufferFormat, GLenum depthBufferFormat)
: mRenderer(renderer),
- SwapChain(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat)
+ SwapChainD3D(nativeWindow, shareHandle, backBufferFormat, depthBufferFormat),
+ mColorRenderTarget(this, false),
+ mDepthStencilRenderTarget(this, true)
{
mSwapChain = NULL;
mBackBuffer = NULL;
@@ -155,8 +156,10 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
const d3d9::TextureFormat &depthBufferd3dFormatInfo = d3d9::GetTextureFormatInfo(mDepthBufferFormat);
+ // Don't create a swapchain for NULLREF devices
+ D3DDEVTYPE deviceType = mRenderer->getD3D9DeviceType();
EGLNativeWindowType window = mNativeWindow.getNativeWindow();
- if (window)
+ if (window && deviceType != D3DDEVTYPE_NULLREF)
{
D3DPRESENT_PARAMETERS presentParameters = {0};
presentParameters.AutoDepthStencilFormat = depthBufferd3dFormatInfo.renderFormat;
@@ -181,7 +184,7 @@ EGLint SwapChain9::reset(int backbufferWidth, int backbufferHeight, EGLint swapI
//
// 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)
+ if (mRenderer->getVendorId() == VENDOR_ID_INTEL)
{
presentParameters.BackBufferWidth = (presentParameters.BackBufferWidth + 63) / 64 * 64;
}
@@ -381,7 +384,7 @@ IDirect3DTexture9 *SwapChain9::getOffscreenTexture()
return mOffscreenTexture;
}
-SwapChain9 *SwapChain9::makeSwapChain9(SwapChain *swapChain)
+SwapChain9 *SwapChain9::makeSwapChain9(SwapChainD3D *swapChain)
{
ASSERT(HAS_DYNAMIC_TYPE(SwapChain9*, swapChain));
return static_cast<SwapChain9*>(swapChain);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
index cb33bfbc0c..81ac08ca7b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h
@@ -6,17 +6,18 @@
// SwapChain9.h: Defines a back-end specific class for the D3D9 swap chain.
-#ifndef LIBGLESV2_RENDERER_SWAPCHAIN9_H_
-#define LIBGLESV2_RENDERER_SWAPCHAIN9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
#include "common/angleutils.h"
-#include "libGLESv2/renderer/SwapChain.h"
+#include "libANGLE/renderer/d3d/SwapChainD3D.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
namespace rx
{
class Renderer9;
-class SwapChain9 : public SwapChain
+class SwapChain9 : public SwapChainD3D
{
public:
SwapChain9(Renderer9 *renderer, NativeWindow nativeWindow, HANDLE shareHandle,
@@ -28,6 +29,9 @@ class SwapChain9 : public SwapChain
virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
virtual void recreate();
+ RenderTargetD3D *getColorRenderTarget() override { return &mColorRenderTarget; }
+ RenderTargetD3D *getDepthStencilRenderTarget() override { return &mDepthStencilRenderTarget; }
+
virtual IDirect3DSurface9 *getRenderTarget();
virtual IDirect3DSurface9 *getDepthStencil();
virtual IDirect3DTexture9 *getOffscreenTexture();
@@ -35,11 +39,9 @@ class SwapChain9 : public SwapChain
EGLint getWidth() const { return mWidth; }
EGLint getHeight() const { return mHeight; }
- static SwapChain9 *makeSwapChain9(SwapChain *swapChain);
+ static SwapChain9 *makeSwapChain9(SwapChainD3D *swapChain);
private:
- DISALLOW_COPY_AND_ASSIGN(SwapChain9);
-
void release();
Renderer9 *mRenderer;
@@ -52,7 +54,10 @@ class SwapChain9 : public SwapChain
IDirect3DSurface9 *mRenderTarget;
IDirect3DSurface9 *mDepthStencil;
IDirect3DTexture9* mOffscreenTexture;
+
+ SurfaceRenderTarget9 mColorRenderTarget;
+ SurfaceRenderTarget9 mDepthStencilRenderTarget;
};
}
-#endif // LIBGLESV2_RENDERER_SWAPCHAIN9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_SWAPCHAIN9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
index 0ff4fd3b0f..139cb3eb08 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp
@@ -8,15 +8,15 @@
// classes TextureStorage9_2D and TextureStorage9_Cube, which act as the interface to the
// D3D9 texture.
-#include "libGLESv2/renderer/d3d/d3d9/TextureStorage9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/SwapChain9.h"
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/main.h"
+#include "libANGLE/renderer/d3d/d3d9/TextureStorage9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/SwapChain9.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/TextureD3D.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Texture.h"
namespace rx
{
@@ -92,7 +92,7 @@ int TextureStorage9::getLevelCount() const
return mMipLevels - mTopLevel;
}
-gl::Error TextureStorage9::setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+gl::Error TextureStorage9::setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData)
{
UNREACHABLE();
@@ -180,7 +180,7 @@ gl::Error TextureStorage9_2D::getSurfaceLevel(int level, bool dirty, IDirect3DSu
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTarget **outRT)
+gl::Error TextureStorage9_2D::getRenderTarget(const gl::ImageIndex &/*index*/, RenderTargetD3D **outRT)
{
if (!mRenderTarget && isRenderTarget())
{
@@ -286,7 +286,7 @@ gl::Error TextureStorage9_2D::copyToStorage(TextureStorage *destStorage)
return gl::Error(GL_NO_ERROR);
}
-TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels)
+TextureStorage9_Cube::TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly)
: TextureStorage9(renderer, GetTextureUsage(internalformat, renderTarget))
{
mTexture = NULL;
@@ -356,7 +356,7 @@ gl::Error TextureStorage9_Cube::getCubeMapSurface(GLenum faceTarget, int level,
return gl::Error(GL_NO_ERROR);
}
-gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT)
+gl::Error TextureStorage9_Cube::getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT)
{
ASSERT(outRT);
ASSERT(index.mipIndex == 0);
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
index da0e1f2f18..5cc06f07b1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h
@@ -8,17 +8,17 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
+#include "libANGLE/renderer/d3d/TextureStorage.h"
#include "common/debug.h"
namespace rx
{
class Renderer9;
class SwapChain9;
-class RenderTarget;
+class RenderTargetD3D;
class RenderTarget9;
class TextureStorage9 : public TextureStorage
@@ -34,14 +34,14 @@ class TextureStorage9 : public TextureStorage
DWORD getUsage() const;
virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture) = 0;
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT) = 0;
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT) = 0;
virtual int getTopLevel() const;
virtual bool isRenderTarget() const;
virtual bool isManaged() const;
virtual int getLevelCount() const;
- virtual gl::Error setData(const gl::ImageIndex &index, Image *image, const gl::Box *destBox, GLenum type,
+ virtual gl::Error setData(const gl::ImageIndex &index, ImageD3D *image, const gl::Box *destBox, GLenum type,
const gl::PixelUnpackState &unpack, const uint8_t *pixelData);
protected:
@@ -57,8 +57,6 @@ class TextureStorage9 : public TextureStorage
TextureStorage9(Renderer9 *renderer, DWORD usage);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage9);
-
const DWORD mD3DUsage;
const D3DPOOL mD3DPool;
};
@@ -73,14 +71,12 @@ class TextureStorage9_2D : public TextureStorage9
static TextureStorage9_2D *makeTextureStorage9_2D(TextureStorage *storage);
gl::Error getSurfaceLevel(int level, bool dirty, IDirect3DSurface9 **outSurface);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
virtual gl::Error copyToStorage(TextureStorage *destStorage);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage9_2D);
-
IDirect3DTexture9 *mTexture;
RenderTarget9 *mRenderTarget;
};
@@ -88,20 +84,18 @@ class TextureStorage9_2D : public TextureStorage9
class TextureStorage9_Cube : public TextureStorage9
{
public:
- TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels);
+ TextureStorage9_Cube(Renderer9 *renderer, GLenum internalformat, bool renderTarget, int size, int levels, bool hintLevelZeroOnly);
virtual ~TextureStorage9_Cube();
static TextureStorage9_Cube *makeTextureStorage9_Cube(TextureStorage *storage);
gl::Error getCubeMapSurface(GLenum faceTarget, int level, bool dirty, IDirect3DSurface9 **outSurface);
- virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTarget **outRT);
+ virtual gl::Error getRenderTarget(const gl::ImageIndex &index, RenderTargetD3D **outRT);
virtual gl::Error getBaseTexture(IDirect3DBaseTexture9 **outTexture);
virtual gl::Error generateMipmap(const gl::ImageIndex &sourceIndex, const gl::ImageIndex &destIndex);
virtual gl::Error copyToStorage(TextureStorage *destStorage);
private:
- DISALLOW_COPY_AND_ASSIGN(TextureStorage9_Cube);
-
static const size_t CUBE_FACE_COUNT = 6;
IDirect3DCubeTexture9 *mTexture;
@@ -110,5 +104,5 @@ class TextureStorage9_Cube : public TextureStorage9
}
-#endif // LIBGLESV2_RENDERER_TEXTURESTORAGE9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_TEXTURESTORAGE9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
index 791c108462..fb626bc0cf 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexArray9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexArray9.h
@@ -6,11 +6,11 @@
// VertexArray9.h: Defines the rx::VertexArray9 class which implements rx::VertexArrayImpl.
-#ifndef LIBGLESV2_RENDERER_VERTEXARRAY9_H_
-#define LIBGLESV2_RENDERER_VERTEXARRAY9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
-#include "libGLESv2/renderer/VertexArrayImpl.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/VertexArrayImpl.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
namespace rx
{
@@ -33,11 +33,9 @@ class VertexArray9 : public VertexArrayImpl
virtual void enableAttribute(size_t idx, bool enabledState) { }
private:
- DISALLOW_COPY_AND_ASSIGN(VertexArray9);
-
Renderer9 *mRenderer;
};
}
-#endif // LIBGLESV2_RENDERER_VERTEXARRAY9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXARRAY9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
index b90133097c..cb5003997f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp
@@ -6,13 +6,13 @@
// VertexBuffer9.cpp: Defines the D3D9 VertexBuffer implementation.
-#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/vertexconversion.h"
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-#include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/Buffer.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+#include "libANGLE/renderer/d3d/BufferD3D.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/Buffer.h"
namespace rx
{
@@ -97,9 +97,9 @@ gl::Error VertexBuffer9::storeVertexAttributes(const gl::VertexAttribute &attrib
{
if (buffer)
{
- BufferD3D *storage = BufferD3D::makeFromBuffer(buffer);
+ BufferD3D *storage = GetImplAs<BufferD3D>(buffer);
ASSERT(storage);
- gl::Error error = storage->getData(&input);
+ error = storage->getData(&input);
if (error.isError())
{
return error;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
index 9af2b98a6e..f5b110b22b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h
@@ -6,10 +6,10 @@
// VertexBuffer9.h: Defines the D3D9 VertexBuffer implementation.
-#ifndef LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
-#define LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
-#include "libGLESv2/renderer/d3d/VertexBuffer.h"
+#include "libANGLE/renderer/d3d/VertexBuffer.h"
namespace rx
{
@@ -37,8 +37,6 @@ class VertexBuffer9 : public VertexBuffer
IDirect3DVertexBuffer9 *getBuffer() const;
private:
- DISALLOW_COPY_AND_ASSIGN(VertexBuffer9);
-
Renderer9 *mRenderer;
IDirect3DVertexBuffer9 *mVertexBuffer;
@@ -51,4 +49,4 @@ class VertexBuffer9 : public VertexBuffer
}
-#endif // LIBGLESV2_RENDERER_VERTEXBUFFER9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXBUFFER9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
index cefd786f11..f9eded9b50 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp
@@ -6,11 +6,11 @@
// VertexDeclarationCache.cpp: Implements a helper class to construct and cache vertex declarations.
-#include "libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h"
-#include "libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/VertexAttribute.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h"
+#include "libANGLE/renderer/d3d/d3d9/VertexBuffer9.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/VertexAttribute.h"
namespace rx
{
@@ -40,7 +40,7 @@ VertexDeclarationCache::~VertexDeclarationCache()
}
}
-gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw)
+gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw)
{
*repeatDraw = 1;
@@ -155,7 +155,7 @@ gl::Error VertexDeclarationCache::applyDeclaration(IDirect3DDevice9 *device, Tra
element->Type = d3d9VertexInfo.nativeFormat;
element->Method = D3DDECLMETHOD_DEFAULT;
element->Usage = D3DDECLUSAGE_TEXCOORD;
- element->UsageIndex = programBinary->getSemanticIndex(i);
+ element->UsageIndex = program->getSemanticIndex(i);
element++;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
index 9af36e0d7a..fbd673097f 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.h
@@ -6,15 +6,16 @@
// VertexDeclarationCache.h: Defines a helper class to construct and cache vertex declarations.
-#ifndef LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
-#define LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
-#include "libGLESv2/Error.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/renderer/d3d/VertexDataManager.h"
namespace gl
{
class VertexDataManager;
+class Program;
}
namespace rx
@@ -26,7 +27,7 @@ class VertexDeclarationCache
VertexDeclarationCache();
~VertexDeclarationCache();
- gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::ProgramBinary *programBinary, GLsizei instances, GLsizei *repeatDraw);
+ gl::Error applyDeclaration(IDirect3DDevice9 *device, TranslatedAttribute attributes[], gl::Program *program, GLsizei instances, GLsizei *repeatDraw);
void markStateDirty();
@@ -56,4 +57,4 @@ class VertexDeclarationCache
}
-#endif // LIBGLESV2_RENDERER_VERTEXDECLARATIONCACHE_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXDECLARATIONCACHE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
index f3acaf7987..9bad5503d9 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp
@@ -7,12 +7,12 @@
// 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"
+#include "libANGLE/renderer/d3d/copyimage.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/d3d9/Renderer9.h"
+#include "libANGLE/renderer/d3d/d3d9/vertexconversion.h"
+#include "libANGLE/renderer/d3d/generatemip.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
namespace rx
{
@@ -57,6 +57,13 @@ D3DFormat::D3DFormat()
: pixelBytes(0),
blockWidth(0),
blockHeight(0),
+ redBits(0),
+ greenBits(0),
+ blueBits(0),
+ alphaBits(0),
+ luminanceBits(0),
+ depthBits(0),
+ stencilBits(0),
internalFormat(GL_NONE),
mipGenerationFunction(NULL),
colorReadFunction(NULL),
@@ -71,13 +78,22 @@ ColorCopyFunction D3DFormat::getFastCopyFunction(GLenum format, GLenum type) con
}
static inline void InsertD3DFormatInfo(D3D9FormatInfoMap *map, D3DFORMAT format, GLuint bits, GLuint blockWidth,
- GLuint blockHeight, GLenum internalFormat, MipGenerationFunction mipFunc,
+ GLuint blockHeight, GLuint redBits, GLuint greenBits, GLuint blueBits,
+ GLuint alphaBits, GLuint lumBits, GLuint depthBits, GLuint stencilBits,
+ GLenum internalFormat, MipGenerationFunction mipFunc,
ColorReadFunction colorReadFunc)
{
D3DFormat info;
info.pixelBytes = bits / 8;
info.blockWidth = blockWidth;
info.blockHeight = blockHeight;
+ info.redBits = redBits;
+ info.greenBits = greenBits;
+ info.blueBits = blueBits;
+ info.alphaBits = alphaBits;
+ info.luminanceBits = lumBits;
+ info.depthBits = depthBits;
+ info.stencilBits = stencilBits;
info.internalFormat = internalFormat;
info.mipGenerationFunction = mipFunc;
info.colorReadFunction = colorReadFunc;
@@ -96,35 +112,35 @@ static D3D9FormatInfoMap BuildD3D9FormatInfoMap()
{
D3D9FormatInfoMap map;
- // | D3DFORMAT | S |W |H | Internal format | Mip generation function | Color read function |
- InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, GL_NONE, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, GL_NONE, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
- InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> );
- InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
-
- InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, GL_DEPTH_COMPONENT16, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, GL_DEPTH_COMPONENT32_OES, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
-
- InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL );
- InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL );
+ // | D3DFORMAT | S |W |H | R | G | B | A | L | D | S | Internal format | Mip generation function | Color read function |
+ InsertD3DFormatInfo(&map, D3DFMT_NULL, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, GL_NONE, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_L8, 8, 1, 1, 0, 0, 0, 0, 8, 0, 0, GL_LUMINANCE8_EXT, GenerateMip<L8>, ReadColor<L8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8, 8, 1, 1, 0, 0, 0, 8, 0, 0, 0, GL_ALPHA8_EXT, GenerateMip<A8>, ReadColor<A8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8L8, 16, 1, 1, 0, 0, 0, 8, 8, 0, 0, GL_LUMINANCE8_ALPHA8_EXT, GenerateMip<A8L8>, ReadColor<A8L8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A4R4G4B4, 16, 1, 1, 4, 4, 4, 4, 0, 0, 0, GL_BGRA4_ANGLEX, GenerateMip<B4G4R4A4>, ReadColor<B4G4R4A4, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A1R5G5B5, 16, 1, 1, 5, 5, 5, 1, 0, 0, 0, GL_BGR5_A1_ANGLEX, GenerateMip<B5G5R5A1>, ReadColor<B5G5R5A1, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_R5G6B5, 16, 1, 1, 5, 6, 5, 0, 0, 0, 0, GL_RGB565, GenerateMip<R5G6B5>, ReadColor<R5G6B5, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_X8R8G8B8, 32, 1, 1, 8, 8, 8, 0, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8X8>, ReadColor<B8G8R8X8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A8R8G8B8, 32, 1, 1, 8, 8, 8, 8, 0, 0, 0, GL_BGRA8_EXT, GenerateMip<B8G8R8A8>, ReadColor<B8G8R8A8, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_R16F, 16, 1, 1, 16, 0, 0, 0, 0, 0, 0, GL_R16F_EXT, GenerateMip<R16F>, ReadColor<R16F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_G16R16F, 32, 1, 1, 16, 16, 0, 0, 0, 0, 0, GL_RG16F_EXT, GenerateMip<R16G16F>, ReadColor<R16G16F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A16B16G16R16F, 64, 1, 1, 16, 16, 16, 16, 0, 0, 0, GL_RGBA16F_EXT, GenerateMip<R16G16B16A16F>, ReadColor<R16G16B16A16F, GLfloat>);
+ InsertD3DFormatInfo(&map, D3DFMT_R32F, 32, 1, 1, 32, 0, 0, 0, 0, 0, 0, GL_R32F_EXT, GenerateMip<R32F>, ReadColor<R32F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_G32R32F, 64, 1, 1, 32, 32, 0, 0, 0, 0, 0, GL_RG32F_EXT, GenerateMip<R32G32F>, ReadColor<R32G32F, GLfloat> );
+ InsertD3DFormatInfo(&map, D3DFMT_A32B32G32R32F, 128, 1, 1, 32, 32, 32, 32, 0, 0, 0, GL_RGBA32F_EXT, GenerateMip<R32G32B32A32F>, ReadColor<R32G32B32A32F, GLfloat>);
+
+ InsertD3DFormatInfo(&map, D3DFMT_D16, 16, 1, 1, 0, 0, 0, 0, 0, 16, 0, GL_DEPTH_COMPONENT16, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D24S8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D24X8, 32, 1, 1, 0, 0, 0, 0, 0, 24, 0, GL_DEPTH_COMPONENT16, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_D32, 32, 1, 1, 0, 0, 0, 0, 0, 32, 0, GL_DEPTH_COMPONENT32_OES, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_INTZ, 32, 1, 1, 0, 0, 0, 0, 0, 24, 8, GL_DEPTH24_STENCIL8_OES, NULL, NULL );
+
+ InsertD3DFormatInfo(&map, D3DFMT_DXT1, 64, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_DXT3, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, NULL, NULL );
+ InsertD3DFormatInfo(&map, D3DFMT_DXT5, 128, 4, 4, 0, 0, 0, 0, 0, 0, 0, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, NULL, NULL );
return map;
}
@@ -192,8 +208,8 @@ typedef std::pair<GLenum, TextureFormat> D3D9FormatPair;
typedef std::map<GLenum, TextureFormat> D3D9FormatMap;
TextureFormat::TextureFormat()
- : texFormat(D3DFMT_NULL),
- renderFormat(D3DFMT_NULL),
+ : texFormat(D3DFMT_UNKNOWN),
+ renderFormat(D3DFMT_UNKNOWN),
dataInitializerFunction(NULL),
loadFunction(UnreachableLoad)
{
@@ -544,7 +560,7 @@ const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::Vert
static bool initialized = false;
static DWORD intializedDeclTypes = 0;
static VertexFormat formatConverters[NUM_GL_VERTEX_ATTRIB_TYPES][2][4];
- if (!initialized)
+ if (intializedDeclTypes != supportedDeclTypes)
{
const TranslationDescription translations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] = // [GL types as enumerated by typeIndex()][normalized][size-1]
{
@@ -576,8 +592,6 @@ const VertexFormat &GetVertexFormatInfo(DWORD supportedDeclTypes, const gl::Vert
intializedDeclTypes = supportedDeclTypes;
}
- ASSERT(intializedDeclTypes == supportedDeclTypes);
-
// Pure integer attributes only supported in ES3.0
ASSERT(!vertexFormat.mPureInteger);
return formatConverters[ComputeTypeIndex(vertexFormat.mType)][vertexFormat.mNormalized][vertexFormat.mComponents - 1];
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
index f26fe43b36..15e26599c8 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/formatutils9.h
@@ -7,10 +7,13 @@
// formatutils9.h: Queries for GL image formats and their translations to D3D9
// formats.
-#ifndef LIBGLESV2_RENDERER_FORMATUTILS9_H_
-#define LIBGLESV2_RENDERER_FORMATUTILS9_H_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
-#include "libGLESv2/formatutils.h"
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+#include "libANGLE/angletypes.h"
+
+#include "common/platform.h"
#include <map>
@@ -32,6 +35,15 @@ struct D3DFormat
GLuint blockWidth;
GLuint blockHeight;
+ GLuint redBits;
+ GLuint greenBits;
+ GLuint blueBits;
+ GLuint alphaBits;
+ GLuint luminanceBits;
+
+ GLuint depthBits;
+ GLuint stencilBits;
+
GLenum internalFormat;
MipGenerationFunction mipGenerationFunction;
@@ -71,4 +83,4 @@ const TextureFormat &GetTextureFormatInfo(GLenum internalFormat);
}
-#endif // LIBGLESV2_RENDERER_FORMATUTILS9_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_FORMATUTILS9_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
index a98b2081f3..c9711ac052 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp
@@ -7,12 +7,13 @@
// renderer9_utils.cpp: Conversion functions and other utility routines
// specific to the D3D9 renderer.
-#include "libGLESv2/renderer/d3d/d3d9/renderer9_utils.h"
-#include "libGLESv2/renderer/d3d/d3d9/formatutils9.h"
-#include "libGLESv2/renderer/Workarounds.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/renderer/d3d/d3d9/RenderTarget9.h"
+#include "libANGLE/renderer/d3d/d3d9/renderer9_utils.h"
+#include "libANGLE/renderer/d3d/d3d9/formatutils9.h"
+#include "libANGLE/renderer/d3d/FramebufferD3D.h"
+#include "libANGLE/renderer/Workarounds.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/renderer/d3d/d3d9/RenderTarget9.h"
#include "common/mathutil.h"
#include "common/debug.h"
@@ -276,29 +277,41 @@ static gl::TextureCaps GenerateTextureFormatCaps(GLenum internalFormat, IDirect3
const d3d9::TextureFormat &d3dFormatInfo = d3d9::GetTextureFormatInfo(internalFormat);
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
- {
- textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
- }
- else
+
+ if (d3dFormatInfo.texFormat != D3DFMT_UNKNOWN)
{
- textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) &&
- SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat));
- }
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
+ {
+ textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+ }
+ else
+ {
+ textureCaps.texturable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat)) &&
+ SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, 0, D3DRTYPE_CUBETEXTURE, d3dFormatInfo.texFormat));
+ }
- textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
- textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat)) ||
- SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+ textureCaps.filterable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_QUERY_FILTER, D3DRTYPE_TEXTURE, d3dFormatInfo.texFormat));
+ }
- textureCaps.sampleCounts.insert(1);
- for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
+ if (d3dFormatInfo.renderFormat != D3DFMT_UNKNOWN)
{
- D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
+ textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_RENDERTARGET, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
- HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
- if (SUCCEEDED(result))
+ if ((formatInfo.depthBits > 0 || formatInfo.stencilBits > 0) && !textureCaps.renderable)
{
- textureCaps.sampleCounts.insert(i);
+ textureCaps.renderable = SUCCEEDED(d3d9->CheckDeviceFormat(adapter, deviceType, adapterFormat, D3DUSAGE_DEPTHSTENCIL, D3DRTYPE_TEXTURE, d3dFormatInfo.renderFormat));
+ }
+
+ textureCaps.sampleCounts.insert(1);
+ for (size_t i = D3DMULTISAMPLE_2_SAMPLES; i <= D3DMULTISAMPLE_16_SAMPLES; i++)
+ {
+ D3DMULTISAMPLE_TYPE multisampleType = D3DMULTISAMPLE_TYPE(i);
+
+ HRESULT result = d3d9->CheckDeviceMultiSampleType(adapter, deviceType, d3dFormatInfo.renderFormat, TRUE, multisampleType, NULL);
+ if (SUCCEEDED(result))
+ {
+ textureCaps.sampleCounts.insert(i);
+ }
}
}
@@ -378,6 +391,22 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
// Program and shader binary formats (no supported shader binary formats)
caps->programBinaryFormats.push_back(GL_PROGRAM_BINARY_ANGLE);
+ caps->vertexHighpFloat.setIEEEFloat();
+ caps->vertexMediumpFloat.setIEEEFloat();
+ caps->vertexLowpFloat.setIEEEFloat();
+ caps->fragmentHighpFloat.setIEEEFloat();
+ caps->fragmentMediumpFloat.setIEEEFloat();
+ caps->fragmentLowpFloat.setIEEEFloat();
+
+ // Some (most) hardware only supports single-precision floating-point numbers,
+ // which can accurately represent integers up to +/-16777216
+ caps->vertexHighpInt.setSimulatedInt(24);
+ caps->vertexMediumpInt.setSimulatedInt(24);
+ caps->vertexLowpInt.setSimulatedInt(24);
+ caps->fragmentHighpInt.setSimulatedInt(24);
+ caps->fragmentMediumpInt.setSimulatedInt(24);
+ caps->fragmentLowpInt.setSimulatedInt(24);
+
// WaitSync is ES3-only, set to zero
caps->maxServerWaitTimeout = 0;
@@ -454,14 +483,23 @@ void GenerateCaps(IDirect3D9 *d3d9, IDirect3DDevice9 *device, D3DDEVTYPE deviceT
extensions->mapBuffer = false;
extensions->mapBufferRange = false;
- // ATI cards on XP have problems with non-power-of-two textures.
+ // textureRG is emulated and not performant.
+ extensions->textureRG = false;
+
D3DADAPTER_IDENTIFIER9 adapterId = { 0 };
if (SUCCEEDED(d3d9->GetAdapterIdentifier(adapter, 0, &adapterId)))
{
+ // ATI cards on XP have problems with non-power-of-two textures.
extensions->textureNPOT = !(deviceCaps.TextureCaps & D3DPTEXTURECAPS_POW2) &&
!(deviceCaps.TextureCaps & D3DPTEXTURECAPS_CUBEMAP_POW2) &&
!(deviceCaps.TextureCaps & D3DPTEXTURECAPS_NONPOW2CONDITIONAL) &&
!(!isWindowsVistaOrGreater() && adapterId.VendorId == VENDOR_ID_AMD);
+
+ // Disable depth texture support on AMD cards (See ANGLE issue 839)
+ if (adapterId.VendorId == VENDOR_ID_AMD)
+ {
+ extensions->depthTextures = false;
+ }
}
else
{
@@ -533,9 +571,9 @@ void MakeValidSize(bool isImage, D3DFORMAT format, GLsizei *requestWidth, GLsize
*levelOffset = upsampleCount;
}
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT)
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT)
{
- RenderTarget *renderTarget = NULL;
+ RenderTargetD3D *renderTarget = NULL;
gl::Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
if (error.isError())
{
@@ -550,6 +588,7 @@ Workarounds GenerateWorkarounds()
Workarounds workarounds;
workarounds.mrtPerfWorkaround = true;
workarounds.setDataFasterThanImageUpload = false;
+ workarounds.useInstancedPointSpriteEmulation = false;
return workarounds;
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
index 9760b9735a..3c6a57aee3 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h
@@ -7,12 +7,12 @@
// 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
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/Error.h"
+#include "libANGLE/angletypes.h"
+#include "libANGLE/Caps.h"
+#include "libANGLE/Error.h"
namespace gl
{
@@ -76,11 +76,11 @@ inline bool isDeviceLostError(HRESULT errorCode)
}
}
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget9 **outRT);
+gl::Error GetAttachmentRenderTarget(const gl::FramebufferAttachment *attachment, RenderTarget9 **outRT);
Workarounds GenerateWorkarounds();
}
}
-#endif // LIBGLESV2_RENDERER_RENDERER9_UTILS_H
+#endif // LIBANGLE_RENDERER_D3D_D3D9_RENDERER9UTILS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
index eb43eb3e7a..dc357d0fa6 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
@@ -11,7 +11,7 @@ uniform float4 add : c1;
// Passthrough Pixel Shader
// Outputs texture 0 sampled at texcoord 0.
-float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR
+float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
{
return tex2D(tex, texcoord.xy);
};
@@ -19,7 +19,7 @@ float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR
// Luminance Conversion Pixel Shader
// Performs a mad operation using the LA data from the texture with mult.xw and add.xw.
// Returns data in the form of llla
-float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR
+float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
{
return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
};
@@ -27,7 +27,7 @@ float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR
// RGB/A Component Mask Pixel Shader
// Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw.
// Returns data in the form of rgba
-float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR
+float4 componentmaskps(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/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
index 3bd611ba5d..3a36980b93 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
@@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0;
// Outputs the homogenous position as-is.
// Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
// C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
-VS_OUTPUT VS_standard(in float4 position : POSITION)
+VS_OUTPUT standardvs(in float4 position : POSITION)
{
VS_OUTPUT Out;
@@ -32,7 +32,7 @@ VS_OUTPUT VS_standard(in float4 position : POSITION)
// Outputs the homogenous position as-is.
// Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
// C0.XY must be the half-pixel width and height. C0.ZW must be 0.
-VS_OUTPUT VS_flipy(in float4 position : POSITION)
+VS_OUTPUT flipyvs(in float4 position : POSITION)
{
VS_OUTPUT Out;
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
index 81ba8a0767..32eb376a78 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/vertexconversion.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/vertexconversion.h
@@ -7,8 +7,8 @@
// 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_
+#ifndef LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
+#define LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
#include <limits>
#include <cstdint>
@@ -194,4 +194,4 @@ struct VertexDataConverter
}
-#endif // LIBGLESV2_VERTEXCONVERSION_H_
+#endif // LIBANGLE_RENDERER_D3D_D3D9_VERTEXCONVERSION_H_
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp
new file mode 100644
index 0000000000..8a4d41cbd9
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.cpp
@@ -0,0 +1,147 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.cpp: Queries for GL image formats and their translations to D3D
+// formats.
+
+#include "libANGLE/renderer/d3d/formatutilsD3D.h"
+
+#include <map>
+
+#include "common/debug.h"
+#include "libANGLE/renderer/d3d/imageformats.h"
+#include "libANGLE/renderer/d3d/copyimage.h"
+
+namespace rx
+{
+
+typedef std::pair<GLenum, GLenum> FormatTypePair;
+typedef std::pair<FormatTypePair, ColorWriteFunction> FormatWriteFunctionPair;
+typedef std::map<FormatTypePair, ColorWriteFunction> FormatWriteFunctionMap;
+
+static inline void InsertFormatWriteFunctionMapping(FormatWriteFunctionMap *map, GLenum format, GLenum type,
+ ColorWriteFunction writeFunc)
+{
+ map->insert(FormatWriteFunctionPair(FormatTypePair(format, type), writeFunc));
+}
+
+static FormatWriteFunctionMap BuildFormatWriteFunctionMap()
+{
+ FormatWriteFunctionMap map;
+
+ // | Format | Type | Color write function |
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_BYTE, WriteColor<R8G8B8A8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4, WriteColor<R4G4B4A4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, WriteColor<R5G5B5A1, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_FLOAT, WriteColor<R32G32B32A32F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT, WriteColor<R16G16B16A16F, GLfloat>);
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA, GL_HALF_FLOAT_OES, WriteColor<R16G16B16A16F, GLfloat>);
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_BYTE, WriteColor<R8G8B8A8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16A16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_SHORT, WriteColor<R16G16B16A16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32A32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_INT, WriteColor<R32G32B32A32S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGBA_INTEGER, GL_UNSIGNED_INT_2_10_10_10_REV, WriteColor<R10G10B10A2, GLuint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_BYTE, WriteColor<R8G8B8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, WriteColor<R5G6B5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_10F_11F_11F_REV, WriteColor<R11G11B10F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_UNSIGNED_INT_5_9_9_9_REV, WriteColor<R9G9B9E5, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_FLOAT, WriteColor<R32G32B32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT, WriteColor<R16G16B16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB, GL_HALF_FLOAT_OES, WriteColor<R16G16B16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_BYTE, WriteColor<R8G8B8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16B16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_SHORT, WriteColor<R16G16B16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32B32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RGB_INTEGER, GL_INT, WriteColor<R32G32B32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_BYTE, WriteColor<R8G8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_FLOAT, WriteColor<R32G32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT, WriteColor<R16G16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG, GL_HALF_FLOAT_OES, WriteColor<R16G16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8G8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_BYTE, WriteColor<R8G8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16G16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_SHORT, WriteColor<R16G16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_UNSIGNED_INT, WriteColor<R32G32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RG_INTEGER, GL_INT, WriteColor<R32G32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_UNSIGNED_BYTE, WriteColor<R8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_BYTE, WriteColor<R8S, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_FLOAT, WriteColor<R32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT, WriteColor<R16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED, GL_HALF_FLOAT_OES, WriteColor<R16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_BYTE, WriteColor<R8, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_BYTE, WriteColor<R8S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_SHORT, WriteColor<R16, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_SHORT, WriteColor<R16S, GLint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_UNSIGNED_INT, WriteColor<R32, GLuint> );
+ InsertFormatWriteFunctionMapping(&map, GL_RED_INTEGER, GL_INT, WriteColor<R32S, GLint> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, WriteColor<L8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_UNSIGNED_BYTE, WriteColor<L8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_UNSIGNED_BYTE, WriteColor<A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_FLOAT, WriteColor<L32A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_FLOAT, WriteColor<L32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_FLOAT, WriteColor<A32F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE_ALPHA, GL_HALF_FLOAT_OES, WriteColor<L16A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_LUMINANCE, GL_HALF_FLOAT_OES, WriteColor<L16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT, WriteColor<A16F, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_ALPHA, GL_HALF_FLOAT_OES, WriteColor<A16F, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_BYTE, WriteColor<B8G8R8A8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT, WriteColor<B4G4R4A4, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_BGRA_EXT, GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT, WriteColor<B5G5R5A1, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8, GLfloat> );
+ InsertFormatWriteFunctionMapping(&map, GL_SRGB_ALPHA_EXT, GL_UNSIGNED_BYTE, WriteColor<R8G8B8A8, GLfloat> );
+
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE, GL_UNSIGNED_BYTE, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE, GL_UNSIGNED_BYTE, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_COMPONENT, GL_FLOAT, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_STENCIL, GL_UNSIGNED_BYTE, NULL );
+
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, NULL );
+ InsertFormatWriteFunctionMapping(&map, GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, NULL );
+
+ return map;
+}
+
+ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type)
+{
+ static const FormatWriteFunctionMap formatTypeMap = BuildFormatWriteFunctionMap();
+ FormatWriteFunctionMap::const_iterator iter = formatTypeMap.find(FormatTypePair(format, type));
+ ASSERT(iter != formatTypeMap.end());
+ if (iter != formatTypeMap.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
new file mode 100644
index 0000000000..6dd59ca94b
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/formatutilsD3D.h
@@ -0,0 +1,50 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// formatutils9.h: Queries for GL image formats and their translations to D3D
+// formats.
+
+#ifndef LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+#define LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
+
+#include "angle_gl.h"
+
+#include <cstddef>
+#include <stdint.h>
+
+namespace rx
+{
+
+typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
+ const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
+ uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
+
+typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth,
+ const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
+
+typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
+ uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
+
+typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
+typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
+
+typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
+
+enum VertexConversionType
+{
+ VERTEX_CONVERT_NONE = 0,
+ VERTEX_CONVERT_CPU = 1,
+ VERTEX_CONVERT_GPU = 2,
+ VERTEX_CONVERT_BOTH = 3
+};
+
+ColorWriteFunction GetColorWriteFunction(GLenum format, GLenum type);
+
+}
+
+#endif // LIBANGLE_RENDERER_D3D_FORMATUTILSD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h
index a57b00d444..398ef26b30 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -7,11 +7,11 @@
// generatemip.h: Defines the GenerateMip function, templated on the format
// type of the image for which mip levels are being generated.
-#ifndef LIBGLESV2_RENDERER_GENERATEMIP_H_
-#define LIBGLESV2_RENDERER_GENERATEMIP_H_
+#ifndef LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
+#define LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
-#include "libGLESv2/renderer/imageformats.h"
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/renderer/d3d/imageformats.h"
+#include "libANGLE/angletypes.h"
namespace rx
{
@@ -25,4 +25,4 @@ inline void GenerateMip(size_t sourceWidth, size_t sourceHeight, size_t sourceDe
#include "generatemip.inl"
-#endif // LIBGLESV2_RENDERER_GENERATEMIP_H_
+#endif // LIBANGLE_RENDERER_D3D_GENERATEMIP_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl
index 6788a42f03..265783641e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/generatemip.inl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/generatemip.inl
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h
index 2140a9ee72..e0f9a16c1a 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/imageformats.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/imageformats.h
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -7,8 +7,10 @@
// imageformats.h: Defines image format types with functions for mip generation
// and copying.
-#ifndef LIBGLESV2_RENDERER_IMAGEFORMATS_H_
-#define LIBGLESV2_RENDERER_IMAGEFORMATS_H_
+#ifndef LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
+#define LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
+
+#include "libANGLE/angletypes.h"
#include "common/mathutil.h"
@@ -2026,4 +2028,4 @@ struct R11G11B10F
}
-#endif // LIBGLESV2_RENDERER_IMAGEFORMATS_H_
+#endif // LIBANGLE_RENDERER_D3D_IMAGEFORMATS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp
index 1986191a75..172832b3e7 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.cpp
@@ -1,12 +1,12 @@
//
-// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// loadimage.cpp: Defines image loading functions.
-#include "libGLESv2/renderer/loadimage.h"
+#include "libANGLE/renderer/d3d/loadimage.h"
namespace rx
{
@@ -91,9 +91,10 @@ void LoadL8ToRGBA8(size_t width, size_t height, size_t depth,
uint8_t *dest = OffsetDataPointer<uint8_t>(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];
+ uint8_t sourceVal = source[x];
+ dest[4 * x + 0] = sourceVal;
+ dest[4 * x + 1] = sourceVal;
+ dest[4 * x + 2] = sourceVal;
dest[4 * x + 3] = 0xFF;
}
}
@@ -341,7 +342,7 @@ void LoadRGBA8ToBGRA8(size_t width, size_t height, size_t depth,
for (size_t x = 0; x < width; x++)
{
uint32_t rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
}
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h
index bcdff24a66..6967dc868e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.h
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.h
@@ -1,17 +1,17 @@
//
-// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2013-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// loadimage.h: Defines image loading functions
-#ifndef LIBGLESV2_RENDERER_LOADIMAGE_H_
-#define LIBGLESV2_RENDERER_LOADIMAGE_H_
+#ifndef LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
+#define LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
-#include "libGLESv2/angletypes.h"
+#include "libANGLE/angletypes.h"
-#include <cstdint>
+#include <stdint.h>
namespace rx
{
@@ -190,4 +190,4 @@ inline const T *OffsetDataPointer(const uint8_t *data, size_t y, size_t z, size_
#include "loadimage.inl"
-#endif // LIBGLESV2_RENDERER_LOADIMAGE_H_
+#endif // LIBANGLE_RENDERER_D3D_LOADIMAGE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl
index abd0a3673c..920e667db1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimage.inl
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimage.inl
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2014-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
index 159b4c7e9f..c87d35c82b 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/loadimageSSE2.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/loadimageSSE2.cpp
@@ -1,5 +1,5 @@
//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2015 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
@@ -8,7 +8,13 @@
// 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"
+#include "libANGLE/renderer/d3d/loadimage.h"
+
+#include "common/platform.h"
+
+#ifdef ANGLE_USE_SSE
+#include <emmintrin.h>
+#endif
namespace rx
{
@@ -17,12 +23,7 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
{
-#if defined(_M_ARM)
- // Ensure that this function is reported as not implemented for ARM builds because
- // the instructions below are not present for that architecture.
- UNIMPLEMENTED();
- return;
-#else
+#if defined(ANGLE_USE_SSE)
__m128i zeroWide = _mm_setzero_si128();
for (size_t z = 0; z < depth; z++)
@@ -60,6 +61,11 @@ void LoadA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
}
}
}
+#else
+ // Ensure that this function is reported as not implemented for ARM builds because
+ // the instructions below are not present for that architecture.
+ UNIMPLEMENTED();
+ return;
#endif
}
@@ -67,12 +73,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch)
{
-#if defined(_M_ARM)
- // Ensure that this function is reported as not implemented for ARM builds because
- // the instructions below are not present for that architecture.
- UNIMPLEMENTED();
- return;
-#else
+#if defined(ANGLE_USE_SSE)
__m128i brMask = _mm_set1_epi32(0x00ff00ff);
for (size_t z = 0; z < depth; z++)
@@ -88,7 +89,7 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
for (; ((reinterpret_cast<intptr_t>(&dest[x]) & 15) != 0) && x < width; x++)
{
uint32_t rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
}
for (; x + 3 < width; x += 4)
@@ -108,11 +109,17 @@ void LoadRGBA8ToBGRA8_SSE2(size_t width, size_t height, size_t depth,
for (; x < width; x++)
{
uint32_t rgba = source[x];
- dest[x] = (_rotl(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
+ dest[x] = (ANGLE_ROTL(rgba, 16) & 0x00ff00ff) | (rgba & 0xff00ff00);
}
}
}
+#else
+ // Ensure that this function is reported as not implemented for ARM builds because
+ // the instructions below are not present for that architecture.
+ UNIMPLEMENTED();
+ return;
#endif
}
}
+
diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
new file mode 100644
index 0000000000..12ee6a2b93
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
@@ -0,0 +1,503 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationEGL.cpp: Validation functions for generic EGL entry point parameters
+
+#include "libANGLE/validationEGL.h"
+
+#include "libANGLE/Config.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+
+#include <EGL/eglext.h>
+
+namespace egl
+{
+
+Error ValidateDisplay(const Display *display)
+{
+ if (display == EGL_NO_DISPLAY)
+ {
+ return Error(EGL_BAD_DISPLAY);
+ }
+
+ if (!display->isInitialized())
+ {
+ return Error(EGL_NOT_INITIALIZED);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateSurface(const Display *display, Surface *surface)
+{
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!display->isValidSurface(surface))
+ {
+ return Error(EGL_BAD_SURFACE);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateConfig(const Display *display, const Config *config)
+{
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!display->isValidConfig(config))
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateContext(const Display *display, gl::Context *context)
+{
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!display->isValidContext(context))
+ {
+ return Error(EGL_BAD_CONTEXT);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+ const AttributeMap& attributes)
+{
+ Error error = ValidateConfig(display, configuration);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ // Get the requested client version (default is 1) and check it is 2 or 3.
+ EGLint clientMajorVersion = 1;
+ EGLint clientMinorVersion = 0;
+ EGLint contextFlags = 0;
+ bool resetNotification = false;
+ bool robustAccess = false;
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLint attribute = attributeIter->first;
+ EGLint value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_CONTEXT_CLIENT_VERSION:
+ clientMajorVersion = value;
+ break;
+
+ case EGL_CONTEXT_MINOR_VERSION:
+ clientMinorVersion = value;
+ break;
+
+ case EGL_CONTEXT_FLAGS_KHR:
+ contextFlags = value;
+ break;
+
+ case EGL_CONTEXT_OPENGL_PROFILE_MASK_KHR:
+ // Only valid for OpenGL (non-ES) contexts
+ return Error(EGL_BAD_ATTRIBUTE);
+
+ case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value != EGL_TRUE && value != EGL_FALSE)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ robustAccess = (value == EGL_TRUE);
+ break;
+
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_KHR:
+ static_assert(EGL_LOSE_CONTEXT_ON_RESET_EXT == EGL_LOSE_CONTEXT_ON_RESET_KHR, "EGL extension enums not equal.");
+ static_assert(EGL_NO_RESET_NOTIFICATION_EXT == EGL_NO_RESET_NOTIFICATION_KHR, "EGL extension enums not equal.");
+ // same as EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT, fall through
+ case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
+ if (!display->getExtensions().createContextRobustness)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value == EGL_LOSE_CONTEXT_ON_RESET_EXT)
+ {
+ resetNotification = true;
+ }
+ else if (value != EGL_NO_RESET_NOTIFICATION_EXT)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if ((clientMajorVersion != 2 && clientMajorVersion != 3) || clientMinorVersion != 0)
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+
+ if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG))
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+
+ // Note: EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE_BIT_KHR does not apply to ES
+ const EGLint validContextFlags = (EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR |
+ EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR);
+ if ((contextFlags & ~validContextFlags) != 0)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ if ((contextFlags & EGL_CONTEXT_OPENGL_ROBUST_ACCESS_BIT_KHR) > 0)
+ {
+ robustAccess = true;
+ }
+
+ if (robustAccess)
+ {
+ // Unimplemented
+ return Error(EGL_BAD_CONFIG);
+ }
+
+ if (shareContext)
+ {
+ // Shared context is invalid or is owned by another display
+ if (!display->isValidContext(shareContext))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if (shareContext->isResetNotificationEnabled() != resetNotification)
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if (shareContext->getClientVersion() != clientMajorVersion)
+ {
+ return Error(EGL_BAD_CONTEXT);
+ }
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+ const AttributeMap& attributes)
+{
+ Error error = ValidateConfig(display, config);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ if (!display->isValidNativeWindow(window))
+ {
+ return Error(EGL_BAD_NATIVE_WINDOW);
+ }
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLint attribute = attributeIter->first;
+ EGLint value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_RENDER_BUFFER:
+ switch (value)
+ {
+ case EGL_BACK_BUFFER:
+ break;
+ case EGL_SINGLE_BUFFER:
+ return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!displayExtensions.postSubBuffer)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (!displayExtensions.windowFixedSize)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!displayExtensions.windowFixedSize)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_VG_COLORSPACE:
+ return Error(EGL_BAD_MATCH);
+
+ case EGL_VG_ALPHA_FORMAT:
+ return Error(EGL_BAD_MATCH);
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (Display::hasExistingWindowSurface(window))
+ {
+ return Error(EGL_BAD_ALLOC);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes)
+{
+ Error error = ValidateConfig(display, config);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLint attribute = attributeIter->first;
+ EGLint value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_LARGEST_PBUFFER:
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ case EGL_VG_COLORSPACE:
+ break;
+
+ case EGL_VG_ALPHA_FORMAT:
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (!(config->surfaceType & EGL_PBUFFER_BIT))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ const Caps &caps = display->getCaps();
+
+ EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+
+ if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+ (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ EGLint width = attributes.get(EGL_WIDTH, 0);
+ EGLint height = attributes.get(EGL_HEIGHT, 0);
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+ Config *config, const AttributeMap& attributes)
+{
+ Error error = ValidateConfig(display, config);
+ if (error.isError())
+ {
+ return error;
+ }
+
+ const DisplayExtensions &displayExtensions = display->getExtensions();
+
+ switch (buftype)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!displayExtensions.d3dShareHandleClientBuffer)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ if (buffer == nullptr)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ default:
+ return Error(EGL_BAD_PARAMETER);
+ }
+
+ for (AttributeMap::const_iterator attributeIter = attributes.begin(); attributeIter != attributes.end(); attributeIter++)
+ {
+ EGLint attribute = attributeIter->first;
+ EGLint value = attributeIter->second;
+
+ switch (attribute)
+ {
+ case EGL_WIDTH:
+ case EGL_HEIGHT:
+ if (!displayExtensions.d3dShareHandleClientBuffer)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ if (value < 0)
+ {
+ return Error(EGL_BAD_PARAMETER);
+ }
+ break;
+
+ case EGL_TEXTURE_FORMAT:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_RGB:
+ case EGL_TEXTURE_RGBA:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_TEXTURE_TARGET:
+ switch (value)
+ {
+ case EGL_NO_TEXTURE:
+ case EGL_TEXTURE_2D:
+ break;
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ break;
+
+ case EGL_MIPMAP_TEXTURE:
+ break;
+
+ default:
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+ }
+
+ if (!(config->surfaceType & EGL_PBUFFER_BIT))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ EGLenum textureFormat = attributes.get(EGL_TEXTURE_FORMAT, EGL_NO_TEXTURE);
+ EGLenum textureTarget = attributes.get(EGL_TEXTURE_TARGET, EGL_NO_TEXTURE);
+ if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
+ (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+
+ if ((textureFormat == EGL_TEXTURE_RGB && config->bindToTextureRGB != EGL_TRUE) ||
+ (textureFormat == EGL_TEXTURE_RGBA && config->bindToTextureRGBA != EGL_TRUE))
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+ if (buftype == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
+ {
+ EGLint width = attributes.get(EGL_WIDTH, 0);
+ EGLint height = attributes.get(EGL_HEIGHT, 0);
+
+ if (width == 0 || height == 0)
+ {
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check
+ const Caps &caps = display->getCaps();
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
+#endif
+ }
+
+ return Error(EGL_SUCCESS);
+}
+
+}
diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.h b/src/3rdparty/angle/src/libANGLE/validationEGL.h
new file mode 100644
index 0000000000..4daff791fd
--- /dev/null
+++ b/src/3rdparty/angle/src/libANGLE/validationEGL.h
@@ -0,0 +1,49 @@
+//
+// Copyright (c) 2015 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// validationEGL.h: Validation functions for generic EGL entry point parameters
+
+#ifndef LIBANGLE_VALIDATIONEGL_H_
+#define LIBANGLE_VALIDATIONEGL_H_
+
+#include "libANGLE/Error.h"
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Context;
+}
+
+namespace egl
+{
+
+class AttributeMap;
+struct Config;
+class Display;
+class Surface;
+
+// Object validation
+Error ValidateDisplay(const Display *display);
+Error ValidateSurface(const Display *display, Surface *surface);
+Error ValidateConfig(const Display *display, const Config *config);
+Error ValidateContext(const Display *display, gl::Context *context);
+
+// Entry point validation
+Error ValidateCreateContext(Display *display, Config *configuration, gl::Context *shareContext,
+ const AttributeMap& attributes);
+
+Error ValidateCreateWindowSurface(Display *display, Config *config, EGLNativeWindowType window,
+ const AttributeMap& attributes);
+
+Error ValidateCreatePbufferSurface(Display *display, Config *config, const AttributeMap& attributes);
+Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, EGLClientBuffer buffer,
+ Config *config, const AttributeMap& attributes);
+
+
+}
+
+#endif // LIBANGLE_VALIDATIONEGL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.cpp b/src/3rdparty/angle/src/libANGLE/validationES.cpp
index 265f4b4fba..d267cbf2e6 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES.cpp
@@ -6,27 +6,24 @@
// validationES.h: Validation functions for generic OpenGL ES entry point parameters
-#include "libGLESv2/validationES.h"
-#include "libGLESv2/validationES2.h"
-#include "libGLESv2/validationES3.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/TransformFeedback.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/renderer/BufferImpl.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/FramebufferAttachment.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Uniform.h"
+#include "libANGLE/TransformFeedback.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/renderer/BufferImpl.h"
#include "common/mathutil.h"
#include "common/utilities.h"
-// FIXME(jmadill): remove this when we support buffer data caching
-#include "libGLESv2/renderer/d3d/BufferD3D.h"
-
namespace gl
{
@@ -95,7 +92,8 @@ bool ValidTexture2DDestinationTarget(const Context *context, GLenum target)
bool ValidFramebufferTarget(GLenum target)
{
- META_ASSERT(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER);
+ static_assert(GL_DRAW_FRAMEBUFFER_ANGLE == GL_DRAW_FRAMEBUFFER && GL_READ_FRAMEBUFFER_ANGLE == GL_READ_FRAMEBUFFER,
+ "ANGLE framebuffer enums must equal the ES3 framebuffer enums.");
switch (target)
{
@@ -212,8 +210,8 @@ bool ValidCompressedImageSize(const Context *context, GLenum internalFormat, GLs
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);
+ static_assert(GL_ANY_SAMPLES_PASSED == GL_ANY_SAMPLES_PASSED_EXT, "GL extension enums not equal.");
+ static_assert(GL_ANY_SAMPLES_PASSED_CONSERVATIVE == GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT, "GL extension enums not equal.");
switch (queryType)
{
@@ -288,9 +286,8 @@ bool ValidateAttachmentTarget(gl::Context *context, GLenum attachment)
return true;
}
-bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height,
- bool angleExtension)
+bool ValidateRenderbufferStorageParametersBase(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
{
switch (target)
{
@@ -316,8 +313,7 @@ bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target,
// 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.
+ // only sized internal formats.
const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
if (formatInfo.pixelBytes == 0)
{
@@ -325,55 +321,47 @@ bool ValidateRenderbufferStorageParameters(gl::Context *context, GLenum target,
return false;
}
- if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
+ if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_VALUE));
return false;
}
- if (static_cast<GLuint>(std::max(width, height)) > context->getCaps().maxRenderbufferSize)
+ GLuint handle = context->getState().getRenderbufferId();
+ if (handle == 0)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
- // to MAX_SAMPLES_ANGLE (Context::getMaxSupportedSamples) while the ES3.0 spec (section 4.4.2)
- // states that samples must be less than or equal to the maximum samples for the specified
- // internal format.
- if (angleExtension)
- {
- ASSERT(context->getExtensions().framebufferMultisample);
- if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
+ return true;
+}
- // Check if this specific format supports enough samples
- if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
- {
- context->recordError(Error(GL_OUT_OF_MEMORY));
- return false;
- }
- }
- else
+bool ValidateRenderbufferStorageParametersANGLE(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ ASSERT(samples == 0 || context->getExtensions().framebufferMultisample);
+
+ // ANGLE_framebuffer_multisample states that the value of samples must be less than or equal
+ // to MAX_SAMPLES_ANGLE (Context::getExtensions().maxSamples) otherwise GL_INVALID_VALUE is
+ // generated.
+ if (static_cast<GLuint>(samples) > context->getExtensions().maxSamples)
{
- if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
}
- GLuint handle = context->getState().getRenderbufferId();
- if (handle == 0)
+ // ANGLE_framebuffer_multisample states GL_OUT_OF_MEMORY is generated on a failure to create
+ // the specified storage. This is different than ES 3.0 in which a sample number higher
+ // than the maximum sample number supported by this format generates a GL_INVALID_VALUE.
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_OUT_OF_MEMORY));
return false;
}
- return true;
+ return ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height);
}
bool ValidateFramebufferRenderbufferParameters(gl::Context *context, GLenum target, GLenum attachment,
@@ -507,13 +495,13 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
return false;
}
- if (!readFramebuffer->completeness(context->getData()))
+ if (!readFramebuffer->checkStatus(context->getData()))
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
}
- if (!drawFramebuffer->completeness(context->getData()))
+ if (!drawFramebuffer->checkStatus(context->getData()))
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
@@ -534,14 +522,14 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
if (readColorBuffer && drawColorBuffer)
{
- GLenum readInternalFormat = readColorBuffer->getActualFormat();
+ GLenum readInternalFormat = readColorBuffer->getInternalFormat();
const InternalFormat &readFormatInfo = GetInternalFormatInfo(readInternalFormat);
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
+ for (GLuint i = 0; i < context->getCaps().maxColorAttachments; i++)
{
if (drawFramebuffer->isEnabledColorAttachment(i))
{
- GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getActualFormat();
+ GLenum drawInternalFormat = drawFramebuffer->getColorbuffer(i)->getInternalFormat();
const InternalFormat &drawFormatInfo = GetInternalFormatInfo(drawInternalFormat);
// The GL ES 3.0.2 spec (pg 193) states that:
@@ -583,21 +571,26 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
if (fromAngleExtension)
{
- const GLenum readColorbufferType = readFramebuffer->getReadColorbufferType();
- if (readColorbufferType != GL_TEXTURE_2D && readColorbufferType != GL_RENDERBUFFER)
+ FramebufferAttachment *readColorAttachment = readFramebuffer->getReadColorbuffer();
+ if (!readColorAttachment ||
+ (!(readColorAttachment->type() == GL_TEXTURE && readColorAttachment->getTextureImageIndex()->type == GL_TEXTURE_2D) &&
+ readColorAttachment->type() != GL_RENDERBUFFER &&
+ readColorAttachment->type() != GL_FRAMEBUFFER_DEFAULT))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
+ for (GLuint colorAttachment = 0; colorAttachment < context->getCaps().maxColorAttachments; ++colorAttachment)
{
if (drawFramebuffer->isEnabledColorAttachment(colorAttachment))
{
FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(colorAttachment);
ASSERT(attachment);
- if (attachment->type() != GL_TEXTURE_2D && attachment->type() != GL_RENDERBUFFER)
+ if (!(attachment->type() == GL_TEXTURE && attachment->getTextureImageIndex()->type == GL_TEXTURE_2D) &&
+ attachment->type() != GL_RENDERBUFFER &&
+ attachment->type() != GL_FRAMEBUFFER_DEFAULT)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -625,77 +618,44 @@ bool ValidateBlitFramebufferParameters(gl::Context *context, GLint srcX0, GLint
}
}
- if (mask & GL_DEPTH_BUFFER_BIT)
+ GLenum masks[] = {GL_DEPTH_BUFFER_BIT, GL_STENCIL_BUFFER_BIT};
+ GLenum attachments[] = {GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT};
+ for (size_t i = 0; i < 2; i++)
{
- gl::FramebufferAttachment *readDepthBuffer = readFramebuffer->getDepthbuffer();
- gl::FramebufferAttachment *drawDepthBuffer = drawFramebuffer->getDepthbuffer();
-
- if (readDepthBuffer && drawDepthBuffer)
+ if (mask & masks[i])
{
- if (readDepthBuffer->getActualFormat() != drawDepthBuffer->getActualFormat())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ gl::FramebufferAttachment *readBuffer = readFramebuffer->getAttachment(attachments[i]);
+ gl::FramebufferAttachment *drawBuffer = drawFramebuffer->getAttachment(attachments[i]);
- if (readDepthBuffer->getSamples() > 0 && !sameBounds)
+ if (readBuffer && drawBuffer)
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (fromAngleExtension)
- {
- if (IsPartialBlit(context, readDepthBuffer, drawDepthBuffer,
- srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ if (readBuffer->getInternalFormat() != drawBuffer->getInternalFormat())
{
- ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
- context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
+ context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- if (readDepthBuffer->getSamples() != 0 || drawDepthBuffer->getSamples() != 0)
+ if (readBuffer->getSamples() > 0 && !sameBounds)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- }
- }
- }
-
- if (mask & GL_STENCIL_BUFFER_BIT)
- {
- gl::FramebufferAttachment *readStencilBuffer = readFramebuffer->getStencilbuffer();
- gl::FramebufferAttachment *drawStencilBuffer = drawFramebuffer->getStencilbuffer();
-
- if (readStencilBuffer && drawStencilBuffer)
- {
- if (readStencilBuffer->getActualFormat() != drawStencilBuffer->getActualFormat())
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- if (readStencilBuffer->getSamples() > 0 && !sameBounds)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (fromAngleExtension)
- {
- if (IsPartialBlit(context, readStencilBuffer, drawStencilBuffer,
- srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ if (fromAngleExtension)
{
- ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
- context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
- return false;
- }
+ if (IsPartialBlit(context, readBuffer, drawBuffer,
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1))
+ {
+ ERR("Only whole-buffer depth and stencil blits are supported by this implementation.");
+ context->recordError(Error(GL_INVALID_OPERATION)); // only whole-buffer copies are permitted
+ return false;
+ }
- if (readStencilBuffer->getSamples() != 0 || drawStencilBuffer->getSamples() != 0)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ if (readBuffer->getSamples() != 0 || drawBuffer->getSamples() != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
}
}
}
@@ -720,7 +680,8 @@ bool ValidateGetVertexAttribParameters(Context *context, GLenum pname)
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);
+ static_assert(GL_VERTEX_ATTRIB_ARRAY_DIVISOR == GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE,
+ "ANGLE extension enums not equal to GL enums.");
return true;
case GL_VERTEX_ATTRIB_ARRAY_INTEGER:
@@ -931,7 +892,7 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize
gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
ASSERT(framebuffer);
- if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
@@ -944,17 +905,18 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize
return false;
}
- if (!framebuffer->getReadColorbuffer())
+ const FramebufferAttachment *readBuffer = framebuffer->getReadColorbuffer();
+ if (!readBuffer)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- GLenum currentInternalFormat, currentFormat, currentType;
+ GLenum currentFormat = framebuffer->getImplementationColorReadFormat();
+ GLenum currentType = framebuffer->getImplementationColorReadType();
+ GLenum currentInternalFormat = readBuffer->getInternalFormat();
GLuint clientVersion = context->getClientVersion();
- context->getCurrentReadFormatType(&currentInternalFormat, &currentFormat, &currentType);
-
bool validReadFormat = (clientVersion < 3) ? ValidES2ReadFormatType(context, format, type) :
ValidES3ReadFormatType(context, currentInternalFormat, format, type);
@@ -967,7 +929,7 @@ bool ValidateReadPixelsParameters(gl::Context *context, GLint x, GLint y, GLsize
GLenum sizedInternalFormat = GetSizedInternalFormat(format, type);
const InternalFormat &sizedFormatInfo = GetInternalFormatInfo(sizedInternalFormat);
- GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment());
+ GLsizei outputPitch = sizedFormatInfo.computeRowPitch(type, width, context->getState().getPackAlignment(), 0);
// sized query sanity check
if (bufSize)
{
@@ -1064,8 +1026,8 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform
return false;
}
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- if (!programBinary)
+ gl::Program *program = context->getState().getProgram();
+ if (!program)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1077,13 +1039,13 @@ static bool ValidateUniformCommonBase(gl::Context *context, GLenum targetUniform
return false;
}
- if (!programBinary->isValidUniformLocation(location))
+ if (!program->isValidUniformLocation(location))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- LinkedUniform *uniform = programBinary->getUniformByLocation(location);
+ LinkedUniform *uniform = program->getUniformByLocation(location);
// attempting to write an array to a non-array uniform is an INVALID_OPERATION
if (uniform->elementCount() == 1 && count > 1)
@@ -1112,7 +1074,7 @@ bool ValidateUniform(gl::Context *context, GLenum uniformType, GLint location, G
}
GLenum targetBoolType = VariableBoolVectorType(uniformType);
- bool samplerUniformCheck = (IsSampler(uniform->type) && uniformType == GL_INT);
+ bool samplerUniformCheck = (IsSamplerType(uniform->type) && uniformType == GL_INT);
if (!samplerUniformCheck && uniformType != uniform->type && targetBoolType != uniform->type)
{
context->recordError(Error(GL_INVALID_OPERATION));
@@ -1163,11 +1125,13 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType,
return false;
}
+ const Caps &caps = context->getCaps();
+
if (pname >= GL_DRAW_BUFFER0 && pname <= GL_DRAW_BUFFER15)
{
unsigned int colorAttachment = (pname - GL_DRAW_BUFFER0);
- if (colorAttachment >= context->getCaps().maxDrawBuffers)
+ if (colorAttachment >= caps.maxDrawBuffers)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1180,7 +1144,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType,
case GL_TEXTURE_BINDING_CUBE_MAP:
case GL_TEXTURE_BINDING_3D:
case GL_TEXTURE_BINDING_2D_ARRAY:
- if (context->getState().getActiveSampler() >= context->getCaps().maxCombinedTextureImageUnits)
+ if (context->getState().getActiveSampler() >= caps.maxCombinedTextureImageUnits)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1192,7 +1156,7 @@ bool ValidateStateQuery(gl::Context *context, GLenum pname, GLenum *nativeType,
{
Framebuffer *framebuffer = context->getState().getReadFramebuffer();
ASSERT(framebuffer);
- if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1256,7 +1220,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
}
gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
@@ -1270,28 +1234,11 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
const gl::Caps &caps = context->getCaps();
- gl::Texture *texture = NULL;
- GLenum textureInternalFormat = GL_NONE;
- GLint textureLevelWidth = 0;
- GLint textureLevelHeight = 0;
- GLint textureLevelDepth = 0;
GLuint maxDimension = 0;
-
switch (target)
{
case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture2d = context->getTexture2D();
- if (texture2d)
- {
- textureInternalFormat = texture2d->getInternalFormat(level);
- textureLevelWidth = texture2d->getWidth(level);
- textureLevelHeight = texture2d->getHeight(level);
- textureLevelDepth = 1;
- texture = texture2d;
- maxDimension = caps.max2DTextureSize;
- }
- }
+ maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
@@ -1300,48 +1247,15 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
- if (textureCube)
- {
- textureInternalFormat = textureCube->getInternalFormat(target, level);
- textureLevelWidth = textureCube->getWidth(target, level);
- textureLevelHeight = textureCube->getHeight(target, level);
- textureLevelDepth = 1;
- texture = textureCube;
- maxDimension = caps.maxCubeMapTextureSize;
- }
- }
+ maxDimension = caps.maxCubeMapTextureSize;
break;
case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture2dArray = context->getTexture2DArray();
- if (texture2dArray)
- {
- textureInternalFormat = texture2dArray->getInternalFormat(level);
- textureLevelWidth = texture2dArray->getWidth(level);
- textureLevelHeight = texture2dArray->getHeight(level);
- textureLevelDepth = texture2dArray->getLayers(level);
- texture = texture2dArray;
- maxDimension = caps.max2DTextureSize;
- }
- }
+ maxDimension = caps.max2DTextureSize;
break;
case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture3d = context->getTexture3D();
- if (texture3d)
- {
- textureInternalFormat = texture3d->getInternalFormat(level);
- textureLevelWidth = texture3d->getWidth(level);
- textureLevelHeight = texture3d->getHeight(level);
- textureLevelDepth = texture3d->getDepth(level);
- texture = texture3d;
- maxDimension = caps.max3DTextureSize;
- }
- }
+ maxDimension = caps.max3DTextureSize;
break;
default:
@@ -1349,6 +1263,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
+ gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
@@ -1369,21 +1284,17 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
return false;
}
- if (formatInfo.compressed)
+ if (formatInfo.compressed && !ValidCompressedImageSize(context, internalformat, width, height))
{
- if (((width % formatInfo.compressedBlockWidth) != 0 && width != textureLevelWidth) ||
- ((height % formatInfo.compressedBlockHeight) != 0 && height != textureLevelHeight))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
}
if (isSubImage)
{
- if (xoffset + width > textureLevelWidth ||
- yoffset + height > textureLevelHeight ||
- zoffset >= textureLevelDepth)
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+ static_cast<size_t>(zoffset) >= texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
@@ -1391,7 +1302,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
}
else
{
- if (IsCubemapTextureTarget(target) && width != height)
+ if (IsCubeMapTextureTarget(target) && width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
@@ -1411,7 +1322,7 @@ bool ValidateCopyTexImageParametersBase(gl::Context* context, GLenum target, GLi
}
}
- *textureFormatOut = textureInternalFormat;
+ *textureFormatOut = texture->getInternalFormat(target, level);
return true;
}
@@ -1461,20 +1372,20 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
}
const gl::Framebuffer *fbo = state.getDrawFramebuffer();
- if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
}
- if (state.getCurrentProgramId() == 0)
+ gl::Program *program = state.getProgram();
+ if (!program)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
- if (!programBinary->validateSamplers(NULL, context->getCaps()))
+ if (!program->validateSamplers(NULL, context->getCaps()))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1485,7 +1396,7 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
- bool attribActive = (programBinary->getSemanticIndex(attributeIndex) != -1);
+ bool attribActive = (program->getSemanticIndex(attributeIndex) != -1);
if (attribActive && attrib.enabled)
{
gl::Buffer *buffer = attrib.buffer.get();
@@ -1525,6 +1436,36 @@ static bool ValidateDrawBase(Context *context, GLenum mode, GLsizei count, GLsiz
}
}
+ // Uniform buffer validation
+ for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < program->getActiveUniformBlockCount(); uniformBlockIndex++)
+ {
+ const gl::UniformBlock *uniformBlock = program->getUniformBlockByIndex(uniformBlockIndex);
+ GLuint blockBinding = program->getUniformBlockBinding(uniformBlockIndex);
+ const gl::Buffer *uniformBuffer = state.getIndexedUniformBuffer(blockBinding);
+
+ if (!uniformBuffer)
+ {
+ // undefined behaviour
+ context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer."));
+ return false;
+ }
+
+ size_t uniformBufferSize = state.getIndexedUniformBufferSize(blockBinding);
+
+ if (uniformBufferSize == 0)
+ {
+ // Bind the whole buffer.
+ uniformBufferSize = uniformBuffer->getSize();
+ }
+
+ if (uniformBufferSize < uniformBlock->dataSize)
+ {
+ // undefined behaviour
+ context->recordError(Error(GL_INVALID_OPERATION, "It is undefined behaviour to use a uniform buffer that is too small."));
+ return false;
+ }
+ }
+
// No-op if zero count
return (count > 0);
}
@@ -1579,13 +1520,13 @@ static bool ValidateDrawInstancedANGLE(Context *context)
// Verify there is at least one active attribute with a divisor of zero
const gl::State& state = context->getState();
- gl::ProgramBinary *programBinary = state.getCurrentProgramBinary();
+ gl::Program *program = state.getProgram();
const VertexArray *vao = state.getVertexArray();
for (int attributeIndex = 0; attributeIndex < MAX_VERTEX_ATTRIBS; attributeIndex++)
{
const VertexAttribute &attrib = vao->getVertexAttribute(attributeIndex);
- bool active = (programBinary->getSemanticIndex(attributeIndex) != -1);
+ bool active = (program->getSemanticIndex(attributeIndex) != -1);
if (active && attrib.divisor == 0)
{
return true;
@@ -1646,7 +1587,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
}
const gl::VertexArray *vao = state.getVertexArray();
- const gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
+ gl::Buffer *elementArrayBuffer = vao->getElementArrayBuffer();
if (!indices && !elementArrayBuffer)
{
context->recordError(Error(GL_INVALID_OPERATION));
@@ -1688,12 +1629,11 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
if (elementArrayBuffer)
{
uintptr_t offset = reinterpret_cast<uintptr_t>(indices);
- if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut, NULL))
+ if (!elementArrayBuffer->getIndexRangeCache()->findRange(type, offset, count, indexRangeOut))
{
- // FIXME(jmadill): Use buffer data caching instead of the D3D back-end
- rx::BufferD3D *bufferD3D = rx::BufferD3D::makeBufferD3D(elementArrayBuffer->getImplementation());
+ rx::BufferImpl *bufferImpl = elementArrayBuffer->getImplementation();
const uint8_t *dataPointer = NULL;
- Error error = bufferD3D->getData(&dataPointer);
+ Error error = bufferImpl->getData(&dataPointer);
if (error.isError())
{
context->recordError(error);
@@ -1702,6 +1642,7 @@ bool ValidateDrawElements(Context *context, GLenum mode, GLsizei count, GLenum t
const uint8_t *offsetPointer = dataPointer + offset;
*indexRangeOut = rx::IndexRangeCache::ComputeRange(type, offsetPointer, count);
+ elementArrayBuffer->getIndexRangeCache()->addRange(type, offset, count, *indexRangeOut);
}
}
else
@@ -1827,12 +1768,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- gl::Texture2D *tex2d = static_cast<gl::Texture2D *>(tex);
- if (tex2d->isCompressed(level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
}
break;
@@ -1853,12 +1788,6 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- gl::TextureCubeMap *texcube = static_cast<gl::TextureCubeMap *>(tex);
- if (texcube->isCompressed(textarget, level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
}
break;
@@ -1866,6 +1795,13 @@ bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attach
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(textarget, level));
+ if (internalFormatInfo.compressed)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
}
return true;
@@ -1892,14 +1828,7 @@ bool ValidateGetUniformBase(Context *context, GLuint program, GLint location)
return false;
}
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
-
- if (!programBinary->isValidUniformLocation(location))
+ if (!programObject->isValidUniformLocation(location))
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -1927,10 +1856,9 @@ static bool ValidateSizedGetUniform(Context *context, GLuint program, GLint loca
gl::Program *programObject = context->getProgram(program);
ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
// sized queries -- ensure the provided buffer is large enough
- LinkedUniform *uniform = programBinary->getUniformByLocation(location);
+ LinkedUniform *uniform = programObject->getUniformByLocation(location);
size_t requiredBytes = VariableExternalSize(uniform->type);
if (static_cast<size_t>(bufSize) < requiredBytes)
{
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES.h b/src/3rdparty/angle/src/libANGLE/validationES.h
index 1fdb633cb6..b0ccd8eecc 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES.h
@@ -6,8 +6,8 @@
// validationES.h: Validation functions for generic OpenGL ES entry point parameters
-#ifndef LIBGLESV2_VALIDATION_ES_H
-#define LIBGLESV2_VALIDATION_ES_H
+#ifndef LIBANGLE_VALIDATION_ES_H_
+#define LIBANGLE_VALIDATION_ES_H_
#include "common/mathutil.h"
@@ -32,9 +32,11 @@ bool ValidQueryType(const Context *context, GLenum queryType);
bool ValidProgram(Context *context, GLuint id);
bool ValidateAttachmentTarget(Context *context, GLenum attachment);
-bool ValidateRenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
- GLenum internalformat, GLsizei width, GLsizei height,
- bool angleExtension);
+bool ValidateRenderbufferStorageParametersBase(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+bool ValidateRenderbufferStorageParametersANGLE(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+
bool ValidateFramebufferRenderbufferParameters(Context *context, GLenum target, GLenum attachment,
GLenum renderbuffertarget, GLuint renderbuffer);
@@ -49,7 +51,7 @@ bool ValidateTexParamParameters(Context *context, GLenum pname, GLint param);
bool ValidateSamplerObjectParameter(Context *context, GLenum pname);
bool ValidateReadPixelsParameters(Context *context, GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels);
+ GLenum format, GLenum type, GLsizei *bufSize, GLvoid *pixels);
bool ValidateBeginQuery(Context *context, GLenum target, GLuint id);
bool ValidateEndQuery(Context *context, GLenum target);
@@ -61,8 +63,8 @@ bool ValidateUniformMatrix(Context *context, GLenum matrixType, GLint location,
bool ValidateStateQuery(Context *context, GLenum pname, GLenum *nativeType, unsigned int *numParams);
bool ValidateCopyTexImageParametersBase(Context* context, GLenum target, GLint level, GLenum internalformat, bool isSubImage,
- GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height,
- GLint border, GLenum *textureInternalFormatOut);
+ GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height,
+ GLint border, GLenum *textureInternalFormatOut);
bool ValidateDrawArrays(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
bool ValidateDrawArraysInstanced(Context *context, GLenum mode, GLint first, GLsizei count, GLsizei primcount);
@@ -79,7 +81,7 @@ bool ValidateDrawElementsInstancedANGLE(Context *context, GLenum mode, GLsizei c
bool ValidateFramebufferTextureBase(Context *context, GLenum target, GLenum attachment,
GLuint texture, GLint level);
bool ValidateFramebufferTexture2D(Context *context, GLenum target, GLenum attachment,
- GLenum textarget, GLuint texture, GLint level);
+ GLenum textarget, GLuint texture, GLint level);
bool ValidateGetUniformBase(Context *context, GLuint program, GLint location);
bool ValidateGetUniformfv(Context *context, GLuint program, GLint location, GLfloat* params);
@@ -89,4 +91,4 @@ bool ValidateGetnUniformivEXT(Context *context, GLuint program, GLint location,
}
-#endif // LIBGLESV2_VALIDATION_ES_H
+#endif // LIBANGLE_VALIDATION_ES_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
index f950454df0..9eece1b54a 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES2.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES2.cpp
@@ -6,15 +6,14 @@
// 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 "libANGLE/validationES2.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "common/mathutil.h"
#include "common/utilities.h"
@@ -22,227 +21,118 @@
namespace gl
{
-static bool ValidateSubImageParams2D(Context *context, bool compressed, GLsizei width, GLsizei height,
- GLint xoffset, GLint yoffset, GLint level, GLenum format, GLenum type,
- gl::Texture2D *texture)
+bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
+ GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type, const GLvoid *pixels)
{
- if (!texture)
+ if (!ValidTexture2DDestinationTarget(context, target))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_ENUM));
return false;
}
- if (compressed != texture->isCompressed(level))
+ if (!ValidImageSize(context, target, level, width, height, 1))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_VALUE));
return false;
}
- if (format != GL_NONE)
- {
- if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
-
- if (compressed)
- {
- if ((width % 4 != 0 && width != texture->getWidth(level)) ||
- (height % 4 != 0 && height != texture->getHeight(level)))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
-
- if (xoffset + width > texture->getWidth(level) ||
- yoffset + height > texture->getHeight(level))
+ if (level < 0 || xoffset < 0 ||
+ std::numeric_limits<GLsizei>::max() - xoffset < width ||
+ std::numeric_limits<GLsizei>::max() - yoffset < height)
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
- return true;
-}
-
-static bool ValidateSubImageParamsCube(Context *context, bool compressed, GLsizei width, GLsizei height,
- GLint xoffset, GLint yoffset, GLenum target, GLint level, GLenum format, GLenum type,
- gl::TextureCubeMap *texture)
-{
- if (!texture)
+ if (!isSubImage && !isCompressed && internalformat != format)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- if (compressed != texture->isCompressed(target, level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
+ const gl::Caps &caps = context->getCaps();
- if (format != GL_NONE)
+ if (target == GL_TEXTURE_2D)
{
- if (gl::GetFormatTypeInfo(format, type).internalFormat != texture->getInternalFormat(target, level))
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_VALUE));
return false;
}
}
-
- if (compressed)
+ else if (IsCubeMapTextureTarget(target))
{
- if ((width % 4 != 0 && width != texture->getWidth(target, 0)) ||
- (height % 4 != 0 && height != texture->getHeight(target, 0)))
+ if (!isSubImage && width != height)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_VALUE));
return false;
}
- }
- if (xoffset + width > texture->getWidth(target, level) ||
- yoffset + height > texture->getHeight(target, level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
}
-
- return true;
-}
-
-bool ValidateES2TexImageParameters(Context *context, GLenum target, GLint level, GLenum internalformat, bool isCompressed, bool isSubImage,
- GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type, const GLvoid *pixels)
-{
- if (!ValidTexture2DDestinationTarget(context, target))
+ else
{
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
- if (!ValidImageSize(context, target, level, width, height, 1))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (level < 0 || xoffset < 0 ||
- std::numeric_limits<GLsizei>::max() - xoffset < width ||
- std::numeric_limits<GLsizei>::max() - yoffset < height)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (!isSubImage && !isCompressed && internalformat != format)
+ gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- const gl::Caps &caps = context->getCaps();
-
- gl::Texture *texture = NULL;
- bool textureCompressed = false;
- GLenum textureInternalFormat = GL_NONE;
- GLint textureLevelWidth = 0;
- GLint textureLevelHeight = 0;
- switch (target)
+ if (isSubImage)
{
- case GL_TEXTURE_2D:
+ if (format != GL_NONE)
{
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- gl::Texture2D *tex2d = context->getTexture2D();
- if (tex2d)
- {
- textureCompressed = tex2d->isCompressed(level);
- textureInternalFormat = tex2d->getInternalFormat(level);
- textureLevelWidth = tex2d->getWidth(level);
- textureLevelHeight = tex2d->getHeight(level);
- texture = tex2d;
- }
-
- if (isSubImage && !ValidateSubImageParams2D(context, isCompressed, width, height, xoffset, yoffset,
- level, format, type, tex2d))
+ if (gl::GetSizedInternalFormat(format, type) != texture->getInternalFormat(target, level))
{
+ context->recordError(Error(GL_INVALID_OPERATION));
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 (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level))
{
- if (!isSubImage && width != height)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.maxCubeMapTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- gl::TextureCubeMap *texCube = context->getTextureCubeMap();
- if (texCube)
- {
- textureCompressed = texCube->isCompressed(target, level);
- textureInternalFormat = texCube->getInternalFormat(target, level);
- textureLevelWidth = texCube->getWidth(target, level);
- textureLevelHeight = texCube->getHeight(target, level);
- texture = texCube;
- }
-
- if (isSubImage && !ValidateSubImageParamsCube(context, isCompressed, width, height, xoffset, yoffset,
- target, level, format, type, texCube))
- {
- return false;
- }
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
}
- break;
-
- default:
- context->recordError(Error(GL_INVALID_ENUM));
- return false;
}
-
- if (!texture)
+ else
{
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
+ if (texture->isImmutable())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
}
- if (!isSubImage && texture->isImmutable())
+ // Verify zero border
+ if (border != 0)
{
- context->recordError(Error(GL_INVALID_OPERATION));
+ context->recordError(Error(GL_INVALID_VALUE));
return false;
}
- // Verify zero border
- if (border != 0)
+ GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
+ const InternalFormat &actualFormatInfo = GetInternalFormatInfo(actualInternalFormat);
+
+ if (isCompressed != actualFormatInfo.compressed)
{
- context->recordError(Error(GL_INVALID_VALUE));
+ context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
if (isCompressed)
{
if (!ValidCompressedImageSize(context, actualInternalFormat, width, height))
@@ -521,7 +411,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
GLenum colorbufferFormat = framebuffer->getReadColorbuffer()->getInternalFormat();
- GLenum textureFormat = gl::GetInternalFormatInfo(textureInternalFormat).format;
+ const auto &internalFormatInfo = gl::GetInternalFormatInfo(textureInternalFormat);
+ GLenum textureFormat = internalFormatInfo.format;
// [OpenGL ES 2.0.24] table 3.9
if (isSubImage)
@@ -558,7 +449,11 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGB8_OES &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_R32F &&
+ colorbufferFormat != GL_RG32F &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -570,7 +465,10 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGB8_OES &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_RG32F &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -581,7 +479,9 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGB8_OES &&
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_RGB32F &&
+ colorbufferFormat != GL_RGBA32F)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -591,7 +491,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
case GL_RGBA:
if (colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_RGBA32F)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -611,6 +512,13 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
+
+ if (internalFormatInfo.type == GL_FLOAT &&
+ !context->getExtensions().textureFloat)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
}
else
{
@@ -621,7 +529,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -635,7 +544,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -649,7 +559,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -662,7 +573,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -674,7 +586,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -685,7 +598,8 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
if (colorbufferFormat != GL_RGBA4 &&
colorbufferFormat != GL_RGB5_A1 &&
colorbufferFormat != GL_BGRA8_EXT &&
- colorbufferFormat != GL_RGBA8_OES)
+ colorbufferFormat != GL_RGBA8_OES &&
+ colorbufferFormat != GL_BGR5_A1_ANGLEX)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
@@ -903,19 +817,7 @@ bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei le
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();
- }
-
+ gl::Texture *texture = context->getTargetTexture(target);
if (!texture || texture->id() == 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES2.h b/src/3rdparty/angle/src/libANGLE/validationES2.h
index 53a0b630ea..b9c1fd3bc4 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES2.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES2.h
@@ -6,8 +6,8 @@
// validationES2.h: Validation functions for OpenGL ES 2.0 entry point parameters
-#ifndef LIBGLESV2_VALIDATION_ES2_H
-#define LIBGLESV2_VALIDATION_ES2_H
+#ifndef LIBANGLE_VALIDATION_ES2_H_
+#define LIBANGLE_VALIDATION_ES2_H_
#include <GLES2/gl2.h>
@@ -25,10 +25,10 @@ bool ValidateES2CopyTexImageParameters(Context* context, GLenum target, GLint le
GLint border);
bool ValidateES2TexStorageParameters(Context *context, GLenum target, GLsizei levels, GLenum internalformat,
- GLsizei width, GLsizei height);
+ GLsizei width, GLsizei height);
bool ValidES2ReadFormatType(Context *context, GLenum format, GLenum type);
}
-#endif // LIBGLESV2_VALIDATION_ES2_H
+#endif // LIBANGLE_VALIDATION_ES2_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
index 2d3a039e13..e141bb6ece 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES3.cpp
+++ b/src/3rdparty/angle/src/libANGLE/validationES3.cpp
@@ -6,17 +6,17 @@
// 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 "libANGLE/validationES3.h"
+#include "libANGLE/validationES.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/formatutils.h"
+#include "libANGLE/FramebufferAttachment.h"
#include "common/mathutil.h"
+#include "common/utilities.h"
namespace gl
{
@@ -311,33 +311,14 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
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<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
{
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- gl::Texture2D *texture2d = context->getTexture2D();
- if (texture2d)
- {
- textureCompressed = texture2d->isCompressed(level);
- textureInternalFormat = texture2d->getInternalFormat(level);
- textureLevelWidth = texture2d->getWidth(level);
- textureLevelHeight = texture2d->getHeight(level);
- textureLevelDepth = 1;
- texture = texture2d;
- }
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
}
break;
@@ -347,83 +328,45 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
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)
{
- if (!isSubImage && width != height)
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
- gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
- if (textureCube)
- {
- textureCompressed = textureCube->isCompressed(target, level);
- textureInternalFormat = textureCube->getInternalFormat(target, level);
- textureLevelWidth = textureCube->getWidth(target, level);
- textureLevelHeight = textureCube->getHeight(target, level);
- textureLevelDepth = 1;
- texture = textureCube;
- }
+ if (static_cast<GLuint>(width) > (caps.maxCubeMapTextureSize >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
}
break;
case GL_TEXTURE_3D:
+ if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
{
- if (static_cast<GLuint>(width) > (caps.max3DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max3DTextureSize >> level) ||
- static_cast<GLuint>(depth) > (caps.max3DTextureSize >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- gl::Texture3D *texture3d = context->getTexture3D();
- if (texture3d)
- {
- textureCompressed = texture3d->isCompressed(level);
- textureInternalFormat = texture3d->getInternalFormat(level);
- textureLevelWidth = texture3d->getWidth(level);
- textureLevelHeight = texture3d->getHeight(level);
- textureLevelDepth = texture3d->getDepth(level);
- texture = texture3d;
- }
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
}
break;
- case GL_TEXTURE_2D_ARRAY:
- {
- if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
- static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
- {
- context->recordError(Error(GL_INVALID_VALUE));
- return false;
- }
-
- gl::Texture2DArray *texture2darray = context->getTexture2DArray();
- if (texture2darray)
- {
- textureCompressed = texture2darray->isCompressed(level);
- textureInternalFormat = texture2darray->getInternalFormat(level);
- textureLevelWidth = texture2darray->getWidth(level);
- textureLevelHeight = texture2darray->getHeight(level);
- textureLevelDepth = texture2darray->getLayers(level);
- texture = texture2darray;
- }
- }
- break;
+ case GL_TEXTURE_2D_ARRAY:
+ if (static_cast<GLuint>(width) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(height) > (caps.max2DTextureSize >> level) ||
+ static_cast<GLuint>(depth) > (caps.maxArrayTextureLayers >> level))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+ break;
default:
context->recordError(Error(GL_INVALID_ENUM));
return false;
}
+ gl::Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
if (!texture)
{
context->recordError(Error(GL_INVALID_OPERATION));
@@ -437,7 +380,7 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
}
// Validate texture formats
- GLenum actualInternalFormat = isSubImage ? textureInternalFormat : internalformat;
+ GLenum actualInternalFormat = isSubImage ? texture->getInternalFormat(target, level) : internalformat;
const gl::InternalFormat &actualFormatInfo = gl::GetInternalFormatInfo(actualInternalFormat);
if (isCompressed)
{
@@ -476,22 +419,12 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
// Validate sub image parameters
if (isSubImage)
{
- if (isCompressed != textureCompressed)
+ if (isCompressed != actualFormatInfo.compressed)
{
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
- if (isCompressed)
- {
- if ((width % 4 != 0 && width != textureLevelWidth) ||
- (height % 4 != 0 && height != textureLevelHeight))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
- }
-
if (width == 0 || height == 0 || depth == 0)
{
return false;
@@ -511,9 +444,9 @@ bool ValidateES3TexImageParameters(Context *context, GLenum target, GLint level,
return false;
}
- if (xoffset + width > textureLevelWidth ||
- yoffset + height > textureLevelHeight ||
- zoffset + depth > textureLevelDepth)
+ if (static_cast<size_t>(xoffset + width) > texture->getWidth(target, level) ||
+ static_cast<size_t>(yoffset + height) > texture->getHeight(target, level) ||
+ static_cast<size_t>(zoffset + depth) > texture->getDepth(target, level))
{
context->recordError(Error(GL_INVALID_VALUE));
return false;
@@ -798,8 +731,8 @@ static bool IsValidES3CopyTexImageCombination(GLenum textureInternalFormat, GLen
{
// Renderbuffers cannot be created with an unsized internal format, so this must be an unsized-format
// texture. We can use the same table we use when creating textures to get its effective sized format.
- const FormatType &typeInfo = GetFormatTypeInfo(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
- sourceEffectiveFormat = &GetInternalFormatInfo(typeInfo.internalFormat);
+ GLenum sizedInternalFormat = GetSizedInternalFormat(framebufferInternalFormatInfo.format, framebufferInternalFormatInfo.type);
+ sourceEffectiveFormat = &GetInternalFormatInfo(sizedInternalFormat);
}
}
else
@@ -876,7 +809,7 @@ bool ValidateES3CopyTexImageParameters(Context *context, GLenum target, GLint le
gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- if (framebuffer->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (framebuffer->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
@@ -932,13 +865,10 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le
const gl::Caps &caps = context->getCaps();
- gl::Texture *texture = NULL;
switch (target)
{
case GL_TEXTURE_2D:
{
- texture = context->getTexture2D();
-
if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
static_cast<GLuint>(height) > caps.max2DTextureSize)
{
@@ -950,8 +880,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le
case GL_TEXTURE_CUBE_MAP:
{
- texture = context->getTextureCubeMap();
-
if (width != height)
{
context->recordError(Error(GL_INVALID_VALUE));
@@ -968,8 +896,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le
case GL_TEXTURE_3D:
{
- texture = context->getTexture3D();
-
if (static_cast<GLuint>(width) > caps.max3DTextureSize ||
static_cast<GLuint>(height) > caps.max3DTextureSize ||
static_cast<GLuint>(depth) > caps.max3DTextureSize)
@@ -982,8 +908,6 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le
case GL_TEXTURE_2D_ARRAY:
{
- texture = context->getTexture2DArray();
-
if (static_cast<GLuint>(width) > caps.max2DTextureSize ||
static_cast<GLuint>(height) > caps.max2DTextureSize ||
static_cast<GLuint>(depth) > caps.maxArrayTextureLayers)
@@ -999,6 +923,7 @@ bool ValidateES3TexStorageParameters(Context *context, GLenum target, GLsizei le
return false;
}
+ gl::Texture *texture = context->getTargetTexture(target);
if (!texture || texture->id() == 0)
{
context->recordError(Error(GL_INVALID_OPERATION));
@@ -1068,13 +993,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
-
- gl::Texture2DArray *texArray = static_cast<gl::Texture2DArray *>(tex);
- if (texArray->isCompressed(level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
}
break;
@@ -1091,13 +1009,6 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_VALUE));
return false;
}
-
- gl::Texture3D *tex3d = static_cast<gl::Texture3D *>(tex);
- if (tex3d->isCompressed(level))
- {
- context->recordError(Error(GL_INVALID_OPERATION));
- return false;
- }
}
break;
@@ -1105,6 +1016,13 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
context->recordError(Error(GL_INVALID_OPERATION));
return false;
}
+
+ const gl::InternalFormat &internalFormatInfo = gl::GetInternalFormatInfo(tex->getInternalFormat(tex->getTarget(), level));
+ if (internalFormatInfo.compressed)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
}
return true;
@@ -1187,6 +1105,33 @@ bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum form
return true;
}
+bool ValidateES3RenderbufferStorageParameters(gl::Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height)
+{
+ if (!ValidateRenderbufferStorageParametersBase(context, target, samples, internalformat, width, height))
+ {
+ return false;
+ }
+
+ //The ES3 spec(section 4.4.2) states that the internal format must be sized and not an integer format if samples is greater than zero.
+ const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
+ if ((formatInfo.componentType == GL_UNSIGNED_INT || formatInfo.componentType == GL_INT) && samples > 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ // The behavior is different than the ANGLE version, which would generate a GL_OUT_OF_MEMORY.
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (static_cast<GLuint>(samples) > formatCaps.getMaxSamples())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return false;
+ }
+
+ return true;
+}
+
bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
const GLenum* attachments)
{
@@ -1263,7 +1208,7 @@ bool ValidateClearBuffer(Context *context)
}
const gl::Framebuffer *fbo = context->getState().getDrawFramebuffer();
- if (!fbo || fbo->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ if (!fbo || fbo->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
{
context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
return false;
@@ -1283,4 +1228,55 @@ bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLu
return ValidateGetUniformBase(context, program, location);
}
+bool ValidateReadBuffer(Context *context, GLenum src)
+{
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return false;
+ }
+
+ Framebuffer *readFBO = context->getState().getReadFramebuffer();
+
+ if (readFBO == nullptr)
+ {
+ context->recordError(gl::Error(GL_INVALID_OPERATION, "No active read framebuffer."));
+ return false;
+ }
+
+ if (src == GL_NONE)
+ {
+ return true;
+ }
+
+ if (src != GL_BACK && (src < GL_COLOR_ATTACHMENT0 || src > GL_COLOR_ATTACHMENT15))
+ {
+ context->recordError(gl::Error(GL_INVALID_ENUM, "Unknown enum for 'src' in ReadBuffer"));
+ return false;
+ }
+
+ if (readFBO->id() == 0)
+ {
+ if (src != GL_BACK)
+ {
+ const char *errorMsg = "'src' must be GL_NONE or GL_BACK when reading from the default framebuffer.";
+ context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ return false;
+ }
+ }
+ else
+ {
+ GLuint drawBuffer = static_cast<GLuint>(src - GL_COLOR_ATTACHMENT0);
+
+ if (drawBuffer >= context->getCaps().maxDrawBuffers)
+ {
+ const char *errorMsg = "'src' is greater than MAX_DRAW_BUFFERS.";
+ context->recordError(gl::Error(GL_INVALID_OPERATION, errorMsg));
+ return false;
+ }
+ }
+
+ return true;
+}
+
}
diff --git a/src/3rdparty/angle/src/libGLESv2/validationES3.h b/src/3rdparty/angle/src/libANGLE/validationES3.h
index cafacca601..517cb5d27f 100644
--- a/src/3rdparty/angle/src/libGLESv2/validationES3.h
+++ b/src/3rdparty/angle/src/libANGLE/validationES3.h
@@ -6,8 +6,8 @@
// validationES3.h: Validation functions for OpenGL ES 3.0 entry point parameters
-#ifndef LIBGLESV2_VALIDATION_ES3_H
-#define LIBGLESV2_VALIDATION_ES3_H
+#ifndef LIBANGLE_VALIDATION_ES3_H_
+#define LIBANGLE_VALIDATION_ES3_H_
#include <GLES3/gl3.h>
@@ -32,6 +32,9 @@ bool ValidateFramebufferTextureLayer(Context *context, GLenum target, GLenum att
bool ValidES3ReadFormatType(Context *context, GLenum internalFormat, GLenum format, GLenum type);
+bool ValidateES3RenderbufferStorageParameters(Context *context, GLenum target, GLsizei samples,
+ GLenum internalformat, GLsizei width, GLsizei height);
+
bool ValidateInvalidateFramebufferParameters(Context *context, GLenum target, GLsizei numAttachments,
const GLenum* attachments);
@@ -39,6 +42,8 @@ bool ValidateClearBuffer(Context *context);
bool ValidateGetUniformuiv(Context *context, GLuint program, GLint location, GLuint* params);
+bool ValidateReadBuffer(Context *context, GLenum mode);
+
}
-#endif // LIBGLESV2_VALIDATION_ES3_H
+#endif // LIBANGLE_VALIDATION_ES3_H_
diff --git a/src/3rdparty/angle/src/libEGL/Config.cpp b/src/3rdparty/angle/src/libEGL/Config.cpp
deleted file mode 100644
index fdc41a95f0..0000000000
--- a/src/3rdparty/angle/src/libEGL/Config.cpp
+++ /dev/null
@@ -1,353 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Config.cpp: Implements the egl::Config class, describing the format, type
-// and size for an egl::Surface. Implements EGLConfig and related functionality.
-// [EGL 1.4] section 3.4 page 15.
-
-#include "libEGL/Config.h"
-
-#include <algorithm>
-#include <vector>
-
-#include "angle_gl.h"
-#include <EGL/eglext.h>
-
-#include "common/debug.h"
-
-using namespace std;
-
-namespace egl
-{
-Config::Config(rx::ConfigDesc desc, EGLint minInterval, EGLint maxInterval, EGLint texWidth, EGLint texHeight)
- : mRenderTargetFormat(desc.renderTargetFormat), mDepthStencilFormat(desc.depthStencilFormat), mMultiSample(desc.multiSample)
-{
- mBindToTextureRGB = EGL_FALSE;
- mBindToTextureRGBA = EGL_FALSE;
- switch (desc.renderTargetFormat)
- {
- case GL_RGB5_A1:
- mBufferSize = 16;
- mRedSize = 5;
- mGreenSize = 5;
- mBlueSize = 5;
- mAlphaSize = 1;
- break;
- case GL_BGR5_A1_ANGLEX:
- mBufferSize = 16;
- mRedSize = 5;
- mGreenSize = 5;
- mBlueSize = 5;
- mAlphaSize = 1;
- break;
- case GL_RGBA8_OES:
- mBufferSize = 32;
- mRedSize = 8;
- mGreenSize = 8;
- mBlueSize = 8;
- mAlphaSize = 8;
- mBindToTextureRGBA = true;
- break;
- case GL_RGB565:
- mBufferSize = 16;
- mRedSize = 5;
- mGreenSize = 6;
- mBlueSize = 5;
- mAlphaSize = 0;
- break;
- case GL_RGB8_OES:
- mBufferSize = 32;
- mRedSize = 8;
- mGreenSize = 8;
- mBlueSize = 8;
- mAlphaSize = 0;
- mBindToTextureRGB = true;
- break;
- case GL_BGRA8_EXT:
- mBufferSize = 32;
- mRedSize = 8;
- mGreenSize = 8;
- mBlueSize = 8;
- mAlphaSize = 8;
- mBindToTextureRGBA = true;
- break;
- default:
- UNREACHABLE(); // Other formats should not be valid
- }
-
- mLuminanceSize = 0;
- mAlphaMaskSize = 0;
- mColorBufferType = EGL_RGB_BUFFER;
- mConfigCaveat = (desc.fastConfig) ? EGL_NONE : EGL_SLOW_CONFIG;
- mConfigID = 0;
- mConformant = EGL_OPENGL_ES2_BIT;
-
- switch (desc.depthStencilFormat)
- {
- case GL_NONE:
- mDepthSize = 0;
- mStencilSize = 0;
- break;
- case GL_DEPTH_COMPONENT32_OES:
- mDepthSize = 32;
- mStencilSize = 0;
- break;
- case GL_DEPTH24_STENCIL8_OES:
- mDepthSize = 24;
- mStencilSize = 8;
- break;
- case GL_DEPTH_COMPONENT24_OES:
- mDepthSize = 24;
- mStencilSize = 0;
- break;
- case GL_DEPTH_COMPONENT16:
- mDepthSize = 16;
- mStencilSize = 0;
- break;
- default:
- UNREACHABLE();
- }
-
- mLevel = 0;
- mMatchNativePixmap = EGL_NONE;
- mMaxPBufferWidth = texWidth;
- mMaxPBufferHeight = texHeight;
- mMaxPBufferPixels = texWidth*texHeight;
- mMaxSwapInterval = maxInterval;
- mMinSwapInterval = minInterval;
- mNativeRenderable = EGL_FALSE;
- mNativeVisualID = 0;
- mNativeVisualType = 0;
- mRenderableType = EGL_OPENGL_ES2_BIT;
- mSampleBuffers = desc.multiSample ? 1 : 0;
- mSamples = desc.multiSample;
- mSurfaceType = EGL_PBUFFER_BIT | EGL_WINDOW_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT;
- mTransparentType = EGL_NONE;
- mTransparentRedValue = 0;
- mTransparentGreenValue = 0;
- mTransparentBlueValue = 0;
-
- if (desc.es3Capable)
- {
- mRenderableType |= EGL_OPENGL_ES3_BIT_KHR;
- mConformant |= EGL_OPENGL_ES3_BIT_KHR;
- }
-}
-
-EGLConfig Config::getHandle() const
-{
- return (EGLConfig)(size_t)mConfigID;
-}
-
-SortConfig::SortConfig(const EGLint *attribList)
- : mWantRed(false), mWantGreen(false), mWantBlue(false), mWantAlpha(false), mWantLuminance(false)
-{
- scanForWantedComponents(attribList);
-}
-
-void SortConfig::scanForWantedComponents(const EGLint *attribList)
-{
- // [EGL] section 3.4.1 page 24
- // Sorting rule #3: by larger total number of color bits, not considering
- // components that are 0 or don't-care.
- for (const EGLint *attr = attribList; attr[0] != EGL_NONE; attr += 2)
- {
- if (attr[1] != 0 && attr[1] != EGL_DONT_CARE)
- {
- switch (attr[0])
- {
- case EGL_RED_SIZE: mWantRed = true; break;
- case EGL_GREEN_SIZE: mWantGreen = true; break;
- case EGL_BLUE_SIZE: mWantBlue = true; break;
- case EGL_ALPHA_SIZE: mWantAlpha = true; break;
- case EGL_LUMINANCE_SIZE: mWantLuminance = true; break;
- }
- }
- }
-}
-
-EGLint SortConfig::wantedComponentsSize(const Config &config) const
-{
- EGLint total = 0;
-
- if (mWantRed) total += config.mRedSize;
- if (mWantGreen) total += config.mGreenSize;
- if (mWantBlue) total += config.mBlueSize;
- if (mWantAlpha) total += config.mAlphaSize;
- if (mWantLuminance) total += config.mLuminanceSize;
-
- return total;
-}
-
-bool SortConfig::operator()(const Config *x, const Config *y) const
-{
- return (*this)(*x, *y);
-}
-
-bool SortConfig::operator()(const Config &x, const Config &y) const
-{
- #define SORT(attribute) \
- if (x.attribute != y.attribute) \
- { \
- return x.attribute < y.attribute; \
- }
-
- META_ASSERT(EGL_NONE < EGL_SLOW_CONFIG && EGL_SLOW_CONFIG < EGL_NON_CONFORMANT_CONFIG);
- SORT(mConfigCaveat);
-
- META_ASSERT(EGL_RGB_BUFFER < EGL_LUMINANCE_BUFFER);
- SORT(mColorBufferType);
-
- // By larger total number of color bits, only considering those that are requested to be > 0.
- EGLint xComponentsSize = wantedComponentsSize(x);
- EGLint yComponentsSize = wantedComponentsSize(y);
- if (xComponentsSize != yComponentsSize)
- {
- return xComponentsSize > yComponentsSize;
- }
-
- SORT(mBufferSize);
- SORT(mSampleBuffers);
- SORT(mSamples);
- SORT(mDepthSize);
- SORT(mStencilSize);
- SORT(mAlphaMaskSize);
- SORT(mNativeVisualType);
- SORT(mConfigID);
-
- #undef SORT
-
- return false;
-}
-
-// We'd like to use SortConfig to also eliminate duplicate configs.
-// This works as long as we never have two configs with different per-RGB-component layouts,
-// but the same total.
-// 5551 and 565 are different because R+G+B is different.
-// 5551 and 555 are different because bufferSize is different.
-const EGLint ConfigSet::mSortAttribs[] =
-{
- EGL_RED_SIZE, 1,
- EGL_GREEN_SIZE, 1,
- EGL_BLUE_SIZE, 1,
- EGL_LUMINANCE_SIZE, 1,
- // BUT NOT ALPHA
- EGL_NONE
-};
-
-ConfigSet::ConfigSet()
- : mSet(SortConfig(mSortAttribs))
-{
-}
-
-void ConfigSet::add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight)
-{
- Config config(desc, minSwapInterval, maxSwapInterval, texWidth, texHeight);
- mSet.insert(config);
-}
-
-size_t ConfigSet::size() const
-{
- return mSet.size();
-}
-
-bool ConfigSet::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
-{
- vector<const Config*> passed;
- passed.reserve(mSet.size());
-
- for (Iterator config = mSet.begin(); config != mSet.end(); config++)
- {
- bool match = true;
- const EGLint *attribute = attribList;
-
- while (attribute[0] != EGL_NONE)
- {
- switch (attribute[0])
- {
- case EGL_BUFFER_SIZE: match = config->mBufferSize >= attribute[1]; break;
- case EGL_ALPHA_SIZE: match = config->mAlphaSize >= attribute[1]; break;
- case EGL_BLUE_SIZE: match = config->mBlueSize >= attribute[1]; break;
- case EGL_GREEN_SIZE: match = config->mGreenSize >= attribute[1]; break;
- case EGL_RED_SIZE: match = config->mRedSize >= attribute[1]; break;
- case EGL_DEPTH_SIZE: match = config->mDepthSize >= attribute[1]; break;
- case EGL_STENCIL_SIZE: match = config->mStencilSize >= attribute[1]; break;
- case EGL_CONFIG_CAVEAT: match = config->mConfigCaveat == (EGLenum) attribute[1]; break;
- case EGL_CONFIG_ID: match = config->mConfigID == attribute[1]; break;
- case EGL_LEVEL: match = config->mLevel >= attribute[1]; break;
- case EGL_NATIVE_RENDERABLE: match = config->mNativeRenderable == (EGLBoolean) attribute[1]; break;
- case EGL_NATIVE_VISUAL_TYPE: match = config->mNativeVisualType == attribute[1]; break;
- case EGL_SAMPLES: match = config->mSamples >= attribute[1]; break;
- case EGL_SAMPLE_BUFFERS: match = config->mSampleBuffers >= attribute[1]; break;
- case EGL_SURFACE_TYPE: match = (config->mSurfaceType & attribute[1]) == attribute[1]; break;
- case EGL_TRANSPARENT_TYPE: match = config->mTransparentType == (EGLenum) attribute[1]; break;
- case EGL_TRANSPARENT_BLUE_VALUE: match = config->mTransparentBlueValue == attribute[1]; break;
- case EGL_TRANSPARENT_GREEN_VALUE: match = config->mTransparentGreenValue == attribute[1]; break;
- case EGL_TRANSPARENT_RED_VALUE: match = config->mTransparentRedValue == attribute[1]; break;
- case EGL_BIND_TO_TEXTURE_RGB: match = config->mBindToTextureRGB == (EGLBoolean) attribute[1]; break;
- case EGL_BIND_TO_TEXTURE_RGBA: match = config->mBindToTextureRGBA == (EGLBoolean) attribute[1]; break;
- case EGL_MIN_SWAP_INTERVAL: match = config->mMinSwapInterval == attribute[1]; break;
- case EGL_MAX_SWAP_INTERVAL: match = config->mMaxSwapInterval == attribute[1]; break;
- case EGL_LUMINANCE_SIZE: match = config->mLuminanceSize >= attribute[1]; break;
- case EGL_ALPHA_MASK_SIZE: match = config->mAlphaMaskSize >= attribute[1]; break;
- case EGL_COLOR_BUFFER_TYPE: match = config->mColorBufferType == (EGLenum) attribute[1]; break;
- case EGL_RENDERABLE_TYPE: match = (config->mRenderableType & attribute[1]) == attribute[1]; break;
- case EGL_MATCH_NATIVE_PIXMAP: match = false; UNIMPLEMENTED(); break;
- case EGL_CONFORMANT: match = (config->mConformant & attribute[1]) == attribute[1]; break;
- case EGL_MAX_PBUFFER_WIDTH: match = config->mMaxPBufferWidth >= attribute[1]; break;
- case EGL_MAX_PBUFFER_HEIGHT: match = config->mMaxPBufferHeight >= attribute[1]; break;
- case EGL_MAX_PBUFFER_PIXELS: match = config->mMaxPBufferPixels >= attribute[1]; break;
- default:
- return false;
- }
-
- if (!match)
- {
- break;
- }
-
- attribute += 2;
- }
-
- if (match)
- {
- passed.push_back(&*config);
- }
- }
-
- if (configs)
- {
- sort(passed.begin(), passed.end(), SortConfig(attribList));
-
- EGLint index;
- for (index = 0; index < configSize && index < static_cast<EGLint>(passed.size()); index++)
- {
- configs[index] = passed[index]->getHandle();
- }
-
- *numConfig = index;
- }
- else
- {
- *numConfig = passed.size();
- }
-
- return true;
-}
-
-const egl::Config *ConfigSet::get(EGLConfig configHandle)
-{
- for (Iterator config = mSet.begin(); config != mSet.end(); config++)
- {
- if (config->getHandle() == configHandle)
- {
- return &(*config);
- }
- }
-
- return NULL;
-}
-}
diff --git a/src/3rdparty/angle/src/libEGL/Config.h b/src/3rdparty/angle/src/libEGL/Config.h
deleted file mode 100644
index 98441142f4..0000000000
--- a/src/3rdparty/angle/src/libEGL/Config.h
+++ /dev/null
@@ -1,114 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Config.h: Defines the egl::Config class, describing the format, type
-// and size for an egl::Surface. Implements EGLConfig and related functionality.
-// [EGL 1.4] section 3.4 page 15.
-
-#ifndef INCLUDE_CONFIG_H_
-#define INCLUDE_CONFIG_H_
-
-#include <EGL/egl.h>
-
-#include <set>
-
-#include "libGLESv2/renderer/Renderer.h"
-#include "common/angleutils.h"
-
-namespace egl
-{
-class Display;
-
-class Config
-{
- public:
- Config(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight);
-
- EGLConfig getHandle() const;
-
- const GLenum mRenderTargetFormat;
- const GLenum mDepthStencilFormat;
- const GLint mMultiSample;
-
- EGLint mBufferSize; // Depth of the color buffer
- EGLint mRedSize; // Bits of Red in the color buffer
- EGLint mGreenSize; // Bits of Green in the color buffer
- EGLint mBlueSize; // Bits of Blue in the color buffer
- EGLint mLuminanceSize; // Bits of Luminance in the color buffer
- EGLint mAlphaSize; // Bits of Alpha in the color buffer
- EGLint mAlphaMaskSize; // Bits of Alpha Mask in the mask buffer
- EGLBoolean mBindToTextureRGB; // True if bindable to RGB textures.
- EGLBoolean mBindToTextureRGBA; // True if bindable to RGBA textures.
- EGLenum mColorBufferType; // Color buffer type
- EGLenum mConfigCaveat; // Any caveats for the configuration
- EGLint mConfigID; // Unique EGLConfig identifier
- EGLint mConformant; // Whether contexts created with this config are conformant
- EGLint mDepthSize; // Bits of Z in the depth buffer
- EGLint mLevel; // Frame buffer level
- EGLBoolean mMatchNativePixmap; // Match the native pixmap format
- EGLint mMaxPBufferWidth; // Maximum width of pbuffer
- EGLint mMaxPBufferHeight; // Maximum height of pbuffer
- EGLint mMaxPBufferPixels; // Maximum size of pbuffer
- EGLint mMaxSwapInterval; // Maximum swap interval
- EGLint mMinSwapInterval; // Minimum swap interval
- EGLBoolean mNativeRenderable; // EGL_TRUE if native rendering APIs can render to surface
- EGLint mNativeVisualID; // Handle of corresponding native visual
- EGLint mNativeVisualType; // Native visual type of the associated visual
- EGLint mRenderableType; // Which client rendering APIs are supported.
- EGLint mSampleBuffers; // Number of multisample buffers
- EGLint mSamples; // Number of samples per pixel
- EGLint mStencilSize; // Bits of Stencil in the stencil buffer
- EGLint mSurfaceType; // Which types of EGL surfaces are supported.
- EGLenum mTransparentType; // Type of transparency supported
- EGLint mTransparentRedValue; // Transparent red value
- EGLint mTransparentGreenValue; // Transparent green value
- EGLint mTransparentBlueValue; // Transparent blue value
-};
-
-// Function object used by STL sorting routines for ordering Configs according to [EGL] section 3.4.1 page 24.
-class SortConfig
-{
- public:
- explicit SortConfig(const EGLint *attribList);
-
- bool operator()(const Config *x, const Config *y) const;
- bool operator()(const Config &x, const Config &y) const;
-
- private:
- void scanForWantedComponents(const EGLint *attribList);
- EGLint wantedComponentsSize(const Config &config) const;
-
- bool mWantRed;
- bool mWantGreen;
- bool mWantBlue;
- bool mWantAlpha;
- bool mWantLuminance;
-};
-
-class ConfigSet
-{
- friend Display;
-
- public:
- ConfigSet();
-
- void add(rx::ConfigDesc desc, EGLint minSwapInterval, EGLint maxSwapInterval, EGLint texWidth, EGLint texHeight);
- size_t size() const;
- bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
- const egl::Config *get(EGLConfig configHandle);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConfigSet);
-
- typedef std::set<Config, SortConfig> Set;
- typedef Set::iterator Iterator;
- Set mSet;
-
- static const EGLint mSortAttribs[];
-};
-}
-
-#endif // INCLUDE_CONFIG_H_
diff --git a/src/3rdparty/angle/src/libEGL/Display.cpp b/src/3rdparty/angle/src/libEGL/Display.cpp
deleted file mode 100644
index eea93b1d87..0000000000
--- a/src/3rdparty/angle/src/libEGL/Display.cpp
+++ /dev/null
@@ -1,648 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Display.cpp: Implements the egl::Display class, representing the abstract
-// display on which graphics are drawn. Implements EGLDisplay.
-// [EGL 1.4] section 2.1.2 page 3.
-
-#include "libEGL/Display.h"
-
-#include <algorithm>
-#include <map>
-#include <vector>
-#include <sstream>
-#include <iterator>
-
-#include "common/debug.h"
-#include "common/mathutil.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/renderer/SwapChain.h"
-
-#include "libEGL/main.h"
-#include "libEGL/Surface.h"
-
-namespace egl
-{
-
-typedef std::map<EGLNativeDisplayType, Display*> DisplayMap;
-static DisplayMap *GetDisplayMap()
-{
- static DisplayMap displays;
- return &displays;
-}
-
-egl::Display *Display::getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap)
-{
- Display *display = NULL;
-
- DisplayMap *displays = GetDisplayMap();
- DisplayMap::const_iterator iter = displays->find(displayId);
- if (iter != displays->end())
- {
- display = iter->second;
- }
- else
- {
- display = new egl::Display(displayId);
- displays->insert(std::make_pair(displayId, display));
- }
-
- // Apply new attributes if the display is not initialized yet.
- if (!display->isInitialized())
- {
- display->setAttributes(attribMap);
- }
-
- return display;
-}
-
-Display::Display(EGLNativeDisplayType displayId)
- : mDisplayId(displayId),
- mAttributeMap(),
- mRenderer(NULL)
-{
-}
-
-Display::~Display()
-{
- terminate();
-
- DisplayMap *displays = GetDisplayMap();
- DisplayMap::iterator iter = displays->find(mDisplayId);
- if (iter != displays->end())
- {
- displays->erase(iter);
- }
-}
-
-void Display::setAttributes(const AttributeMap &attribMap)
-{
- mAttributeMap = attribMap;
-}
-
-Error Display::initialize()
-{
- if (isInitialized())
- {
- return Error(EGL_SUCCESS);
- }
-
- mRenderer = glCreateRenderer(this, mDisplayId, mAttributeMap);
-
- if (!mRenderer)
- {
- terminate();
- return Error(EGL_NOT_INITIALIZED);
- }
-
- //TODO(jmadill): should be part of caps?
- EGLint minSwapInterval = mRenderer->getMinSwapInterval();
- EGLint maxSwapInterval = mRenderer->getMaxSwapInterval();
- EGLint maxTextureSize = mRenderer->getRendererCaps().max2DTextureSize;
-
- rx::ConfigDesc *descList;
- int numConfigs = mRenderer->generateConfigs(&descList);
- ConfigSet configSet;
-
- for (int i = 0; i < numConfigs; ++i)
- {
- configSet.add(descList[i], minSwapInterval, maxSwapInterval, maxTextureSize, maxTextureSize);
- }
-
- // Give the sorted configs a unique ID and store them internally
- EGLint index = 1;
- for (ConfigSet::Iterator config = configSet.mSet.begin(); config != configSet.mSet.end(); config++)
- {
- Config configuration = *config;
- configuration.mConfigID = index;
- index++;
-
- mConfigSet.mSet.insert(configuration);
- }
-
- mRenderer->deleteConfigs(descList);
- descList = NULL;
-
- if (!isInitialized())
- {
- terminate();
- return Error(EGL_NOT_INITIALIZED);
- }
-
- initDisplayExtensionString();
- initVendorString();
-
- return Error(EGL_SUCCESS);
-}
-
-void Display::terminate()
-{
- while (!mSurfaceSet.empty())
- {
- destroySurface(*mSurfaceSet.begin());
- }
-
- while (!mContextSet.empty())
- {
- destroyContext(*mContextSet.begin());
- }
-
- glDestroyRenderer(mRenderer);
- mRenderer = NULL;
-
- mConfigSet.mSet.clear();
-}
-
-bool Display::getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig)
-{
- return mConfigSet.getConfigs(configs, attribList, configSize, numConfig);
-}
-
-bool Display::getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value)
-{
- const egl::Config *configuration = mConfigSet.get(config);
-
- switch (attribute)
- {
- case EGL_BUFFER_SIZE: *value = configuration->mBufferSize; break;
- case EGL_ALPHA_SIZE: *value = configuration->mAlphaSize; break;
- case EGL_BLUE_SIZE: *value = configuration->mBlueSize; break;
- case EGL_GREEN_SIZE: *value = configuration->mGreenSize; break;
- case EGL_RED_SIZE: *value = configuration->mRedSize; break;
- case EGL_DEPTH_SIZE: *value = configuration->mDepthSize; break;
- case EGL_STENCIL_SIZE: *value = configuration->mStencilSize; break;
- case EGL_CONFIG_CAVEAT: *value = configuration->mConfigCaveat; break;
- case EGL_CONFIG_ID: *value = configuration->mConfigID; break;
- case EGL_LEVEL: *value = configuration->mLevel; break;
- case EGL_NATIVE_RENDERABLE: *value = configuration->mNativeRenderable; break;
- case EGL_NATIVE_VISUAL_TYPE: *value = configuration->mNativeVisualType; break;
- case EGL_SAMPLES: *value = configuration->mSamples; break;
- case EGL_SAMPLE_BUFFERS: *value = configuration->mSampleBuffers; break;
- case EGL_SURFACE_TYPE: *value = configuration->mSurfaceType; break;
- case EGL_TRANSPARENT_TYPE: *value = configuration->mTransparentType; break;
- case EGL_TRANSPARENT_BLUE_VALUE: *value = configuration->mTransparentBlueValue; break;
- case EGL_TRANSPARENT_GREEN_VALUE: *value = configuration->mTransparentGreenValue; break;
- case EGL_TRANSPARENT_RED_VALUE: *value = configuration->mTransparentRedValue; break;
- case EGL_BIND_TO_TEXTURE_RGB: *value = configuration->mBindToTextureRGB; break;
- case EGL_BIND_TO_TEXTURE_RGBA: *value = configuration->mBindToTextureRGBA; break;
- case EGL_MIN_SWAP_INTERVAL: *value = configuration->mMinSwapInterval; break;
- case EGL_MAX_SWAP_INTERVAL: *value = configuration->mMaxSwapInterval; break;
- case EGL_LUMINANCE_SIZE: *value = configuration->mLuminanceSize; break;
- case EGL_ALPHA_MASK_SIZE: *value = configuration->mAlphaMaskSize; break;
- case EGL_COLOR_BUFFER_TYPE: *value = configuration->mColorBufferType; break;
- case EGL_RENDERABLE_TYPE: *value = configuration->mRenderableType; break;
- case EGL_MATCH_NATIVE_PIXMAP: *value = false; UNIMPLEMENTED(); break;
- case EGL_CONFORMANT: *value = configuration->mConformant; break;
- case EGL_MAX_PBUFFER_WIDTH: *value = configuration->mMaxPBufferWidth; break;
- case EGL_MAX_PBUFFER_HEIGHT: *value = configuration->mMaxPBufferHeight; break;
- case EGL_MAX_PBUFFER_PIXELS: *value = configuration->mMaxPBufferPixels; break;
- default:
- return false;
- }
-
- return true;
-}
-
-
-
-Error Display::createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface)
-{
- const Config *configuration = mConfigSet.get(config);
- EGLint postSubBufferSupported = EGL_FALSE;
-
- EGLint width = 0;
- EGLint height = 0;
- EGLint fixedSize = EGL_FALSE;
-
- if (attribList)
- {
- while (*attribList != EGL_NONE)
- {
- switch (attribList[0])
- {
- case EGL_RENDER_BUFFER:
- switch (attribList[1])
- {
- case EGL_BACK_BUFFER:
- break;
- case EGL_SINGLE_BUFFER:
- return Error(EGL_BAD_MATCH); // Rendering directly to front buffer not supported
- default:
- return Error(EGL_BAD_ATTRIBUTE);
- }
- break;
- case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
- postSubBufferSupported = attribList[1];
- break;
- case EGL_WIDTH:
- width = attribList[1];
- break;
- case EGL_HEIGHT:
- height = attribList[1];
- break;
- case EGL_FIXED_SIZE_ANGLE:
- fixedSize = attribList[1];
- break;
- case EGL_VG_COLORSPACE:
- return Error(EGL_BAD_MATCH);
- case EGL_VG_ALPHA_FORMAT:
- return Error(EGL_BAD_MATCH);
- default:
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
- attribList += 2;
- }
- }
-
- if (width < 0 || height < 0)
- {
- return Error(EGL_BAD_PARAMETER);
- }
-
- if (!fixedSize)
- {
- width = -1;
- height = -1;
- }
-
- if (hasExistingWindowSurface(window))
- {
- return Error(EGL_BAD_ALLOC);
- }
-
- if (mRenderer->testDeviceLost(false))
- {
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
- }
-
- Surface *surface = new Surface(this, configuration, window, fixedSize, width, height, postSubBufferSupported);
- Error error = surface->initialize();
- if (error.isError())
- {
- SafeDelete(surface);
- return error;
- }
-
- mSurfaceSet.insert(surface);
-
- *outSurface = surface;
- return Error(EGL_SUCCESS);
-}
-
-Error Display::createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface)
-{
- EGLint width = 0, height = 0;
- EGLenum textureFormat = EGL_NO_TEXTURE;
- EGLenum textureTarget = EGL_NO_TEXTURE;
- const Config *configuration = mConfigSet.get(config);
-
- if (attribList)
- {
- while (*attribList != EGL_NONE)
- {
- switch (attribList[0])
- {
- case EGL_WIDTH:
- width = attribList[1];
- break;
- case EGL_HEIGHT:
- height = attribList[1];
- break;
- case EGL_LARGEST_PBUFFER:
- if (attribList[1] != EGL_FALSE)
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_TEXTURE_FORMAT:
- switch (attribList[1])
- {
- case EGL_NO_TEXTURE:
- case EGL_TEXTURE_RGB:
- case EGL_TEXTURE_RGBA:
- textureFormat = attribList[1];
- break;
- default:
- return Error(EGL_BAD_ATTRIBUTE);
- }
- break;
- case EGL_TEXTURE_TARGET:
- switch (attribList[1])
- {
- case EGL_NO_TEXTURE:
- case EGL_TEXTURE_2D:
- textureTarget = attribList[1];
- break;
- default:
- return Error(EGL_BAD_ATTRIBUTE);
- }
- break;
- case EGL_MIPMAP_TEXTURE:
- if (attribList[1] != EGL_FALSE)
- return Error(EGL_BAD_ATTRIBUTE);
- break;
- case EGL_VG_COLORSPACE:
- return Error(EGL_BAD_MATCH);
- case EGL_VG_ALPHA_FORMAT:
- return Error(EGL_BAD_MATCH);
- default:
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
- attribList += 2;
- }
- }
-
- if (width < 0 || height < 0)
- {
- return Error(EGL_BAD_PARAMETER);
- }
-
- if (width == 0 || height == 0)
- {
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
- if (textureFormat != EGL_NO_TEXTURE && !mRenderer->getRendererExtensions().textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
- {
- return Error(EGL_BAD_MATCH);
- }
-
- if ((textureFormat != EGL_NO_TEXTURE && textureTarget == EGL_NO_TEXTURE) ||
- (textureFormat == EGL_NO_TEXTURE && textureTarget != EGL_NO_TEXTURE))
- {
- return Error(EGL_BAD_MATCH);
- }
-
- if (!(configuration->mSurfaceType & EGL_PBUFFER_BIT))
- {
- return Error(EGL_BAD_MATCH);
- }
-
- if ((textureFormat == EGL_TEXTURE_RGB && configuration->mBindToTextureRGB != EGL_TRUE) ||
- (textureFormat == EGL_TEXTURE_RGBA && configuration->mBindToTextureRGBA != EGL_TRUE))
- {
- return Error(EGL_BAD_ATTRIBUTE);
- }
-
- if (mRenderer->testDeviceLost(false))
- {
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
- }
-
- Surface *surface = new Surface(this, configuration, shareHandle, width, height, textureFormat, textureTarget);
- Error error = surface->initialize();
- if (error.isError())
- {
- SafeDelete(surface);
- return error;
- }
-
- mSurfaceSet.insert(surface);
-
- *outSurface = surface;
- return Error(EGL_SUCCESS);
-}
-
-Error Display::createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
- bool robustAccess, EGLContext *outContext)
-{
- if (!mRenderer)
- {
- *outContext = EGL_NO_CONTEXT;
- return Error(EGL_SUCCESS);
- }
- else if (mRenderer->testDeviceLost(false)) // Lost device
- {
- Error error = restoreLostDevice();
- if (error.isError())
- {
- return error;
- }
- }
-
- //TODO(jmadill): shader model is not cross-platform
- if (clientVersion > 2 && mRenderer->getMajorShaderModel() < 4)
- {
- return Error(EGL_BAD_CONFIG);
- }
-
- gl::Context *context = glCreateContext(clientVersion, shareContext, mRenderer, notifyResets, robustAccess);
- mContextSet.insert(context);
-
- *outContext = context;
- return Error(EGL_SUCCESS);
-}
-
-Error Display::restoreLostDevice()
-{
- for (ContextSet::iterator ctx = mContextSet.begin(); ctx != mContextSet.end(); ctx++)
- {
- if ((*ctx)->isResetNotificationEnabled())
- {
- // If reset notifications have been requested, application must delete all contexts first
- return Error(EGL_CONTEXT_LOST);
- }
- }
-
- // Release surface resources to make the Reset() succeed
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
- {
- (*surface)->release();
- }
-
- if (!mRenderer->resetDevice())
- {
- return Error(EGL_BAD_ALLOC);
- }
-
- // Restore any surfaces that may have been lost
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
- {
- Error error = (*surface)->resetSwapChain();
- if (error.isError())
- {
- return error;
- }
- }
-
- return Error(EGL_SUCCESS);
-}
-
-
-void Display::destroySurface(egl::Surface *surface)
-{
- delete surface;
- mSurfaceSet.erase(surface);
-}
-
-void Display::destroyContext(gl::Context *context)
-{
- glDestroyContext(context);
- mContextSet.erase(context);
-}
-
-void Display::notifyDeviceLost()
-{
- for (ContextSet::iterator context = mContextSet.begin(); context != mContextSet.end(); context++)
- {
- (*context)->markContextLost();
- }
-}
-
-void Display::recreateSwapChains()
-{
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
- {
- (*surface)->getSwapChain()->recreate();
- }
-}
-
-bool Display::isInitialized() const
-{
- return mRenderer != NULL && mConfigSet.size() > 0;
-}
-
-bool Display::isValidConfig(EGLConfig config)
-{
- return mConfigSet.get(config) != NULL;
-}
-
-bool Display::isValidContext(gl::Context *context)
-{
- return mContextSet.find(context) != mContextSet.end();
-}
-
-bool Display::isValidSurface(egl::Surface *surface)
-{
- return mSurfaceSet.find(surface) != mSurfaceSet.end();
-}
-
-bool Display::hasExistingWindowSurface(EGLNativeWindowType window)
-{
- for (SurfaceSet::iterator surface = mSurfaceSet.begin(); surface != mSurfaceSet.end(); surface++)
- {
- if ((*surface)->getWindowHandle() == window)
- {
- return true;
- }
- }
-
- return false;
-}
-
-std::string Display::generateClientExtensionString()
-{
- std::vector<std::string> extensions;
-
- extensions.push_back("EGL_EXT_client_extensions");
-
- extensions.push_back("ANGLE_platform_angle");
-
- if (supportsPlatformD3D())
- {
- extensions.push_back("ANGLE_platform_angle_d3d");
- }
-
- if (supportsPlatformOpenGL())
- {
- extensions.push_back("ANGLE_platform_angle_opengl");
- }
-
- std::ostringstream stream;
- std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " "));
- return stream.str();
-}
-
-void Display::initDisplayExtensionString()
-{
- std::vector<std::string> extensions;
-
- // Multi-vendor (EXT) extensions
- extensions.push_back("EGL_EXT_create_context_robustness");
-
- // ANGLE-specific extensions
- if (mRenderer->getShareHandleSupport())
- {
- extensions.push_back("EGL_ANGLE_d3d_share_handle_client_buffer");
- extensions.push_back("EGL_ANGLE_surface_d3d_texture_2d_share_handle");
- }
-
- extensions.push_back("EGL_ANGLE_query_surface_pointer");
- extensions.push_back("EGL_ANGLE_window_fixed_size");
-
- if (mRenderer->getPostSubBufferSupport())
- {
- extensions.push_back("EGL_NV_post_sub_buffer");
- }
-
-#if defined (ANGLE_TEST_CONFIG)
- // TODO: complete support for the EGL_KHR_create_context extension
- extensions.push_back("EGL_KHR_create_context");
-#endif
-
- std::ostringstream stream;
- std::copy(extensions.begin(), extensions.end(), std::ostream_iterator<std::string>(stream, " "));
- mDisplayExtensionString = stream.str();
-}
-
-const char *Display::getExtensionString(egl::Display *display)
-{
- if (display != EGL_NO_DISPLAY)
- {
- return display->mDisplayExtensionString.c_str();
- }
- else
- {
- static std::string clientExtensions = generateClientExtensionString();
- return clientExtensions.c_str();
- }
-}
-
-bool Display::supportsPlatformD3D()
-{
-#if defined(ANGLE_ENABLE_D3D9) || defined(ANGLE_ENABLE_D3D11)
- return true;
-#else
- return false;
-#endif
-}
-
-bool Display::supportsPlatformOpenGL()
-{
- return false;
-}
-
-void Display::initVendorString()
-{
- mVendorString = "Google Inc.";
-
- LUID adapterLuid = {0};
-
- //TODO(jmadill): LUID is not cross-platform
- if (mRenderer && mRenderer->getLUID(&adapterLuid))
- {
- char adapterLuidString[64];
- sprintf_s(adapterLuidString, sizeof(adapterLuidString), " (adapter LUID: %08x%08x)", adapterLuid.HighPart, adapterLuid.LowPart);
-
- mVendorString += adapterLuidString;
- }
-}
-
-const char *Display::getVendorString() const
-{
- return mVendorString.c_str();
-}
-
-}
diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
deleted file mode 100644
index b3ffcc84c5..0000000000
--- a/src/3rdparty/angle/src/libEGL/Display.h
+++ /dev/null
@@ -1,104 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Display.h: Defines the egl::Display class, representing the abstract
-// display on which graphics are drawn. Implements EGLDisplay.
-// [EGL 1.4] section 2.1.2 page 3.
-
-#ifndef LIBEGL_DISPLAY_H_
-#define LIBEGL_DISPLAY_H_
-
-#include <set>
-#include <vector>
-
-#include "libEGL/Error.h"
-#include "libEGL/Config.h"
-#include "libEGL/AttributeMap.h"
-
-namespace gl
-{
-class Context;
-}
-
-namespace egl
-{
-class Surface;
-
-class Display
-{
- public:
- ~Display();
-
- Error initialize();
- void terminate();
-
- static egl::Display *getDisplay(EGLNativeDisplayType displayId, const AttributeMap &attribMap);
-
- static const char *getExtensionString(egl::Display *display);
-
- static bool supportsPlatformD3D();
- static bool supportsPlatformOpenGL();
-
- bool getConfigs(EGLConfig *configs, const EGLint *attribList, EGLint configSize, EGLint *numConfig);
- bool getConfigAttrib(EGLConfig config, EGLint attribute, EGLint *value);
-
- Error createWindowSurface(EGLNativeWindowType window, EGLConfig config, const EGLint *attribList, EGLSurface *outSurface);
- Error createOffscreenSurface(EGLConfig config, HANDLE shareHandle, const EGLint *attribList, EGLSurface *outSurface);
- Error createContext(EGLConfig configHandle, EGLint clientVersion, const gl::Context *shareContext, bool notifyResets,
- bool robustAccess, EGLContext *outContext);
-
- void destroySurface(egl::Surface *surface);
- void destroyContext(gl::Context *context);
-
- bool isInitialized() const;
- bool isValidConfig(EGLConfig config);
- bool isValidContext(gl::Context *context);
- bool isValidSurface(egl::Surface *surface);
- bool hasExistingWindowSurface(EGLNativeWindowType window);
-
- rx::Renderer *getRenderer() { return mRenderer; };
-
- // exported methods must be virtual
- virtual void notifyDeviceLost();
- virtual void recreateSwapChains();
-
- const char *getExtensionString() const;
- const char *getVendorString() const;
- EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Display);
-
- Display(EGLNativeDisplayType displayId);
-
- void setAttributes(const AttributeMap &attribMap);
-
- Error restoreLostDevice();
-
- EGLNativeDisplayType mDisplayId;
- AttributeMap mAttributeMap;
-
- typedef std::set<Surface*> SurfaceSet;
- SurfaceSet mSurfaceSet;
-
- ConfigSet mConfigSet;
-
- typedef std::set<gl::Context*> ContextSet;
- ContextSet mContextSet;
-
- rx::Renderer *mRenderer;
-
- static std::string generateClientExtensionString();
-
- void initDisplayExtensionString();
- std::string mDisplayExtensionString;
-
- void initVendorString();
- std::string mVendorString;
-};
-}
-
-#endif // LIBEGL_DISPLAY_H_
diff --git a/src/3rdparty/angle/src/libEGL/Error.cpp b/src/3rdparty/angle/src/libEGL/Error.cpp
deleted file mode 100644
index df5f163d32..0000000000
--- a/src/3rdparty/angle/src/libEGL/Error.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Error.cpp: Implements the egl::Error class which encapsulates an EGL error
-// and optional error message.
-
-#include "libEGL/Error.h"
-
-#include "common/angleutils.h"
-
-#include <cstdarg>
-
-namespace egl
-{
-
-Error::Error(EGLint errorCode)
- : mCode(errorCode),
- mMessage()
-{
-}
-
-Error::Error(EGLint errorCode, const char *msg, ...)
- : mCode(errorCode),
- mMessage()
-{
- va_list vararg;
- va_start(vararg, msg);
- mMessage = FormatString(msg, vararg);
- va_end(vararg);
-}
-
-Error::Error(const Error &other)
- : mCode(other.mCode),
- mMessage(other.mMessage)
-{
-}
-
-Error &Error::operator=(const Error &other)
-{
- mCode = other.mCode;
- mMessage = other.mMessage;
- return *this;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libEGL/Error.h b/src/3rdparty/angle/src/libEGL/Error.h
deleted file mode 100644
index 71805d2fb7..0000000000
--- a/src/3rdparty/angle/src/libEGL/Error.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Error.h: Defines the egl::Error class which encapsulates an EGL error
-// and optional error message.
-
-#ifndef LIBEGL_ERROR_H_
-#define LIBEGL_ERROR_H_
-
-#include <EGL/egl.h>
-
-#include <string>
-
-namespace egl
-{
-
-class Error
-{
- public:
- explicit Error(EGLint errorCode);
- Error(EGLint errorCode, const char *msg, ...);
- Error(const Error &other);
- Error &operator=(const Error &other);
-
- EGLint getCode() const { return mCode; }
- bool isError() const { return (mCode != EGL_SUCCESS); }
-
- const std::string &getMessage() const { return mMessage; }
-
- private:
- EGLint mCode;
- std::string mMessage;
-};
-
-}
-
-#endif // LIBEGL_ERROR_H_
diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
deleted file mode 100644
index b664a8530e..0000000000
--- a/src/3rdparty/angle/src/libEGL/Surface.cpp
+++ /dev/null
@@ -1,505 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Surface.cpp: Implements the egl::Surface class, representing a drawing surface
-// such as the client area of a window, including any back buffers.
-// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
-
-#include <tchar.h>
-
-#include <algorithm>
-
-#include "libEGL/Surface.h"
-
-#include "common/debug.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/renderer/SwapChain.h"
-#include "libGLESv2/main.h"
-
-#include "libEGL/main.h"
-#include "libEGL/Display.h"
-
-#include "common/NativeWindow.h"
-
-//TODO(jmadill): phase this out
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-
-namespace egl
-{
-
-Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
- : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
-{
- //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
- mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
- mSwapChain = NULL;
- mShareHandle = NULL;
- mTexture = NULL;
- mTextureFormat = EGL_NO_TEXTURE;
- mTextureTarget = EGL_NO_TEXTURE;
-
- mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
- mRenderBuffer = EGL_BACK_BUFFER;
- mSwapBehavior = EGL_BUFFER_PRESERVED;
- mSwapInterval = -1;
- mWidth = width;
- mHeight = height;
- mFixedWidth = mWidth;
- mFixedHeight = mHeight;
- setSwapInterval(1);
- mFixedSize = fixedSize;
-
- subclassWindow();
-}
-
-Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
- : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
-{
- //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
- mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
- mSwapChain = NULL;
- mWindowSubclassed = false;
- mTexture = NULL;
- mTextureFormat = textureFormat;
- mTextureTarget = textureType;
-
- mPixelAspectRatio = (EGLint)(1.0 * EGL_DISPLAY_SCALING); // FIXME: Determine actual pixel aspect ratio
- mRenderBuffer = EGL_BACK_BUFFER;
- mSwapBehavior = EGL_BUFFER_PRESERVED;
- mSwapInterval = -1;
- setSwapInterval(1);
- // This constructor is for offscreen surfaces, which are always fixed-size.
- mFixedSize = EGL_TRUE;
- mFixedWidth = mWidth;
- mFixedHeight = mHeight;
-}
-
-Surface::~Surface()
-{
- unsubclassWindow();
- release();
-}
-
-Error Surface::initialize()
-{
- if (mNativeWindow.getNativeWindow())
- {
- if (!mNativeWindow.initialize())
- {
- return Error(EGL_BAD_SURFACE);
- }
- }
-
- Error error = resetSwapChain();
- if (error.isError())
- {
- return error;
- }
-
- return Error(EGL_SUCCESS);
-}
-
-void Surface::release()
-{
- delete mSwapChain;
- mSwapChain = NULL;
-
- if (mTexture)
- {
- mTexture->releaseTexImage();
- mTexture = NULL;
- }
-}
-
-Error Surface::resetSwapChain()
-{
- ASSERT(!mSwapChain);
-
- int width;
- int height;
-
- if (!mFixedSize)
- {
- RECT windowRect;
- if (!mNativeWindow.getClientRect(&windowRect))
- {
- ASSERT(false);
-
- return Error(EGL_BAD_SURFACE, "Could not retrieve the window dimensions");
- }
-
- width = windowRect.right - windowRect.left;
- height = windowRect.bottom - windowRect.top;
- }
- else
- {
- // non-window surface - size is determined at creation
- width = mWidth;
- height = mHeight;
- }
-
- mSwapChain = mRenderer->createSwapChain(mNativeWindow, mShareHandle,
- mConfig->mRenderTargetFormat,
- mConfig->mDepthStencilFormat);
- if (!mSwapChain)
- {
- return Error(EGL_BAD_ALLOC);
- }
-
- Error error = resetSwapChain(width, height);
- if (error.isError())
- {
- SafeDelete(mSwapChain);
- return error;
- }
-
- return Error(EGL_SUCCESS);
-}
-
-Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
-{
- ASSERT(mSwapChain);
-
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- backbufferWidth = std::max(1, backbufferWidth);
- backbufferHeight = std::max(1, backbufferHeight);
-#endif
- EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
-
- if (status == EGL_CONTEXT_LOST)
- {
- mDisplay->notifyDeviceLost();
- return Error(status);
- }
- else if (status != EGL_SUCCESS)
- {
- return Error(status);
- }
-
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
-
- return Error(EGL_SUCCESS);
-}
-
-Error Surface::resetSwapChain(int backbufferWidth, int backbufferHeight)
-{
- ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
- ASSERT(mSwapChain);
-
- EGLint status = mSwapChain->reset(std::max(1, backbufferWidth), std::max(1, backbufferHeight), mSwapInterval);
-
- if (status == EGL_CONTEXT_LOST)
- {
- mRenderer->notifyDeviceLost();
- return Error(status);
- }
- else if (status != EGL_SUCCESS)
- {
- return Error(status);
- }
-
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
- mSwapIntervalDirty = false;
-
- return Error(EGL_SUCCESS);
-}
-
-Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-{
- if (!mSwapChain)
- {
- return Error(EGL_SUCCESS);
- }
-
- if (x + width > abs(mWidth))
- {
- width = abs(mWidth) - x;
- }
-
- if (y + height > abs(mHeight))
- {
- height = abs(mHeight) - y;
- }
-
- if (width == 0 || height == 0)
- {
- return Error(EGL_SUCCESS);
- }
-
- ASSERT(width > 0);
- ASSERT(height > 0);
-
- EGLint status = mSwapChain->swapRect(x, y, width, height);
-
- if (status == EGL_CONTEXT_LOST)
- {
- mRenderer->notifyDeviceLost();
- return Error(status);
- }
- else if (status != EGL_SUCCESS)
- {
- return Error(status);
- }
-
- checkForOutOfDateSwapChain();
-
- return Error(EGL_SUCCESS);
-}
-
-EGLNativeWindowType Surface::getWindowHandle()
-{
- return mNativeWindow.getNativeWindow();
-}
-
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-#define kSurfaceProperty _TEXT("Egl::SurfaceOwner")
-#define kParentWndProc _TEXT("Egl::SurfaceParentWndProc")
-
-static LRESULT CALLBACK SurfaceWindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
-{
- if (message == WM_SIZE)
- {
- Surface* surf = reinterpret_cast<Surface*>(GetProp(hwnd, kSurfaceProperty));
- if(surf)
- {
- surf->checkForOutOfDateSwapChain();
- }
- }
- WNDPROC prevWndFunc = reinterpret_cast<WNDPROC >(GetProp(hwnd, kParentWndProc));
- return CallWindowProc(prevWndFunc, hwnd, message, wparam, lparam);
-}
-#endif
-
-void Surface::subclassWindow()
-{
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- HWND window = mNativeWindow.getNativeWindow();
- if (!window)
- {
- return;
- }
-
- DWORD processId;
- DWORD threadId = GetWindowThreadProcessId(window, &processId);
- if (processId != GetCurrentProcessId() || threadId != GetCurrentThreadId())
- {
- return;
- }
-
- SetLastError(0);
- LONG_PTR oldWndProc = SetWindowLongPtr(window, GWLP_WNDPROC, reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
- if(oldWndProc == 0 && GetLastError() != ERROR_SUCCESS)
- {
- mWindowSubclassed = false;
- return;
- }
-
- SetProp(window, kSurfaceProperty, reinterpret_cast<HANDLE>(this));
- SetProp(window, kParentWndProc, reinterpret_cast<HANDLE>(oldWndProc));
- mWindowSubclassed = true;
-#endif
-}
-
-void Surface::unsubclassWindow()
-{
- if(!mWindowSubclassed)
- {
- return;
- }
-
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- HWND window = mNativeWindow.getNativeWindow();
- if (!window)
- {
- return;
- }
-
- // un-subclass
- LONG_PTR parentWndFunc = reinterpret_cast<LONG_PTR>(GetProp(window, kParentWndProc));
-
- // Check the windowproc is still SurfaceWindowProc.
- // If this assert fails, then it is likely the application has subclassed the
- // hwnd as well and did not unsubclass before destroying its EGL context. The
- // application should be modified to either subclass before initializing the
- // EGL context, or to unsubclass before destroying the EGL context.
- if(parentWndFunc)
- {
- LONG_PTR prevWndFunc = SetWindowLongPtr(window, GWLP_WNDPROC, parentWndFunc);
- UNUSED_ASSERTION_VARIABLE(prevWndFunc);
- ASSERT(prevWndFunc == reinterpret_cast<LONG_PTR>(SurfaceWindowProc));
- }
-
- RemoveProp(window, kSurfaceProperty);
- RemoveProp(window, kParentWndProc);
-#endif
- mWindowSubclassed = false;
-}
-
-bool Surface::checkForOutOfDateSwapChain()
-{
- RECT client;
- int clientWidth = getWidth();
- int clientHeight = getHeight();
- bool sizeDirty = false;
- if (!mFixedSize && !mNativeWindow.isIconic())
- {
- // The window is automatically resized to 150x22 when it's minimized, but the swapchain shouldn't be resized
- // because that's not a useful size to render to.
- if (!mNativeWindow.getClientRect(&client))
- {
- ASSERT(false);
- return false;
- }
-
- // Grow the buffer now, if the window has grown. We need to grow now to avoid losing information.
- clientWidth = client.right - client.left;
- clientHeight = client.bottom - client.top;
- sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
- }
-
- if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
- {
- clientWidth = mFixedWidth;
- clientHeight = mFixedHeight;
- sizeDirty = true;
- }
-
- bool wasDirty = (mSwapIntervalDirty || sizeDirty);
-
- if (mSwapIntervalDirty)
- {
- resetSwapChain(clientWidth, clientHeight);
- }
- else if (sizeDirty)
- {
- resizeSwapChain(clientWidth, clientHeight);
- }
-
- if (wasDirty)
- {
- if (static_cast<egl::Surface*>(getCurrentDrawSurface()) == this)
- {
- glMakeCurrent(glGetCurrentContext(), static_cast<egl::Display*>(getCurrentDisplay()), this);
- }
-
- return true;
- }
-
- return false;
-}
-
-Error Surface::swap()
-{
- return swapRect(0, 0, abs(mWidth), abs(mHeight));
-}
-
-Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
-{
- if (!mPostSubBufferSupported)
- {
- // Spec is not clear about how this should be handled.
- return Error(EGL_SUCCESS);
- }
-
- return swapRect(x, y, width, height);
-}
-
-EGLint Surface::isPostSubBufferSupported() const
-{
- return mPostSubBufferSupported;
-}
-
-rx::SwapChain *Surface::getSwapChain() const
-{
- return mSwapChain;
-}
-
-void Surface::setSwapInterval(EGLint interval)
-{
- if (mSwapInterval == interval)
- {
- return;
- }
-
- mSwapInterval = interval;
- mSwapInterval = std::max(mSwapInterval, mRenderer->getMinSwapInterval());
- mSwapInterval = std::min(mSwapInterval, mRenderer->getMaxSwapInterval());
-
- mSwapIntervalDirty = true;
-}
-
-EGLint Surface::getConfigID() const
-{
- return mConfig->mConfigID;
-}
-
-EGLint Surface::getWidth() const
-{
- return mWidth;
-}
-
-EGLint Surface::getHeight() const
-{
- return mHeight;
-}
-
-EGLint Surface::getPixelAspectRatio() const
-{
- return mPixelAspectRatio;
-}
-
-EGLenum Surface::getRenderBuffer() const
-{
- return mRenderBuffer;
-}
-
-EGLenum Surface::getSwapBehavior() const
-{
- return mSwapBehavior;
-}
-
-EGLenum Surface::getTextureFormat() const
-{
- return mTextureFormat;
-}
-
-EGLenum Surface::getTextureTarget() const
-{
- return mTextureTarget;
-}
-
-void Surface::setBoundTexture(gl::Texture2D *texture)
-{
- mTexture = texture;
-}
-
-gl::Texture2D *Surface::getBoundTexture() const
-{
- return mTexture;
-}
-
-EGLint Surface::isFixedSize() const
-{
- return mFixedSize;
-}
-
-void Surface::setFixedWidth(EGLint width)
-{
- mFixedWidth = width;
-}
-
-void Surface::setFixedHeight(EGLint height)
-{
- mFixedHeight = height;
-}
-
-EGLenum Surface::getFormat() const
-{
- return mConfig->mRenderTargetFormat;
-}
-}
diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
deleted file mode 100644
index 46382d06e1..0000000000
--- a/src/3rdparty/angle/src/libEGL/Surface.h
+++ /dev/null
@@ -1,120 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Surface.h: Defines the egl::Surface class, representing a drawing surface
-// such as the client area of a window, including any back buffers.
-// Implements EGLSurface and related functionality. [EGL 1.4] section 2.2 page 3.
-
-#ifndef LIBEGL_SURFACE_H_
-#define LIBEGL_SURFACE_H_
-
-#include "libEGL/Error.h"
-
-#include <EGL/egl.h>
-
-#include "common/angleutils.h"
-#include "common/NativeWindow.h"
-
-namespace gl
-{
-class Texture2D;
-}
-namespace rx
-{
-class SwapChain;
-class RendererD3D; //TODO(jmadill): remove this
-}
-
-namespace egl
-{
-class Display;
-class Config;
-
-class Surface
-{
- public:
- Surface(Display *display, const egl::Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported);
- Surface(Display *display, const egl::Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureTarget);
-
- virtual ~Surface();
-
- Error initialize();
- void release();
- Error resetSwapChain();
-
- EGLNativeWindowType getWindowHandle();
- Error swap();
- Error postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height);
-
- virtual EGLint isPostSubBufferSupported() const;
-
- virtual rx::SwapChain *getSwapChain() const;
-
- void setSwapInterval(EGLint interval);
- bool checkForOutOfDateSwapChain(); // Returns true if swapchain changed due to resize or interval update
-
- virtual EGLint getConfigID() const;
- virtual EGLint getWidth() const;
- virtual EGLint getHeight() const;
- virtual EGLint getPixelAspectRatio() const;
- virtual EGLenum getRenderBuffer() const;
- virtual EGLenum getSwapBehavior() const;
- virtual EGLenum getTextureFormat() const;
- virtual EGLenum getTextureTarget() const;
- virtual EGLenum getFormat() const;
-
- virtual void setBoundTexture(gl::Texture2D *texture);
- virtual gl::Texture2D *getBoundTexture() const;
-
- EGLint isFixedSize() const;
- void setFixedWidth(EGLint width);
- void setFixedHeight(EGLint height);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Surface);
-
- Display *const mDisplay;
- rx::RendererD3D *mRenderer;
-
- HANDLE mShareHandle;
- rx::SwapChain *mSwapChain;
-
- void subclassWindow();
- void unsubclassWindow();
- Error resizeSwapChain(int backbufferWidth, int backbufferHeight);
- Error resetSwapChain(int backbufferWidth, int backbufferHeight);
- Error swapRect(EGLint x, EGLint y, EGLint width, EGLint height);
-
- rx::NativeWindow mNativeWindow; // Handler for the Window that the surface is created for.
- bool mWindowSubclassed; // Indicates whether we successfully subclassed mWindow for WM_RESIZE hooking
- const egl::Config *mConfig; // EGL config surface was created with
- EGLint mHeight; // Height of surface
- EGLint mWidth; // Width of surface
- EGLint mFixedHeight; // Pending height of the surface
- EGLint mFixedWidth; // Pending width of the surface
-// EGLint horizontalResolution; // Horizontal dot pitch
-// EGLint verticalResolution; // Vertical dot pitch
-// EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
-// EGLBoolean mipmapTexture; // True if texture has mipmaps
-// EGLint mipmapLevel; // Mipmap level to render to
-// EGLenum multisampleResolve; // Multisample resolve behavior
- EGLint mPixelAspectRatio; // Display aspect ratio
- EGLenum mRenderBuffer; // Render buffer
- EGLenum mSwapBehavior; // Buffer swap behavior
- EGLenum mTextureFormat; // Format of texture: RGB, RGBA, or no texture
- EGLenum mTextureTarget; // Type of texture: 2D or no texture
-// EGLenum vgAlphaFormat; // Alpha format for OpenVG
-// EGLenum vgColorSpace; // Color space for OpenVG
- EGLint mSwapInterval;
- EGLint mPostSubBufferSupported;
- EGLint mFixedSize;
-
- bool mSwapIntervalDirty;
- gl::Texture2D *mTexture;
-};
-}
-
-#endif // LIBEGL_SURFACE_H_
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
index 68399d63a4..d09219e308 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
@@ -6,1258 +6,245 @@
// libEGL.cpp: Implements the exported EGL functions.
-#undef EGLAPI
-#define EGLAPI
+#include "libGLESv2/entry_points_egl.h"
+#include "libGLESv2/entry_points_egl_ext.h"
-#include <exception>
-
-#include "common/debug.h"
-#include "common/version.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/SwapChain.h"
-#if defined(ANGLE_ENABLE_D3D11)
-# include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#endif
-
-#include "libEGL/main.h"
-#include "libEGL/Display.h"
-#include "libEGL/Surface.h"
-
-#include "common/NativeWindow.h"
-
-bool validateDisplay(egl::Display *display)
+extern "C"
{
- if (display == EGL_NO_DISPLAY)
- {
- recordError(egl::Error(EGL_BAD_DISPLAY));
- return false;
- }
-
- if (!display->isInitialized())
- {
- recordError(egl::Error(EGL_NOT_INITIALIZED));
- return false;
- }
- return true;
+EGLBoolean EGLAPIENTRY eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ return egl::ChooseConfig(dpy, attrib_list, configs, config_size, num_config);
}
-bool validateConfig(egl::Display *display, EGLConfig config)
+EGLBoolean EGLAPIENTRY eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
{
- if (!validateDisplay(display))
- {
- return false;
- }
-
- if (!display->isValidConfig(config))
- {
- recordError(egl::Error(EGL_BAD_CONFIG));
- return false;
- }
-
- return true;
+ return egl::CopyBuffers(dpy, surface, target);
}
-bool validateContext(egl::Display *display, gl::Context *context)
+EGLContext EGLAPIENTRY eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
{
- if (!validateDisplay(display))
- {
- return false;
- }
-
- if (!display->isValidContext(context))
- {
- recordError(egl::Error(EGL_BAD_CONTEXT));
- return false;
- }
-
- return true;
+ return egl::CreateContext(dpy, config, share_context, attrib_list);
}
-bool validateSurface(egl::Display *display, egl::Surface *surface)
+EGLSurface EGLAPIENTRY eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
{
- if (!validateDisplay(display))
- {
- return false;
- }
-
- if (!display->isValidSurface(surface))
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return false;
- }
-
- return true;
+ return egl::CreatePbufferSurface(dpy, config, attrib_list);
}
-extern "C"
-{
-EGLint __stdcall eglGetError(void)
+EGLSurface EGLAPIENTRY eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
{
- EVENT("()");
-
- EGLint error = egl::getCurrentError();
- recordError(egl::Error(EGL_SUCCESS));
- return error;
+ return egl::CreatePixmapSurface(dpy, config, pixmap, attrib_list);
}
-EGLDisplay __stdcall eglGetDisplay(EGLNativeDisplayType display_id)
+EGLSurface EGLAPIENTRY eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
{
- EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
-
- return egl::Display::getDisplay(display_id, egl::AttributeMap());
+ return egl::CreateWindowSurface(dpy, config, win, attrib_list);
}
-EGLDisplay __stdcall eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
{
- EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
- platform, native_display, attrib_list);
-
- switch (platform)
- {
- case EGL_PLATFORM_ANGLE_ANGLE:
- break;
-
- default:
- recordError(egl::Error(EGL_BAD_CONFIG));
- return EGL_NO_DISPLAY;
- }
-
- EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
-
-#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- // Validate the display device context
- if (WindowFromDC(displayId) == NULL)
- {
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
-#endif
-
- EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
- bool majorVersionSpecified = false;
- bool minorVersionSpecified = false;
- bool requestedWARP = false;
-
- if (attrib_list)
- {
- for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
- {
- switch (curAttrib[0])
- {
- case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
- switch (curAttrib[1])
- {
- case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
- break;
-
- case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
- case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
- if (!egl::Display::supportsPlatformD3D())
- {
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
- case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
- if (!egl::Display::supportsPlatformOpenGL())
- {
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
- break;
-
- default:
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
- platformType = curAttrib[1];
- break;
-
- case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
- if (curAttrib[1] != EGL_DONT_CARE)
- {
- majorVersionSpecified = true;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
- if (curAttrib[1] != EGL_DONT_CARE)
- {
- minorVersionSpecified = true;
- }
- break;
-
- case EGL_PLATFORM_ANGLE_USE_WARP_ANGLE:
- if (!egl::Display::supportsPlatformD3D())
- {
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
-
- switch (curAttrib[1])
- {
- case EGL_FALSE:
- case EGL_TRUE:
- break;
-
- default:
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_DISPLAY;
- }
-
- requestedWARP = (curAttrib[1] == EGL_TRUE);
- break;
-
- default:
- break;
- }
- }
- }
-
- if (!majorVersionSpecified && minorVersionSpecified)
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
-
- if (platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE && requestedWARP)
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_DISPLAY;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return egl::Display::getDisplay(displayId, egl::AttributeMap(attrib_list));
+ return egl::DestroyContext(dpy, ctx);
}
-EGLBoolean __stdcall eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+EGLBoolean EGLAPIENTRY eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
- dpy, major, minor);
-
- if (dpy == EGL_NO_DISPLAY)
- {
- recordError(egl::Error(EGL_BAD_DISPLAY));
- return EGL_FALSE;
- }
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- egl::Error error = display->initialize();
- if (error.isError())
- {
- recordError(error);
- return EGL_FALSE;
- }
-
- if (major) *major = 1;
- if (minor) *minor = 4;
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::DestroySurface(dpy, surface);
}
-EGLBoolean __stdcall eglTerminate(EGLDisplay dpy)
+EGLBoolean EGLAPIENTRY eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
-
- if (dpy == EGL_NO_DISPLAY)
- {
- recordError(egl::Error(EGL_BAD_DISPLAY));
- return EGL_FALSE;
- }
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- display->terminate();
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::GetConfigAttrib(dpy, config, attribute, value);
}
-const char *__stdcall eglQueryString(EGLDisplay dpy, EGLint name)
+EGLBoolean EGLAPIENTRY eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS) && !validateDisplay(display))
- {
- return NULL;
- }
-
- const char *result;
- switch (name)
- {
- case EGL_CLIENT_APIS:
- result = "OpenGL_ES";
- break;
- case EGL_EXTENSIONS:
- result = egl::Display::getExtensionString(display);
- break;
- case EGL_VENDOR:
- result = display->getVendorString();
- break;
- case EGL_VERSION:
- result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
- break;
- default:
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return NULL;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return result;
+ return egl::GetConfigs(dpy, configs, config_size, num_config);
}
-EGLBoolean __stdcall eglGetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLDisplay EGLAPIENTRY eglGetCurrentDisplay(void)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
- "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
- dpy, configs, config_size, num_config);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateDisplay(display))
- {
- return EGL_FALSE;
- }
-
- if (!num_config)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- const EGLint attribList[] = {EGL_NONE};
-
- if (!display->getConfigs(configs, attribList, config_size, num_config))
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::GetCurrentDisplay();
}
-EGLBoolean __stdcall eglChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+EGLSurface EGLAPIENTRY eglGetCurrentSurface(EGLint readdraw)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
- "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
- dpy, attrib_list, configs, config_size, num_config);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateDisplay(display))
- {
- return EGL_FALSE;
- }
-
- if (!num_config)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- const EGLint attribList[] = {EGL_NONE};
-
- if (!attrib_list)
- {
- attrib_list = attribList;
- }
-
- display->getConfigs(configs, attrib_list, config_size, num_config);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::GetCurrentSurface(readdraw);
}
-EGLBoolean __stdcall eglGetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+EGLDisplay EGLAPIENTRY eglGetDisplay(EGLNativeDisplayType display_id)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, config, attribute, value);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateConfig(display, config))
- {
- return EGL_FALSE;
- }
-
- if (!display->getConfigAttrib(config, attribute, value))
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::GetDisplay(display_id);
}
-EGLSurface __stdcall eglCreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+EGLint EGLAPIENTRY eglGetError(void)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateConfig(display, config))
- {
- return EGL_NO_SURFACE;
- }
-
- if (!rx::IsValidEGLNativeWindowType(win))
- {
- recordError(egl::Error(EGL_BAD_NATIVE_WINDOW));
- return EGL_NO_SURFACE;
- }
-
- EGLSurface surface = EGL_NO_SURFACE;
- egl::Error error = display->createWindowSurface(win, config, attrib_list, &surface);
- if (error.isError())
- {
- recordError(error);
- return EGL_NO_SURFACE;
- }
-
- return surface;
+ return egl::GetError();
}
-EGLSurface __stdcall eglCreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglInitialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
- dpy, config, attrib_list);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateConfig(display, config))
- {
- return EGL_NO_SURFACE;
- }
-
- EGLSurface surface = EGL_NO_SURFACE;
- egl::Error error = display->createOffscreenSurface(config, NULL, attrib_list, &surface);
- if (error.isError())
- {
- recordError(error);
- return EGL_NO_SURFACE;
- }
-
- return surface;
+ return egl::Initialize(dpy, major, minor);
}
-EGLSurface __stdcall eglCreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateConfig(display, config))
- {
- return EGL_NO_SURFACE;
- }
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_NO_SURFACE;
+ return egl::MakeCurrent(dpy, draw, read, ctx);
}
-EGLBoolean __stdcall eglDestroySurface(EGLDisplay dpy, EGLSurface surface)
+EGLBoolean EGLAPIENTRY eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- display->destroySurface((egl::Surface*)surface);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::QueryContext(dpy, ctx, attribute, value);
}
-EGLBoolean __stdcall eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+const char* EGLAPIENTRY eglQueryString(EGLDisplay dpy, EGLint name)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, surface, attribute, value);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = (egl::Surface*)surface;
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- switch (attribute)
- {
- case EGL_VG_ALPHA_FORMAT:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_VG_COLORSPACE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_CONFIG_ID:
- *value = eglSurface->getConfigID();
- break;
- case EGL_HEIGHT:
- *value = eglSurface->getHeight();
- break;
- case EGL_HORIZONTAL_RESOLUTION:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_LARGEST_PBUFFER:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MIPMAP_TEXTURE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MIPMAP_LEVEL:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_MULTISAMPLE_RESOLVE:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_PIXEL_ASPECT_RATIO:
- *value = eglSurface->getPixelAspectRatio();
- break;
- case EGL_RENDER_BUFFER:
- *value = eglSurface->getRenderBuffer();
- break;
- case EGL_SWAP_BEHAVIOR:
- *value = eglSurface->getSwapBehavior();
- break;
- case EGL_TEXTURE_FORMAT:
- *value = eglSurface->getTextureFormat();
- break;
- case EGL_TEXTURE_TARGET:
- *value = eglSurface->getTextureTarget();
- break;
- case EGL_VERTICAL_RESOLUTION:
- UNIMPLEMENTED(); // FIXME
- break;
- case EGL_WIDTH:
- *value = eglSurface->getWidth();
- break;
- case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
- *value = eglSurface->isPostSubBufferSupported();
- break;
- case EGL_FIXED_SIZE_ANGLE:
- *value = eglSurface->isFixedSize();
- break;
- default:
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::QueryString(dpy, name);
}
-EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+EGLBoolean EGLAPIENTRY eglQuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
{
- TRACE("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
- dpy, surface, attribute, value);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = (egl::Surface*)surface;
-
- switch (attribute)
- {
- case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
- {
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- rx::SwapChain *swapchain = eglSurface->getSwapChain();
- *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
- }
- break;
-#if defined(ANGLE_ENABLE_D3D11)
- case EGL_DEVICE_EXT:
- {
- if (!validateDisplay(display))
- {
- return EGL_FALSE;
- }
-
- rx::Renderer *renderer = display->getRenderer();
- if (!renderer)
- {
- *value = NULL;
- break;
- }
-
- if (renderer->getMajorShaderModel() < 4)
- {
- recordError(egl::Error(EGL_BAD_CONTEXT));
- return EGL_FALSE;
- }
-
- *value = static_cast<rx::Renderer11*>(renderer)->getDevice();
- }
- break;
-#endif
- default:
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::QuerySurface(dpy, surface, attribute, value);
}
-EGLBoolean __stdcall eglBindAPI(EGLenum api)
+EGLBoolean EGLAPIENTRY eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
{
- EVENT("(EGLenum api = 0x%X)", api);
-
- switch (api)
- {
- case EGL_OPENGL_API:
- case EGL_OPENVG_API:
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE; // Not supported by this implementation
- case EGL_OPENGL_ES_API:
- break;
- default:
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- egl::setCurrentAPI(api);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::SwapBuffers(dpy, surface);
}
-EGLenum __stdcall eglQueryAPI(void)
+EGLBoolean EGLAPIENTRY eglTerminate(EGLDisplay dpy)
{
- EVENT("()");
-
- EGLenum API = egl::getCurrentAPI();
-
- recordError(egl::Error(EGL_SUCCESS));
- return API;
+ return egl::Terminate(dpy);
}
-EGLBoolean __stdcall eglWaitClient(void)
+EGLBoolean EGLAPIENTRY eglWaitGL(void)
{
- EVENT("()");
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return 0;
+ return egl::WaitGL();
}
-EGLBoolean __stdcall eglReleaseThread(void)
+EGLBoolean EGLAPIENTRY eglWaitNative(EGLint engine)
{
- EVENT("()");
-
- eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::WaitNative(engine);
}
-EGLSurface __stdcall eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+EGLBoolean EGLAPIENTRY eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
- "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
- dpy, buftype, buffer, config, attrib_list);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateConfig(display, config))
- {
- return EGL_NO_SURFACE;
- }
-
- if (buftype != EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || !buffer)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_NO_SURFACE;
- }
-
- EGLSurface surface = EGL_NO_SURFACE;
- egl::Error error = display->createOffscreenSurface(config, (HANDLE)buffer, attrib_list, &surface);
- if (error.isError())
- {
- recordError(error);
- return EGL_NO_SURFACE;
- }
-
- return surface;
+ return egl::BindTexImage(dpy, surface, buffer);
}
-EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+EGLBoolean EGLAPIENTRY eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
- dpy, surface, attribute, value);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- switch (attribute)
- {
- case EGL_WIDTH:
- if (!eglSurface->isFixedSize() || !value) {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
- eglSurface->setFixedWidth(value);
- return EGL_TRUE;
- case EGL_HEIGHT:
- if (!eglSurface->isFixedSize() || !value) {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
- eglSurface->setFixedHeight(value);
- return EGL_TRUE;
- default:
- break;
- }
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::ReleaseTexImage(dpy, surface, buffer);
}
-EGLBoolean __stdcall eglBindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+EGLBoolean EGLAPIENTRY eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (buffer != EGL_BACK_BUFFER)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- if (eglSurface->getBoundTexture())
- {
- recordError(egl::Error(EGL_BAD_ACCESS));
- return EGL_FALSE;
- }
-
- if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- if (!glBindTexImage(eglSurface))
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::SurfaceAttrib(dpy, surface, attribute, value);
}
-EGLBoolean __stdcall eglReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+EGLBoolean EGLAPIENTRY eglSwapInterval(EGLDisplay dpy, EGLint interval)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (buffer != EGL_BACK_BUFFER)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE || eglSurface->getWindowHandle())
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- gl::Texture2D *texture = eglSurface->getBoundTexture();
-
- if (texture)
- {
- texture->releaseTexImage();
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::SwapInterval(dpy, interval);
}
-EGLBoolean __stdcall eglSwapInterval(EGLDisplay dpy, EGLint interval)
+EGLBoolean EGLAPIENTRY eglBindAPI(EGLenum api)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (!validateDisplay(display))
- {
- return EGL_FALSE;
- }
-
- egl::Surface *draw_surface = static_cast<egl::Surface*>(egl::getCurrentDrawSurface());
-
- if (draw_surface == NULL)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- draw_surface->setSwapInterval(interval);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::BindAPI(api);
}
-EGLContext __stdcall eglCreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+EGLenum EGLAPIENTRY eglQueryAPI(void)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
- "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
-
- // Get the requested client version (default is 1) and check it is 2 or 3.
- EGLint client_version = 1;
- bool reset_notification = false;
- bool robust_access = false;
-
- if (attrib_list)
- {
- for (const EGLint* attribute = attrib_list; attribute[0] != EGL_NONE; attribute += 2)
- {
- switch (attribute[0])
- {
- case EGL_CONTEXT_CLIENT_VERSION:
- client_version = attribute[1];
- break;
- case EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT:
- if (attribute[1] == EGL_TRUE)
- {
- recordError(egl::Error(EGL_BAD_CONFIG)); // Unimplemented
- return EGL_NO_CONTEXT;
- // robust_access = true;
- }
- else if (attribute[1] != EGL_FALSE)
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_CONTEXT;
- }
- break;
- case EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT:
- if (attribute[1] == EGL_LOSE_CONTEXT_ON_RESET_EXT)
- {
- reset_notification = true;
- }
- else if (attribute[1] != EGL_NO_RESET_NOTIFICATION_EXT)
- {
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_CONTEXT;
- }
- break;
- default:
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_NO_CONTEXT;
- }
- }
- }
-
- if (client_version != 2 && client_version != 3)
- {
- recordError(egl::Error(EGL_BAD_CONFIG));
- return EGL_NO_CONTEXT;
- }
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
-
- if (share_context)
- {
- gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
-
- if (sharedGLContext->isResetNotificationEnabled() != reset_notification)
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_NO_CONTEXT;
- }
-
- if (sharedGLContext->getClientVersion() != client_version)
- {
- recordError(egl::Error(EGL_BAD_CONTEXT));
- return EGL_NO_CONTEXT;
- }
-
- // Can not share contexts between displays
- if (sharedGLContext->getRenderer() != display->getRenderer())
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_NO_CONTEXT;
- }
- }
-
- if (!validateConfig(display, config))
- {
- return EGL_NO_CONTEXT;
- }
-
- EGLContext context = EGL_NO_CONTEXT;
- egl::Error error = display->createContext(config, client_version, static_cast<gl::Context*>(share_context),
- reset_notification, robust_access, &context);
- if (error.isError())
- {
- recordError(error);
- return EGL_NO_CONTEXT;
- }
-
- return context;
+ return egl::QueryAPI();
}
-EGLBoolean __stdcall eglDestroyContext(EGLDisplay dpy, EGLContext ctx)
+EGLSurface EGLAPIENTRY eglCreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
-
- if (!validateContext(display, context))
- {
- return EGL_FALSE;
- }
-
- if (ctx == EGL_NO_CONTEXT)
- {
- recordError(egl::Error(EGL_BAD_CONTEXT));
- return EGL_FALSE;
- }
-
- display->destroyContext(context);
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::CreatePbufferFromClientBuffer(dpy, buftype, buffer, config, attrib_list);
}
-EGLBoolean __stdcall eglMakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+EGLBoolean EGLAPIENTRY eglReleaseThread(void)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
- dpy, draw, read, ctx);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
-
- bool noContext = (ctx == EGL_NO_CONTEXT);
- bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
- if (noContext != noSurface)
- {
- recordError(egl::Error(EGL_BAD_MATCH));
- return EGL_FALSE;
- }
-
- if (ctx != EGL_NO_CONTEXT && !validateContext(display, context))
- {
- return EGL_FALSE;
- }
-
- if (dpy != EGL_NO_DISPLAY && display->isInitialized())
- {
- rx::Renderer *renderer = display->getRenderer();
- if (renderer->testDeviceLost(true))
- {
- return EGL_FALSE;
- }
-
- if (renderer->isDeviceLost())
- {
- recordError(egl::Error(EGL_CONTEXT_LOST));
- return EGL_FALSE;
- }
- }
-
- if ((draw != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(draw))) ||
- (read != EGL_NO_SURFACE && !validateSurface(display, static_cast<egl::Surface*>(read))))
- {
- return EGL_FALSE;
- }
-
- if (draw != read)
- {
- UNIMPLEMENTED(); // FIXME
- }
-
- egl::setCurrentDisplay(dpy);
- egl::setCurrentDrawSurface(draw);
- egl::setCurrentReadSurface(read);
-
- glMakeCurrent(context, display, static_cast<egl::Surface*>(draw));
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::ReleaseThread();
}
-EGLContext __stdcall eglGetCurrentContext(void)
+EGLBoolean EGLAPIENTRY eglWaitClient(void)
{
- EVENT("()");
-
- EGLContext context = glGetCurrentContext();
-
- recordError(egl::Error(EGL_SUCCESS));
- return context;
+ return egl::WaitClient();
}
-EGLSurface __stdcall eglGetCurrentSurface(EGLint readdraw)
+EGLContext EGLAPIENTRY eglGetCurrentContext(void)
{
- EVENT("(EGLint readdraw = %d)", readdraw);
-
- if (readdraw == EGL_READ)
- {
- recordError(egl::Error(EGL_SUCCESS));
- return egl::getCurrentReadSurface();
- }
- else if (readdraw == EGL_DRAW)
- {
- recordError(egl::Error(EGL_SUCCESS));
- return egl::getCurrentDrawSurface();
- }
- else
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_NO_SURFACE;
- }
+ return egl::GetCurrentContext();
}
-EGLDisplay __stdcall eglGetCurrentDisplay(void)
+EGLSync EGLAPIENTRY eglCreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
{
- EVENT("()");
-
- EGLDisplay dpy = egl::getCurrentDisplay();
-
- recordError(egl::Error(EGL_SUCCESS));
- return dpy;
+ return egl::CreateSync(dpy, type, attrib_list);
}
-EGLBoolean __stdcall eglQueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+EGLBoolean EGLAPIENTRY eglDestroySync(EGLDisplay dpy, EGLSync sync)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
- dpy, ctx, attribute, value);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- gl::Context *context = static_cast<gl::Context*>(ctx);
-
- if (!validateContext(display, context))
- {
- return EGL_FALSE;
- }
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return 0;
+ return egl::DestroySync(dpy, sync);
}
-EGLBoolean __stdcall eglWaitGL(void)
+EGLint EGLAPIENTRY eglClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
{
- EVENT("()");
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return 0;
+ return egl::ClientWaitSync(dpy, sync, flags, timeout);
}
-EGLBoolean __stdcall eglWaitNative(EGLint engine)
+EGLBoolean EGLAPIENTRY eglGetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
{
- EVENT("(EGLint engine = %d)", engine);
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return 0;
+ return egl::GetSyncAttrib(dpy, sync, attribute, value);
}
-EGLBoolean __stdcall eglSwapBuffers(EGLDisplay dpy, EGLSurface surface)
+EGLImage EGLAPIENTRY eglCreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = (egl::Surface*)surface;
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (display->getRenderer()->isDeviceLost())
- {
- recordError(egl::Error(EGL_CONTEXT_LOST));
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
-
- egl::Error error = eglSurface->swap();
- if (error.isError())
- {
- recordError(error);
- return EGL_FALSE;
- }
-
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+ return egl::CreateImage(dpy, ctx, target, buffer, attrib_list);
}
-EGLBoolean __stdcall eglCopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+EGLBoolean EGLAPIENTRY eglDestroyImage(EGLDisplay dpy, EGLImage image)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (display->getRenderer()->isDeviceLost())
- {
- recordError(egl::Error(EGL_CONTEXT_LOST));
- return EGL_FALSE;
- }
-
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
- return 0;
+ return egl::DestroyImage(dpy, image);
}
-EGLBoolean __stdcall eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+EGLDisplay EGLAPIENTRY eglGetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
{
- EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
-
- if (x < 0 || y < 0 || width < 0 || height < 0)
- {
- recordError(egl::Error(EGL_BAD_PARAMETER));
- return EGL_FALSE;
- }
-
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = static_cast<egl::Surface*>(surface);
-
- if (!validateSurface(display, eglSurface))
- {
- return EGL_FALSE;
- }
-
- if (display->getRenderer()->isDeviceLost())
- {
- recordError(egl::Error(EGL_CONTEXT_LOST));
- return EGL_FALSE;
- }
-
- if (surface == EGL_NO_SURFACE)
- {
- recordError(egl::Error(EGL_BAD_SURFACE));
- return EGL_FALSE;
- }
+ return egl::GetPlatformDisplay(platform, native_display, attrib_list);
+}
- egl::Error error = eglSurface->postSubBuffer(x, y, width, height);
- if (error.isError())
- {
- recordError(error);
- return EGL_FALSE;
- }
+EGLSurface EGLAPIENTRY eglCreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
+{
+ return egl::CreatePlatformWindowSurface(dpy, config, native_window, attrib_list);
+}
- recordError(egl::Error(EGL_SUCCESS));
- return EGL_TRUE;
+EGLSurface EGLAPIENTRY eglCreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
+{
+ return egl::CreatePlatformPixmapSurface(dpy, config, native_pixmap, attrib_list);
}
-__eglMustCastToProperFunctionPointerType __stdcall eglGetProcAddress(const char *procname)
+EGLBoolean EGLAPIENTRY eglWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
{
- EVENT("(const char *procname = \"%s\")", procname);
+ return egl::WaitSync(dpy, sync, flags);
+}
- struct Extension
- {
- const char *name;
- __eglMustCastToProperFunctionPointerType address;
- };
+EGLBoolean EGLAPIENTRY eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+ return egl::QuerySurfacePointerANGLE(dpy, surface, attribute, value);
+}
- static const Extension eglExtensions[] =
- {
- { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)eglQuerySurfacePointerANGLE },
- { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)eglPostSubBufferNV },
- { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)eglGetPlatformDisplayEXT },
- { "", NULL },
- };
+EGLBoolean EGLAPIENTRY eglPostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ return egl::PostSubBufferNV(dpy, surface, x, y, width, height);
+}
- for (unsigned int ext = 0; ext < ArraySize(eglExtensions); ext++)
- {
- if (strcmp(procname, eglExtensions[ext].name) == 0)
- {
- return (__eglMustCastToProperFunctionPointerType)eglExtensions[ext].address;
- }
- }
+EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+{
+ return egl::GetPlatformDisplayEXT(platform, native_display, attrib_list);
+}
- return glGetProcAddress(procname);
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY eglGetProcAddress(const char *procname)
+{
+ return egl::GetProcAddress(procname);
}
+
}
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.def b/src/3rdparty/angle/src/libEGL/libEGL.def
index d7949d0354..823cba2f88 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL.def
+++ b/src/3rdparty/angle/src/libEGL/libEGL.def
@@ -39,3 +39,15 @@ EXPORTS
eglGetPlatformDisplayEXT @35
eglQuerySurfacePointerANGLE @36
eglPostSubBufferNV @37
+
+ ; 1.5 entry points
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/libEGL.rc b/src/3rdparty/angle/src/libEGL/libEGL.rc
deleted file mode 100644
index 65e0aa50c8..0000000000
--- a/src/3rdparty/angle/src/libEGL/libEGL.rc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include "../common/version.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "#include ""../common/version.h""\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0
- PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "FileDescription", "ANGLE libEGL Dynamic Link Library"
- VALUE "FileVersion", ANGLE_VERSION_STRING
- VALUE "InternalName", "libEGL"
- VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
- VALUE "OriginalFilename", "libEGL.dll"
- VALUE "PrivateBuild", ANGLE_VERSION_STRING
- VALUE "ProductName", "ANGLE libEGL Dynamic Link Library"
- VALUE "ProductVersion", ANGLE_VERSION_STRING
- VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
index 492ad4d0cf..6a771a54b8 100644
--- a/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
+++ b/src/3rdparty/angle/src/libEGL/libEGL_mingw32.def
@@ -39,3 +39,15 @@ EXPORTS
eglGetPlatformDisplayEXT@12 @35
eglQuerySurfacePointerANGLE@16 @36
eglPostSubBufferNV@24 @37
+
+ ; 1.5 entry points
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/libEGLd.def b/src/3rdparty/angle/src/libEGL/libEGLd.def
index 0ebd27d0e1..cab7dc9d24 100644
--- a/src/3rdparty/angle/src/libEGL/libEGLd.def
+++ b/src/3rdparty/angle/src/libEGL/libEGLd.def
@@ -39,3 +39,15 @@ EXPORTS
eglGetPlatformDisplayEXT @35
eglQuerySurfacePointerANGLE @36
eglPostSubBufferNV @37
+
+ ; 1.5 entry points
+ eglCreateSync @38
+ eglDestroySync @39
+ eglClientWaitSync @40
+ eglGetSyncAttrib @41
+ eglCreateImage @42
+ eglDestroyImage @43
+ eglGetPlatformDisplay @44
+ eglCreatePlatformWindowSurface @45
+ eglCreatePlatformPixmapSurface @46
+ eglWaitSync @47
diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
deleted file mode 100644
index e88cad775f..0000000000
--- a/src/3rdparty/angle/src/libEGL/main.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.cpp: DLL entry point and management of thread-local data.
-
-#include "libEGL/main.h"
-
-#include "common/debug.h"
-#include "common/tls.h"
-
-static TLSIndex currentTLS = TLS_OUT_OF_INDEXES;
-
-namespace egl
-{
-
-Current *AllocateCurrent()
-{
- ASSERT(currentTLS != TLS_OUT_OF_INDEXES);
- if (currentTLS == TLS_OUT_OF_INDEXES)
- {
- return NULL;
- }
-
- Current *current = new Current();
- current->error = EGL_SUCCESS;
- current->API = EGL_OPENGL_ES_API;
- current->display = EGL_NO_DISPLAY;
- current->drawSurface = EGL_NO_SURFACE;
- current->readSurface = EGL_NO_SURFACE;
-
- if (!SetTLSValue(currentTLS, current))
- {
- ERR("Could not set thread local storage.");
- return NULL;
- }
-
- return current;
-}
-
-void DeallocateCurrent()
-{
- Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
- SafeDelete(current);
- SetTLSValue(currentTLS, NULL);
-}
-
-}
-
-#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
-
-extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
-{
- switch (reason)
- {
- case DLL_PROCESS_ATTACH:
- {
-#if defined(ANGLE_ENABLE_DEBUG_TRACE)
- FILE *debug = fopen(TRACE_OUTPUT_FILE, "rt");
-
- if (debug)
- {
- fclose(debug);
- debug = fopen(TRACE_OUTPUT_FILE, "wt"); // Erase
-
- if (debug)
- {
- fclose(debug);
- }
- }
-#endif
-
- currentTLS = CreateTLSIndex();
- if (currentTLS == TLS_OUT_OF_INDEXES)
- {
- return FALSE;
- }
-
-#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
- gl::InitializeDebugAnnotations();
-#endif
- }
- // Fall through to initialize index
- case DLL_THREAD_ATTACH:
- {
- egl::AllocateCurrent();
- }
- break;
- case DLL_THREAD_DETACH:
- {
- egl::DeallocateCurrent();
- }
- break;
- case DLL_PROCESS_DETACH:
- {
- egl::DeallocateCurrent();
- DestroyTLSIndex(currentTLS);
-
-#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
- gl::UninitializeDebugAnnotations();
-#endif
- }
- break;
- default:
- break;
- }
-
- return TRUE;
-}
-
-#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
-
-namespace egl
-{
-
-Current *GetCurrentData()
-{
-#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
- Current *current = reinterpret_cast<Current*>(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 &current;
-#endif
-}
-
-void recordError(const Error &error)
-{
- Current *current = GetCurrentData();
-
- current->error = error.getCode();
-}
-
-EGLint getCurrentError()
-{
- Current *current = GetCurrentData();
-
- return current->error;
-}
-
-void setCurrentAPI(EGLenum API)
-{
- Current *current = GetCurrentData();
-
- current->API = API;
-}
-
-EGLenum getCurrentAPI()
-{
- Current *current = GetCurrentData();
-
- return current->API;
-}
-
-void setCurrentDisplay(EGLDisplay dpy)
-{
- Current *current = GetCurrentData();
-
- current->display = dpy;
-}
-
-EGLDisplay getCurrentDisplay()
-{
- Current *current = GetCurrentData();
-
- return current->display;
-}
-
-void setCurrentDrawSurface(EGLSurface surface)
-{
- Current *current = GetCurrentData();
-
- current->drawSurface = surface;
-}
-
-EGLSurface getCurrentDrawSurface()
-{
- Current *current = GetCurrentData();
-
- return current->drawSurface;
-}
-
-void setCurrentReadSurface(EGLSurface surface)
-{
- Current *current = GetCurrentData();
-
- current->readSurface = surface;
-}
-
-EGLSurface getCurrentReadSurface()
-{
- Current *current = GetCurrentData();
-
- return current->readSurface;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libEGL/main.h b/src/3rdparty/angle/src/libEGL/main.h
deleted file mode 100644
index e5361a4a5e..0000000000
--- a/src/3rdparty/angle/src/libEGL/main.h
+++ /dev/null
@@ -1,45 +0,0 @@
-//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.h: Management of thread-local data.
-
-#ifndef LIBEGL_MAIN_H_
-#define LIBEGL_MAIN_H_
-
-#include "libEGL/Error.h"
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-
-namespace egl
-{
-struct Current
-{
- EGLint error;
- EGLenum API;
- EGLDisplay display;
- EGLSurface drawSurface;
- EGLSurface readSurface;
-};
-
-void recordError(const Error &error);
-EGLint getCurrentError();
-
-void setCurrentAPI(EGLenum API);
-EGLenum getCurrentAPI();
-
-void setCurrentDisplay(EGLDisplay dpy);
-EGLDisplay getCurrentDisplay();
-
-void setCurrentDrawSurface(EGLSurface surface);
-EGLSurface getCurrentDrawSurface();
-
-void setCurrentReadSurface(EGLSurface surface);
-EGLSurface getCurrentReadSurface();
-
-}
-
-#endif // LIBEGL_MAIN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Error.cpp b/src/3rdparty/angle/src/libGLESv2/Error.cpp
deleted file mode 100644
index cc7d17eb37..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Error.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Error.cpp: Implements the gl::Error class which encapsulates an OpenGL error
-// and optional error message.
-
-#include "libGLESv2/Error.h"
-
-#include "common/angleutils.h"
-
-#include <cstdarg>
-
-namespace gl
-{
-
-Error::Error(GLenum errorCode)
- : mCode(errorCode),
- mMessage()
-{
-}
-
-Error::Error(GLenum errorCode, const char *msg, ...)
- : mCode(errorCode),
- mMessage()
-{
- va_list vararg;
- va_start(vararg, msg);
- mMessage = FormatString(msg, vararg);
- va_end(vararg);
-}
-
-Error::Error(const Error &other)
- : mCode(other.mCode),
- mMessage(other.mMessage)
-{
-}
-
-Error &Error::operator=(const Error &other)
-{
- mCode = other.mCode;
- mMessage = other.mMessage;
- return *this;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/Error.h b/src/3rdparty/angle/src/libGLESv2/Error.h
deleted file mode 100644
index b70b5a531c..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Error.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Error.h: Defines the gl::Error class which encapsulates an OpenGL error
-// and optional error message.
-
-#ifndef LIBGLESV2_ERROR_H_
-#define LIBGLESV2_ERROR_H_
-
-#include "angle_gl.h"
-
-#include <string>
-
-namespace gl
-{
-
-class Error
-{
- public:
- explicit Error(GLenum errorCode);
- Error(GLenum errorCode, const char *msg, ...);
- Error(const Error &other);
- Error &operator=(const Error &other);
-
- GLenum getCode() const { return mCode; }
- bool isError() const { return (mCode != GL_NO_ERROR); }
-
- const std::string &getMessage() const { return mMessage; }
-
- private:
- GLenum mCode;
- std::string mMessage;
-};
-
-}
-
-#endif // LIBGLESV2_ERROR_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py b/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
deleted file mode 100644
index cf039bfc21..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Float16ToFloat32.py
+++ /dev/null
@@ -1,78 +0,0 @@
-# Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-#
-
-# This script generates a function that converts 16-bit precision floating
-# point numbers to 32-bit.
-# It is based on ftp://ftp.fox-toolkit.org/pub/fasthalffloatconversion.pdf.
-
-def convertMantissa(i):
- if i == 0:
- return 0
- elif i < 1024:
- m = i << 13
- e = 0
- while not (m & 0x00800000):
- e -= 0x00800000
- m = m << 1
- m &= ~0x00800000
- e += 0x38800000
- return m | e
- else:
- return 0x38000000 + ((i - 1024) << 13)
-
-def convertExponent(i):
- if i == 0:
- return 0
- elif i in range(1, 31):
- return i << 23
- elif i == 31:
- return 0x47800000
- elif i == 32:
- return 0x80000000
- elif i in range(33, 63):
- return 0x80000000 + ((i - 32) << 23)
- else:
- return 0xC7800000
-
-def convertOffset(i):
- if i == 0 or i == 32:
- return 0
- else:
- return 1024
-
-print """//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// This file is automatically generated.
-
-namespace gl
-{
-"""
-
-print "const static unsigned g_mantissa[2048] = {"
-for i in range(0, 2048):
- print " %#010x," % convertMantissa(i)
-print "};\n"
-
-print "const static unsigned g_exponent[64] = {"
-for i in range(0, 64):
- print " %#010x," % convertExponent(i)
-print "};\n"
-
-print "const static unsigned g_offset[64] = {"
-for i in range(0, 64):
- print " %#010x," % convertOffset(i)
-print "};\n"
-
-print """float float16ToFloat32(unsigned short h)
-{
- unsigned i32 = g_mantissa[g_offset[h >> 10] + (h & 0x3ff)] + g_exponent[h >> 10];
- return *(float*) &i32;
-}
-}
-"""
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp b/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
deleted file mode 100644
index 3d57262e3c..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.cpp
+++ /dev/null
@@ -1,672 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Framebuffer.cpp: Implements the gl::Framebuffer class. Implements GL framebuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
-
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/renderer/Renderer.h"
-#include "libGLESv2/renderer/RenderTarget.h"
-#include "libGLESv2/renderer/RenderbufferImpl.h"
-#include "libGLESv2/renderer/Workarounds.h"
-#include "libGLESv2/renderer/d3d/TextureD3D.h"
-#include "libGLESv2/renderer/d3d/RenderbufferD3D.h"
-
-#include "common/utilities.h"
-
-namespace rx
-{
-// TODO: Move these functions, and the D3D-specific header inclusions above,
-// to FramebufferD3D.
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT)
-{
- if (attachment->isTexture())
- {
- gl::Texture *texture = attachment->getTexture();
- ASSERT(texture);
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- const gl::ImageIndex *index = attachment->getTextureImageIndex();
- ASSERT(index);
- return textureD3D->getRenderTarget(*index, outRT);
- }
- else
- {
- gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
- ASSERT(renderbuffer);
- RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
- *outRT = renderbufferD3D->getRenderTarget();
- return gl::Error(GL_NO_ERROR);
- }
-}
-
-// Note: RenderTarget serials should ideally be in the RenderTargets themselves.
-unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment)
-{
- if (attachment->isTexture())
- {
- gl::Texture *texture = attachment->getTexture();
- ASSERT(texture);
- TextureD3D *textureD3D = TextureD3D::makeTextureD3D(texture->getImplementation());
- const gl::ImageIndex *index = attachment->getTextureImageIndex();
- ASSERT(index);
- return textureD3D->getRenderTargetSerial(*index);
- }
-
- gl::Renderbuffer *renderbuffer = attachment->getRenderbuffer();
- ASSERT(renderbuffer);
- RenderbufferD3D *renderbufferD3D = RenderbufferD3D::makeRenderbufferD3D(renderbuffer->getImplementation());
- return renderbufferD3D->getRenderTargetSerial();
-}
-
-}
-
-namespace gl
-{
-
-Framebuffer::Framebuffer(GLuint id)
- : mId(id),
- mReadBufferState(GL_COLOR_ATTACHMENT0_EXT),
- mDepthbuffer(NULL),
- mStencilbuffer(NULL)
-{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- mColorbuffers[colorAttachment] = NULL;
- mDrawBufferStates[colorAttachment] = GL_NONE;
- }
- mDrawBufferStates[0] = GL_COLOR_ATTACHMENT0_EXT;
-}
-
-Framebuffer::~Framebuffer()
-{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- SafeDelete(mColorbuffers[colorAttachment]);
- }
- SafeDelete(mDepthbuffer);
- SafeDelete(mStencilbuffer);
-}
-
-void Framebuffer::detachTexture(GLuint textureId)
-{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
-
- if (attachment && attachment->isTextureWithId(textureId))
- {
- SafeDelete(mColorbuffers[colorAttachment]);
- }
- }
-
- if (mDepthbuffer && mDepthbuffer->isTextureWithId(textureId))
- {
- SafeDelete(mDepthbuffer);
- }
-
- if (mStencilbuffer && mStencilbuffer->isTextureWithId(textureId))
- {
- SafeDelete(mStencilbuffer);
- }
-}
-
-void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
-{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- FramebufferAttachment *attachment = mColorbuffers[colorAttachment];
-
- if (attachment && attachment->isRenderbufferWithId(renderbufferId))
- {
- SafeDelete(mColorbuffers[colorAttachment]);
- }
- }
-
- if (mDepthbuffer && mDepthbuffer->isRenderbufferWithId(renderbufferId))
- {
- SafeDelete(mDepthbuffer);
- }
-
- if (mStencilbuffer && mStencilbuffer->isRenderbufferWithId(renderbufferId))
- {
- SafeDelete(mStencilbuffer);
- }
-}
-
-FramebufferAttachment *Framebuffer::getColorbuffer(unsigned int colorAttachment) const
-{
- ASSERT(colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS);
- return mColorbuffers[colorAttachment];
-}
-
-FramebufferAttachment *Framebuffer::getDepthbuffer() const
-{
- return mDepthbuffer;
-}
-
-FramebufferAttachment *Framebuffer::getStencilbuffer() const
-{
- return mStencilbuffer;
-}
-
-FramebufferAttachment *Framebuffer::getDepthStencilBuffer() const
-{
- return (hasValidDepthStencil() ? mDepthbuffer : NULL);
-}
-
-FramebufferAttachment *Framebuffer::getDepthOrStencilbuffer() const
-{
- FramebufferAttachment *depthstencilbuffer = mDepthbuffer;
-
- if (!depthstencilbuffer)
- {
- depthstencilbuffer = mStencilbuffer;
- }
-
- return depthstencilbuffer;
-}
-
-FramebufferAttachment *Framebuffer::getReadColorbuffer() const
-{
- // Will require more logic if glReadBuffers is supported
- return mColorbuffers[0];
-}
-
-GLenum Framebuffer::getReadColorbufferType() const
-{
- // Will require more logic if glReadBuffers is supported
- return (mColorbuffers[0] ? mColorbuffers[0]->type() : GL_NONE);
-}
-
-FramebufferAttachment *Framebuffer::getFirstColorbuffer() const
-{
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (mColorbuffers[colorAttachment])
- {
- return mColorbuffers[colorAttachment];
- }
- }
-
- return NULL;
-}
-
-FramebufferAttachment *Framebuffer::getAttachment(GLenum attachment) const
-{
- if (attachment >= GL_COLOR_ATTACHMENT0 && attachment <= GL_COLOR_ATTACHMENT15)
- {
- return getColorbuffer(attachment - GL_COLOR_ATTACHMENT0);
- }
- else
- {
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT:
- return getDepthbuffer();
- case GL_STENCIL_ATTACHMENT:
- return getStencilbuffer();
- case GL_DEPTH_STENCIL_ATTACHMENT:
- return getDepthStencilBuffer();
- default:
- UNREACHABLE();
- return NULL;
- }
- }
-}
-
-GLenum Framebuffer::getDrawBufferState(unsigned int colorAttachment) const
-{
- return mDrawBufferStates[colorAttachment];
-}
-
-void Framebuffer::setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer)
-{
- mDrawBufferStates[colorAttachment] = drawBuffer;
-}
-
-bool Framebuffer::isEnabledColorAttachment(unsigned int colorAttachment) const
-{
- return (mColorbuffers[colorAttachment] && mDrawBufferStates[colorAttachment] != GL_NONE);
-}
-
-bool Framebuffer::hasEnabledColorAttachment() const
-{
- for (unsigned int colorAttachment = 0; colorAttachment < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (isEnabledColorAttachment(colorAttachment))
- {
- return true;
- }
- }
-
- return false;
-}
-
-bool Framebuffer::hasStencil() const
-{
- return (mStencilbuffer && mStencilbuffer->getStencilSize() > 0);
-}
-
-bool Framebuffer::usingExtendedDrawBuffers() const
-{
- for (unsigned int colorAttachment = 1; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (isEnabledColorAttachment(colorAttachment))
- {
- return true;
- }
- }
-
- return false;
-}
-
-GLenum Framebuffer::completeness(const gl::Data &data) const
-{
- int width = 0;
- int height = 0;
- unsigned int colorbufferSize = 0;
- int samples = -1;
- bool missingAttachment = true;
-
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- const FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
-
- if (colorbuffer)
- {
- if (colorbuffer->getWidth() == 0 || colorbuffer->getHeight() == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- GLenum internalformat = colorbuffer->getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (colorbuffer->isTexture())
- {
- if (!formatCaps.renderable)
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
- else
- {
- if (!formatCaps.renderable || formatInfo.depthBits > 0 || formatInfo.stencilBits > 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
-
- if (!missingAttachment)
- {
- // all color attachments must have the same width and height
- if (colorbuffer->getWidth() != width || colorbuffer->getHeight() != height)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
- }
-
- // APPLE_framebuffer_multisample, which EXT_draw_buffers refers to, requires that
- // all color attachments have the same number of samples for the FBO to be complete.
- if (colorbuffer->getSamples() != samples)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_EXT;
- }
-
- // in GLES 2.0, all color attachments attachments must have the same number of bitplanes
- // in GLES 3.0, there is no such restriction
- if (data.clientVersion < 3)
- {
- if (formatInfo.pixelBytes != colorbufferSize)
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
- }
-
- // D3D11 does not allow for overlapping RenderTargetViews, so ensure uniqueness
- for (unsigned int previousColorAttachment = 0; previousColorAttachment < colorAttachment; previousColorAttachment++)
- {
- const FramebufferAttachment *previousAttachment = mColorbuffers[previousColorAttachment];
-
- if (previousAttachment &&
- (colorbuffer->id() == previousAttachment->id() &&
- colorbuffer->type() == previousAttachment->type()))
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
- }
- }
- else
- {
- width = colorbuffer->getWidth();
- height = colorbuffer->getHeight();
- samples = colorbuffer->getSamples();
- colorbufferSize = formatInfo.pixelBytes;
- missingAttachment = false;
- }
- }
- }
-
- if (mDepthbuffer)
- {
- if (mDepthbuffer->getWidth() == 0 || mDepthbuffer->getHeight() == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- GLenum internalformat = mDepthbuffer->getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (mDepthbuffer->isTexture())
- {
- // depth texture attachments require OES/ANGLE_depth_texture
- if (!data.extensions->depthTextures)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (!formatCaps.renderable)
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- if (formatInfo.depthBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
- else
- {
- if (!formatCaps.renderable || formatInfo.depthBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
-
- if (missingAttachment)
- {
- width = mDepthbuffer->getWidth();
- height = mDepthbuffer->getHeight();
- samples = mDepthbuffer->getSamples();
- missingAttachment = false;
- }
- else if (width != mDepthbuffer->getWidth() || height != mDepthbuffer->getHeight())
- {
- return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
- }
- else if (samples != mDepthbuffer->getSamples())
- {
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
- }
- }
-
- if (mStencilbuffer)
- {
- if (mStencilbuffer->getWidth() == 0 || mStencilbuffer->getHeight() == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- GLenum internalformat = mStencilbuffer->getInternalFormat();
- const TextureCaps &formatCaps = data.textureCaps->get(internalformat);
- const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
- if (mStencilbuffer->isTexture())
- {
- // texture stencil attachments come along as part
- // of OES_packed_depth_stencil + OES/ANGLE_depth_texture
- if (!data.extensions->depthTextures)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
-
- if (!formatCaps.renderable)
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- if (formatInfo.stencilBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
- else
- {
- if (!formatCaps.renderable || formatInfo.stencilBits == 0)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT;
- }
- }
-
- if (missingAttachment)
- {
- width = mStencilbuffer->getWidth();
- height = mStencilbuffer->getHeight();
- samples = mStencilbuffer->getSamples();
- missingAttachment = false;
- }
- else if (width != mStencilbuffer->getWidth() || height != mStencilbuffer->getHeight())
- {
- return GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS;
- }
- else if (samples != mStencilbuffer->getSamples())
- {
- return GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE;
- }
- }
-
- // if we have both a depth and stencil buffer, they must refer to the same object
- // since we only support packed_depth_stencil and not separate depth and stencil
- if (mDepthbuffer && mStencilbuffer && !hasValidDepthStencil())
- {
- return GL_FRAMEBUFFER_UNSUPPORTED;
- }
-
- // we need to have at least one attachment to be complete
- if (missingAttachment)
- {
- return GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT;
- }
-
- return GL_FRAMEBUFFER_COMPLETE;
-}
-
-Error Framebuffer::invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments)
-{
- GLuint maxDimension = caps.maxRenderbufferSize;
- return invalidateSub(numAttachments, attachments, 0, 0, maxDimension, maxDimension);
-}
-
-Error Framebuffer::invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height)
-{
- for (GLsizei attachIndex = 0; attachIndex < numAttachments; ++attachIndex)
- {
- GLenum attachmentTarget = attachments[attachIndex];
-
- FramebufferAttachment *attachment = (attachmentTarget == GL_DEPTH_STENCIL_ATTACHMENT) ? getDepthOrStencilbuffer()
- : getAttachment(attachmentTarget);
-
- if (attachment)
- {
- rx::RenderTarget *renderTarget = NULL;
- Error error = rx::GetAttachmentRenderTarget(attachment, &renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- renderTarget->invalidate(x, y, width, height);
- }
- }
-
- return Error(GL_NO_ERROR);
-}
-
-DefaultFramebuffer::DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil)
- : Framebuffer(0)
-{
- Renderbuffer *colorRenderbuffer = new Renderbuffer(colorbuffer, 0);
- mColorbuffers[0] = new RenderbufferAttachment(GL_BACK, colorRenderbuffer);
-
- Renderbuffer *depthStencilBuffer = new Renderbuffer(depthStencil, 0);
-
- // Make a new attachment objects to ensure we do not double-delete
- // See angle issue 686
- mDepthbuffer = (depthStencilBuffer->getDepthSize() != 0 ? new RenderbufferAttachment(GL_DEPTH_ATTACHMENT, depthStencilBuffer) : NULL);
- mStencilbuffer = (depthStencilBuffer->getStencilSize() != 0 ? new RenderbufferAttachment(GL_STENCIL_ATTACHMENT, depthStencilBuffer) : NULL);
-
- mDrawBufferStates[0] = GL_BACK;
- mReadBufferState = GL_BACK;
-}
-
-int Framebuffer::getSamples(const gl::Data &data) const
-{
- if (completeness(data) == GL_FRAMEBUFFER_COMPLETE)
- {
- // for a complete framebuffer, all attachments must have the same sample count
- // in this case return the first nonzero sample size
- for (unsigned int colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; colorAttachment++)
- {
- if (mColorbuffers[colorAttachment])
- {
- return mColorbuffers[colorAttachment]->getSamples();
- }
- }
- }
-
- return 0;
-}
-
-bool Framebuffer::hasValidDepthStencil() const
-{
- // A valid depth-stencil attachment has the same resource bound to both the
- // depth and stencil attachment points.
- return (mDepthbuffer && mStencilbuffer &&
- mDepthbuffer->type() == mStencilbuffer->type() &&
- mDepthbuffer->id() == mStencilbuffer->id());
-}
-
-ColorbufferInfo Framebuffer::getColorbuffersForRender(const rx::Workarounds &workarounds) const
-{
- ColorbufferInfo colorbuffersForRender;
-
- for (size_t colorAttachment = 0; colorAttachment < IMPLEMENTATION_MAX_DRAW_BUFFERS; ++colorAttachment)
- {
- GLenum drawBufferState = mDrawBufferStates[colorAttachment];
- FramebufferAttachment *colorbuffer = mColorbuffers[colorAttachment];
-
- if (colorbuffer != NULL && drawBufferState != GL_NONE)
- {
- ASSERT(drawBufferState == GL_BACK || drawBufferState == (GL_COLOR_ATTACHMENT0_EXT + colorAttachment));
- colorbuffersForRender.push_back(colorbuffer);
- }
- else if (!workarounds.mrtPerfWorkaround)
- {
- colorbuffersForRender.push_back(NULL);
- }
- }
-
- return colorbuffersForRender;
-}
-
-void Framebuffer::setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex)
-{
- setAttachment(attachment, new TextureAttachment(attachment, texture, imageIndex));
-}
-
-void Framebuffer::setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer)
-{
- setAttachment(attachment, new RenderbufferAttachment(attachment, renderbuffer));
-}
-
-void Framebuffer::setNULLAttachment(GLenum attachment)
-{
- setAttachment(attachment, NULL);
-}
-
-void Framebuffer::setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj)
-{
- if (attachment >= GL_COLOR_ATTACHMENT0 && attachment < (GL_COLOR_ATTACHMENT0 + IMPLEMENTATION_MAX_DRAW_BUFFERS))
- {
- size_t colorAttachment = attachment - GL_COLOR_ATTACHMENT0;
- SafeDelete(mColorbuffers[colorAttachment]);
- mColorbuffers[colorAttachment] = attachmentObj;
- }
- else if (attachment == GL_DEPTH_ATTACHMENT)
- {
- SafeDelete(mDepthbuffer);
- mDepthbuffer = attachmentObj;
- }
- else if (attachment == GL_STENCIL_ATTACHMENT)
- {
- SafeDelete(mStencilbuffer);
- mStencilbuffer = attachmentObj;
- }
- else if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
- {
- SafeDelete(mDepthbuffer);
- SafeDelete(mStencilbuffer);
-
- // ensure this is a legitimate depth+stencil format
- if (attachmentObj && attachmentObj->getDepthSize() > 0 && attachmentObj->getStencilSize() > 0)
- {
- mDepthbuffer = attachmentObj;
-
- // Make a new attachment object to ensure we do not double-delete
- // See angle issue 686
- if (attachmentObj->isTexture())
- {
- mStencilbuffer = new TextureAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getTexture(),
- *attachmentObj->getTextureImageIndex());
- }
- else
- {
- mStencilbuffer = new RenderbufferAttachment(GL_DEPTH_STENCIL_ATTACHMENT, attachmentObj->getRenderbuffer());
- }
- }
- }
- else
- {
- UNREACHABLE();
- }
-}
-
-GLenum DefaultFramebuffer::completeness(const gl::Data &) const
-{
- // The default framebuffer *must* always be complete, though it may not be
- // subject to the same rules as application FBOs. ie, it could have 0x0 size.
- return GL_FRAMEBUFFER_COMPLETE;
-}
-
-FramebufferAttachment *DefaultFramebuffer::getAttachment(GLenum attachment) const
-{
- switch (attachment)
- {
- case GL_COLOR:
- case GL_BACK:
- return getColorbuffer(0);
- case GL_DEPTH:
- return getDepthbuffer();
- case GL_STENCIL:
- return getStencilbuffer();
- case GL_DEPTH_STENCIL:
- return getDepthStencilBuffer();
- default:
- UNREACHABLE();
- return NULL;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h b/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
deleted file mode 100644
index d0fe8935ea..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Framebuffer.h
+++ /dev/null
@@ -1,126 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Framebuffer.h: Defines the gl::Framebuffer class. Implements GL framebuffer
-// objects and related functionality. [OpenGL ES 2.0.24] section 4.4 page 105.
-
-#ifndef LIBGLESV2_FRAMEBUFFER_H_
-#define LIBGLESV2_FRAMEBUFFER_H_
-
-#include "libGLESv2/Error.h"
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "Constants.h"
-
-#include <vector>
-
-namespace rx
-{
-class RenderbufferImpl;
-struct Workarounds;
-}
-
-namespace gl
-{
-class FramebufferAttachment;
-class Texture;
-class Renderbuffer;
-struct ImageIndex;
-struct Caps;
-struct Extensions;
-class TextureCapsMap;
-struct Data;
-
-typedef std::vector<FramebufferAttachment *> ColorbufferInfo;
-
-class Framebuffer
-{
- public:
- Framebuffer(GLuint id);
- virtual ~Framebuffer();
-
- GLuint id() const { return mId; }
-
- void setTextureAttachment(GLenum attachment, Texture *texture, const ImageIndex &imageIndex);
- void setRenderbufferAttachment(GLenum attachment, Renderbuffer *renderbuffer);
- void setNULLAttachment(GLenum attachment);
-
- void detachTexture(GLuint texture);
- void detachRenderbuffer(GLuint renderbuffer);
-
- FramebufferAttachment *getColorbuffer(unsigned int colorAttachment) const;
- FramebufferAttachment *getDepthbuffer() const;
- FramebufferAttachment *getStencilbuffer() const;
- FramebufferAttachment *getDepthStencilBuffer() const;
- FramebufferAttachment *getDepthOrStencilbuffer() const;
- FramebufferAttachment *getReadColorbuffer() const;
- GLenum getReadColorbufferType() const;
- FramebufferAttachment *getFirstColorbuffer() const;
-
- virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
-
- GLenum getDrawBufferState(unsigned int colorAttachment) const;
- void setDrawBufferState(unsigned int colorAttachment, GLenum drawBuffer);
-
- bool isEnabledColorAttachment(unsigned int colorAttachment) const;
- bool hasEnabledColorAttachment() const;
- bool hasStencil() const;
- int getSamples(const gl::Data &data) const;
- bool usingExtendedDrawBuffers() const;
-
- virtual GLenum completeness(const gl::Data &data) const;
- bool hasValidDepthStencil() const;
-
- Error invalidate(const Caps &caps, GLsizei numAttachments, const GLenum *attachments);
- Error invalidateSub(GLsizei numAttachments, const GLenum *attachments, GLint x, GLint y, GLsizei width, GLsizei height);
-
- // Use this method to retrieve the color buffer map when doing rendering.
- // It will apply a workaround for poor shader performance on some systems
- // by compacting the list to skip NULL values.
- ColorbufferInfo getColorbuffersForRender(const rx::Workarounds &workarounds) const;
-
- protected:
- GLuint mId;
-
- FramebufferAttachment *mColorbuffers[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- GLenum mDrawBufferStates[IMPLEMENTATION_MAX_DRAW_BUFFERS];
- GLenum mReadBufferState;
-
- FramebufferAttachment *mDepthbuffer;
- FramebufferAttachment *mStencilbuffer;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Framebuffer);
-
- void setAttachment(GLenum attachment, FramebufferAttachment *attachmentObj);
-};
-
-class DefaultFramebuffer : public Framebuffer
-{
- public:
- DefaultFramebuffer(rx::RenderbufferImpl *colorbuffer, rx::RenderbufferImpl *depthStencil);
-
- GLenum completeness(const gl::Data &data) const override;
- virtual FramebufferAttachment *getAttachment(GLenum attachment) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DefaultFramebuffer);
-};
-
-}
-
-namespace rx
-{
-class RenderTarget;
-
-// TODO: place this in FramebufferD3D.h
-gl::Error GetAttachmentRenderTarget(gl::FramebufferAttachment *attachment, RenderTarget **outRT);
-unsigned int GetAttachmentSerial(gl::FramebufferAttachment *attachment);
-
-}
-
-#endif // LIBGLESV2_FRAMEBUFFER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
deleted file mode 100644
index c498f8a178..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// HandleAllocator.cpp: Implements the gl::HandleAllocator class, which is used
-// to allocate GL handles.
-
-#include "libGLESv2/HandleAllocator.h"
-
-#include "libGLESv2/main.h"
-
-namespace gl
-{
-
-HandleAllocator::HandleAllocator() : mBaseValue(1), mNextValue(1)
-{
-}
-
-HandleAllocator::~HandleAllocator()
-{
-}
-
-void HandleAllocator::setBaseHandle(GLuint value)
-{
- ASSERT(mBaseValue == mNextValue);
- mBaseValue = value;
- mNextValue = value;
-}
-
-GLuint HandleAllocator::allocate()
-{
- if (mFreeValues.size())
- {
- GLuint handle = mFreeValues.back();
- mFreeValues.pop_back();
- return handle;
- }
- return mNextValue++;
-}
-
-void HandleAllocator::release(GLuint handle)
-{
- if (handle == mNextValue - 1)
- {
- // Don't drop below base value
- if(mNextValue > mBaseValue)
- {
- mNextValue--;
- }
- }
- else
- {
- // Only free handles that we own - don't drop below the base value
- if (handle >= mBaseValue)
- {
- mFreeValues.push_back(handle);
- }
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h b/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
deleted file mode 100644
index a89cc86775..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/HandleAllocator.h
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// HandleAllocator.h: Defines the gl::HandleAllocator class, which is used to
-// allocate GL handles.
-
-#ifndef LIBGLESV2_HANDLEALLOCATOR_H_
-#define LIBGLESV2_HANDLEALLOCATOR_H_
-
-#include "common/angleutils.h"
-
-#include "angle_gl.h"
-
-#include <vector>
-
-namespace gl
-{
-
-class HandleAllocator
-{
- public:
- HandleAllocator();
- virtual ~HandleAllocator();
-
- void setBaseHandle(GLuint value);
-
- GLuint allocate();
- void release(GLuint handle);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HandleAllocator);
-
- GLuint mBaseValue;
- GLuint mNextValue;
- typedef std::vector<GLuint> HandleList;
- HandleList mFreeValues;
-};
-
-}
-
-#endif // LIBGLESV2_HANDLEALLOCATOR_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.cpp b/src/3rdparty/angle/src/libGLESv2/Program.cpp
deleted file mode 100644
index 3faa8c56f6..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Program.cpp
+++ /dev/null
@@ -1,668 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Program.cpp: Implements the gl::Program class. Implements GL program objects
-// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-namespace gl
-{
-const char * const g_fakepath = "C:\\fakepath";
-
-AttributeBindings::AttributeBindings()
-{
-}
-
-AttributeBindings::~AttributeBindings()
-{
-}
-
-InfoLog::InfoLog() : mInfoLog(NULL)
-{
-}
-
-InfoLog::~InfoLog()
-{
- delete[] mInfoLog;
-}
-
-
-int InfoLog::getLength() const
-{
- if (!mInfoLog)
- {
- return 0;
- }
- else
- {
- return strlen(mInfoLog) + 1;
- }
-}
-
-void InfoLog::getLog(GLsizei bufSize, GLsizei *length, char *infoLog)
-{
- int index = 0;
-
- if (bufSize > 0)
- {
- if (mInfoLog)
- {
- index = std::min(bufSize - 1, (int)strlen(mInfoLog));
- memcpy(infoLog, mInfoLog, index);
- }
-
- infoLog[index] = '\0';
- }
-
- if (length)
- {
- *length = index;
- }
-}
-
-// append a santized message to the program info log.
-// The D3D compiler includes a fake file path in some of the warning or error
-// messages, so lets remove all occurrences of this fake file path from the log.
-void InfoLog::appendSanitized(const char *message)
-{
- std::string msg(message);
-
- size_t found;
- do
- {
- found = msg.find(g_fakepath);
- if (found != std::string::npos)
- {
- msg.erase(found, strlen(g_fakepath));
- }
- }
- while (found != std::string::npos);
-
- append("%s", msg.c_str());
-}
-
-void InfoLog::append(const char *format, ...)
-{
- if (!format)
- {
- return;
- }
-
- va_list vararg;
- va_start(vararg, format);
- size_t infoLength = vsnprintf(NULL, 0, format, vararg);
- va_end(vararg);
-
- char *logPointer = NULL;
-
- if (!mInfoLog)
- {
- mInfoLog = new char[infoLength + 2];
- logPointer = mInfoLog;
- }
- else
- {
- size_t currentlogLength = strlen(mInfoLog);
- char *newLog = new char[currentlogLength + infoLength + 2];
- strcpy(newLog, mInfoLog);
-
- delete[] mInfoLog;
- mInfoLog = newLog;
-
- logPointer = mInfoLog + currentlogLength;
- }
-
- va_start(vararg, format);
- vsnprintf(logPointer, infoLength, format, vararg);
- va_end(vararg);
-
- logPointer[infoLength] = 0;
- strcpy(logPointer + infoLength, "\n");
-}
-
-void InfoLog::reset()
-{
- if (mInfoLog)
- {
- delete [] mInfoLog;
- mInfoLog = NULL;
- }
-}
-
-Program::Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle) : mResourceManager(manager), mHandle(handle)
-{
- mFragmentShader = NULL;
- mVertexShader = NULL;
- mProgramBinary.set(NULL);
- mDeleteStatus = false;
- mLinked = false;
- mRefCount = 0;
- mRenderer = renderer;
-
- resetUniformBlockBindings();
-}
-
-Program::~Program()
-{
- unlink(true);
-
- if (mVertexShader != NULL)
- {
- mVertexShader->release();
- }
-
- if (mFragmentShader != NULL)
- {
- mFragmentShader->release();
- }
-}
-
-bool Program::attachShader(Shader *shader)
-{
- if (shader->getType() == GL_VERTEX_SHADER)
- {
- if (mVertexShader)
- {
- return false;
- }
-
- mVertexShader = shader;
- mVertexShader->addRef();
- }
- else if (shader->getType() == GL_FRAGMENT_SHADER)
- {
- if (mFragmentShader)
- {
- return false;
- }
-
- mFragmentShader = shader;
- mFragmentShader->addRef();
- }
- else UNREACHABLE();
-
- return true;
-}
-
-bool Program::detachShader(Shader *shader)
-{
- if (shader->getType() == GL_VERTEX_SHADER)
- {
- if (mVertexShader != shader)
- {
- return false;
- }
-
- mVertexShader->release();
- mVertexShader = NULL;
- }
- else if (shader->getType() == GL_FRAGMENT_SHADER)
- {
- if (mFragmentShader != shader)
- {
- return false;
- }
-
- mFragmentShader->release();
- mFragmentShader = NULL;
- }
- else UNREACHABLE();
-
- return true;
-}
-
-int Program::getAttachedShadersCount() const
-{
- return (mVertexShader ? 1 : 0) + (mFragmentShader ? 1 : 0);
-}
-
-void AttributeBindings::bindAttributeLocation(GLuint index, const char *name)
-{
- if (index < MAX_VERTEX_ATTRIBS)
- {
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- mAttributeBinding[i].erase(name);
- }
-
- mAttributeBinding[index].insert(name);
- }
-}
-
-void Program::bindAttributeLocation(GLuint index, const char *name)
-{
- mAttributeBindings.bindAttributeLocation(index, name);
-}
-
-// Links the HLSL code of the vertex and pixel shader by matching up their varyings,
-// compiling them into binaries, determining the attribute mappings, and collecting
-// a list of uniforms
-Error Program::link(const Data &data)
-{
- unlink(false);
-
- mInfoLog.reset();
- resetUniformBlockBindings();
-
- mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
- LinkResult result = mProgramBinary->link(data, mInfoLog, mAttributeBindings, mFragmentShader, mVertexShader,
- mTransformFeedbackVaryings, mTransformFeedbackBufferMode);
- if (result.error.isError())
- {
- return result.error;
- }
-
- mLinked = result.linkSuccess;
- return gl::Error(GL_NO_ERROR);
-}
-
-int AttributeBindings::getAttributeBinding(const std::string &name) const
-{
- for (int location = 0; location < MAX_VERTEX_ATTRIBS; location++)
- {
- if (mAttributeBinding[location].find(name) != mAttributeBinding[location].end())
- {
- return location;
- }
- }
-
- return -1;
-}
-
-// Returns the program object to an unlinked state, before re-linking, or at destruction
-void Program::unlink(bool destroy)
-{
- if (destroy) // Object being destructed
- {
- if (mFragmentShader)
- {
- mFragmentShader->release();
- mFragmentShader = NULL;
- }
-
- if (mVertexShader)
- {
- mVertexShader->release();
- mVertexShader = NULL;
- }
- }
-
- mProgramBinary.set(NULL);
- mLinked = false;
-}
-
-bool Program::isLinked()
-{
- return mLinked;
-}
-
-ProgramBinary* Program::getProgramBinary() const
-{
- return mProgramBinary.get();
-}
-
-Error Program::setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length)
-{
- unlink(false);
-
- mInfoLog.reset();
-
- mProgramBinary.set(new ProgramBinary(mRenderer->createProgram()));
- LinkResult result = mProgramBinary->load(mInfoLog, binaryFormat, binary, length);
- if (result.error.isError())
- {
- mProgramBinary.set(NULL);
- return result.error;
- }
-
- mLinked = result.linkSuccess;
- return Error(GL_NO_ERROR);
-}
-
-void Program::release()
-{
- mRefCount--;
-
- if (mRefCount == 0 && mDeleteStatus)
- {
- mResourceManager->deleteProgram(mHandle);
- }
-}
-
-void Program::addRef()
-{
- mRefCount++;
-}
-
-unsigned int Program::getRefCount() const
-{
- return mRefCount;
-}
-
-GLint Program::getProgramBinaryLength() const
-{
- ProgramBinary *programBinary = mProgramBinary.get();
- if (programBinary)
- {
- return programBinary->getLength();
- }
- else
- {
- return 0;
- }
-}
-
-int Program::getInfoLogLength() const
-{
- return mInfoLog.getLength();
-}
-
-void Program::getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog)
-{
- return mInfoLog.getLog(bufSize, length, infoLog);
-}
-
-void Program::getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders)
-{
- int total = 0;
-
- if (mVertexShader)
- {
- if (total < maxCount)
- {
- shaders[total] = mVertexShader->getHandle();
- }
-
- total++;
- }
-
- if (mFragmentShader)
- {
- if (total < maxCount)
- {
- shaders[total] = mFragmentShader->getHandle();
- }
-
- total++;
- }
-
- if (count)
- {
- *count = total;
- }
-}
-
-void Program::getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- programBinary->getActiveAttribute(index, bufsize, length, size, type, name);
- }
- else
- {
- if (bufsize > 0)
- {
- name[0] = '\0';
- }
-
- if (length)
- {
- *length = 0;
- }
-
- *type = GL_NONE;
- *size = 1;
- }
-}
-
-GLint Program::getActiveAttributeCount()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getActiveAttributeCount();
- }
- else
- {
- return 0;
- }
-}
-
-GLint Program::getActiveAttributeMaxLength()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getActiveAttributeMaxLength();
- }
- else
- {
- return 0;
- }
-}
-
-void Program::getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getActiveUniform(index, bufsize, length, size, type, name);
- }
- else
- {
- if (bufsize > 0)
- {
- name[0] = '\0';
- }
-
- if (length)
- {
- *length = 0;
- }
-
- *size = 0;
- *type = GL_NONE;
- }
-}
-
-GLint Program::getActiveUniformCount()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getActiveUniformCount();
- }
- else
- {
- return 0;
- }
-}
-
-GLint Program::getActiveUniformMaxLength()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getActiveUniformMaxLength();
- }
- else
- {
- return 0;
- }
-}
-
-void Program::flagForDeletion()
-{
- mDeleteStatus = true;
-}
-
-bool Program::isFlaggedForDeletion() const
-{
- return mDeleteStatus;
-}
-
-void Program::validate(const Caps &caps)
-{
- mInfoLog.reset();
-
- ProgramBinary *programBinary = getProgramBinary();
- if (isLinked() && programBinary)
- {
- programBinary->validate(mInfoLog, caps);
- }
- else
- {
- mInfoLog.append("Program has not been successfully linked.");
- }
-}
-
-bool Program::isValidated() const
-{
- ProgramBinary *programBinary = mProgramBinary.get();
- if (programBinary)
- {
- return programBinary->isValidated();
- }
- else
- {
- return false;
- }
-}
-
-GLint Program::getActiveUniformBlockCount()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return static_cast<GLint>(programBinary->getActiveUniformBlockCount());
- }
- else
- {
- return 0;
- }
-}
-
-GLint Program::getActiveUniformBlockMaxLength()
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return static_cast<GLint>(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<GLsizei>(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<GLsizei>(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<GLsizei>(varying.name.length() + 1));
- }
-
- return maxSize;
- }
- else
- {
- return 0;
- }
-}
-
-GLenum Program::getTransformFeedbackBufferMode() const
-{
- ProgramBinary *programBinary = getProgramBinary();
- if (programBinary)
- {
- return programBinary->getTransformFeedbackBufferMode();
- }
- else
- {
- return mTransformFeedbackBufferMode;
- }
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/Program.h b/src/3rdparty/angle/src/libGLESv2/Program.h
deleted file mode 100644
index b92349eeef..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Program.h
+++ /dev/null
@@ -1,151 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Program.h: Defines the gl::Program class. Implements GL program objects
-// and related functionality. [OpenGL ES 2.0.24] section 2.10.3 page 28.
-
-#ifndef LIBGLESV2_PROGRAM_H_
-#define LIBGLESV2_PROGRAM_H_
-
-#include "common/angleutils.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/ProgramBinary.h"
-
-#include <GLES2/gl2.h>
-
-#include <vector>
-#include <string>
-#include <set>
-
-namespace rx
-{
-class Renderer;
-}
-
-namespace gl
-{
-struct Caps;
-struct Data;
-class ResourceManager;
-class Shader;
-
-extern const char * const g_fakepath;
-
-class AttributeBindings
-{
- public:
- AttributeBindings();
- ~AttributeBindings();
-
- void bindAttributeLocation(GLuint index, const char *name);
- int getAttributeBinding(const std::string &name) const;
-
- private:
- std::set<std::string> mAttributeBinding[MAX_VERTEX_ATTRIBS];
-};
-
-class InfoLog
-{
- public:
- InfoLog();
- ~InfoLog();
-
- int getLength() const;
- void getLog(GLsizei bufSize, GLsizei *length, char *infoLog);
-
- void appendSanitized(const char *message);
- void append(const char *info, ...);
- void reset();
- private:
- DISALLOW_COPY_AND_ASSIGN(InfoLog);
- char *mInfoLog;
-};
-
-class Program
-{
- public:
- Program(rx::Renderer *renderer, ResourceManager *manager, GLuint handle);
-
- ~Program();
-
- bool attachShader(Shader *shader);
- bool detachShader(Shader *shader);
- int getAttachedShadersCount() const;
-
- void bindAttributeLocation(GLuint index, const char *name);
-
- Error link(const Data &data);
- bool isLinked();
- Error setProgramBinary(GLenum binaryFormat, const void *binary, GLsizei length);
- ProgramBinary *getProgramBinary() const;
-
- int getInfoLogLength() const;
- void getInfoLog(GLsizei bufSize, GLsizei *length, char *infoLog);
- void getAttachedShaders(GLsizei maxCount, GLsizei *count, GLuint *shaders);
-
- void getActiveAttribute(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
- GLint getActiveAttributeCount();
- GLint getActiveAttributeMaxLength();
-
- void getActiveUniform(GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name);
- GLint getActiveUniformCount();
- GLint getActiveUniformMaxLength();
-
- GLint getActiveUniformBlockCount();
- GLint getActiveUniformBlockMaxLength();
-
- void bindUniformBlock(GLuint uniformBlockIndex, GLuint uniformBlockBinding);
- GLuint getUniformBlockBinding(GLuint uniformBlockIndex) const;
-
- void setTransformFeedbackVaryings(GLsizei count, const GLchar *const *varyings, GLenum bufferMode);
- void getTransformFeedbackVarying(GLuint index, GLsizei bufSize, GLsizei *length, GLsizei *size, GLenum *type, GLchar *name) const;
- GLsizei getTransformFeedbackVaryingCount() const;
- GLsizei getTransformFeedbackVaryingMaxLength() const;
- GLenum getTransformFeedbackBufferMode() const;
-
- void addRef();
- void release();
- unsigned int getRefCount() const;
- void flagForDeletion();
- bool isFlaggedForDeletion() const;
-
- void validate(const Caps &caps);
- bool isValidated() const;
-
- GLint getProgramBinaryLength() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Program);
-
- void unlink(bool destroy = false);
- void resetUniformBlockBindings();
-
- Shader *mFragmentShader;
- Shader *mVertexShader;
-
- AttributeBindings mAttributeBindings;
-
- GLuint mUniformBlockBindings[IMPLEMENTATION_MAX_COMBINED_SHADER_UNIFORM_BUFFERS];
-
- std::vector<std::string> mTransformFeedbackVaryings;
- GLuint mTransformFeedbackBufferMode;
-
- BindingPointer<ProgramBinary> mProgramBinary;
- bool mLinked;
- bool mDeleteStatus; // Flag to indicate that the program can be deleted when no longer in use
-
- unsigned int mRefCount;
-
- ResourceManager *mResourceManager;
- rx::Renderer *mRenderer;
- const GLuint mHandle;
-
- InfoLog mInfoLog;
-};
-}
-
-#endif // LIBGLESV2_PROGRAM_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.cpp b/src/3rdparty/angle/src/libGLESv2/Texture.cpp
deleted file mode 100644
index cd4fc4e32a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Texture.cpp
+++ /dev/null
@@ -1,1012 +0,0 @@
-//
-// Copyright (c) 2002-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Texture.cpp: Implements the gl::Texture class and its derived classes
-// Texture2D and TextureCubeMap. Implements GL texture objects and related
-// functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
-
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/ImageIndex.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/renderer/Image.h"
-#include "libGLESv2/renderer/d3d/TextureStorage.h"
-
-#include "libEGL/Surface.h"
-
-#include "common/mathutil.h"
-#include "common/utilities.h"
-
-namespace gl
-{
-
-bool IsMipmapFiltered(const gl::SamplerState &samplerState)
-{
- switch (samplerState.minFilter)
- {
- case GL_NEAREST:
- case GL_LINEAR:
- return false;
- case GL_NEAREST_MIPMAP_NEAREST:
- case GL_LINEAR_MIPMAP_NEAREST:
- case GL_NEAREST_MIPMAP_LINEAR:
- case GL_LINEAR_MIPMAP_LINEAR:
- return true;
- default: UNREACHABLE();
- return false;
- }
-}
-
-bool IsPointSampled(const gl::SamplerState &samplerState)
-{
- return (samplerState.magFilter == GL_NEAREST && (samplerState.minFilter == GL_NEAREST || samplerState.minFilter == GL_NEAREST_MIPMAP_NEAREST));
-}
-
-unsigned int Texture::mCurrentTextureSerial = 1;
-
-Texture::Texture(rx::TextureImpl *impl, GLuint id, GLenum target)
- : RefCountObject(id),
- mTexture(impl),
- mTextureSerial(issueTextureSerial()),
- mUsage(GL_NONE),
- mImmutableLevelCount(0),
- mTarget(target)
-{
-}
-
-Texture::~Texture()
-{
- SafeDelete(mTexture);
-}
-
-GLenum Texture::getTarget() const
-{
- return mTarget;
-}
-
-void Texture::setUsage(GLenum usage)
-{
- mUsage = usage;
- getImplementation()->setUsage(usage);
-}
-
-GLenum Texture::getUsage() const
-{
- return mUsage;
-}
-
-GLint Texture::getBaseLevelWidth() const
-{
- const rx::Image *baseImage = getBaseLevelImage();
- return (baseImage ? baseImage->getWidth() : 0);
-}
-
-GLint Texture::getBaseLevelHeight() const
-{
- const rx::Image *baseImage = getBaseLevelImage();
- return (baseImage ? baseImage->getHeight() : 0);
-}
-
-GLint Texture::getBaseLevelDepth() const
-{
- const rx::Image *baseImage = getBaseLevelImage();
- return (baseImage ? baseImage->getDepth() : 0);
-}
-
-// Note: "base level image" is loosely defined to be any image from the base level,
-// where in the base of 2D array textures and cube maps there are several. Don't use
-// the base level image for anything except querying texture format and size.
-GLenum Texture::getBaseLevelInternalFormat() const
-{
- const rx::Image *baseImage = getBaseLevelImage();
- return (baseImage ? baseImage->getInternalFormat() : GL_NONE);
-}
-
-GLsizei Texture::getWidth(const ImageIndex &index) const
-{
- rx::Image *image = mTexture->getImage(index);
- return image->getWidth();
-}
-
-GLsizei Texture::getHeight(const ImageIndex &index) const
-{
- rx::Image *image = mTexture->getImage(index);
- return image->getHeight();
-}
-
-GLenum Texture::getInternalFormat(const ImageIndex &index) const
-{
- rx::Image *image = mTexture->getImage(index);
- return image->getInternalFormat();
-}
-
-GLenum Texture::getActualFormat(const ImageIndex &index) const
-{
- rx::Image *image = mTexture->getImage(index);
- return image->getActualFormat();
-}
-
-Error Texture::generateMipmaps()
-{
- return getImplementation()->generateMipmaps();
-}
-
-Error Texture::copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source)
-{
- return mTexture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, source);
-}
-
-unsigned int Texture::getTextureSerial() const
-{
- return mTextureSerial;
-}
-
-unsigned int Texture::issueTextureSerial()
-{
- return mCurrentTextureSerial++;
-}
-
-bool Texture::isImmutable() const
-{
- return (mImmutableLevelCount > 0);
-}
-
-int Texture::immutableLevelCount()
-{
- return mImmutableLevelCount;
-}
-
-int Texture::mipLevels() const
-{
- return log2(std::max(std::max(getBaseLevelWidth(), getBaseLevelHeight()), getBaseLevelDepth())) + 1;
-}
-
-const rx::Image *Texture::getBaseLevelImage() const
-{
- return (getImplementation()->getLayerCount(0) > 0 ? getImplementation()->getImage(0, 0) : NULL);
-}
-
-Texture2D::Texture2D(rx::TextureImpl *impl, GLuint id)
- : Texture(impl, id, GL_TEXTURE_2D)
-{
- mSurface = NULL;
-}
-
-Texture2D::~Texture2D()
-{
- if (mSurface)
- {
- mSurface->setBoundTexture(NULL);
- mSurface = NULL;
- }
-}
-
-GLsizei Texture2D::getWidth(GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, 0)->getWidth();
- else
- return 0;
-}
-
-GLsizei Texture2D::getHeight(GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, 0)->getHeight();
- else
- return 0;
-}
-
-GLenum Texture2D::getInternalFormat(GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, 0)->getInternalFormat();
- else
- return GL_NONE;
-}
-
-GLenum Texture2D::getActualFormat(GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, 0)->getActualFormat();
- else
- return GL_NONE;
-}
-
-Error Texture2D::setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- releaseTexImage();
-
- return mTexture->setImage(GL_TEXTURE_2D, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-void Texture2D::bindTexImage(egl::Surface *surface)
-{
- releaseTexImage();
-
- mTexture->bindTexImage(surface);
-
- mSurface = surface;
- mSurface->setBoundTexture(this);
-}
-
-void Texture2D::releaseTexImage()
-{
- if (mSurface)
- {
- mSurface->setBoundTexture(NULL);
- mSurface = NULL;
-
- mTexture->releaseTexImage();
- }
-}
-
-Error Texture2D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize,
- const PixelUnpackState &unpack, const void *pixels)
-{
- releaseTexImage();
-
- return mTexture->setCompressedImage(GL_TEXTURE_2D, level, format, width, height, 1, imageSize, unpack, pixels);
-}
-
-Error Texture2D::subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImage(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
-}
-
-Error Texture2D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImageCompressed(GL_TEXTURE_2D, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
-}
-
-Error Texture2D::copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height,
- Framebuffer *source)
-{
- releaseTexImage();
-
- return mTexture->copyImage(GL_TEXTURE_2D, level, format, x, y, width, height, source);
-}
-
-Error Texture2D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
-{
- Error error = mTexture->storage(GL_TEXTURE_2D, levels, internalformat, width, height, 1);
- if (error.isError())
- {
- return error;
- }
-
- mImmutableLevelCount = levels;
-
- return Error(GL_NO_ERROR);
-}
-
-// Tests for 2D texture sampling completeness. [OpenGL ES 2.0.24] section 3.8.2 page 85.
-bool Texture2D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
-{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
-
- if (width <= 0 || height <= 0)
- {
- return false;
- }
-
- if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
- {
- return false;
- }
-
- bool npotSupport = extensions.textureNPOT;
-
- if (!npotSupport)
- {
- if ((samplerState.wrapS != GL_CLAMP_TO_EDGE && !gl::isPow2(width)) ||
- (samplerState.wrapT != GL_CLAMP_TO_EDGE && !gl::isPow2(height)))
- {
- return false;
- }
- }
-
- if (IsMipmapFiltered(samplerState))
- {
- if (!npotSupport)
- {
- if (!gl::isPow2(width) || !gl::isPow2(height))
- {
- return false;
- }
- }
-
- if (!isMipmapComplete())
- {
- return false;
- }
- }
-
- // OpenGLES 3.0.2 spec section 3.8.13 states that a texture is not mipmap complete if:
- // The internalformat specified for the texture arrays is a sized internal depth or
- // depth and stencil format (see table 3.13), the value of TEXTURE_COMPARE_-
- // MODE is NONE, and either the magnification filter is not NEAREST or the mini-
- // fication filter is neither NEAREST nor NEAREST_MIPMAP_NEAREST.
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(getInternalFormat(0));
- if (formatInfo.depthBits > 0 && clientVersion > 2)
- {
- if (samplerState.compareMode == GL_NONE)
- {
- if ((samplerState.minFilter != GL_NEAREST && samplerState.minFilter != GL_NEAREST_MIPMAP_NEAREST) ||
- samplerState.magFilter != GL_NEAREST)
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool Texture2D::isCompressed(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).compressed;
-}
-
-bool Texture2D::isDepth(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
-}
-
-Error Texture2D::generateMipmaps()
-{
- releaseTexImage();
-
- return mTexture->generateMipmaps();
-}
-
-// Tests for 2D texture (mipmap) completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool Texture2D::isMipmapComplete() const
-{
- int levelCount = mipLevels();
-
- for (int level = 0; level < levelCount; level++)
- {
- if (!isLevelComplete(level))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool Texture2D::isLevelComplete(int level) const
-{
- if (isImmutable())
- {
- return true;
- }
-
- const rx::Image *baseImage = getBaseLevelImage();
-
- GLsizei width = baseImage->getWidth();
- GLsizei height = baseImage->getHeight();
-
- if (width <= 0 || height <= 0)
- {
- return false;
- }
-
- // The base image level is complete if the width and height are positive
- if (level == 0)
- {
- return true;
- }
-
- ASSERT(level >= 1 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
- rx::Image *image = mTexture->getImage(level, 0);
-
- if (image->getInternalFormat() != baseImage->getInternalFormat())
- {
- return false;
- }
-
- if (image->getWidth() != std::max(1, width >> level))
- {
- return false;
- }
-
- if (image->getHeight() != std::max(1, height >> level))
- {
- return false;
- }
-
- return true;
-}
-
-TextureCubeMap::TextureCubeMap(rx::TextureImpl *impl, GLuint id)
- : Texture(impl, id, GL_TEXTURE_CUBE_MAP)
-{
-}
-
-TextureCubeMap::~TextureCubeMap()
-{
-}
-
-GLsizei TextureCubeMap::getWidth(GLenum target, GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, targetToLayerIndex(target))->getWidth();
- else
- return 0;
-}
-
-GLsizei TextureCubeMap::getHeight(GLenum target, GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, targetToLayerIndex(target))->getHeight();
- else
- return 0;
-}
-
-GLenum TextureCubeMap::getInternalFormat(GLenum target, GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, targetToLayerIndex(target))->getInternalFormat();
- else
- return GL_NONE;
-}
-
-GLenum TextureCubeMap::getActualFormat(GLenum target, GLint level) const
-{
- if (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS)
- return mTexture->getImage(level, targetToLayerIndex(target))->getActualFormat();
- else
- return GL_NONE;
-}
-
-Error TextureCubeMap::setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setImage(target, level, width, height, 1, internalFormat, format, type, unpack, pixels);
-}
-
-Error TextureCubeMap::setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setCompressedImage(target, level, format, width, height, 1, imageSize, unpack, pixels);
-}
-
-Error TextureCubeMap::subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImage(target, level, xoffset, yoffset, 0, width, height, 1, format, type, unpack, pixels);
-}
-
-Error TextureCubeMap::subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset,
- GLsizei width, GLsizei height, GLenum format,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImageCompressed(target, level, xoffset, yoffset, 0, width, height, 1, format, imageSize, unpack, pixels);
-}
-
-// Tests for cube texture completeness. [OpenGL ES 2.0.24] section 3.7.10 page 81.
-bool TextureCubeMap::isCubeComplete() const
-{
- int baseWidth = getBaseLevelWidth();
- int baseHeight = getBaseLevelHeight();
- GLenum baseFormat = getBaseLevelInternalFormat();
-
- if (baseWidth <= 0 || baseWidth != baseHeight)
- {
- return false;
- }
-
- for (int faceIndex = 1; faceIndex < 6; faceIndex++)
- {
- const rx::Image *faceBaseImage = mTexture->getImage(0, faceIndex);
-
- if (faceBaseImage->getWidth() != baseWidth ||
- faceBaseImage->getHeight() != baseHeight ||
- faceBaseImage->getInternalFormat() != baseFormat )
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool TextureCubeMap::isCompressed(GLenum target, GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(target, level)).compressed;
-}
-
-bool TextureCubeMap::isDepth(GLenum target, GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(target, level)).depthBits > 0;
-}
-
-Error TextureCubeMap::copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y,
- GLsizei width, GLsizei height, Framebuffer *source)
-{
- return mTexture->copyImage(target, level, format, x, y, width, height, source);
-}
-
-Error TextureCubeMap::storage(GLsizei levels, GLenum internalformat, GLsizei size)
-{
- Error error = mTexture->storage(GL_TEXTURE_CUBE_MAP, levels, internalformat, size, size, 1);
- if (error.isError())
- {
- return error;
- }
-
- mImmutableLevelCount = levels;
-
- return Error(GL_NO_ERROR);
-}
-
-// Tests for texture sampling completeness
-bool TextureCubeMap::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
-{
- int size = getBaseLevelWidth();
-
- bool mipmapping = IsMipmapFiltered(samplerState);
-
- if (!textureCaps.get(getInternalFormat(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0)).filterable && !IsPointSampled(samplerState))
- {
- return false;
- }
-
- if (!gl::isPow2(size) && !extensions.textureNPOT)
- {
- if (samplerState.wrapS != GL_CLAMP_TO_EDGE || samplerState.wrapT != GL_CLAMP_TO_EDGE || mipmapping)
- {
- return false;
- }
- }
-
- if (!mipmapping)
- {
- if (!isCubeComplete())
- {
- return false;
- }
- }
- else
- {
- if (!isMipmapComplete()) // Also tests for isCubeComplete()
- {
- return false;
- }
- }
-
- return true;
-}
-
-int TextureCubeMap::targetToLayerIndex(GLenum target)
-{
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
-
- return target - GL_TEXTURE_CUBE_MAP_POSITIVE_X;
-}
-
-GLenum TextureCubeMap::layerIndexToTarget(GLint layer)
-{
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_X - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 1);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 2);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 3);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_POSITIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 4);
- META_ASSERT(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z - GL_TEXTURE_CUBE_MAP_POSITIVE_X == 5);
-
- return GL_TEXTURE_CUBE_MAP_POSITIVE_X + layer;
-}
-
-bool TextureCubeMap::isMipmapComplete() const
-{
- if (isImmutable())
- {
- return true;
- }
-
- if (!isCubeComplete())
- {
- return false;
- }
-
- int levelCount = mipLevels();
-
- for (int face = 0; face < 6; face++)
- {
- for (int level = 1; level < levelCount; level++)
- {
- if (!isFaceLevelComplete(face, level))
- {
- return false;
- }
- }
- }
-
- return true;
-}
-
-bool TextureCubeMap::isFaceLevelComplete(int faceIndex, int level) const
-{
- ASSERT(level >= 0 && faceIndex < 6 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, faceIndex) != NULL);
-
- if (isImmutable())
- {
- return true;
- }
-
- int baseSize = getBaseLevelWidth();
-
- if (baseSize <= 0)
- {
- return false;
- }
-
- // "isCubeComplete" checks for base level completeness and we must call that
- // to determine if any face at level 0 is complete. We omit that check here
- // to avoid re-checking cube-completeness for every face at level 0.
- if (level == 0)
- {
- return true;
- }
-
- // Check that non-zero levels are consistent with the base level.
- const rx::Image *faceLevelImage = mTexture->getImage(level, faceIndex);
-
- if (faceLevelImage->getInternalFormat() != getBaseLevelInternalFormat())
- {
- return false;
- }
-
- if (faceLevelImage->getWidth() != std::max(1, baseSize >> level))
- {
- return false;
- }
-
- return true;
-}
-
-
-Texture3D::Texture3D(rx::TextureImpl *impl, GLuint id)
- : Texture(impl, id, GL_TEXTURE_3D)
-{
-}
-
-Texture3D::~Texture3D()
-{
-}
-
-GLsizei Texture3D::getWidth(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getWidth() : 0;
-}
-
-GLsizei Texture3D::getHeight(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getHeight() : 0;
-}
-
-GLsizei Texture3D::getDepth(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getDepth() : 0;
-}
-
-GLenum Texture3D::getInternalFormat(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
-}
-
-GLenum Texture3D::getActualFormat(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
-}
-
-bool Texture3D::isCompressed(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).compressed;
-}
-
-bool Texture3D::isDepth(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
-}
-
-Error Texture3D::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setImage(GL_TEXTURE_3D, level, width, height, depth, internalFormat, format, type, unpack, pixels);
-}
-
-Error Texture3D::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setCompressedImage(GL_TEXTURE_3D, level, format, width, height, depth, imageSize, unpack, pixels);
-}
-
-Error Texture3D::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImage(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
-}
-
-Error Texture3D::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImageCompressed(GL_TEXTURE_3D, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
-}
-
-Error Texture3D::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
-{
- Error error = mTexture->storage(GL_TEXTURE_3D, levels, internalformat, width, height, depth);
- if (error.isError())
- {
- return error;
- }
-
- mImmutableLevelCount = levels;
-
- return Error(GL_NO_ERROR);
-}
-
-bool Texture3D::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
-{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getBaseLevelDepth();
-
- if (width <= 0 || height <= 0 || depth <= 0)
- {
- return false;
- }
-
- if (!textureCaps.get(getInternalFormat(0)).filterable && !IsPointSampled(samplerState))
- {
- return false;
- }
-
- if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
- {
- return false;
- }
-
- return true;
-}
-
-bool Texture3D::isMipmapComplete() const
-{
- int levelCount = mipLevels();
-
- for (int level = 0; level < levelCount; level++)
- {
- if (!isLevelComplete(level))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool Texture3D::isLevelComplete(int level) const
-{
- ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getImage(level, 0) != NULL);
-
- if (isImmutable())
- {
- return true;
- }
-
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getBaseLevelDepth();
-
- if (width <= 0 || height <= 0 || depth <= 0)
- {
- return false;
- }
-
- if (level == 0)
- {
- return true;
- }
-
- rx::Image *levelImage = mTexture->getImage(level, 0);
-
- if (levelImage->getInternalFormat() != getBaseLevelInternalFormat())
- {
- return false;
- }
-
- if (levelImage->getWidth() != std::max(1, width >> level))
- {
- return false;
- }
-
- if (levelImage->getHeight() != std::max(1, height >> level))
- {
- return false;
- }
-
- if (levelImage->getDepth() != std::max(1, depth >> level))
- {
- return false;
- }
-
- return true;
-}
-
-Texture2DArray::Texture2DArray(rx::TextureImpl *impl, GLuint id)
- : Texture(impl, id, GL_TEXTURE_2D_ARRAY)
-{
-}
-
-Texture2DArray::~Texture2DArray()
-{
-}
-
-GLsizei Texture2DArray::getWidth(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getWidth() : 0;
-}
-
-GLsizei Texture2DArray::getHeight(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getHeight() : 0;
-}
-
-GLsizei Texture2DArray::getLayers(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS) ? mTexture->getLayerCount(level) : 0;
-}
-
-GLenum Texture2DArray::getInternalFormat(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getInternalFormat() : GL_NONE;
-}
-
-GLenum Texture2DArray::getActualFormat(GLint level) const
-{
- return (level < IMPLEMENTATION_MAX_TEXTURE_LEVELS && mTexture->getLayerCount(level) > 0) ? mTexture->getImage(level, 0)->getActualFormat() : GL_NONE;
-}
-
-bool Texture2DArray::isCompressed(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).compressed;
-}
-
-bool Texture2DArray::isDepth(GLint level) const
-{
- return GetInternalFormatInfo(getInternalFormat(level)).depthBits > 0;
-}
-
-Error Texture2DArray::setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setImage(GL_TEXTURE_2D_ARRAY, level, width, height, depth, internalFormat, format, type, unpack, pixels);
-}
-
-Error Texture2DArray::setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->setCompressedImage(GL_TEXTURE_2D_ARRAY, level, format, width, height, depth, imageSize, unpack, pixels);
-}
-
-Error Texture2DArray::subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImage(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, type, unpack, pixels);
-}
-
-Error Texture2DArray::subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset,
- GLsizei width, GLsizei height, GLsizei depth, GLenum format,
- GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels)
-{
- return mTexture->subImageCompressed(GL_TEXTURE_2D_ARRAY, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, unpack, pixels);
-}
-
-Error Texture2DArray::storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
-{
- Error error = mTexture->storage(GL_TEXTURE_2D_ARRAY, levels, internalformat, width, height, depth);
- if (error.isError())
- {
- return error;
- }
-
- mImmutableLevelCount = levels;
-
- return Error(GL_NO_ERROR);
-}
-
-bool Texture2DArray::isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const
-{
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei depth = getLayers(0);
-
- if (width <= 0 || height <= 0 || depth <= 0)
- {
- return false;
- }
-
- if (!textureCaps.get(getBaseLevelInternalFormat()).filterable && !IsPointSampled(samplerState))
- {
- return false;
- }
-
- if (IsMipmapFiltered(samplerState) && !isMipmapComplete())
- {
- return false;
- }
-
- return true;
-}
-
-bool Texture2DArray::isMipmapComplete() const
-{
- int levelCount = mipLevels();
-
- for (int level = 1; level < levelCount; level++)
- {
- if (!isLevelComplete(level))
- {
- return false;
- }
- }
-
- return true;
-}
-
-bool Texture2DArray::isLevelComplete(int level) const
-{
- ASSERT(level >= 0 && level < IMPLEMENTATION_MAX_TEXTURE_LEVELS);
-
- if (isImmutable())
- {
- return true;
- }
-
- GLsizei width = getBaseLevelWidth();
- GLsizei height = getBaseLevelHeight();
- GLsizei layers = getLayers(0);
-
- if (width <= 0 || height <= 0 || layers <= 0)
- {
- return false;
- }
-
- if (level == 0)
- {
- return true;
- }
-
- if (getInternalFormat(level) != getInternalFormat(0))
- {
- return false;
- }
-
- if (getWidth(level) != std::max(1, width >> level))
- {
- return false;
- }
-
- if (getHeight(level) != std::max(1, height >> level))
- {
- return false;
- }
-
- if (getLayers(level) != layers)
- {
- return false;
- }
-
- return true;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/Texture.h b/src/3rdparty/angle/src/libGLESv2/Texture.h
deleted file mode 100644
index 66d4df8015..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/Texture.h
+++ /dev/null
@@ -1,241 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Texture.h: Defines the abstract gl::Texture class and its concrete derived
-// classes Texture2D and TextureCubeMap. Implements GL texture objects and
-// related functionality. [OpenGL ES 2.0.24] section 3.7 page 63.
-
-#ifndef LIBGLESV2_TEXTURE_H_
-#define LIBGLESV2_TEXTURE_H_
-
-#include "common/debug.h"
-#include "common/RefCountObject.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/Constants.h"
-#include "libGLESv2/renderer/TextureImpl.h"
-#include "libGLESv2/Caps.h"
-
-#include "angle_gl.h"
-
-#include <vector>
-
-namespace egl
-{
-class Surface;
-}
-
-namespace rx
-{
-class TextureStorageInterface;
-class Image;
-}
-
-namespace gl
-{
-class Framebuffer;
-class FramebufferAttachment;
-struct ImageIndex;
-
-bool IsMipmapFiltered(const gl::SamplerState &samplerState);
-
-class Texture : public RefCountObject
-{
- public:
- Texture(rx::TextureImpl *impl, GLuint id, GLenum target);
-
- virtual ~Texture();
-
- GLenum getTarget() const;
-
- const SamplerState &getSamplerState() const { return mSamplerState; }
- SamplerState &getSamplerState() { return mSamplerState; }
-
- void setUsage(GLenum usage);
- GLenum getUsage() const;
-
- GLint getBaseLevelWidth() const;
- GLint getBaseLevelHeight() const;
- GLint getBaseLevelDepth() const;
- GLenum getBaseLevelInternalFormat() const;
-
- GLsizei getWidth(const ImageIndex &index) const;
- GLsizei getHeight(const ImageIndex &index) const;
- GLenum getInternalFormat(const ImageIndex &index) const;
- GLenum getActualFormat(const ImageIndex &index) const;
-
- virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const = 0;
-
- virtual Error generateMipmaps();
-
- virtual Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
-
- // Texture serials provide a unique way of identifying a Texture that isn't a raw pointer.
- // "id" is not good enough, as Textures can be deleted, then re-allocated with the same id.
- unsigned int getTextureSerial() const;
-
- bool isImmutable() const;
- GLsizei immutableLevelCount();
-
- rx::TextureImpl *getImplementation() { return mTexture; }
- const rx::TextureImpl *getImplementation() const { return mTexture; }
-
- static const GLuint INCOMPLETE_TEXTURE_ID = static_cast<GLuint>(-1); // Every texture takes an id at creation time. The value is arbitrary because it is never registered with the resource manager.
-
- protected:
- int mipLevels() const;
- const rx::Image *getBaseLevelImage() const;
- static unsigned int issueTextureSerial();
-
- rx::TextureImpl *mTexture;
-
- SamplerState mSamplerState;
- GLenum mUsage;
-
- GLsizei mImmutableLevelCount;
-
- GLenum mTarget;
-
- const unsigned int mTextureSerial;
- static unsigned int mCurrentTextureSerial;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Texture);
-};
-
-class Texture2D : public Texture
-{
- public:
- Texture2D(rx::TextureImpl *impl, GLuint id);
-
- virtual ~Texture2D();
-
- GLsizei getWidth(GLint level) const;
- GLsizei getHeight(GLint level) const;
- GLenum getInternalFormat(GLint level) const;
- GLenum getActualFormat(GLint level) const;
- bool isCompressed(GLint level) const;
- bool isDepth(GLint level) const;
-
- Error setImage(GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error subImage(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error copyImage(GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
- Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
-
- virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
- virtual void bindTexImage(egl::Surface *surface);
- virtual void releaseTexImage();
-
- virtual Error generateMipmaps();
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Texture2D);
-
- bool isMipmapComplete() const;
- bool isLevelComplete(int level) const;
-
- egl::Surface *mSurface;
-};
-
-class TextureCubeMap : public Texture
-{
- public:
- TextureCubeMap(rx::TextureImpl *impl, GLuint id);
-
- virtual ~TextureCubeMap();
-
- GLsizei getWidth(GLenum target, GLint level) const;
- GLsizei getHeight(GLenum target, GLint level) const;
- GLenum getInternalFormat(GLenum target, GLint level) const;
- GLenum getActualFormat(GLenum target, GLint level) const;
- bool isCompressed(GLenum target, GLint level) const;
- bool isDepth(GLenum target, GLint level) const;
-
- Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, Framebuffer *source);
- Error storage(GLsizei levels, GLenum internalformat, GLsizei size);
-
- virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
-
- bool isCubeComplete() const;
-
- static int targetToLayerIndex(GLenum target);
- static GLenum layerIndexToTarget(GLint layer);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TextureCubeMap);
-
- bool isMipmapComplete() const;
- bool isFaceLevelComplete(int faceIndex, int level) const;
-};
-
-class Texture3D : public Texture
-{
- public:
- Texture3D(rx::TextureImpl *impl, GLuint id);
-
- virtual ~Texture3D();
-
- GLsizei getWidth(GLint level) const;
- GLsizei getHeight(GLint level) const;
- GLsizei getDepth(GLint level) const;
- GLenum getInternalFormat(GLint level) const;
- GLenum getActualFormat(GLint level) const;
- bool isCompressed(GLint level) const;
- bool isDepth(GLint level) const;
-
- Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-
- virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Texture3D);
-
- bool isMipmapComplete() const;
- bool isLevelComplete(int level) const;
-};
-
-class Texture2DArray : public Texture
-{
- public:
- Texture2DArray(rx::TextureImpl *impl, GLuint id);
-
- virtual ~Texture2DArray();
-
- GLsizei getWidth(GLint level) const;
- GLsizei getHeight(GLint level) const;
- GLsizei getLayers(GLint level) const;
- GLenum getInternalFormat(GLint level) const;
- GLenum getActualFormat(GLint level) const;
- bool isCompressed(GLint level) const;
- bool isDepth(GLint level) const;
-
- Error setImage(GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error setCompressedImage(GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error subImage(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const PixelUnpackState &unpack, const void *pixels);
- Error subImageCompressed(GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const PixelUnpackState &unpack, const void *pixels);
- Error storage(GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
-
- virtual bool isSamplerComplete(const SamplerState &samplerState, const TextureCapsMap &textureCaps, const Extensions &extensions, int clientVersion) const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Texture2DArray);
-
- bool isMipmapComplete() const;
- bool isLevelComplete(int level) const;
-};
-
-}
-
-#endif // LIBGLESV2_TEXTURE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp
new file mode 100644
index 0000000000..a6db1585e7
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.cpp
@@ -0,0 +1,1127 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl.cpp : Implements the EGL entry points.
+
+#include "libGLESv2/entry_points_egl.h"
+#include "libGLESv2/entry_points_egl_ext.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/entry_points_gles_3_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Display.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/validationEGL.h"
+
+#include "common/debug.h"
+#include "common/version.h"
+
+#include <EGL/eglext.h>
+
+namespace egl
+{
+
+// EGL 1.0
+EGLint EGLAPIENTRY GetError(void)
+{
+ EVENT("()");
+
+ EGLint error = GetGlobalError();
+ SetGlobalError(Error(EGL_SUCCESS));
+ return error;
+}
+
+EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id)
+{
+ EVENT("(EGLNativeDisplayType display_id = 0x%0.8p)", display_id);
+
+ return Display::getDisplay(display_id, AttributeMap());
+}
+
+EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint *major = 0x%0.8p, EGLint *minor = 0x%0.8p)",
+ dpy, major, minor);
+
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ SetGlobalError(Error(EGL_BAD_DISPLAY));
+ return EGL_FALSE;
+ }
+
+ Display *display = static_cast<Display*>(dpy);
+
+ Error error = display->initialize();
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (major) *major = 1;
+ if (minor) *minor = 4;
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p)", dpy);
+
+ if (dpy == EGL_NO_DISPLAY)
+ {
+ SetGlobalError(Error(EGL_BAD_DISPLAY));
+ return EGL_FALSE;
+ }
+
+ Display *display = static_cast<Display*>(dpy);
+ gl::Context *context = GetGlobalContext();
+
+ if (display->isValidContext(context))
+ {
+ SetGlobalContext(NULL);
+ SetGlobalDisplay(NULL);
+ }
+
+ display->terminate();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint name = %d)", dpy, name);
+
+ Display *display = static_cast<Display*>(dpy);
+ if (!(display == EGL_NO_DISPLAY && name == EGL_EXTENSIONS))
+ {
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return NULL;
+ }
+ }
+
+ const char *result;
+ switch (name)
+ {
+ case EGL_CLIENT_APIS:
+ result = "OpenGL_ES";
+ break;
+ case EGL_EXTENSIONS:
+ if (display == EGL_NO_DISPLAY)
+ {
+ result = Display::getClientExtensionString().c_str();
+ }
+ else
+ {
+ result = display->getExtensionString().c_str();
+ }
+ break;
+ case EGL_VENDOR:
+ result = display->getVendorString().c_str();
+ break;
+ case EGL_VERSION:
+ result = "1.4 (ANGLE " ANGLE_VERSION_STRING ")";
+ break;
+ default:
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return NULL;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return result;
+}
+
+EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig *configs = 0x%0.8p, "
+ "EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, configs, config_size, num_config);
+
+ Display *display = static_cast<Display*>(dpy);
+
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap());
+ if (configs)
+ {
+ filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
+ for (size_t i = 0; i < filteredConfigs.size(); i++)
+ {
+ configs[i] = const_cast<Config*>(filteredConfigs[i]);
+ }
+ }
+ *num_config = filteredConfigs.size();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p, "
+ "EGLConfig *configs = 0x%0.8p, EGLint config_size = %d, EGLint *num_config = 0x%0.8p)",
+ dpy, attrib_list, configs, config_size, num_config);
+
+ Display *display = static_cast<Display*>(dpy);
+
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (!num_config)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ std::vector<const Config*> filteredConfigs = display->getConfigs(AttributeMap(attrib_list));
+ if (configs)
+ {
+ filteredConfigs.resize(std::min<size_t>(filteredConfigs.size(), config_size));
+ for (size_t i = 0; i < filteredConfigs.size(); i++)
+ {
+ configs[i] = const_cast<Config*>(filteredConfigs[i]);
+ }
+ }
+ *num_config = filteredConfigs.size();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, config, attribute, value);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+
+ Error error = ValidateConfig(display, configuration);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (!display->getConfigAttrib(configuration, attribute, value))
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativeWindowType win = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, win, attrib_list);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+ AttributeMap attributes(attrib_list);
+
+ Error error = ValidateCreateWindowSurface(display, configuration, win, attributes);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ egl::Surface *surface = nullptr;
+ error = display->createWindowSurface(configuration, win, attributes, &surface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ return static_cast<EGLSurface>(surface);
+}
+
+EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, config, attrib_list);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+ AttributeMap attributes(attrib_list);
+
+ Error error = ValidateCreatePbufferSurface(display, configuration, attributes);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ egl::Surface *surface = nullptr;
+ error = display->createPbufferSurface(configuration, attributes, &surface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ return static_cast<EGLSurface>(surface);
+}
+
+EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLNativePixmapType pixmap = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, pixmap, attrib_list);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+
+ Error error = ValidateConfig(display, configuration);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ display->destroySurface((Surface*)surface);
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = (Surface*)surface;
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ switch (attribute)
+ {
+ case EGL_VG_ALPHA_FORMAT:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_VG_COLORSPACE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_CONFIG_ID:
+ *value = eglSurface->getConfig()->configID;
+ break;
+ case EGL_HEIGHT:
+ *value = eglSurface->getHeight();
+ break;
+ case EGL_HORIZONTAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_LARGEST_PBUFFER:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_TEXTURE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MIPMAP_LEVEL:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_MULTISAMPLE_RESOLVE:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_PIXEL_ASPECT_RATIO:
+ *value = eglSurface->getPixelAspectRatio();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = eglSurface->getRenderBuffer();
+ break;
+ case EGL_SWAP_BEHAVIOR:
+ *value = eglSurface->getSwapBehavior();
+ break;
+ case EGL_TEXTURE_FORMAT:
+ *value = eglSurface->getTextureFormat();
+ break;
+ case EGL_TEXTURE_TARGET:
+ *value = eglSurface->getTextureTarget();
+ break;
+ case EGL_VERTICAL_RESOLUTION:
+ UNIMPLEMENTED(); // FIXME
+ break;
+ case EGL_WIDTH:
+ *value = eglSurface->getWidth();
+ break;
+ case EGL_POST_SUB_BUFFER_SUPPORTED_NV:
+ if (!display->getExtensions().postSubBuffer)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+ *value = eglSurface->isPostSubBufferSupported();
+ break;
+ case EGL_FIXED_SIZE_ANGLE:
+ if (!display->getExtensions().windowFixedSize)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+ *value = eglSurface->isFixedSize();
+ break;
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, EGLContext share_context = 0x%0.8p, "
+ "const EGLint *attrib_list = 0x%0.8p)", dpy, config, share_context, attrib_list);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+ gl::Context* sharedGLContext = static_cast<gl::Context*>(share_context);
+ AttributeMap attributes(attrib_list);
+
+ Error error = ValidateCreateContext(display, configuration, sharedGLContext, attributes);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_CONTEXT;
+ }
+
+ gl::Context *context = nullptr;
+ error = display->createContext(configuration, sharedGLContext, attributes, &context);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_CONTEXT;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return static_cast<EGLContext>(context);
+}
+
+EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p)", dpy, ctx);
+
+ Display *display = static_cast<Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+
+ Error error = ValidateContext(display, context);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (ctx == EGL_NO_CONTEXT)
+ {
+ SetGlobalError(Error(EGL_BAD_CONTEXT));
+ return EGL_FALSE;
+ }
+
+ if (context == GetGlobalContext())
+ {
+ SetGlobalDisplay(NULL);
+ SetGlobalContext(NULL);
+ }
+
+ display->destroyContext(context);
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface draw = 0x%0.8p, EGLSurface read = 0x%0.8p, EGLContext ctx = 0x%0.8p)",
+ dpy, draw, read, ctx);
+
+ Display *display = static_cast<Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+
+ bool noContext = (ctx == EGL_NO_CONTEXT);
+ bool noSurface = (draw == EGL_NO_SURFACE || read == EGL_NO_SURFACE);
+ if (noContext != noSurface)
+ {
+ SetGlobalError(Error(EGL_BAD_MATCH));
+ return EGL_FALSE;
+ }
+
+ if (ctx != EGL_NO_CONTEXT)
+ {
+ Error error = ValidateContext(display, context);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+ }
+
+ if (dpy != EGL_NO_DISPLAY && display->isInitialized())
+ {
+ if (display->testDeviceLost())
+ {
+ display->notifyDeviceLost();
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ SetGlobalError(Error(EGL_CONTEXT_LOST));
+ return EGL_FALSE;
+ }
+ }
+
+ Surface *drawSurface = static_cast<Surface*>(draw);
+ if (draw != EGL_NO_SURFACE)
+ {
+ Error error = ValidateSurface(display, drawSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+ }
+
+ Surface *readSurface = static_cast<Surface*>(read);
+ if (read != EGL_NO_SURFACE)
+ {
+ Error error = ValidateSurface(display, readSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+ }
+
+ if (draw != read)
+ {
+ UNIMPLEMENTED(); // FIXME
+ }
+
+ SetGlobalDisplay(display);
+ SetGlobalDrawSurface(drawSurface);
+ SetGlobalReadSurface(readSurface);
+ SetGlobalContext(context);
+
+ if (context != nullptr && display != nullptr && drawSurface != nullptr)
+ {
+ display->makeCurrent(drawSurface, readSurface, context);
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw)
+{
+ EVENT("(EGLint readdraw = %d)", readdraw);
+
+ if (readdraw == EGL_READ)
+ {
+ SetGlobalError(Error(EGL_SUCCESS));
+ return GetGlobalReadSurface();
+ }
+ else if (readdraw == EGL_DRAW)
+ {
+ SetGlobalError(Error(EGL_SUCCESS));
+ return GetGlobalDrawSurface();
+ }
+ else
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_NO_SURFACE;
+ }
+}
+
+EGLDisplay EGLAPIENTRY GetCurrentDisplay(void)
+{
+ EVENT("()");
+
+ EGLDisplay dpy = GetGlobalDisplay();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return dpy;
+}
+
+EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLint attribute = %d, EGLint *value = 0x%0.8p)",
+ dpy, ctx, attribute, value);
+
+ Display *display = static_cast<Display*>(dpy);
+ gl::Context *context = static_cast<gl::Context*>(ctx);
+
+ Error error = ValidateContext(display, context);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ switch (attribute)
+ {
+ case EGL_CONFIG_ID:
+ *value = context->getConfigID();
+ break;
+ case EGL_CONTEXT_CLIENT_TYPE:
+ *value = context->getClientType();
+ break;
+ case EGL_CONTEXT_CLIENT_VERSION:
+ *value = context->getClientVersion();
+ break;
+ case EGL_RENDER_BUFFER:
+ *value = context->getRenderBuffer();
+ break;
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY WaitGL(void)
+{
+ EVENT("()");
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return 0;
+}
+
+EGLBoolean EGLAPIENTRY WaitNative(EGLint engine)
+{
+ EVENT("(EGLint engine = %d)", engine);
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return 0;
+}
+
+EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p)", dpy, surface);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = (Surface*)surface;
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ SetGlobalError(Error(EGL_CONTEXT_LOST));
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ error = eglSurface->swap();
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLNativePixmapType target = 0x%0.8p)", dpy, surface, target);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ SetGlobalError(Error(EGL_CONTEXT_LOST));
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return 0;
+}
+
+// EGL 1.1
+EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ if (eglSurface->getBoundTexture())
+ {
+ SetGlobalError(Error(EGL_BAD_ACCESS));
+ return EGL_FALSE;
+ }
+
+ if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+ {
+ SetGlobalError(Error(EGL_BAD_MATCH));
+ return EGL_FALSE;
+ }
+
+ gl::Context *context = GetGlobalContext();
+ if (context)
+ {
+ gl::Texture *textureObject = context->getTargetTexture(GL_TEXTURE_2D);
+ ASSERT(textureObject != NULL);
+
+ if (textureObject->isImmutable())
+ {
+ SetGlobalError(Error(EGL_BAD_MATCH));
+ return EGL_FALSE;
+ }
+
+ eglSurface->bindTexImage(textureObject, buffer);
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, EGLint value = %d)",
+ dpy, surface, attribute, value);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint buffer = %d)", dpy, surface, buffer);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (buffer != EGL_BACK_BUFFER)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE || eglSurface->getType() == EGL_WINDOW_BIT)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ if (eglSurface->getTextureFormat() == EGL_NO_TEXTURE)
+ {
+ SetGlobalError(Error(EGL_BAD_MATCH));
+ return EGL_FALSE;
+ }
+
+ gl::Texture *texture = eglSurface->getBoundTexture();
+
+ if (texture)
+ {
+ eglSurface->releaseTexImage(buffer);
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLint interval = %d)", dpy, interval);
+
+ Display *display = static_cast<Display*>(dpy);
+
+ Error error = ValidateDisplay(display);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ Surface *draw_surface = static_cast<Surface*>(GetGlobalDrawSurface());
+
+ if (draw_surface == NULL)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ const egl::Config *surfaceConfig = draw_surface->getConfig();
+ EGLint clampedInterval = std::min(std::max(interval, surfaceConfig->minSwapInterval), surfaceConfig->maxSwapInterval);
+
+ draw_surface->setSwapInterval(clampedInterval);
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+
+// EGL 1.2
+EGLBoolean EGLAPIENTRY BindAPI(EGLenum api)
+{
+ EVENT("(EGLenum api = 0x%X)", api);
+
+ switch (api)
+ {
+ case EGL_OPENGL_API:
+ case EGL_OPENVG_API:
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE; // Not supported by this implementation
+ case EGL_OPENGL_ES_API:
+ break;
+ default:
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ SetGlobalAPI(api);
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLenum EGLAPIENTRY QueryAPI(void)
+{
+ EVENT("()");
+
+ EGLenum API = GetGlobalAPI();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return API;
+}
+
+EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum buftype = 0x%X, EGLClientBuffer buffer = 0x%0.8p, "
+ "EGLConfig config = 0x%0.8p, const EGLint *attrib_list = 0x%0.8p)",
+ dpy, buftype, buffer, config, attrib_list);
+
+ Display *display = static_cast<Display*>(dpy);
+ Config *configuration = static_cast<Config*>(config);
+ AttributeMap attributes(attrib_list);
+
+ Error error = ValidateCreatePbufferFromClientBuffer(display, buftype, buffer, configuration, attributes);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ egl::Surface *surface = nullptr;
+ error = display->createPbufferFromClientBuffer(configuration, buffer, attributes, &surface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_NO_SURFACE;
+ }
+
+ return static_cast<EGLSurface>(surface);
+}
+
+EGLBoolean EGLAPIENTRY ReleaseThread(void)
+{
+ EVENT("()");
+
+ MakeCurrent(EGL_NO_DISPLAY, EGL_NO_CONTEXT, EGL_NO_SURFACE, EGL_NO_SURFACE);
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+EGLBoolean EGLAPIENTRY WaitClient(void)
+{
+ EVENT("()");
+
+ UNIMPLEMENTED(); // FIXME
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return 0;
+}
+
+// EGL 1.4
+EGLContext EGLAPIENTRY GetCurrentContext(void)
+{
+ EVENT("()");
+
+ gl::Context *context = GetGlobalContext();
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return static_cast<EGLContext>(context);
+}
+
+// EGL 1.5
+EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLenum type = 0x%X, const EGLint* attrib_list = 0x%0.8p)", dpy, type, attrib_list);
+
+ UNIMPLEMENTED();
+ return EGL_NO_SYNC;
+}
+
+EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p)", dpy, sync);
+
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X, EGLTime timeout = %d)", dpy, sync, flags, timeout);
+
+ UNIMPLEMENTED();
+ return 0;
+}
+
+EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint attribute = 0x%X, EGLAttrib *value = 0x%0.8p)", dpy, sync, attribute, value);
+
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLContext ctx = 0x%0.8p, EGLenum target = 0x%X, "
+ "EGLClientBuffer buffer = 0x%0.8p, const EGLAttrib *attrib_list = 0x%0.8p)",
+ dpy, ctx, target, buffer, attrib_list);
+
+ UNIMPLEMENTED();
+ return EGL_NO_IMAGE;
+}
+
+EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLImage image = 0x%0.8p)", dpy, image);
+
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
+ platform, native_display, attrib_list);
+
+ UNIMPLEMENTED();
+ return EGL_NO_DISPLAY;
+}
+
+EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_window = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
+ dpy, config, native_window, attrib_list);
+
+ UNIMPLEMENTED();
+ return EGL_NO_SURFACE;
+}
+
+EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLConfig config = 0x%0.8p, void* native_pixmap = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
+ dpy, config, native_pixmap, attrib_list);
+
+ UNIMPLEMENTED();
+ return EGL_NO_SURFACE;
+}
+
+EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSync sync = 0x%0.8p, EGLint flags = 0x%X)", dpy, sync, flags);
+
+ UNIMPLEMENTED();
+ return EGL_FALSE;
+}
+
+__eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname)
+{
+ EVENT("(const char *procname = \"%s\")", procname);
+
+ struct Extension
+ {
+ const char *name;
+ __eglMustCastToProperFunctionPointerType address;
+ };
+
+ static const Extension extensions[] =
+ {
+ { "eglQuerySurfacePointerANGLE", (__eglMustCastToProperFunctionPointerType)QuerySurfacePointerANGLE },
+ { "eglPostSubBufferNV", (__eglMustCastToProperFunctionPointerType)PostSubBufferNV },
+ { "eglGetPlatformDisplayEXT", (__eglMustCastToProperFunctionPointerType)GetPlatformDisplayEXT },
+ { "glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)gl::BlitFramebufferANGLE },
+ { "glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)gl::RenderbufferStorageMultisampleANGLE },
+ { "glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)gl::DeleteFencesNV },
+ { "glGenFencesNV", (__eglMustCastToProperFunctionPointerType)gl::GenFencesNV },
+ { "glIsFenceNV", (__eglMustCastToProperFunctionPointerType)gl::IsFenceNV },
+ { "glTestFenceNV", (__eglMustCastToProperFunctionPointerType)gl::TestFenceNV },
+ { "glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)gl::GetFenceivNV },
+ { "glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)gl::FinishFenceNV },
+ { "glSetFenceNV", (__eglMustCastToProperFunctionPointerType)gl::SetFenceNV },
+ { "glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)gl::GetTranslatedShaderSourceANGLE },
+ { "glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)gl::TexStorage2DEXT },
+ { "glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)gl::GetGraphicsResetStatusEXT },
+ { "glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)gl::ReadnPixelsEXT },
+ { "glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformfvEXT },
+ { "glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetnUniformivEXT },
+ { "glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::GenQueriesEXT },
+ { "glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)gl::DeleteQueriesEXT },
+ { "glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::IsQueryEXT },
+ { "glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::BeginQueryEXT },
+ { "glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)gl::EndQueryEXT },
+ { "glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryivEXT },
+ { "glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)gl::GetQueryObjectuivEXT },
+ { "glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)gl::DrawBuffersEXT },
+ { "glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)gl::VertexAttribDivisorANGLE },
+ { "glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawArraysInstancedANGLE },
+ { "glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)gl::DrawElementsInstancedANGLE },
+ { "glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::GetProgramBinaryOES },
+ { "glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)gl::ProgramBinaryOES },
+ { "glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)gl::GetBufferPointervOES },
+ { "glMapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::MapBufferOES },
+ { "glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)gl::UnmapBufferOES },
+ { "glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::MapBufferRangeEXT },
+ { "glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)gl::FlushMappedBufferRangeEXT },
+ { "", NULL },
+ };
+
+ for (const Extension *extension = &extensions[0]; extension->address != nullptr; extension++)
+ {
+ if (strcmp(procname, extension->name) == 0)
+ {
+ return reinterpret_cast<__eglMustCastToProperFunctionPointerType>(extension->address);
+ }
+ }
+
+ return NULL;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h
new file mode 100644
index 0000000000..259a209684
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl.h
@@ -0,0 +1,74 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl.h : Defines the EGL entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSEGL_H_
+#define LIBGLESV2_ENTRYPOINTSEGL_H_
+
+#include <EGL/egl.h>
+#include <export.h>
+
+namespace egl
+{
+
+// EGL 1.0
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ChooseConfig(EGLDisplay dpy, const EGLint *attrib_list, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY CopyBuffers(EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target);
+ANGLE_EXPORT EGLContext EGLAPIENTRY CreateContext(EGLDisplay dpy, EGLConfig config, EGLContext share_context, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePixmapSurface(EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, const EGLint *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreateWindowSurface(EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyContext(EGLDisplay dpy, EGLContext ctx);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySurface(EGLDisplay dpy, EGLSurface surface);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigAttrib(EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetConfigs(EGLDisplay dpy, EGLConfig *configs, EGLint config_size, EGLint *num_config);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetCurrentDisplay(void);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY GetCurrentSurface(EGLint readdraw);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetDisplay(EGLNativeDisplayType display_id);
+ANGLE_EXPORT EGLint EGLAPIENTRY GetError(void);
+ANGLE_EXPORT __eglMustCastToProperFunctionPointerType EGLAPIENTRY GetProcAddress(const char *procname);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY Initialize(EGLDisplay dpy, EGLint *major, EGLint *minor);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY MakeCurrent(EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QueryContext(EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint *value);
+ANGLE_EXPORT const char *EGLAPIENTRY QueryString(EGLDisplay dpy, EGLint name);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurface(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint *value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapBuffers(EGLDisplay dpy, EGLSurface surface);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY Terminate(EGLDisplay dpy);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitGL(void);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitNative(EGLint engine);
+
+// EGL 1.1
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseTexImage(EGLDisplay dpy, EGLSurface surface, EGLint buffer);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY SwapInterval(EGLDisplay dpy, EGLint interval);
+
+// EGL 1.2
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY BindAPI(EGLenum api);
+ANGLE_EXPORT EGLenum EGLAPIENTRY QueryAPI(void);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePbufferFromClientBuffer(EGLDisplay dpy, EGLenum buftype, EGLClientBuffer buffer, EGLConfig config, const EGLint *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY ReleaseThread(void);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitClient(void);
+
+// EGL 1.4
+ANGLE_EXPORT EGLContext EGLAPIENTRY GetCurrentContext(void);
+
+// EGL 1.5
+ANGLE_EXPORT EGLSync EGLAPIENTRY CreateSync(EGLDisplay dpy, EGLenum type, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroySync(EGLDisplay dpy, EGLSync sync);
+ANGLE_EXPORT EGLint EGLAPIENTRY ClientWaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags, EGLTime timeout);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY GetSyncAttrib(EGLDisplay dpy, EGLSync sync, EGLint attribute, EGLAttrib *value);
+ANGLE_EXPORT EGLImage EGLAPIENTRY CreateImage(EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY DestroyImage(EGLDisplay dpy, EGLImage image);
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplay(EGLenum platform, void *native_display, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformWindowSurface(EGLDisplay dpy, EGLConfig config, void *native_window, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLSurface EGLAPIENTRY CreatePlatformPixmapSurface(EGLDisplay dpy, EGLConfig config, void *native_pixmap, const EGLAttrib *attrib_list);
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY WaitSync(EGLDisplay dpy, EGLSync sync, EGLint flags);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTSEGL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
new file mode 100644
index 0000000000..ded73dbb48
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp
@@ -0,0 +1,271 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_ext.cpp : Implements the EGL extension entry points.
+
+#include "libGLESv2/entry_points_egl_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Display.h"
+#include "libANGLE/Surface.h"
+#include "libANGLE/validationEGL.h"
+
+#include "common/debug.h"
+
+namespace egl
+{
+
+// EGL_ANGLE_query_surface_pointer
+EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint attribute = %d, void **value = 0x%0.8p)",
+ dpy, surface, attribute, value);
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (!display->getExtensions().querySurfacePointer)
+ {
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ // validate the attribute parameter
+ switch (attribute)
+ {
+ case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
+ if (!display->getExtensions().surfaceD3DTexture2DShareHandle)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+ break;
+
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_FALSE;
+ }
+
+ error = eglSurface->querySurfacePointerANGLE(attribute, value);
+ SetGlobalError(error);
+ return (error.isError() ? EGL_FALSE : EGL_TRUE);
+}
+
+
+// EGL_NV_post_sub_buffer
+EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height)
+{
+ EVENT("(EGLDisplay dpy = 0x%0.8p, EGLSurface surface = 0x%0.8p, EGLint x = %d, EGLint y = %d, EGLint width = %d, EGLint height = %d)", dpy, surface, x, y, width, height);
+
+ if (x < 0 || y < 0 || width < 0 || height < 0)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_FALSE;
+ }
+
+ Display *display = static_cast<Display*>(dpy);
+ Surface *eglSurface = static_cast<Surface*>(surface);
+
+ Error error = ValidateSurface(display, eglSurface);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ if (display->isDeviceLost())
+ {
+ SetGlobalError(Error(EGL_CONTEXT_LOST));
+ return EGL_FALSE;
+ }
+
+ if (surface == EGL_NO_SURFACE)
+ {
+ SetGlobalError(Error(EGL_BAD_SURFACE));
+ return EGL_FALSE;
+ }
+
+ if (!display->getExtensions().postSubBuffer)
+ {
+ // Spec is not clear about how this should be handled.
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+ }
+
+ error = eglSurface->postSubBuffer(x, y, width, height);
+ if (error.isError())
+ {
+ SetGlobalError(error);
+ return EGL_FALSE;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+ return EGL_TRUE;
+}
+
+// EGL_EXT_platform_base
+EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list)
+{
+ EVENT("(EGLenum platform = %d, void* native_display = 0x%0.8p, const EGLint* attrib_list = 0x%0.8p)",
+ platform, native_display, attrib_list);
+
+ const ClientExtensions &clientExtensions = Display::getClientExtensions();
+
+ switch (platform)
+ {
+ case EGL_PLATFORM_ANGLE_ANGLE:
+ if (!clientExtensions.platformANGLE)
+ {
+ SetGlobalError(Error(EGL_BAD_PARAMETER));
+ return EGL_NO_DISPLAY;
+ }
+ break;
+
+ default:
+ SetGlobalError(Error(EGL_BAD_CONFIG));
+ return EGL_NO_DISPLAY;
+ }
+
+ EGLint platformType = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE;
+ EGLint deviceType = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE;
+ bool majorVersionSpecified = false;
+ bool minorVersionSpecified = false;
+ bool enableAutoTrimSpecified = false;
+
+ if (attrib_list)
+ {
+ for (const EGLint *curAttrib = attrib_list; curAttrib[0] != EGL_NONE; curAttrib += 2)
+ {
+ switch (curAttrib[0])
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_ANGLE:
+ switch (curAttrib[1])
+ {
+ case EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE:
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE:
+ if (!clientExtensions.platformANGLED3D)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGL_ANGLE:
+ case EGL_PLATFORM_ANGLE_TYPE_OPENGLES_ANGLE:
+ if (!clientExtensions.platformANGLEOpenGL)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+ break;
+
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+ platformType = curAttrib[1];
+ break;
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE:
+ if (curAttrib[1] != EGL_DONT_CARE)
+ {
+ majorVersionSpecified = true;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE:
+ if (curAttrib[1] != EGL_DONT_CARE)
+ {
+ minorVersionSpecified = true;
+ }
+ break;
+
+ case EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE:
+ switch (curAttrib[1])
+ {
+ case EGL_TRUE:
+ case EGL_FALSE:
+ break;
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+ enableAutoTrimSpecified = true;
+ break;
+
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE:
+ if (!clientExtensions.platformANGLED3D)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+
+ switch (curAttrib[1])
+ {
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_REFERENCE_ANGLE:
+ case EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE:
+ break;
+
+ default:
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+ deviceType = curAttrib[1];
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!majorVersionSpecified && minorVersionSpecified)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE));
+ return EGL_NO_DISPLAY;
+ }
+
+ if (deviceType == EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE requires a device type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
+ return EGL_NO_DISPLAY;
+ }
+
+ if (enableAutoTrimSpecified &&
+ platformType != EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
+ {
+ SetGlobalError(Error(EGL_BAD_ATTRIBUTE, "EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE requires a device type of "
+ "EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE."));
+ return EGL_NO_DISPLAY;
+ }
+
+ SetGlobalError(Error(EGL_SUCCESS));
+
+ EGLNativeDisplayType displayId = static_cast<EGLNativeDisplayType>(native_display);
+ return Display::getDisplay(displayId, AttributeMap(attrib_list));
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h
new file mode 100644
index 0000000000..9de1027082
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.h
@@ -0,0 +1,30 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_egl_ext.h : Defines the EGL extension entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTSEGLEXT_H_
+#define LIBGLESV2_ENTRYPOINTSEGLEXT_H_
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <export.h>
+
+namespace egl
+{
+
+// EGL_ANGLE_query_surface_pointer
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surface, EGLint attribute, void **value);
+
+// EGL_NV_post_sub_buffer
+ANGLE_EXPORT EGLBoolean EGLAPIENTRY PostSubBufferNV(EGLDisplay dpy, EGLSurface surface, EGLint x, EGLint y, EGLint width, EGLint height);
+
+// EGL_EXT_platform_base
+ANGLE_EXPORT EGLDisplay EGLAPIENTRY GetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTSEGLEXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp
new file mode 100644
index 0000000000..6d3089ba4f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.cpp
@@ -0,0 +1,4318 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0.cpp : Implements the GLES 2.0 entry points.
+
+#include "libGLESv2/entry_points_gles_2_0.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Compiler.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Renderbuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Program.h"
+#include "libANGLE/Texture.h"
+#include "libANGLE/VertexArray.h"
+#include "libANGLE/VertexAttribute.h"
+#include "libANGLE/FramebufferAttachment.h"
+
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/queryconversions.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+#include "common/version.h"
+
+namespace gl
+{
+
+void GL_APIENTRY ActiveTexture(GLenum texture)
+{
+ EVENT("(GLenum texture = 0x%X)", texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->getState().setActiveSampler(texture - GL_TEXTURE0);
+ }
+}
+
+void GL_APIENTRY AttachShader(GLuint program, GLuint shader)
+{
+ EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (!programObject->attachShader(shaderObject))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name)
+{
+ EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (strncmp(name, "gl_", 3) == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ programObject->bindAttributeLocation(index, name);
+ }
+}
+
+void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_ARRAY_BUFFER:
+ context->bindArrayBuffer(buffer);
+ return;
+ case GL_ELEMENT_ARRAY_BUFFER:
+ context->bindElementArrayBuffer(buffer);
+ return;
+ case GL_COPY_READ_BUFFER:
+ context->bindCopyReadBuffer(buffer);
+ return;
+ case GL_COPY_WRITE_BUFFER:
+ context->bindCopyWriteBuffer(buffer);
+ return;
+ case GL_PIXEL_PACK_BUFFER:
+ context->bindPixelPackBuffer(buffer);
+ return;
+ case GL_PIXEL_UNPACK_BUFFER:
+ context->bindPixelUnpackBuffer(buffer);
+ return;
+ case GL_UNIFORM_BUFFER:
+ context->bindGenericUniformBuffer(buffer);
+ return;
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ return;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidFramebufferTarget(target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+ {
+ context->bindReadFramebuffer(framebuffer);
+ }
+
+ if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
+ {
+ context->bindDrawFramebuffer(framebuffer);
+ }
+ }
+}
+
+void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (target != GL_RENDERBUFFER)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->bindRenderbuffer(renderbuffer);
+ }
+}
+
+void GL_APIENTRY BindTexture(GLenum target, GLuint texture)
+{
+ EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Texture *textureObject = context->getTexture(texture);
+
+ if (textureObject && textureObject->getTarget() != target && texture != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TEXTURE_2D:
+ case GL_TEXTURE_CUBE_MAP:
+ break;
+
+ case GL_TEXTURE_3D:
+ case GL_TEXTURE_2D_ARRAY:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->bindTexture(target, texture);
+ }
+}
+
+void GL_APIENTRY BlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ red, green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha));
+ }
+}
+
+void GL_APIENTRY BlendEquation(GLenum mode)
+{
+ BlendEquationSeparate(mode, mode);
+}
+
+void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
+{
+ EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (modeRGB)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ case GL_MIN:
+ case GL_MAX:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (modeAlpha)
+ {
+ case GL_FUNC_ADD:
+ case GL_FUNC_SUBTRACT:
+ case GL_FUNC_REVERSE_SUBTRACT:
+ case GL_MIN:
+ case GL_MAX:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->getState().setBlendEquation(modeRGB, modeAlpha);
+ }
+}
+
+void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor)
+{
+ BlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+}
+
+void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
+{
+ EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
+ srcRGB, dstRGB, srcAlpha, dstAlpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (srcRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (dstRGB)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ break;
+
+ case GL_SRC_ALPHA_SATURATE:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (srcAlpha)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ case GL_SRC_ALPHA_SATURATE:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (dstAlpha)
+ {
+ case GL_ZERO:
+ case GL_ONE:
+ case GL_SRC_COLOR:
+ case GL_ONE_MINUS_SRC_COLOR:
+ case GL_DST_COLOR:
+ case GL_ONE_MINUS_DST_COLOR:
+ case GL_SRC_ALPHA:
+ case GL_ONE_MINUS_SRC_ALPHA:
+ case GL_DST_ALPHA:
+ case GL_ONE_MINUS_DST_ALPHA:
+ case GL_CONSTANT_COLOR:
+ case GL_ONE_MINUS_CONSTANT_COLOR:
+ case GL_CONSTANT_ALPHA:
+ case GL_ONE_MINUS_CONSTANT_ALPHA:
+ break;
+
+ case GL_SRC_ALPHA_SATURATE:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
+ dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
+
+ bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
+ dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
+
+ if (constantColorUsed && constantAlphaUsed)
+ {
+ ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
+ }
+}
+
+void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
+{
+ EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
+ target, size, data, usage);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (size < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (usage)
+ {
+ case GL_STREAM_DRAW:
+ case GL_STATIC_DRAW:
+ case GL_DYNAMIC_DRAW:
+ break;
+
+ case GL_STREAM_READ:
+ case GL_STREAM_COPY:
+ case GL_STATIC_READ:
+ case GL_STATIC_COPY:
+ case GL_DYNAMIC_READ:
+ case GL_DYNAMIC_COPY:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Error error = buffer->bufferData(data, size, usage);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
+ target, offset, size, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (size < 0 || offset < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (data == NULL)
+ {
+ return;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Check for possible overflow of size + offset
+ if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset))
+ {
+ context->recordError(Error(GL_OUT_OF_MEMORY));
+ return;
+ }
+
+ if (size + offset > buffer->getSize())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Error error = buffer->bufferSubData(data, size, offset);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidFramebufferTarget(target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return 0;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ return framebuffer->checkStatus(context->getData());
+ }
+
+ return 0;
+}
+
+void GL_APIENTRY Clear(GLbitfield mask)
+{
+ EVENT("(GLbitfield mask = 0x%X)", mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ if (framebufferObject->checkStatus(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_FRAMEBUFFER_OPERATION));
+ return;
+ }
+
+ if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Error error = framebufferObject->clear(context->getData(), mask);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+{
+ EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
+ red, green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setColorClearValue(red, green, blue, alpha);
+ }
+}
+
+void GL_APIENTRY ClearDepthf(GLclampf depth)
+{
+ EVENT("(GLclampf depth = %f)", depth);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setDepthClearValue(depth);
+ }
+}
+
+void GL_APIENTRY ClearStencil(GLint s)
+{
+ EVENT("(GLint s = %d)", s);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setStencilClearValue(s);
+ }
+}
+
+void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
+{
+ EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
+ red, green, blue, alpha);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
+ }
+}
+
+void GL_APIENTRY CompileShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %d)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ shaderObject->compile(context->getCompiler());
+ }
+}
+
+void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
+ GLint border, GLsizei imageSize, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, border, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, width, height, border, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Extents size(width, height, 1);
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(data));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
+ "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true,
+ xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
+ xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(data));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
+ target, level, internalformat, x, y, width, height, border);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false,
+ 0, 0, x, y, width, height, border))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false,
+ 0, 0, 0, x, y, width, height, border))
+ {
+ return;
+ }
+
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->copyImage(target, level, sourceArea, internalformat, framebuffer);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true,
+ xoffset, yoffset, x, y, width, height, 0))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true,
+ xoffset, yoffset, 0, x, y, width, height, 0))
+ {
+ return;
+ }
+
+ Offset destOffset(xoffset, yoffset, 0);
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+GLuint GL_APIENTRY CreateProgram(void)
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ return context->createProgram();
+ }
+
+ return 0;
+}
+
+GLuint GL_APIENTRY CreateShader(GLenum type)
+{
+ EVENT("(GLenum type = 0x%X)", type);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (type)
+ {
+ case GL_FRAGMENT_SHADER:
+ case GL_VERTEX_SHADER:
+ return context->createShader(type);
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+void GL_APIENTRY CullFace(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (mode)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->getState().setCullMode(mode);
+ }
+}
+
+void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteBuffer(buffers[i]);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (framebuffers[i] != 0)
+ {
+ context->deleteFramebuffer(framebuffers[i]);
+ }
+ }
+ }
+}
+
+void GL_APIENTRY DeleteProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (program == 0)
+ {
+ return;
+ }
+
+ if (!context->getProgram(program))
+ {
+ if(context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ context->deleteProgram(program);
+ }
+}
+
+void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
+{
+ EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteRenderbuffer(renderbuffers[i]);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %d)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (shader == 0)
+ {
+ return;
+ }
+
+ if (!context->getShader(shader))
+ {
+ if(context->getProgram(shader))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ context->deleteShader(shader);
+ }
+}
+
+void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures)
+{
+ EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ if (textures[i] != 0)
+ {
+ context->deleteTexture(textures[i]);
+ }
+ }
+ }
+}
+
+void GL_APIENTRY DepthFunc(GLenum func)
+{
+ EVENT("(GLenum func = 0x%X)", func);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GREATER:
+ case GL_GEQUAL:
+ case GL_NOTEQUAL:
+ context->getState().setDepthFunc(func);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DepthMask(GLboolean flag)
+{
+ EVENT("(GLboolean flag = %u)", flag);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setDepthMask(flag != GL_FALSE);
+ }
+}
+
+void GL_APIENTRY DepthRangef(GLclampf zNear, GLclampf zFar)
+{
+ EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setDepthRange(zNear, zFar);
+ }
+}
+
+void GL_APIENTRY DetachShader(GLuint program, GLuint shader)
+{
+ EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!programObject)
+ {
+ Shader *shaderByProgramHandle;
+ shaderByProgramHandle = context->getShader(program);
+ if (!shaderByProgramHandle)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+
+ if (!shaderObject)
+ {
+ Program *programByShaderHandle = context->getProgram(shader);
+ if (!programByShaderHandle)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+
+ if (!programObject->detachShader(shaderObject))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY Disable(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidCap(context, cap))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->getState().setEnableFeature(cap, false);
+ }
+}
+
+void GL_APIENTRY DisableVertexAttribArray(GLuint index)
+{
+ EVENT("(GLuint index = %d)", index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setEnableVertexAttribArray(index, false);
+ }
+}
+
+void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateDrawArrays(context, mode, first, count, 0))
+ {
+ return;
+ }
+
+ Error error = context->drawArrays(mode, first, count, 0);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
+{
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
+ mode, count, type, indices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
+ {
+ return;
+ }
+
+ Error error = context->drawElements(mode, count, type, indices, 0, indexRange);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY Enable(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidCap(context, cap))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ context->getState().setEnableFeature(cap, true);
+ }
+}
+
+void GL_APIENTRY EnableVertexAttribArray(GLuint index)
+{
+ EVENT("(GLuint index = %d)", index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setEnableVertexAttribArray(index, true);
+ }
+}
+
+void GL_APIENTRY Finish(void)
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Error error = context->finish();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY Flush(void)
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Error error = context->flush();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
+{
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
+ "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer))
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (renderbuffer != 0)
+ {
+ Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
+ framebuffer->setRenderbufferAttachment(attachment, renderbufferObject);
+ }
+ else
+ {
+ framebuffer->setNULLAttachment(attachment);
+ }
+ }
+}
+
+void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
+{
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
+ "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObj = context->getTexture(texture);
+
+ ImageIndex index = ImageIndex::MakeInvalid();
+
+ if (textarget == GL_TEXTURE_2D)
+ {
+ index = ImageIndex::Make2D(level);
+ }
+ else
+ {
+ ASSERT(IsCubeMapTextureTarget(textarget));
+ index = ImageIndex::MakeCube(textarget, level);
+ }
+
+ framebuffer->setTextureAttachment(attachment, textureObj, index);
+ }
+ else
+ {
+ framebuffer->setNULLAttachment(attachment);
+ }
+ }
+}
+
+void GL_APIENTRY FrontFace(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (mode)
+ {
+ case GL_CW:
+ case GL_CCW:
+ context->getState().setFrontFace(mode);
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers)
+{
+ EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ buffers[i] = context->createBuffer();
+ }
+ }
+}
+
+void GL_APIENTRY GenerateMipmap(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidTextureTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+
+ if (texture == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ GLenum baseTarget = (target == GL_TEXTURE_CUBE_MAP) ? GL_TEXTURE_CUBE_MAP_POSITIVE_X : target;
+ GLenum internalFormat = texture->getInternalFormat(baseTarget, 0);
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalFormat);
+
+ // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
+ // unsized formats or that are color renderable and filterable. Since we do not track if
+ // the texture was created with sized or unsized format (only sized formats are stored),
+ // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
+ // be able to) because they aren't color renderable. Simply do a special case for LUMA
+ // textures since they're the only texture format that can be created with unsized formats
+ // that is not color renderable. New unsized formats are unlikely to be added, since ES2
+ // was the last version to use add them.
+ bool isLUMA = internalFormat == GL_LUMINANCE8_EXT ||
+ internalFormat == GL_LUMINANCE8_ALPHA8_EXT ||
+ internalFormat == GL_ALPHA8_EXT;
+
+ if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable ||
+ (!formatCaps.renderable && !isLUMA) || formatInfo.compressed)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // GL_EXT_sRGB does not support mipmap generation on sRGB textures
+ if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Non-power of 2 ES2 check
+ if (!context->getExtensions().textureNPOT && (!isPow2(texture->getWidth(baseTarget, 0)) || !isPow2(texture->getHeight(baseTarget, 0))))
+ {
+ ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Cube completeness check
+ if (target == GL_TEXTURE_CUBE_MAP && !texture->isCubeComplete())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Error error = texture->generateMipmaps();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers)
+{
+ EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ framebuffers[i] = context->createFramebuffer();
+ }
+ }
+}
+
+void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+{
+ EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ renderbuffers[i] = context->createRenderbuffer();
+ }
+ }
+}
+
+void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures)
+{
+ EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ textures[i] = context->createTexture();
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
+{
+ EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
+ "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
+ program, index, bufsize, length, size, type, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (index >= (GLuint)programObject->getActiveAttributeCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getActiveAttribute(index, bufsize, length, size, type, name);
+ }
+}
+
+void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
+{
+ EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
+ "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+ program, index, bufsize, length, size, type, name);
+
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (index >= (GLuint)programObject->getActiveUniformCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getActiveUniform(index, bufsize, length, size, type, name);
+ }
+}
+
+void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
+{
+ EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
+ program, maxcount, count, shaders);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (maxcount < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ return programObject->getAttachedShaders(maxcount, count, shaders);
+ }
+}
+
+GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name)
+{
+ EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return -1;
+ }
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+
+ return programObject->getAttributeLocation(name);
+ }
+
+ return -1;
+}
+
+void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_BOOL)
+ {
+ context->getBooleanv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!ValidBufferParameter(context, pname))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = static_cast<GLint>(buffer->getUsage());
+ break;
+ case GL_BUFFER_SIZE:
+ *params = clampCast<GLint>(buffer->getSize());
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = buffer->getAccessFlags();
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = static_cast<GLint>(buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = clampCast<GLint>(buffer->getMapOffset());
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = clampCast<GLint>(buffer->getMapLength());
+ break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+GLenum GL_APIENTRY GetError(void)
+{
+ EVENT("()");
+
+ Context *context = GetGlobalContext();
+
+ if (context)
+ {
+ return context->getError();
+ }
+
+ return GL_NO_ERROR;
+}
+
+void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_FLOAT)
+ {
+ context->getFloatv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ target, attachment, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidFramebufferTarget(target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ int clientVersion = context->getClientVersion();
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ if (clientVersion < 3 && !context->getExtensions().sRGB)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (clientVersion < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ // Determine if the attachment is a valid enum
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_FRONT:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (clientVersion < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ default:
+ if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
+ (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->id() == 0)
+ {
+ if (clientVersion < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (attachment)
+ {
+ case GL_BACK:
+ case GL_DEPTH:
+ case GL_STENCIL:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ else
+ {
+ if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
+ {
+ // Valid attachment query
+ }
+ else
+ {
+ switch (attachment)
+ {
+ case GL_DEPTH_ATTACHMENT:
+ case GL_STENCIL_ATTACHMENT:
+ break;
+
+ case GL_DEPTH_STENCIL_ATTACHMENT:
+ if (framebuffer->hasValidDepthStencil())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ }
+
+ const FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
+ if (attachmentObject)
+ {
+ ASSERT(attachmentObject->type() == GL_RENDERBUFFER ||
+ attachmentObject->type() == GL_TEXTURE ||
+ attachmentObject->type() == GL_FRAMEBUFFER_DEFAULT);
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = attachmentObject->type();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (attachmentObject->type() != GL_RENDERBUFFER && attachmentObject->type() != GL_TEXTURE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = attachmentObject->id();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = attachmentObject->mipLevel();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = attachmentObject->cubeMapFace();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
+ *params = attachmentObject->getRedSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
+ *params = attachmentObject->getGreenSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
+ *params = attachmentObject->getBlueSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
+ *params = attachmentObject->getAlphaSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
+ *params = attachmentObject->getDepthSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
+ *params = attachmentObject->getStencilSize();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
+ if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ *params = attachmentObject->getComponentType();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
+ *params = attachmentObject->getColorEncoding();
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
+ if (attachmentObject->type() != GL_TEXTURE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = attachmentObject->layer();
+ break;
+
+ default:
+ UNREACHABLE();
+ break;
+ }
+ }
+ else
+ {
+ // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
+ // is NONE, then querying any other pname will generate INVALID_ENUM.
+
+ // ES 3.0.2 spec pg 235 states that if the attachment type is none,
+ // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
+ // INVALID_OPERATION for all other pnames
+
+ switch (pname)
+ {
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
+ *params = GL_NONE;
+ break;
+
+ case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
+ if (clientVersion < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = 0;
+ break;
+
+ default:
+ if (clientVersion < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_INT)
+ {
+ context->getIntegerv(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (context->getClientVersion() < 3)
+ {
+ switch (pname)
+ {
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+
+ switch (pname)
+ {
+ case GL_DELETE_STATUS:
+ *params = programObject->isFlaggedForDeletion();
+ return;
+ case GL_LINK_STATUS:
+ *params = programObject->isLinked();
+ return;
+ case GL_VALIDATE_STATUS:
+ *params = programObject->isValidated();
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = programObject->getInfoLogLength();
+ return;
+ case GL_ATTACHED_SHADERS:
+ *params = programObject->getAttachedShadersCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = programObject->getActiveAttributeCount();
+ return;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = programObject->getActiveAttributeMaxLength();
+ return;
+ case GL_ACTIVE_UNIFORMS:
+ *params = programObject->getActiveUniformCount();
+ return;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = programObject->getActiveUniformMaxLength();
+ return;
+ case GL_PROGRAM_BINARY_LENGTH_OES:
+ *params = programObject->getBinaryLength();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCKS:
+ *params = programObject->getActiveUniformBlockCount();
+ return;
+ case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
+ *params = programObject->getActiveUniformBlockMaxLength();
+ break;
+ case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
+ *params = programObject->getTransformFeedbackBufferMode();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYINGS:
+ *params = programObject->getTransformFeedbackVaryingCount();
+ break;
+ case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
+ *params = programObject->getTransformFeedbackVaryingMaxLength();
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+ EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ program, bufsize, length, infolog);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getInfoLog(bufsize, length, infolog);
+ }
+}
+
+void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (target != GL_RENDERBUFFER)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (context->getState().getRenderbufferId() == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId());
+
+ switch (pname)
+ {
+ case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
+ case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
+ case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
+ case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
+ case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
+ case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
+ case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
+ case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
+ case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
+
+ case GL_RENDERBUFFER_SAMPLES_ANGLE:
+ if (!context->getExtensions().framebufferMultisample)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = renderbuffer->getSamples();
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_SHADER_TYPE:
+ *params = shaderObject->getType();
+ return;
+ case GL_DELETE_STATUS:
+ *params = shaderObject->isFlaggedForDeletion();
+ return;
+ case GL_COMPILE_STATUS:
+ *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
+ return;
+ case GL_INFO_LOG_LENGTH:
+ *params = shaderObject->getInfoLogLength();
+ return;
+ case GL_SHADER_SOURCE_LENGTH:
+ *params = shaderObject->getSourceLength();
+ return;
+ case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
+ *params = shaderObject->getTranslatedSourceLength();
+ return;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
+{
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
+ shader, bufsize, length, infolog);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ shaderObject->getInfoLog(bufsize, length, infolog);
+ }
+}
+
+void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
+{
+ EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
+ shadertype, precisiontype, range, precision);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (shadertype)
+ {
+ case GL_VERTEX_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ context->getCaps().vertexLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ context->getCaps().vertexMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ context->getCaps().vertexHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ context->getCaps().vertexLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ context->getCaps().vertexMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ context->getCaps().vertexHighpInt.get(range, precision);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+ case GL_FRAGMENT_SHADER:
+ switch (precisiontype)
+ {
+ case GL_LOW_FLOAT:
+ context->getCaps().fragmentLowpFloat.get(range, precision);
+ break;
+ case GL_MEDIUM_FLOAT:
+ context->getCaps().fragmentMediumpFloat.get(range, precision);
+ break;
+ case GL_HIGH_FLOAT:
+ context->getCaps().fragmentHighpFloat.get(range, precision);
+ break;
+
+ case GL_LOW_INT:
+ context->getCaps().fragmentLowpInt.get(range, precision);
+ break;
+ case GL_MEDIUM_INT:
+ context->getCaps().fragmentMediumpInt.get(range, precision);
+ break;
+ case GL_HIGH_INT:
+ context->getCaps().fragmentHighpInt.get(range, precision);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ }
+}
+
+void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+ shader, bufsize, length, source);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ shaderObject->getSource(bufsize, length, source);
+ }
+}
+
+const GLubyte *GL_APIENTRY GetString(GLenum name)
+{
+ EVENT("(GLenum name = 0x%X)", name);
+
+ Context *context = GetValidGlobalContext();
+
+ switch (name)
+ {
+ case GL_VENDOR:
+ return (GLubyte*)"Google Inc.";
+
+ case GL_RENDERER:
+ return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE");
+
+ case GL_VERSION:
+ if (context->getClientVersion() == 2)
+ {
+ return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+ else
+ {
+ return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+
+ case GL_SHADING_LANGUAGE_VERSION:
+ if (context->getClientVersion() == 2)
+ {
+ return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+ else
+ {
+ return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")";
+ }
+
+ case GL_EXTENSIONS:
+ return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : "");
+
+ default:
+ if (context)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ }
+ return NULL;
+ }
+}
+
+void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Texture *texture = context->getTargetTexture(target);
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = (GLfloat)texture->getSamplerState().magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = (GLfloat)texture->getSamplerState().minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = (GLfloat)texture->getSamplerState().wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = (GLfloat)texture->getSamplerState().wrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().wrapR;
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
+ *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->immutableLevelCount();
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = (GLfloat)texture->getUsage();
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().maxAnisotropy;
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleRed;
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleGreen;
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleBlue;
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().swizzleAlpha;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLfloat)texture->getSamplerState().maxLevel;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().maxLod;
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Texture *texture = context->getTargetTexture(target);
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_MAG_FILTER:
+ *params = texture->getSamplerState().magFilter;
+ break;
+ case GL_TEXTURE_MIN_FILTER:
+ *params = texture->getSamplerState().minFilter;
+ break;
+ case GL_TEXTURE_WRAP_S:
+ *params = texture->getSamplerState().wrapS;
+ break;
+ case GL_TEXTURE_WRAP_T:
+ *params = texture->getSamplerState().wrapT;
+ break;
+ case GL_TEXTURE_WRAP_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().wrapR;
+ break;
+ case GL_TEXTURE_IMMUTABLE_FORMAT:
+ // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
+ *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
+ break;
+ case GL_TEXTURE_IMMUTABLE_LEVELS:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = static_cast<GLint>(texture->immutableLevelCount());
+ break;
+ case GL_TEXTURE_USAGE_ANGLE:
+ *params = texture->getUsage();
+ break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT:
+ if (!context->getExtensions().textureFilterAnisotropic)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().maxAnisotropy;
+ break;
+ case GL_TEXTURE_SWIZZLE_R:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleRed;
+ break;
+ case GL_TEXTURE_SWIZZLE_G:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleGreen;
+ break;
+ case GL_TEXTURE_SWIZZLE_B:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleBlue;
+ break;
+ case GL_TEXTURE_SWIZZLE_A:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().swizzleAlpha;
+ break;
+ case GL_TEXTURE_BASE_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().baseLevel;
+ break;
+ case GL_TEXTURE_MAX_LEVEL:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = texture->getSamplerState().maxLevel;
+ break;
+ case GL_TEXTURE_MIN_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().minLod;
+ break;
+ case GL_TEXTURE_MAX_LOD:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ *params = (GLint)texture->getSamplerState().maxLod;
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGetUniformfv(context, program, location, params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformfv(location, params);
+ }
+}
+
+void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGetUniformiv(context, program, location, params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformiv(location, params);
+ }
+}
+
+GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name)
+{
+ EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (strstr(name, "gl_") == name)
+ {
+ return -1;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return -1;
+ }
+ }
+
+ if (!programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+
+ return programObject->getUniformLocation(name);
+ }
+
+ return -1;
+}
+
+void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
+{
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
+ {
+ params[i] = currentValueData.FloatValues[i];
+ }
+ }
+ else
+ {
+ const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
+ *params = QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
+ {
+ float currentValue = currentValueData.FloatValues[i];
+ params[i] = iround<GLint>(currentValue);
+ }
+ }
+ else
+ {
+ const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
+ *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
+{
+ EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index));
+ }
+}
+
+void GL_APIENTRY Hint(GLenum target, GLenum mode)
+{
+ EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (mode)
+ {
+ case GL_FASTEST:
+ case GL_NICEST:
+ case GL_DONT_CARE:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_GENERATE_MIPMAP_HINT:
+ context->getState().setGenerateMipmapHint(mode);
+ break;
+
+ case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
+ context->getState().setFragmentShaderDerivativeHint(mode);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsBuffer(GLuint buffer)
+{
+ EVENT("(GLuint buffer = %d)", buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context && buffer)
+ {
+ Buffer *bufferObject = context->getBuffer(buffer);
+
+ if (bufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsEnabled(GLenum cap)
+{
+ EVENT("(GLenum cap = 0x%X)", cap);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidCap(context, cap))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return GL_FALSE;
+ }
+
+ return context->getState().getEnableFeature(cap);
+ }
+
+ return false;
+}
+
+GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer)
+{
+ EVENT("(GLuint framebuffer = %d)", framebuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context && framebuffer)
+ {
+ Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
+
+ if (framebufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context && program)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (programObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer)
+{
+ EVENT("(GLuint renderbuffer = %d)", renderbuffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context && renderbuffer)
+ {
+ Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
+
+ if (renderbufferObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsShader(GLuint shader)
+{
+ EVENT("(GLuint shader = %d)", shader);
+
+ Context *context = GetValidGlobalContext();
+ if (context && shader)
+ {
+ Shader *shaderObject = context->getShader(shader);
+
+ if (shaderObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsTexture(GLuint texture)
+{
+ EVENT("(GLuint texture = %d)", texture);
+
+ Context *context = GetValidGlobalContext();
+ if (context && texture)
+ {
+ Texture *textureObject = context->getTexture(texture);
+
+ if (textureObject)
+ {
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY LineWidth(GLfloat width)
+{
+ EVENT("(GLfloat width = %f)", width);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (width <= 0.0f)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setLineWidth(width);
+ }
+}
+
+void GL_APIENTRY LinkProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ Error error = programObject->link(context->getData());
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY PixelStorei(GLenum pname, GLint param)
+{
+ EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ switch (pname)
+ {
+ case GL_UNPACK_IMAGE_HEIGHT:
+ case GL_UNPACK_SKIP_IMAGES:
+ case GL_UNPACK_ROW_LENGTH:
+ case GL_UNPACK_SKIP_ROWS:
+ case GL_UNPACK_SKIP_PIXELS:
+ case GL_PACK_ROW_LENGTH:
+ case GL_PACK_SKIP_ROWS:
+ case GL_PACK_SKIP_PIXELS:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+
+ if (param < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE, "Cannot use negative values in PixelStorei"));
+ return;
+ }
+
+ State &state = context->getState();
+
+ switch (pname)
+ {
+ case GL_UNPACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ state.setUnpackAlignment(param);
+ break;
+
+ case GL_PACK_ALIGNMENT:
+ if (param != 1 && param != 2 && param != 4 && param != 8)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ state.setPackAlignment(param);
+ break;
+
+ case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
+ state.setPackReverseRowOrder(param != 0);
+ break;
+
+ case GL_UNPACK_ROW_LENGTH:
+ ASSERT(context->getClientVersion() >= 3);
+ state.setUnpackRowLength(param);
+ break;
+
+ case GL_UNPACK_IMAGE_HEIGHT:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getUnpackState().imageHeight = param;
+ break;
+
+ case GL_UNPACK_SKIP_IMAGES:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getUnpackState().skipImages = param;
+ break;
+
+ case GL_UNPACK_SKIP_ROWS:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getUnpackState().skipRows = param;
+ break;
+
+ case GL_UNPACK_SKIP_PIXELS:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getUnpackState().skipPixels = param;
+ break;
+
+ case GL_PACK_ROW_LENGTH:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getPackState().rowLength = param;
+ break;
+
+ case GL_PACK_SKIP_ROWS:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getPackState().skipRows = param;
+ break;
+
+ case GL_PACK_SKIP_PIXELS:
+ ASSERT(context->getClientVersion() >= 3);
+ state.getPackState().skipPixels = param;
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units)
+{
+ EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ context->getState().setPolygonOffsetParams(factor, units);
+ }
+}
+
+void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid* pixels)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
+ x, y, width, height, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (width < 0 || height < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateReadPixelsParameters(context, x, y, width, height,
+ format, type, NULL, pixels))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getReadFramebuffer();
+ ASSERT(framebufferObject);
+
+ Rectangle area(x, y, width, height);
+ Error error = framebufferObject->readPixels(context->getState(), area, format, type, pixels);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ReleaseShaderCompiler(void)
+{
+ EVENT("()");
+
+ Context *context = GetValidGlobalContext();
+
+ if (context)
+ {
+ Compiler *compiler = context->getCompiler();
+ Error error = compiler->release();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateRenderbufferStorageParametersANGLE(context, target, 0, internalformat,
+ width, height))
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+ Error error = renderbuffer->setStorage(internalformat, width, height);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY SampleCoverage(GLclampf value, GLboolean invert)
+{
+ EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
+
+ Context* context = GetValidGlobalContext();
+
+ if (context)
+ {
+ context->getState().setSampleCoverageParams(clamp01(value), invert == GL_TRUE);
+ }
+}
+
+void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+ Context* context = GetValidGlobalContext();
+ if (context)
+ {
+ if (width < 0 || height < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setScissorParams(x, y, width, height);
+ }
+}
+
+void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
+{
+ EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
+ "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
+ n, shaders, binaryformat, binary, length);
+
+ Context* context = GetValidGlobalContext();
+ if (context)
+ {
+ const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
+ if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end())
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ // No binary shader formats are supported.
+ UNIMPLEMENTED();
+ }
+}
+
+void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
+{
+ EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
+ shader, count, string, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ if (context->getProgram(shader))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ shaderObject->setSource(count, string, length);
+ }
+}
+
+void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask)
+{
+ StencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+}
+
+void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
+{
+ EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (func)
+ {
+ case GL_NEVER:
+ case GL_ALWAYS:
+ case GL_LESS:
+ case GL_LEQUAL:
+ case GL_EQUAL:
+ case GL_GEQUAL:
+ case GL_GREATER:
+ case GL_NOTEQUAL:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilParams(func, ref, mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackParams(func, ref, mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilMask(GLuint mask)
+{
+ StencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+}
+
+void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask)
+{
+ EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilWritemask(mask);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackWritemask(mask);
+ }
+ }
+}
+
+void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass)
+{
+ StencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+}
+
+void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
+{
+ EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
+ face, fail, zfail, zpass);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ switch (face)
+ {
+ case GL_FRONT:
+ case GL_BACK:
+ case GL_FRONT_AND_BACK:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (fail)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (zfail)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (zpass)
+ {
+ case GL_ZERO:
+ case GL_KEEP:
+ case GL_REPLACE:
+ case GL_INCR:
+ case GL_DECR:
+ case GL_INVERT:
+ case GL_INCR_WRAP:
+ case GL_DECR_WRAP:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilOperations(fail, zfail, zpass);
+ }
+
+ if (face == GL_BACK || face == GL_FRONT_AND_BACK)
+ {
+ context->getState().setStencilBackOperations(fail, zfail, zpass);
+ }
+ }
+}
+
+void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
+ GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, border, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, width, height, border, format, type, pixels))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, 0, width, height, 1, border, format, type, pixels))
+ {
+ return;
+ }
+
+ Extents size(width, height, 1);
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(pixels));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = uiround<GLenum>(param); break;
+ case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = uiround<GLenum>(param); break;
+ case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = uiround<GLenum>(param); break;
+ case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = uiround<GLenum>(param); break;
+ case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = uiround<GLenum>(param); break;
+ case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(uiround<GLenum>(param)); break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min(param, context->getExtensions().maxTextureAnisotropy); break;
+ case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = uiround<GLenum>(param); break;
+ case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = uiround<GLenum>(param); break;
+ case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = uiround<GLenum>(param); break;
+ case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = iround<GLint>(param); break;
+ case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = iround<GLint>(param); break;
+ case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break;
+ case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
+{
+ TexParameterf(target, pname, (GLfloat)*params);
+}
+
+void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateTexParamParameters(context, pname, param))
+ {
+ return;
+ }
+
+ Texture *texture = context->getTargetTexture(target);
+
+ if (!texture)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break;
+ case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break;
+ case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break;
+ case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break;
+ case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break;
+ case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break;
+ case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break;
+ case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break;
+ case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break;
+ case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break;
+ case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break;
+ case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break;
+ case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break;
+ case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params)
+{
+ TexParameteri(target, pname, *params);
+}
+
+void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
+ "const GLvoid* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, width, height, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, width, height, 0, format, type, pixels))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ Box area(xoffset, yoffset, 0, width, height, 1);
+ Texture *texture = context->getTargetTexture(IsCubeMapTextureTarget(target) ? GL_TEXTURE_CUBE_MAP : target);
+ Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(pixels));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY Uniform1f(GLint location, GLfloat x)
+{
+ Uniform1fv(location, 1, &x);
+}
+
+void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform1fv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform1i(GLint location, GLint x)
+{
+ Uniform1iv(location, 1, &x);
+}
+
+void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform1iv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y)
+{
+ GLfloat xy[2] = {x, y};
+
+ Uniform2fv(location, 1, xy);
+}
+
+void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform2fv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y)
+{
+ GLint xy[2] = {x, y};
+
+ Uniform2iv(location, 1, xy);
+}
+
+void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC2, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform2iv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
+{
+ GLfloat xyz[3] = {x, y, z};
+
+ Uniform3fv(location, 1, xyz);
+}
+
+void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform3fv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z)
+{
+ GLint xyz[3] = {x, y, z};
+
+ Uniform3iv(location, 1, xyz);
+}
+
+void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC3, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform3iv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ GLfloat xyzw[4] = {x, y, z, w};
+
+ Uniform4fv(location, 1, xyzw);
+}
+
+void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform4fv(location, count, v);
+ }
+}
+
+void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
+{
+ GLint xyzw[4] = {x, y, z, w};
+
+ Uniform4iv(location, 1, xyzw);
+}
+
+void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_INT_VEC4, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform4iv(location, count, v);
+ }
+}
+
+void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix2fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix3fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix4fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UseProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject && program != 0)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (program != 0 && !programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->useProgram(program);
+ }
+}
+
+void GL_APIENTRY ValidateProgram(GLuint program)
+{
+ EVENT("(GLuint program = %d)", program);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ programObject->validate(context->getCaps());
+ }
+}
+
+void GL_APIENTRY VertexAttrib1f(GLuint index, GLfloat x)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, 0, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib1fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], 0, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib2fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], values[1], 0, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, z, 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib3fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { values[0], values[1], values[2], 1 };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLfloat vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribf(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttrib4fv(GLuint index, const GLfloat* values)
+{
+ EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setVertexAttribf(index, values);
+ }
+}
+
+void GL_APIENTRY VertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
+{
+ EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
+ "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
+ index, size, type, normalized, stride, ptr);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (size < 1 || size > 4)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_FIXED:
+ case GL_FLOAT:
+ break;
+
+ case GL_HALF_FLOAT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (stride < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type,
+ normalized == GL_TRUE, false, stride, ptr);
+ }
+}
+
+void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (width < 0 || height < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setViewportParams(x, y, width, height);
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h
new file mode 100644
index 0000000000..eee5fb5468
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0.h
@@ -0,0 +1,163 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0.h : Defines the GLES 2.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES20_H_
+#define LIBGLESV2_ENTRYPOINTGLES20_H_
+
+#include <GLES2/gl2.h>
+#include <export.h>
+
+namespace gl
+{
+
+ANGLE_EXPORT void GL_APIENTRY ActiveTexture(GLenum texture);
+ANGLE_EXPORT void GL_APIENTRY AttachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY BindAttribLocation(GLuint program, GLuint index, const GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY BindBuffer(GLenum target, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY BindFramebuffer(GLenum target, GLuint framebuffer);
+ANGLE_EXPORT void GL_APIENTRY BindRenderbuffer(GLenum target, GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY BindTexture(GLenum target, GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY BlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY BlendEquation(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY BlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha);
+ANGLE_EXPORT void GL_APIENTRY BlendFunc(GLenum sfactor, GLenum dfactor);
+ANGLE_EXPORT void GL_APIENTRY BlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha);
+ANGLE_EXPORT void GL_APIENTRY BufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage);
+ANGLE_EXPORT void GL_APIENTRY BufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data);
+ANGLE_EXPORT GLenum GL_APIENTRY CheckFramebufferStatus(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY Clear(GLbitfield mask);
+ANGLE_EXPORT void GL_APIENTRY ClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+ANGLE_EXPORT void GL_APIENTRY ClearDepthf(GLfloat depth);
+ANGLE_EXPORT void GL_APIENTRY ClearStencil(GLint s);
+ANGLE_EXPORT void GL_APIENTRY ColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+ANGLE_EXPORT void GL_APIENTRY CompileShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data);
+ANGLE_EXPORT void GL_APIENTRY CopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateProgram(void);
+ANGLE_EXPORT GLuint GL_APIENTRY CreateShader(GLenum type);
+ANGLE_EXPORT void GL_APIENTRY CullFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY DeleteBuffers(GLsizei n, const GLuint* buffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteFramebuffers(GLsizei n, const GLuint* framebuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY DeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY DeleteShader(GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY DeleteTextures(GLsizei n, const GLuint* textures);
+ANGLE_EXPORT void GL_APIENTRY DepthFunc(GLenum func);
+ANGLE_EXPORT void GL_APIENTRY DepthMask(GLboolean flag);
+ANGLE_EXPORT void GL_APIENTRY DepthRangef(GLfloat n, GLfloat f);
+ANGLE_EXPORT void GL_APIENTRY DetachShader(GLuint program, GLuint shader);
+ANGLE_EXPORT void GL_APIENTRY Disable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY DisableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY DrawArrays(GLenum mode, GLint first, GLsizei count);
+ANGLE_EXPORT void GL_APIENTRY DrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices);
+ANGLE_EXPORT void GL_APIENTRY Enable(GLenum cap);
+ANGLE_EXPORT void GL_APIENTRY EnableVertexAttribArray(GLuint index);
+ANGLE_EXPORT void GL_APIENTRY Finish(void);
+ANGLE_EXPORT void GL_APIENTRY Flush(void);
+ANGLE_EXPORT void GL_APIENTRY FramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer);
+ANGLE_EXPORT void GL_APIENTRY FramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level);
+ANGLE_EXPORT void GL_APIENTRY FrontFace(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY GenBuffers(GLsizei n, GLuint* buffers);
+ANGLE_EXPORT void GL_APIENTRY GenerateMipmap(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GenFramebuffers(GLsizei n, GLuint* framebuffers);
+ANGLE_EXPORT void GL_APIENTRY GenRenderbuffers(GLsizei n, GLuint* renderbuffers);
+ANGLE_EXPORT void GL_APIENTRY GenTextures(GLsizei n, GLuint* textures);
+ANGLE_EXPORT void GL_APIENTRY GetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY GetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders);
+ANGLE_EXPORT GLint GL_APIENTRY GetAttribLocation(GLuint program, const GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY GetBooleanv(GLenum pname, GLboolean* params);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteriv(GLenum target, GLenum pname, GLint* params);
+ANGLE_EXPORT GLenum GL_APIENTRY GetError(void);
+ANGLE_EXPORT void GL_APIENTRY GetFloatv(GLenum pname, GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY GetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetIntegerv(GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramiv(GLuint program, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+ANGLE_EXPORT void GL_APIENTRY GetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderiv(GLuint shader, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog);
+ANGLE_EXPORT void GL_APIENTRY GetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision);
+ANGLE_EXPORT void GL_APIENTRY GetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetString(GLenum name);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameterfv(GLenum target, GLenum pname, GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY GetTexParameteriv(GLenum target, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformfv(GLuint program, GLint location, GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY GetUniformiv(GLuint program, GLint location, GLint* params);
+ANGLE_EXPORT GLint GL_APIENTRY GetUniformLocation(GLuint program, const GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribiv(GLuint index, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer);
+ANGLE_EXPORT void GL_APIENTRY Hint(GLenum target, GLenum mode);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsBuffer(GLuint buffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsEnabled(GLenum cap);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsFramebuffer(GLuint framebuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsProgram(GLuint program);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsRenderbuffer(GLuint renderbuffer);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsShader(GLuint shader);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTexture(GLuint texture);
+ANGLE_EXPORT void GL_APIENTRY LineWidth(GLfloat width);
+ANGLE_EXPORT void GL_APIENTRY LinkProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY PixelStorei(GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY PolygonOffset(GLfloat factor, GLfloat units);
+ANGLE_EXPORT void GL_APIENTRY ReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels);
+ANGLE_EXPORT void GL_APIENTRY ReleaseShaderCompiler(void);
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY SampleCoverage(GLfloat value, GLboolean invert);
+ANGLE_EXPORT void GL_APIENTRY Scissor(GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY ShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length);
+ANGLE_EXPORT void GL_APIENTRY StencilFunc(GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMask(GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilMaskSeparate(GLenum face, GLuint mask);
+ANGLE_EXPORT void GL_APIENTRY StencilOp(GLenum fail, GLenum zfail, GLenum zpass);
+ANGLE_EXPORT void GL_APIENTRY StencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass);
+ANGLE_EXPORT void GL_APIENTRY TexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ANGLE_EXPORT void GL_APIENTRY TexParameterf(GLenum target, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY TexParameterfv(GLenum target, GLenum pname, const GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY TexParameteri(GLenum target, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY TexParameteriv(GLenum target, GLenum pname, const GLint* params);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels);
+ANGLE_EXPORT void GL_APIENTRY Uniform1f(GLint location, GLfloat x);
+ANGLE_EXPORT void GL_APIENTRY Uniform1fv(GLint location, GLsizei count, const GLfloat* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform1i(GLint location, GLint x);
+ANGLE_EXPORT void GL_APIENTRY Uniform1iv(GLint location, GLsizei count, const GLint* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform2f(GLint location, GLfloat x, GLfloat y);
+ANGLE_EXPORT void GL_APIENTRY Uniform2fv(GLint location, GLsizei count, const GLfloat* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform2i(GLint location, GLint x, GLint y);
+ANGLE_EXPORT void GL_APIENTRY Uniform2iv(GLint location, GLsizei count, const GLint* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z);
+ANGLE_EXPORT void GL_APIENTRY Uniform3fv(GLint location, GLsizei count, const GLfloat* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform3i(GLint location, GLint x, GLint y, GLint z);
+ANGLE_EXPORT void GL_APIENTRY Uniform3iv(GLint location, GLsizei count, const GLint* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ANGLE_EXPORT void GL_APIENTRY Uniform4fv(GLint location, GLsizei count, const GLfloat* v);
+ANGLE_EXPORT void GL_APIENTRY Uniform4i(GLint location, GLint x, GLint y, GLint z, GLint w);
+ANGLE_EXPORT void GL_APIENTRY Uniform4iv(GLint location, GLsizei count, const GLint* v);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UseProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY ValidateProgram(GLuint program);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1f(GLuint indx, GLfloat x);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib1fv(GLuint indx, const GLfloat* values);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib2fv(GLuint indx, const GLfloat* values);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib3fv(GLuint indx, const GLfloat* values);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttrib4fv(GLuint indx, const GLfloat* values);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr);
+ANGLE_EXPORT void GL_APIENTRY Viewport(GLint x, GLint y, GLsizei width, GLsizei height);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTGLES20_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
new file mode 100644
index 0000000000..8be6ae7d2f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.cpp
@@ -0,0 +1,1058 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0_ext.cpp : Implements the GLES 2.0 extension entry points.
+
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Shader.h"
+#include "libANGLE/Query.h"
+
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES2.h"
+#include "libANGLE/validationES3.h"
+
+#include "common/debug.h"
+#include "common/utilities.h"
+
+namespace gl
+{
+
+void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateBeginQuery(context, target, id))
+ {
+ return;
+ }
+
+ Error error = context->beginQuery(target, id);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences)
+{
+ EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteFenceNV(fences[i]);
+ }
+ }
+}
+
+void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteQuery(ids[i]);
+ }
+ }
+}
+
+void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount))
+ {
+ return;
+ }
+
+ Error error = context->drawArrays(mode, first, count, primcount);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
+{
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
+ mode, count, type, indices, primcount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange))
+ {
+ return;
+ }
+
+ Error error = context->drawElements(mode, count, type, indices, primcount, indexRange);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY EndQueryEXT(GLenum target)
+{
+ EVENT("GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateEndQuery(context, target))
+ {
+ return;
+ }
+
+ Error error = context->endQuery(target);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY FinishFenceNV(GLuint fence)
+{
+ EVENT("(GLuint fence = %d)", fence);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ fenceObject->finishFence();
+ }
+}
+
+void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences)
+{
+ EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ fences[i] = context->createFenceNV();
+ }
+ }
+}
+
+void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (GLsizei i = 0; i < n; i++)
+ {
+ ids[i] = context->createQuery();
+ }
+ }
+}
+
+void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+ EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_FENCE_STATUS_NV:
+ {
+ // GL_NV_fence spec:
+ // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
+ // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
+ GLboolean status = GL_TRUE;
+ if (fenceObject->getStatus() != GL_TRUE)
+ {
+ Error error = fenceObject->testFence(&status);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ *params = status;
+ break;
+ }
+
+ case GL_FENCE_CONDITION_NV:
+ {
+ *params = static_cast<GLint>(fenceObject->getCondition());
+ break;
+ }
+
+ default:
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+ }
+}
+
+GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void)
+{
+ EVENT("()");
+
+ Context *context = GetGlobalContext();
+
+ if (context)
+ {
+ return context->getResetStatus();
+ }
+
+ return GL_NO_ERROR;
+}
+
+void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY_EXT:
+ params[0] = context->getState().getActiveQueryId(target);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
+{
+ EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (context->getState().getActiveQueryId(queryObject->getType()) == id)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch(pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ {
+ Error error = queryObject->getResult(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ break;
+
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ {
+ Error error = queryObject->isResultAvailable(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
+{
+ EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
+ shader, bufsize, length, source);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (bufsize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Shader *shaderObject = context->getShader(shader);
+
+ if (!shaderObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined
+ shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source);
+ }
+}
+
+void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
+ program, location, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformfv(location, params);
+ }
+}
+
+void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
+{
+ EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
+ program, location, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformiv(location, params);
+ }
+}
+
+GLboolean GL_APIENTRY IsFenceNV(GLuint fence)
+{
+ EVENT("(GLuint fence = %d)", fence);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == NULL)
+ {
+ return GL_FALSE;
+ }
+
+ return fenceObject->isFence();
+ }
+
+ return GL_FALSE;
+}
+
+GLboolean GL_APIENTRY IsQueryEXT(GLuint id)
+{
+ EVENT("(GLuint id = %d)", id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLsizei bufSize,
+ GLvoid *data)
+{
+ EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
+ x, y, width, height, format, type, bufSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (width < 0 || height < 0 || bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateReadPixelsParameters(context, x, y, width, height,
+ format, type, &bufSize, data))
+ {
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getReadFramebuffer();
+ ASSERT(framebufferObject);
+
+ Rectangle area(x, y, width, height);
+ Error error = framebufferObject->readPixels(context->getState(), area, format, type, data);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, samples, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateRenderbufferStorageParametersANGLE(context, target, samples, internalformat,
+ width, height))
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+ Error error = renderbuffer->setStorageMultisample(samples, internalformat, width, height);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition)
+{
+ EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (condition != GL_ALL_COMPLETED_NV)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Error error = fenceObject->setFence(condition);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+GLboolean GL_APIENTRY TestFenceNV(GLuint fence)
+{
+ EVENT("(GLuint fence = %d)", fence);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ FenceNV *fenceObject = context->getFenceNV(fence);
+
+ if (fenceObject == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_TRUE;
+ }
+
+ if (fenceObject->isFence() != GL_TRUE)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_TRUE;
+ }
+
+ GLboolean result;
+ Error error = fenceObject->testFence(&result);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return GL_TRUE;
+ }
+
+ return result;
+ }
+
+ return GL_TRUE;
+}
+
+void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!context->getExtensions().textureStorage)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (context->getClientVersion() < 3 &&
+ !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height))
+ {
+ return;
+ }
+
+ if (context->getClientVersion() >= 3 &&
+ !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
+ {
+ return;
+ }
+
+ Extents size(width, height, 1);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setStorage(target, levels, internalformat, size);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->setVertexAttribDivisor(index, divisor);
+ }
+}
+
+void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter)
+{
+ EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
+ "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
+ "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ true))
+ {
+ return;
+ }
+
+ Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ ASSERT(readFramebuffer);
+
+ Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+ ASSERT(drawFramebuffer);
+
+ Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+ Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+ Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY TexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
+ GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
+ "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+ UNIMPLEMENTED(); // FIXME
+}
+
+void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, void *binary)
+{
+ EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
+ program, bufSize, length, binaryFormat, binary);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Error error = programObject->saveBinary(binaryFormat, binary, bufSize, length);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const void *binary, GLint length)
+{
+ EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
+ program, binaryFormat, binary, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
+ if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end())
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ if (!programObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Error error = programObject->loadBinary(binaryFormat, binary, length);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs)
+{
+ EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ ASSERT(context->getState().getDrawFramebuffer());
+
+ if (context->getState().getDrawFramebuffer()->id() == 0)
+ {
+ if (n != 1)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ else
+ {
+ for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
+ {
+ const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
+ if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ }
+ }
+
+ Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
+ ASSERT(framebuffer);
+
+ framebuffer->setDrawBuffers(n, bufs);
+ }
+}
+
+void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, void** params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (pname != GL_BUFFER_MAP_POINTER)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer || !buffer->isMapped())
+ {
+ *params = NULL;
+ }
+ else
+ {
+ *params = buffer->getMapPointer();
+ }
+ }
+}
+
+void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access)
+{
+ EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if (access != GL_WRITE_ONLY_OES)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (buffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return NULL;
+ }
+
+ return buffer->getMapPointer();
+ }
+
+ return NULL;
+}
+
+GLboolean GL_APIENTRY UnmapBufferOES(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return GL_FALSE;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL || !buffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ // TODO: detect if we had corruption. if so, throw an error and return false.
+
+ Error error = buffer->unmap();
+ if (error.isError())
+ {
+ context->recordError(error);
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+ }
+
+ return GL_FALSE;
+}
+
+void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
+ target, offset, length, access);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (offset < 0 || length < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ // Check for buffer overflow
+ size_t offsetSize = static_cast<size_t>(offset);
+ size_t lengthSize = static_cast<size_t>(length);
+
+ if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
+ offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ // Check for invalid bits in the mask
+ GLbitfield allAccessBits = GL_MAP_READ_BIT |
+ GL_MAP_WRITE_BIT |
+ GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_INVALIDATE_BUFFER_BIT |
+ GL_MAP_FLUSH_EXPLICIT_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if (access & ~(allAccessBits))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ if (length == 0 || buffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ // Check for invalid bit combinations
+ if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT |
+ GL_MAP_INVALIDATE_BUFFER_BIT |
+ GL_MAP_UNSYNCHRONIZED_BIT;
+
+ if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ Error error = buffer->mapRange(offset, length, access);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return NULL;
+ }
+
+ return buffer->getMapPointer();
+ }
+
+ return NULL;
+}
+
+void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (offset < 0 || length < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (buffer == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Check for buffer overflow
+ size_t offsetSize = static_cast<size_t>(offset);
+ size_t lengthSize = static_cast<size_t>(length);
+
+ if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
+ offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // We do not currently support a non-trivial implementation of FlushMappedBufferRange
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
new file mode 100644
index 0000000000..816519fe1f
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_2_0_ext.h
@@ -0,0 +1,78 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_2_0_ext.h : Defines the GLES 2.0 extension entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES20EXT_H_
+#define LIBGLESV2_ENTRYPOINTGLES20EXT_H_
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <export.h>
+
+namespace gl
+{
+
+// GL_ANGLE_framebuffer_blit
+ANGLE_EXPORT void GL_APIENTRY BlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+
+// GL_ANGLE_framebuffer_multisample
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+
+// GL_NV_fence
+ANGLE_EXPORT void GL_APIENTRY DeleteFencesNV(GLsizei n, const GLuint* fences);
+ANGLE_EXPORT void GL_APIENTRY GenFencesNV(GLsizei n, GLuint* fences);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsFenceNV(GLuint fence);
+ANGLE_EXPORT GLboolean GL_APIENTRY TestFenceNV(GLuint fence);
+ANGLE_EXPORT void GL_APIENTRY GetFenceivNV(GLuint fence, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY FinishFenceNV(GLuint fence);
+ANGLE_EXPORT void GL_APIENTRY SetFenceNV(GLuint fence, GLenum condition);
+
+// GL_ANGLE_translated_shader_source
+ANGLE_EXPORT void GL_APIENTRY GetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source);
+
+// GL_EXT_texture_storage
+ANGLE_EXPORT void GL_APIENTRY TexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+
+// GL_EXT_robustness
+ANGLE_EXPORT GLenum GL_APIENTRY GetGraphicsResetStatusEXT(void);
+ANGLE_EXPORT void GL_APIENTRY ReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params);
+ANGLE_EXPORT void GL_APIENTRY GetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params);
+
+// GL_EXT_occlusion_query_boolean
+ANGLE_EXPORT void GL_APIENTRY GenQueriesEXT(GLsizei n, GLuint *ids);
+ANGLE_EXPORT void GL_APIENTRY DeleteQueriesEXT(GLsizei n, const GLuint *ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsQueryEXT(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY BeginQueryEXT(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY EndQueryEXT(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryivEXT(GLenum target, GLenum pname, GLint *params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params);
+
+// GL_EXT_draw_buffers
+ANGLE_EXPORT void GL_APIENTRY DrawBuffersEXT(GLsizei n, const GLenum *bufs);
+
+// GL_ANGLE_instanced_arrays
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisorANGLE(GLuint index, GLuint divisor);
+
+// GL_OES_get_program_binary
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length);
+
+// GL_OES_mapbuffer
+ANGLE_EXPORT void *GL_APIENTRY MapBufferOES(GLenum target, GLenum access);
+ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBufferOES(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params);
+
+// GL_EXT_map_buffer_range
+ANGLE_EXPORT void *GL_APIENTRY MapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTGLES20EXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp
new file mode 100644
index 0000000000..d8bdcd2e50
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.cpp
@@ -0,0 +1,3394 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0.cpp : Implements the GLES 3.0 entry points.
+
+#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/formatutils.h"
+#include "libANGLE/Buffer.h"
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+#include "libANGLE/Fence.h"
+#include "libANGLE/Framebuffer.h"
+#include "libANGLE/Query.h"
+#include "libANGLE/VertexArray.h"
+
+#include "libANGLE/validationES.h"
+#include "libANGLE/validationES3.h"
+#include "libANGLE/queryconversions.h"
+
+#include "common/debug.h"
+
+namespace gl
+{
+
+void GL_APIENTRY ReadBuffer(GLenum mode)
+{
+ EVENT("(GLenum mode = 0x%X)", mode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateReadBuffer(context, mode))
+ {
+ return;
+ }
+
+ Framebuffer *readFBO = context->getState().getReadFramebuffer();
+ readFBO->setReadBuffer(mode);
+ }
+}
+
+void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
+{
+ EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
+ "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
+ {
+ return;
+ }
+ if (indexRange.end > end || indexRange.start < start)
+ {
+ // GL spec says that behavior in this case is undefined - generating an error is fine.
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // As long as index validation is done, it doesn't matter whether the context receives a drawElements or
+ // a drawRangeElements call - the GL back-end is free to choose to call drawRangeElements based on the
+ // validated index range. If index validation is removed, adding drawRangeElements to the context interface
+ // should be reconsidered.
+ Error error = context->drawElements(mode, count, type, indices, 0, indexRange);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
+ "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
+ 0, 0, 0, width, height, depth, border, format, type, pixels))
+ {
+ return;
+ }
+
+ Extents size(width, height, depth);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setImage(target, level, internalformat, size, format, type, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(pixels));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
+ xoffset, yoffset, zoffset, width, height, depth, 0,
+ format, type, pixels))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0 || depth == 0)
+ {
+ return;
+ }
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setSubImage(target, level, area, format, type, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(pixels));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, level, xoffset, yoffset, zoffset, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset,
+ x, y, width, height, 0))
+ {
+ return;
+ }
+
+ Offset destOffset(xoffset, yoffset, zoffset);
+ Rectangle sourceArea(x, y, width, height);
+
+ const Framebuffer *framebuffer = context->getState().getReadFramebuffer();
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->copySubImage(target, level, destOffset, sourceArea, framebuffer);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
+ "const GLvoid* data = 0x%0.8p)",
+ target, level, internalformat, width, height, depth, border, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(internalformat);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
+ 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ Extents size(width, height, depth);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setCompressedImage(target, level, internalformat, size, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(data));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+ EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
+ "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
+ "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
+ target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const InternalFormat &formatInfo = GetInternalFormatInfo(format);
+ if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!data)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // validateES3TexImageFormat sets the error code if there is an error
+ if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
+ 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data))
+ {
+ return;
+ }
+
+ // Zero sized uploads are valid but no-ops
+ if (width == 0 || height == 0)
+ {
+ return;
+ }
+
+ Box area(xoffset, yoffset, zoffset, width, height, depth);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setCompressedSubImage(target, level, area, format, context->getState().getUnpackState(),
+ reinterpret_cast<const uint8_t *>(data));
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (GLsizei i = 0; i < n; i++)
+ {
+ ids[i] = context->createQuery();
+ }
+ }
+}
+
+void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (GLsizei i = 0; i < n; i++)
+ {
+ context->deleteQuery(ids[i]);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsQuery(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY BeginQuery(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateBeginQuery(context, target, id))
+ {
+ return;
+ }
+
+ Error error = context->beginQuery(target, id);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY EndQuery(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateEndQuery(context, target))
+ {
+ return;
+ }
+
+ Error error = context->endQuery(target);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidQueryType(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_CURRENT_QUERY:
+ params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target));
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
+{
+ EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Query *queryObject = context->getQuery(id, false, GL_NONE);
+
+ if (!queryObject)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (context->getState().getActiveQueryId(queryObject->getType()) == id)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch(pname)
+ {
+ case GL_QUERY_RESULT_EXT:
+ {
+ Error error = queryObject->getResult(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ break;
+
+ case GL_QUERY_RESULT_AVAILABLE_EXT:
+ {
+ Error error = queryObject->isResultAvailable(params);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+GLboolean GL_APIENTRY UnmapBuffer(GLenum target)
+{
+ EVENT("(GLenum target = 0x%X)", target);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return UnmapBufferOES(target);
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ GetBufferPointervOES(target, pname, params);
+ }
+}
+
+void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs)
+{
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ DrawBuffersEXT(n, bufs);
+ }
+}
+
+void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix2x3fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix3x2fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix2x4fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix4x2fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix3x4fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
+ location, count, transpose, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniformMatrix4x3fv(location, count, transpose, value);
+ }
+}
+
+void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
+ "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
+ srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
+ dstX0, dstY0, dstX1, dstY1, mask, filter,
+ false))
+ {
+ return;
+ }
+
+ Framebuffer *readFramebuffer = context->getState().getReadFramebuffer();
+ ASSERT(readFramebuffer);
+
+ Framebuffer *drawFramebuffer = context->getState().getDrawFramebuffer();
+ ASSERT(drawFramebuffer);
+
+ Rectangle srcArea(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
+ Rectangle dstArea(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
+
+ Error error = drawFramebuffer->blit(context->getState(), srcArea, dstArea, mask, filter, readFramebuffer);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, samples, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3RenderbufferStorageParameters(context, target, samples, internalformat, width, height))
+ {
+ return;
+ }
+
+ Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
+ renderbuffer->setStorageMultisample(samples, internalformat, width, height);
+ }
+}
+
+void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
+{
+ EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
+ target, attachment, texture, level, layer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateFramebufferTextureLayer(context, target, attachment, texture,
+ level, layer))
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (texture != 0)
+ {
+ Texture *textureObject = context->getTexture(texture);
+
+ ImageIndex index = ImageIndex::MakeInvalid();
+
+ if (textureObject->getTarget() == GL_TEXTURE_3D)
+ {
+ index = ImageIndex::Make3D(level, layer);
+ }
+ else
+ {
+ ASSERT(textureObject->getTarget() == GL_TEXTURE_2D_ARRAY);
+ index = ImageIndex::Make2DArray(level, layer);
+ }
+
+ framebuffer->setTextureAttachment(attachment, textureObject, index);
+ }
+ else
+ {
+ framebuffer->setNULLAttachment(attachment);
+ }
+ }
+}
+
+GLvoid *GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
+ target, offset, length, access);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ return MapBufferRangeEXT(target, offset, length, access);
+ }
+
+ return NULL;
+}
+
+void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
+{
+ EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ FlushMappedBufferRangeEXT(target, offset, length);
+ }
+}
+
+void GL_APIENTRY BindVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ VertexArray *vao = context->getVertexArray(array);
+
+ if (!vao)
+ {
+ // The default VAO should always exist
+ ASSERT(array != 0);
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindVertexArray(array);
+ }
+}
+
+void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays)
+{
+ EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ if (arrays[arrayIndex] != 0)
+ {
+ context->deleteVertexArray(arrays[arrayIndex]);
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays)
+{
+ EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (n < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
+ {
+ arrays[arrayIndex] = context->createVertexArray();
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsVertexArray(GLuint array)
+{
+ EVENT("(GLuint array = %u)", array);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ if (array == 0)
+ {
+ return GL_FALSE;
+ }
+
+ VertexArray *vao = context->getVertexArray(array);
+
+ return (vao != NULL ? GL_TRUE : GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
+ target, index, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxCombinedUniformBlocks)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!(context->getIndexedIntegerv(target, index, data)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (numParams == 0)
+ {
+ return; // it is known that pname is valid, but there are no parameters to return
+ }
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
+ GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
+ GLint64 *int64Params = new GLint64[numParams];
+
+ context->getIndexedInteger64v(target, index, int64Params);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
+ data[i] = static_cast<GLint>(clampedValue);
+ }
+
+ delete [] int64Params;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ }
+}
+
+void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode)
+{
+ EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (primitiveMode)
+ {
+ case GL_TRIANGLES:
+ case GL_LINES:
+ case GL_POINTS:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ if (transformFeedback->isStarted())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (transformFeedback->isPaused())
+ {
+ transformFeedback->resume();
+ }
+ else
+ {
+ transformFeedback->start(primitiveMode);
+ }
+ }
+}
+
+void GL_APIENTRY EndTransformFeedback(void)
+{
+ EVENT("(void)");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ if (!transformFeedback->isStarted())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ transformFeedback->stop();
+ }
+}
+
+void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
+ target, index, buffer, offset, size);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (buffer != 0 && size <= 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ {
+ // size and offset must be a multiple of 4
+ if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
+ TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ break;
+ }
+
+ case GL_UNIFORM_BUFFER:
+
+ // it is an error to bind an offset not a multiple of the alignment
+ if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->bindIndexedUniformBuffer(buffer, index, offset, size);
+ context->bindGenericUniformBuffer(buffer);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
+ target, index, buffer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER:
+ {
+ // Cannot bind a transform feedback buffer if the current transform feedback is active (3.0.4 pg 91 section 2.15.2)
+ TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
+ context->bindGenericTransformFeedbackBuffer(buffer);
+ break;
+ }
+ case GL_UNIFORM_BUFFER:
+ context->bindIndexedUniformBuffer(buffer, index, 0, 0);
+ context->bindGenericUniformBuffer(buffer);
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+ }
+}
+
+void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
+{
+ EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
+ program, count, varyings, bufferMode);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (bufferMode)
+ {
+ case GL_INTERLEAVED_ATTRIBS:
+ break;
+ case GL_SEPARATE_ATTRIBS:
+ if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!ValidProgram(context, program))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
+ }
+}
+
+void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
+{
+ EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
+ "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
+ program, index, bufSize, length, size, type, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidProgram(context, program))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
+ }
+}
+
+void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
+{
+ EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
+ index, size, type, stride, pointer);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (size < 1 || size > 4)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (type)
+ {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ case GL_INT:
+ case GL_UNSIGNED_INT:
+ case GL_INT_2_10_10_10_REV:
+ case GL_UNSIGNED_INT_2_10_10_10_REV:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (stride < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // [OpenGL ES 3.0.2] Section 2.8 page 24:
+ // An INVALID_OPERATION error is generated when a non-zero vertex array object
+ // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
+ // and the pointer argument is not NULL.
+ if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true,
+ stride, pointer);
+ }
+}
+
+void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ index, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
+ {
+ params[i] = currentValueData.IntValues[i];
+ }
+ }
+ else
+ {
+ const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
+ *params = QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
+ }
+ }
+}
+
+void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
+{
+ EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
+ index, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (!ValidateGetVertexAttribParameters(context, pname))
+ {
+ return;
+ }
+
+ if (pname == GL_CURRENT_VERTEX_ATTRIB)
+ {
+ const VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
+ for (int i = 0; i < 4; ++i)
+ {
+ params[i] = currentValueData.UnsignedIntValues[i];
+ }
+ }
+ else
+ {
+ const VertexAttribute &attribState = context->getState().getVertexArray()->getVertexAttribute(index);
+ *params = QuerySingleVertexAttributeParameter<GLuint>(attribState, pname);
+ }
+ }
+}
+
+void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
+{
+ EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
+ index, x, y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLint vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribi(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
+{
+ EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
+ index, x, y, z, w);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ GLuint vals[4] = { x, y, z, w };
+ context->getState().setVertexAttribu(index, vals);
+ }
+}
+
+void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v)
+{
+ EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setVertexAttribi(index, v);
+ }
+}
+
+void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v)
+{
+ EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->getState().setVertexAttribu(index, v);
+ }
+}
+
+void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params)
+{
+ EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
+ program, location, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateGetUniformuiv(context, program, location, params))
+ {
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+ ASSERT(programObject);
+
+ programObject->getUniformuiv(location, params);
+ }
+}
+
+GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name)
+{
+ EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
+ program, name);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+
+ if (program == 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return -1;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject || !programObject->isLinked())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return -1;
+ }
+
+ return programObject->getFragDataLocation(name);
+ }
+
+ return 0;
+}
+
+void GL_APIENTRY Uniform1ui(GLint location, GLuint v0)
+{
+ Uniform1uiv(location, 1, &v0);
+}
+
+void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1)
+{
+ const GLuint xy[] = { v0, v1 };
+ Uniform2uiv(location, 1, xy);
+}
+
+void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
+{
+ const GLuint xyz[] = { v0, v1, v2 };
+ Uniform3uiv(location, 1, xyz);
+}
+
+void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
+{
+ const GLuint xyzw[] = { v0, v1, v2, v3 };
+ Uniform4uiv(location, 1, xyzw);
+}
+
+void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform1uiv(location, count, value);
+ }
+}
+
+void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform2uiv(location, count, value);
+ }
+}
+
+void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
+ location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform3uiv(location, count, value);
+ }
+}
+
+void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value)
+{
+ EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
+ location, count, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
+ {
+ return;
+ }
+
+ Program *program = context->getState().getProgram();
+ program->setUniform4uiv(location, count, value);
+ }
+}
+
+void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ Error error = framebufferObject->clearBufferiv(context->getState(), buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ Error error = framebufferObject->clearBufferuiv(context->getState(), buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
+ buffer, drawbuffer, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
+ {
+ case GL_COLOR:
+ if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_DEPTH:
+ if (drawbuffer != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ Error error = framebufferObject->clearBufferfv(context->getState(), buffer, drawbuffer, value);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
+{
+ EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
+ buffer, drawbuffer, depth, stencil);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (!ValidateClearBuffer(context))
+ {
+ return;
+ }
+
+ switch (buffer)
+ {
+ case GL_DEPTH_STENCIL:
+ if (drawbuffer != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
+ ASSERT(framebufferObject);
+
+ Error error = framebufferObject->clearBufferfi(context->getState(), buffer, drawbuffer, depth, stencil);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index)
+{
+ EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return NULL;
+ }
+
+ if (name != GL_EXTENSIONS)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return NULL;
+ }
+
+ if (index >= context->getExtensionStringCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return NULL;
+ }
+
+ return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
+ }
+
+ return NULL;
+}
+
+void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
+{
+ EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
+ readTarget, writeTarget, readOffset, writeOffset, size);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidBufferTarget(context, readTarget) || !ValidBufferTarget(context, writeTarget))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
+ Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
+
+ if (!readBuffer || !writeBuffer)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Verify that readBuffer and writeBuffer are not currently mapped
+ if (readBuffer->isMapped() || writeBuffer->isMapped())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (readOffset < 0 || writeOffset < 0 || size < 0 ||
+ static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
+ static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ // if size is zero, the copy is a successful no-op
+ if (size > 0)
+ {
+ Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
+{
+ EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
+ program, uniformCount, uniformNames, uniformIndices);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (!programObject->isLinked())
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = GL_INVALID_INDEX;
+ }
+ }
+ else
+ {
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ uniformIndices[uniformId] = programObject->getUniformIndex(uniformNames[uniformId]);
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ program, uniformCount, uniformIndices, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (uniformCount < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_TYPE:
+ case GL_UNIFORM_SIZE:
+ case GL_UNIFORM_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_INDEX:
+ case GL_UNIFORM_OFFSET:
+ case GL_UNIFORM_ARRAY_STRIDE:
+ case GL_UNIFORM_MATRIX_STRIDE:
+ case GL_UNIFORM_IS_ROW_MAJOR:
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (uniformCount > programObject->getActiveUniformCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+
+ if (index >= static_cast<GLuint>(programObject->getActiveUniformCount()))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ for (int uniformId = 0; uniformId < uniformCount; uniformId++)
+ {
+ const GLuint index = uniformIndices[uniformId];
+ params[uniformId] = programObject->getActiveUniformi(index, pname);
+ }
+ }
+}
+
+GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
+{
+ EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_INVALID_INDEX;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_INVALID_INDEX;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return GL_INVALID_INDEX;
+ }
+ }
+
+ return programObject->getUniformBlockIndex(uniformBlockName);
+ }
+
+ return 0;
+}
+
+void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
+ program, uniformBlockIndex, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_UNIFORM_BLOCK_BINDING:
+ *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
+ break;
+
+ case GL_UNIFORM_BLOCK_DATA_SIZE:
+ case GL_UNIFORM_BLOCK_NAME_LENGTH:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
+ case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
+ case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
+ programObject->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
+{
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
+ program, uniformBlockIndex, bufSize, length, uniformBlockName);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
+ }
+}
+
+void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
+{
+ EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
+ program, uniformBlockIndex, uniformBlockBinding);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Program *programObject = context->getProgram(program);
+
+ if (!programObject)
+ {
+ if (context->getShader(program))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+ else
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ }
+
+ // if never linked, there won't be any uniform blocks
+ if (uniformBlockIndex >= programObject->getActiveUniformBlockCount())
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
+ }
+}
+
+void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
+{
+ EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
+ mode, first, count, instanceCount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateDrawArraysInstanced(context, mode, first, count, instanceCount))
+ {
+ return;
+ }
+
+ Error error = context->drawArrays(mode, first, count, instanceCount);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
+{
+ EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
+ mode, count, type, indices, instanceCount);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ rx::RangeUI indexRange;
+ if (!ValidateDrawElementsInstanced(context, mode, count, type, indices, instanceCount, &indexRange))
+ {
+ return;
+ }
+
+ Error error = context->drawElements(mode, count, type, indices, instanceCount, indexRange);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags)
+{
+ EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return 0;
+ }
+
+ if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return 0;
+ }
+
+ if (flags != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return 0;
+ }
+
+ GLsync fenceSync = context->createFenceSync();
+
+ FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
+ Error error = fenceSyncObject->set(condition);
+ if (error.isError())
+ {
+ context->deleteFenceSync(fenceSync);
+ context->recordError(error);
+ return NULL;
+ }
+
+ return fenceSync;
+ }
+
+ return NULL;
+}
+
+GLboolean GL_APIENTRY IsSync(GLsync sync)
+{
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return (context->getFenceSync(sync) != NULL);
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY DeleteSync(GLsync sync)
+{
+ EVENT("(GLsync sync = 0x%0.8p)", sync);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->deleteFenceSync(sync);
+ }
+}
+
+GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
+ sync, flags, timeout);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_WAIT_FAILED;
+ }
+
+ if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return GL_WAIT_FAILED;
+ }
+
+ FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return GL_WAIT_FAILED;
+ }
+
+ GLenum result = GL_WAIT_FAILED;
+ Error error = fenceSync->clientWait(flags, timeout, &result);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return GL_WAIT_FAILED;
+ }
+
+ return result;
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
+ sync, flags, timeout);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (flags != 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ if (timeout != GL_TIMEOUT_IGNORED)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ Error error = fenceSync->serverWait(flags, timeout);
+ if (error.isError())
+ {
+ context->recordError(error);
+ }
+ }
+}
+
+void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params)
+{
+ EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
+ pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
+ {
+ return;
+ }
+
+ if (nativeType == GL_INT_64_ANGLEX)
+ {
+ context->getInteger64v(pname, params);
+ }
+ else
+ {
+ CastStateValues(context, nativeType, pname, numParams, params);
+ }
+ }
+}
+
+void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
+{
+ EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
+ sync, pname, bufSize, length, values);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ FenceSync *fenceSync = context->getFenceSync(sync);
+
+ if (!fenceSync)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
+ case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
+ case GL_SYNC_FLAGS: values[0] = 0; break;
+
+ case GL_SYNC_STATUS:
+ {
+ Error error = fenceSync->getStatus(values);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ break;
+ }
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data)
+{
+ EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
+ target, index, data);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const Caps &caps = context->getCaps();
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK_BUFFER_START:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
+ case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
+ if (index >= caps.maxTransformFeedbackSeparateAttributes)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ case GL_UNIFORM_BUFFER_START:
+ case GL_UNIFORM_BUFFER_SIZE:
+ case GL_UNIFORM_BUFFER_BINDING:
+ if (index >= caps.maxUniformBufferBindings)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!(context->getIndexedInteger64v(target, index, data)))
+ {
+ GLenum nativeType;
+ unsigned int numParams = 0;
+ if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (numParams == 0)
+ return; // it is known that pname is valid, but there are no parameters to return
+
+ if (nativeType == GL_INT)
+ {
+ GLint *intParams = new GLint[numParams];
+
+ context->getIndexedIntegerv(target, index, intParams);
+
+ for (unsigned int i = 0; i < numParams; ++i)
+ {
+ data[i] = static_cast<GLint64>(intParams[i]);
+ }
+
+ delete [] intParams;
+ }
+ else
+ {
+ UNREACHABLE();
+ }
+ }
+ }
+}
+
+void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
+ target, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidBufferTarget(context, target))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (!ValidBufferParameter(context, pname))
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ Buffer *buffer = context->getState().getTargetBuffer(target);
+
+ if (!buffer)
+ {
+ // A null buffer means that "0" is bound to the requested buffer target
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_BUFFER_USAGE:
+ *params = static_cast<GLint64>(buffer->getUsage());
+ break;
+ case GL_BUFFER_SIZE:
+ *params = buffer->getSize();
+ break;
+ case GL_BUFFER_ACCESS_FLAGS:
+ *params = static_cast<GLint64>(buffer->getAccessFlags());
+ break;
+ case GL_BUFFER_MAPPED:
+ *params = static_cast<GLint64>(buffer->isMapped());
+ break;
+ case GL_BUFFER_MAP_OFFSET:
+ *params = buffer->getMapOffset();
+ break;
+ case GL_BUFFER_MAP_LENGTH:
+ *params = buffer->getMapLength();
+ break;
+ default: UNREACHABLE(); break;
+ }
+ }
+}
+
+void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers)
+{
+ EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ samplers[i] = context->createSampler();
+ }
+ }
+}
+
+void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers)
+{
+ EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (count < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ for (int i = 0; i < count; i++)
+ {
+ context->deleteSampler(samplers[i]);
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsSampler(GLuint sampler)
+{
+ EVENT("(GLuint sampler = %u)", sampler);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return context->isSampler(sampler);
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler)
+{
+ EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (sampler != 0 && !context->isSampler(sampler))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (unit >= context->getCaps().maxCombinedTextureImageUnits)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->bindSampler(unit, sampler);
+ }
+}
+
+void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!ValidateTexParamParameters(context, pname, param))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->samplerParameteri(sampler, pname, param);
+ }
+}
+
+void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
+{
+ SamplerParameteri(sampler, pname, *param);
+}
+
+void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->samplerParameterf(sampler, pname, param);
+ }
+}
+
+void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
+{
+ SamplerParameterf(sampler, pname, *param);
+}
+
+void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
+{
+ EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ *params = context->getSamplerParameteri(sampler, pname);
+ }
+}
+
+void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+{
+ EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateSamplerObjectParameter(context, pname))
+ {
+ return;
+ }
+
+ if (!context->isSampler(sampler))
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ *params = context->getSamplerParameterf(sampler, pname);
+ }
+}
+
+void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (index >= MAX_VERTEX_ATTRIBS)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ context->setVertexAttribDivisor(index, divisor);
+ }
+}
+
+void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id)
+{
+ EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ switch (target)
+ {
+ case GL_TRANSFORM_FEEDBACK:
+ {
+ // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
+ TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
+ if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
+ if (context->getTransformFeedback(id) == NULL)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ context->bindTransformFeedback(id);
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ context->deleteTransformFeedback(ids[i]);
+ }
+ }
+}
+
+void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids)
+{
+ EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ for (int i = 0; i < n; i++)
+ {
+ ids[i] = context->createTransformFeedback();
+ }
+ }
+}
+
+GLboolean GL_APIENTRY IsTransformFeedback(GLuint id)
+{
+ EVENT("(GLuint id = %u)", id);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return GL_FALSE;
+ }
+
+ return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE);
+ }
+
+ return GL_FALSE;
+}
+
+void GL_APIENTRY PauseTransformFeedback(void)
+{
+ EVENT("(void)");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86)
+ if (!transformFeedback->isStarted() || transformFeedback->isPaused())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ transformFeedback->pause();
+ }
+}
+
+void GL_APIENTRY ResumeTransformFeedback(void)
+{
+ EVENT("(void)");
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
+ ASSERT(transformFeedback != NULL);
+
+ // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86)
+ if (!transformFeedback->isStarted() || !transformFeedback->isPaused())
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ transformFeedback->resume();
+ }
+}
+
+void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+{
+ EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
+ program, bufSize, length, binaryFormat, binary);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // TODO: Pipe through to the OES extension for now, needs proper validation
+ return GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
+ }
+}
+
+void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+{
+ EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
+ program, binaryFormat, binary, length);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // TODO: Pipe through to the OES extension for now, needs proper validation
+ return ProgramBinaryOES(program, binaryFormat, binary, length);
+ }
+}
+
+void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+ EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
+ program, pname, value);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ // glProgramParameteri
+ UNIMPLEMENTED();
+ }
+}
+
+void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
+ target, numAttachments, attachments);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
+ {
+ Error error = framebuffer->invalidate(numAttachments, attachments);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ }
+}
+
+void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
+ "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
+ target, numAttachments, attachments, x, y, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
+ {
+ return;
+ }
+
+ Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
+ ASSERT(framebuffer);
+
+ if (framebuffer->checkStatus(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
+ {
+ Rectangle area(x, y, width, height);
+ Error error = framebuffer->invalidateSub(numAttachments, attachments, area);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+ }
+}
+
+void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
+ target, levels, internalformat, width, height);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
+ {
+ return;
+ }
+
+ Extents size(width, height, 1);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setStorage(target, levels, internalformat, size);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+{
+ EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
+ "GLsizei height = %d, GLsizei depth = %d)",
+ target, levels, internalformat, width, height, depth);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
+ {
+ return;
+ }
+
+ Extents size(width, height, depth);
+ Texture *texture = context->getTargetTexture(target);
+ Error error = texture->setStorage(target, levels, internalformat, size);
+ if (error.isError())
+ {
+ context->recordError(error);
+ return;
+ }
+ }
+}
+
+void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+{
+ EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
+ "GLint* params = 0x%0.8p)",
+ target, internalformat, pname, bufSize, params);
+
+ Context *context = GetValidGlobalContext();
+ if (context)
+ {
+ if (context->getClientVersion() < 3)
+ {
+ context->recordError(Error(GL_INVALID_OPERATION));
+ return;
+ }
+
+ const TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
+ if (!formatCaps.renderable)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (target != GL_RENDERBUFFER)
+ {
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+
+ if (bufSize < 0)
+ {
+ context->recordError(Error(GL_INVALID_VALUE));
+ return;
+ }
+
+ switch (pname)
+ {
+ case GL_NUM_SAMPLE_COUNTS:
+ if (bufSize != 0)
+ {
+ *params = formatCaps.sampleCounts.size();
+ }
+ break;
+
+ case GL_SAMPLES:
+ {
+ size_t returnCount = std::min<size_t>(bufSize, formatCaps.sampleCounts.size());
+ auto sampleReverseIt = formatCaps.sampleCounts.rbegin();
+ for (size_t sampleIndex = 0; sampleIndex < returnCount; ++sampleIndex)
+ {
+ params[sampleIndex] = *sampleReverseIt++;;
+ }
+ }
+ break;
+
+ default:
+ context->recordError(Error(GL_INVALID_ENUM));
+ return;
+ }
+ }
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h
new file mode 100644
index 0000000000..09ca0e4641
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0.h
@@ -0,0 +1,125 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0.h : Defines the GLES 3.0 entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES30_H_
+#define LIBGLESV2_ENTRYPOINTGLES30_H_
+
+#include <GLES3/gl3.h>
+#include <export.h>
+
+namespace gl
+{
+
+ANGLE_EXPORT void GL_APIENTRY ReadBuffer(GLenum mode);
+ANGLE_EXPORT void GL_APIENTRY DrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices);
+ANGLE_EXPORT void GL_APIENTRY TexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels);
+ANGLE_EXPORT void GL_APIENTRY TexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels);
+ANGLE_EXPORT void GL_APIENTRY CopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data);
+ANGLE_EXPORT void GL_APIENTRY CompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data);
+ANGLE_EXPORT void GL_APIENTRY GenQueries(GLsizei n, GLuint* ids);
+ANGLE_EXPORT void GL_APIENTRY DeleteQueries(GLsizei n, const GLuint* ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsQuery(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY BeginQuery(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY EndQuery(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetQueryiv(GLenum target, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params);
+ANGLE_EXPORT GLboolean GL_APIENTRY UnmapBuffer(GLenum target);
+ANGLE_EXPORT void GL_APIENTRY GetBufferPointerv(GLenum target, GLenum pname, GLvoid** params);
+ANGLE_EXPORT void GL_APIENTRY DrawBuffers(GLsizei n, const GLenum* bufs);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY UniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY BlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter);
+ANGLE_EXPORT void GL_APIENTRY RenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY FramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer);
+ANGLE_EXPORT GLvoid* GL_APIENTRY MapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access);
+ANGLE_EXPORT void GL_APIENTRY FlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
+ANGLE_EXPORT void GL_APIENTRY BindVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY DeleteVertexArrays(GLsizei n, const GLuint* arrays);
+ANGLE_EXPORT void GL_APIENTRY GenVertexArrays(GLsizei n, GLuint* arrays);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsVertexArray(GLuint array);
+ANGLE_EXPORT void GL_APIENTRY GetIntegeri_v(GLenum target, GLuint index, GLint* data);
+ANGLE_EXPORT void GL_APIENTRY BeginTransformFeedback(GLenum primitiveMode);
+ANGLE_EXPORT void GL_APIENTRY EndTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY BindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY BindBufferBase(GLenum target, GLuint index, GLuint buffer);
+ANGLE_EXPORT void GL_APIENTRY TransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode);
+ANGLE_EXPORT void GL_APIENTRY GetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIiv(GLuint index, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4iv(GLuint index, const GLint* v);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribI4uiv(GLuint index, const GLuint* v);
+ANGLE_EXPORT void GL_APIENTRY GetUniformuiv(GLuint program, GLint location, GLuint* params);
+ANGLE_EXPORT GLint GL_APIENTRY GetFragDataLocation(GLuint program, const GLchar *name);
+ANGLE_EXPORT void GL_APIENTRY Uniform1ui(GLint location, GLuint v0);
+ANGLE_EXPORT void GL_APIENTRY Uniform2ui(GLint location, GLuint v0, GLuint v1);
+ANGLE_EXPORT void GL_APIENTRY Uniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2);
+ANGLE_EXPORT void GL_APIENTRY Uniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3);
+ANGLE_EXPORT void GL_APIENTRY Uniform1uiv(GLint location, GLsizei count, const GLuint* value);
+ANGLE_EXPORT void GL_APIENTRY Uniform2uiv(GLint location, GLsizei count, const GLuint* value);
+ANGLE_EXPORT void GL_APIENTRY Uniform3uiv(GLint location, GLsizei count, const GLuint* value);
+ANGLE_EXPORT void GL_APIENTRY Uniform4uiv(GLint location, GLsizei count, const GLuint* value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value);
+ANGLE_EXPORT void GL_APIENTRY ClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil);
+ANGLE_EXPORT const GLubyte *GL_APIENTRY GetStringi(GLenum name, GLuint index);
+ANGLE_EXPORT void GL_APIENTRY CopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
+ANGLE_EXPORT void GL_APIENTRY GetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params);
+ANGLE_EXPORT GLuint GL_APIENTRY GetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName);
+ANGLE_EXPORT void GL_APIENTRY UniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding);
+ANGLE_EXPORT void GL_APIENTRY DrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount);
+ANGLE_EXPORT void GL_APIENTRY DrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount);
+ANGLE_EXPORT GLsync GL_APIENTRY FenceSync_(GLenum condition, GLbitfield flags);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSync(GLsync sync);
+ANGLE_EXPORT void GL_APIENTRY DeleteSync(GLsync sync);
+ANGLE_EXPORT GLenum GL_APIENTRY ClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY WaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64v(GLenum pname, GLint64* params);
+ANGLE_EXPORT void GL_APIENTRY GetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values);
+ANGLE_EXPORT void GL_APIENTRY GetInteger64i_v(GLenum target, GLuint index, GLint64* data);
+ANGLE_EXPORT void GL_APIENTRY GetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params);
+ANGLE_EXPORT void GL_APIENTRY GenSamplers(GLsizei count, GLuint* samplers);
+ANGLE_EXPORT void GL_APIENTRY DeleteSamplers(GLsizei count, const GLuint* samplers);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsSampler(GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY BindSampler(GLuint unit, GLuint sampler);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteri(GLuint sampler, GLenum pname, GLint param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterf(GLuint sampler, GLenum pname, GLfloat param);
+ANGLE_EXPORT void GL_APIENTRY SamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params);
+ANGLE_EXPORT void GL_APIENTRY GetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params);
+ANGLE_EXPORT void GL_APIENTRY VertexAttribDivisor(GLuint index, GLuint divisor);
+ANGLE_EXPORT void GL_APIENTRY BindTransformFeedback(GLenum target, GLuint id);
+ANGLE_EXPORT void GL_APIENTRY DeleteTransformFeedbacks(GLsizei n, const GLuint* ids);
+ANGLE_EXPORT void GL_APIENTRY GenTransformFeedbacks(GLsizei n, GLuint* ids);
+ANGLE_EXPORT GLboolean GL_APIENTRY IsTransformFeedback(GLuint id);
+ANGLE_EXPORT void GL_APIENTRY PauseTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY ResumeTransformFeedback(void);
+ANGLE_EXPORT void GL_APIENTRY GetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary);
+ANGLE_EXPORT void GL_APIENTRY ProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length);
+ANGLE_EXPORT void GL_APIENTRY ProgramParameteri(GLuint program, GLenum pname, GLint value);
+ANGLE_EXPORT void GL_APIENTRY InvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments);
+ANGLE_EXPORT void GL_APIENTRY InvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY TexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height);
+ANGLE_EXPORT void GL_APIENTRY TexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth);
+ANGLE_EXPORT void GL_APIENTRY GetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params);
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTGLES30_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp
new file mode 100644
index 0000000000..6f6983fd91
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.cpp
@@ -0,0 +1,14 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0_ext.cpp : Implements the GLES 3.0 extension entry points.
+
+#include "libGLESv2/entry_points_gles_3_0_ext.h"
+#include "libGLESv2/global_state.h"
+
+namespace gl
+{
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h
new file mode 100644
index 0000000000..fec4c1298a
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/entry_points_gles_3_0_ext.h
@@ -0,0 +1,23 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// entry_points_gles_3_0_ext.h : Defines the GLES 3.0 extension entry points.
+
+#ifndef LIBGLESV2_ENTRYPOINTGLES30EXT_H_
+#define LIBGLESV2_ENTRYPOINTGLES30EXT_H_
+
+#include <GLES3/gl3.h>
+#include <GLES3/gl3ext.h>
+#include <export.h>
+
+namespace gl
+{
+
+// No GLES 3.0 extensions yet
+
+}
+
+#endif // LIBGLESV2_ENTRYPOINTGLES30EXT_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/formatutils.h b/src/3rdparty/angle/src/libGLESv2/formatutils.h
deleted file mode 100644
index 25106a52e5..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/formatutils.h
+++ /dev/null
@@ -1,106 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// formatutils.h: Queries for GL image formats.
-
-#ifndef LIBGLESV2_FORMATUTILS_H_
-#define LIBGLESV2_FORMATUTILS_H_
-
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/angletypes.h"
-
-#include "angle_gl.h"
-
-#include <cstddef>
-#include <cstdint>
-
-typedef void (*MipGenerationFunction)(size_t sourceWidth, size_t sourceHeight, size_t sourceDepth,
- const uint8_t *sourceData, size_t sourceRowPitch, size_t sourceDepthPitch,
- uint8_t *destData, size_t destRowPitch, size_t destDepthPitch);
-
-typedef void (*LoadImageFunction)(size_t width, size_t height, size_t depth,
- const uint8_t *input, size_t inputRowPitch, size_t inputDepthPitch,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-typedef void (*InitializeTextureDataFunction)(size_t width, size_t height, size_t depth,
- uint8_t *output, size_t outputRowPitch, size_t outputDepthPitch);
-
-typedef void (*ColorReadFunction)(const uint8_t *source, uint8_t *dest);
-typedef void (*ColorWriteFunction)(const uint8_t *source, uint8_t *dest);
-typedef void (*ColorCopyFunction)(const uint8_t *source, uint8_t *dest);
-
-typedef void (*VertexCopyFunction)(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
-
-namespace gl
-{
-
-struct FormatType
-{
- FormatType();
-
- GLenum internalFormat;
- ColorWriteFunction colorWriteFunction;
-};
-const FormatType &GetFormatTypeInfo(GLenum format, GLenum type);
-
-struct Type
-{
- Type();
-
- GLuint bytes;
- bool specialInterpretation;
-};
-const Type &GetTypeInfo(GLenum type);
-
-struct InternalFormat
-{
- InternalFormat();
-
- GLuint redBits;
- GLuint greenBits;
- GLuint blueBits;
-
- GLuint luminanceBits;
-
- GLuint alphaBits;
- GLuint sharedBits;
-
- GLuint depthBits;
- GLuint stencilBits;
-
- GLuint pixelBytes;
-
- GLuint componentCount;
-
- bool compressed;
- GLuint compressedBlockWidth;
- GLuint compressedBlockHeight;
-
- GLenum format;
- GLenum type;
-
- GLenum componentType;
- GLenum colorEncoding;
-
- typedef bool (*SupportCheckFunction)(GLuint, const Extensions &);
- SupportCheckFunction textureSupport;
- SupportCheckFunction renderSupport;
- SupportCheckFunction filterSupport;
-
- GLuint computeRowPitch(GLenum type, GLsizei width, GLint alignment) const;
- GLuint computeDepthPitch(GLenum type, GLsizei width, GLsizei height, GLint alignment) const;
- GLuint computeBlockSize(GLenum type, GLsizei width, GLsizei height) const;
-};
-const InternalFormat &GetInternalFormatInfo(GLenum internalFormat);
-
-GLenum GetSizedInternalFormat(GLenum internalFormat, GLenum type);
-
-typedef std::set<GLenum> FormatSet;
-const FormatSet &GetAllSizedInternalFormats();
-
-}
-
-#endif // LIBGLESV2_FORMATUTILS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
new file mode 100644
index 0000000000..686f0bf49b
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
@@ -0,0 +1,235 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// global_state.cpp : Implements functions for querying the thread-local GL and EGL state.
+
+#include "libGLESv2/global_state.h"
+
+#include "libANGLE/Context.h"
+#include "libANGLE/Error.h"
+
+#include "common/debug.h"
+#include "common/platform.h"
+#include "common/tls.h"
+
+namespace
+{
+
+static TLSIndex currentTLS = TLS_INVALID_INDEX;
+
+struct Current
+{
+ EGLint error;
+ EGLenum API;
+ egl::Display *display;
+ egl::Surface *drawSurface;
+ egl::Surface *readSurface;
+ gl::Context *context;
+};
+
+Current *AllocateCurrent()
+{
+ ASSERT(currentTLS != TLS_INVALID_INDEX);
+ if (currentTLS == TLS_INVALID_INDEX)
+ {
+ return NULL;
+ }
+
+ Current *current = new Current();
+ current->error = EGL_SUCCESS;
+ current->API = EGL_OPENGL_ES_API;
+ current->display = reinterpret_cast<egl::Display*>(EGL_NO_DISPLAY);
+ current->drawSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE);
+ current->readSurface = reinterpret_cast<egl::Surface*>(EGL_NO_SURFACE);
+ current->context = reinterpret_cast<gl::Context*>(EGL_NO_CONTEXT);
+
+ if (!SetTLSValue(currentTLS, current))
+ {
+ ERR("Could not set thread local storage.");
+ return NULL;
+ }
+
+ return current;
+}
+
+void DeallocateCurrent()
+{
+ Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
+ SafeDelete(current);
+ SetTLSValue(currentTLS, NULL);
+}
+
+Current *GetCurrentData()
+{
+ // Create a TLS index if one has not been created for this DLL
+ if (currentTLS == TLS_INVALID_INDEX)
+ {
+ currentTLS = CreateTLSIndex();
+ }
+
+ Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
+
+ // ANGLE issue 488: when the dll is loaded after thread initialization,
+ // thread local storage (current) might not exist yet.
+ return (current ? current : AllocateCurrent());
+}
+
+#ifdef ANGLE_PLATFORM_WINDOWS
+extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ currentTLS = CreateTLSIndex();
+ if (currentTLS == TLS_INVALID_INDEX)
+ {
+ return FALSE;
+ }
+ AllocateCurrent();
+ break;
+
+ case DLL_THREAD_ATTACH:
+ AllocateCurrent();
+ break;
+
+ case DLL_THREAD_DETACH:
+ DeallocateCurrent();
+ break;
+
+ case DLL_PROCESS_DETACH:
+ DeallocateCurrent();
+ if (currentTLS != TLS_INVALID_INDEX)
+ {
+ DestroyTLSIndex(currentTLS);
+ currentTLS = TLS_INVALID_INDEX;
+ }
+ break;
+ }
+
+ return TRUE;
+}
+#endif
+
+}
+
+namespace gl
+{
+
+Context *GetGlobalContext()
+{
+ Current *current = GetCurrentData();
+
+ return current->context;
+}
+
+Context *GetValidGlobalContext()
+{
+ gl::Context *context = GetGlobalContext();
+ if (context)
+ {
+ if (context->isContextLost())
+ {
+ context->recordError(gl::Error(GL_OUT_OF_MEMORY, "Context has been lost."));
+ return nullptr;
+ }
+ else
+ {
+ return context;
+ }
+ }
+ return nullptr;
+}
+
+}
+
+namespace egl
+{
+
+void SetGlobalError(const Error &error)
+{
+ Current *current = GetCurrentData();
+
+ current->error = error.getCode();
+}
+
+EGLint GetGlobalError()
+{
+ Current *current = GetCurrentData();
+
+ return current->error;
+}
+
+EGLenum GetGlobalAPI()
+{
+ Current *current = GetCurrentData();
+
+ return current->API;
+}
+
+void SetGlobalAPI(EGLenum API)
+{
+ Current *current = GetCurrentData();
+
+ current->API = API;
+}
+
+void SetGlobalDisplay(Display *dpy)
+{
+ Current *current = GetCurrentData();
+
+ current->display = dpy;
+}
+
+Display *GetGlobalDisplay()
+{
+ Current *current = GetCurrentData();
+
+ return current->display;
+}
+
+void SetGlobalDrawSurface(Surface *surface)
+{
+ Current *current = GetCurrentData();
+
+ current->drawSurface = surface;
+}
+
+Surface *GetGlobalDrawSurface()
+{
+ Current *current = GetCurrentData();
+
+ return current->drawSurface;
+}
+
+void SetGlobalReadSurface(Surface *surface)
+{
+ Current *current = GetCurrentData();
+
+ current->readSurface = surface;
+}
+
+Surface *GetGlobalReadSurface()
+{
+ Current *current = GetCurrentData();
+
+ return current->readSurface;
+}
+
+void SetGlobalContext(gl::Context *context)
+{
+ Current *current = GetCurrentData();
+
+ current->context = context;
+}
+
+gl::Context *GetGlobalContext()
+{
+ Current *current = GetCurrentData();
+
+ return current->context;
+}
+
+}
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.h b/src/3rdparty/angle/src/libGLESv2/global_state.h
new file mode 100644
index 0000000000..db202539cb
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.h
@@ -0,0 +1,49 @@
+//
+// Copyright(c) 2014 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// global_state.h : Defines functions for querying the thread-local GL and EGL state.
+
+#ifndef LIBGLESV2_GLOBALSTATE_H_
+#define LIBGLESV2_GLOBALSTATE_H_
+
+#include <EGL/egl.h>
+
+namespace gl
+{
+class Context;
+
+Context *GetGlobalContext();
+Context *GetValidGlobalContext();
+
+}
+
+namespace egl
+{
+class Error;
+class Display;
+class Surface;
+
+void SetGlobalError(const Error &error);
+EGLint GetGlobalError();
+
+void SetGlobalAPI(EGLenum API);
+EGLenum GetGlobalAPI();
+
+void SetGlobalDisplay(Display *dpy);
+Display *GetGlobalDisplay();
+
+void SetGlobalDrawSurface(Surface *surface);
+Surface *GetGlobalDrawSurface();
+
+void SetGlobalReadSurface(Surface *surface);
+Surface *GetGlobalReadSurface();
+
+void SetGlobalContext(gl::Context *context);
+gl::Context *GetGlobalContext();
+
+}
+
+#endif // LIBGLESV2_GLOBALSTATE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
index 587950a139..e69e04aa60 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
@@ -6,8977 +6,1416 @@
// libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
-#undef GL_APICALL
-#define GL_APICALL
-#define GL_GLEXT_PROTOTYPES
-
-#include "common/version.h"
-#include "common/utilities.h"
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/formatutils.h"
-#include "libGLESv2/Buffer.h"
-#include "libGLESv2/Fence.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/Renderbuffer.h"
-#include "libGLESv2/Program.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/Texture.h"
-#include "libGLESv2/Query.h"
-#include "libGLESv2/Context.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/VertexAttribute.h"
-#include "libGLESv2/TransformFeedback.h"
-#include "libGLESv2/FramebufferAttachment.h"
-
-#include "libGLESv2/validationES.h"
-#include "libGLESv2/validationES2.h"
-#include "libGLESv2/validationES3.h"
-#include "libGLESv2/queryconversions.h"
+#include "libGLESv2/entry_points_gles_2_0.h"
+#include "libGLESv2/entry_points_gles_2_0_ext.h"
+#include "libGLESv2/entry_points_gles_3_0.h"
+#include "libGLESv2/entry_points_gles_3_0_ext.h"
+
+#include "common/event_tracer.h"
extern "C"
{
-// OpenGL ES 2.0 functions
-
void GL_APIENTRY glActiveTexture(GLenum texture)
{
- EVENT("(GLenum texture = 0x%X)", texture);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (texture < GL_TEXTURE0 || texture > GL_TEXTURE0 + context->getCaps().maxCombinedTextureImageUnits - 1)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setActiveSampler(texture - GL_TEXTURE0);
- }
+ return gl::ActiveTexture(texture);
}
void GL_APIENTRY glAttachShader(GLuint program, GLuint shader)
{
- EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (!shaderObject)
- {
- if (context->getProgram(shader))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (!programObject->attachShader(shaderObject))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
-}
-
-void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
-{
- EVENT("(GLenum target = 0x%X, GLuint %d)", target, id);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateBeginQuery(context, target, id))
- {
- return;
- }
-
- gl::Error error = context->beginQuery(target, id);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::AttachShader(program, shader);
}
void GL_APIENTRY glBindAttribLocation(GLuint program, GLuint index, const GLchar* name)
{
- EVENT("(GLuint program = %d, GLuint index = %d, const GLchar* name = 0x%0.8p)", program, index, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (strncmp(name, "gl_", 3) == 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- programObject->bindAttributeLocation(index, name);
- }
+ return gl::BindAttribLocation(program, index, name);
}
void GL_APIENTRY glBindBuffer(GLenum target, GLuint buffer)
{
- EVENT("(GLenum target = 0x%X, GLuint buffer = %d)", target, buffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_ARRAY_BUFFER:
- context->bindArrayBuffer(buffer);
- return;
- case GL_ELEMENT_ARRAY_BUFFER:
- context->bindElementArrayBuffer(buffer);
- return;
- case GL_COPY_READ_BUFFER:
- context->bindCopyReadBuffer(buffer);
- return;
- case GL_COPY_WRITE_BUFFER:
- context->bindCopyWriteBuffer(buffer);
- return;
- case GL_PIXEL_PACK_BUFFER:
- context->bindPixelPackBuffer(buffer);
- return;
- case GL_PIXEL_UNPACK_BUFFER:
- context->bindPixelUnpackBuffer(buffer);
- return;
- case GL_UNIFORM_BUFFER:
- context->bindGenericUniformBuffer(buffer);
- return;
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- context->bindGenericTransformFeedbackBuffer(buffer);
- return;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::BindBuffer(target, buffer);
}
void GL_APIENTRY glBindFramebuffer(GLenum target, GLuint framebuffer)
{
- EVENT("(GLenum target = 0x%X, GLuint framebuffer = %d)", target, framebuffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidFramebufferTarget(target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (target == GL_READ_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindReadFramebuffer(framebuffer);
- }
-
- if (target == GL_DRAW_FRAMEBUFFER_ANGLE || target == GL_FRAMEBUFFER)
- {
- context->bindDrawFramebuffer(framebuffer);
- }
- }
+ return gl::BindFramebuffer(target, framebuffer);
}
void GL_APIENTRY glBindRenderbuffer(GLenum target, GLuint renderbuffer)
{
- EVENT("(GLenum target = 0x%X, GLuint renderbuffer = %d)", target, renderbuffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->bindRenderbuffer(renderbuffer);
- }
+ return gl::BindRenderbuffer(target, renderbuffer);
}
void GL_APIENTRY glBindTexture(GLenum target, GLuint texture)
{
- EVENT("(GLenum target = 0x%X, GLuint texture = %d)", target, texture);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Texture *textureObject = context->getTexture(texture);
-
- if (textureObject && textureObject->getTarget() != target && texture != 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- case GL_TEXTURE_CUBE_MAP:
- break;
-
- case GL_TEXTURE_3D:
- case GL_TEXTURE_2D_ARRAY:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->bindTexture(target, texture);
- }
+ return gl::BindTexture(target, texture);
}
-void GL_APIENTRY glBlendColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glBlendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
- EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
- red, green, blue, alpha);
-
- gl::Context* context = gl::getNonLostContext();
-
- if (context)
- {
- context->getState().setBlendColor(gl::clamp01(red), gl::clamp01(green), gl::clamp01(blue), gl::clamp01(alpha));
- }
+ return gl::BlendColor(red, green, blue, alpha);
}
void GL_APIENTRY glBlendEquation(GLenum mode)
{
- glBlendEquationSeparate(mode, mode);
+ return gl::BlendEquation(mode);
}
void GL_APIENTRY glBlendEquationSeparate(GLenum modeRGB, GLenum modeAlpha)
{
- EVENT("(GLenum modeRGB = 0x%X, GLenum modeAlpha = 0x%X)", modeRGB, modeAlpha);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (modeRGB)
- {
- case GL_FUNC_ADD:
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- case GL_MIN:
- case GL_MAX:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (modeAlpha)
- {
- case GL_FUNC_ADD:
- case GL_FUNC_SUBTRACT:
- case GL_FUNC_REVERSE_SUBTRACT:
- case GL_MIN:
- case GL_MAX:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setBlendEquation(modeRGB, modeAlpha);
- }
+ return gl::BlendEquationSeparate(modeRGB, modeAlpha);
}
void GL_APIENTRY glBlendFunc(GLenum sfactor, GLenum dfactor)
{
- glBlendFuncSeparate(sfactor, dfactor, sfactor, dfactor);
+ return gl::BlendFunc(sfactor, dfactor);
}
void GL_APIENTRY glBlendFuncSeparate(GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha)
{
- EVENT("(GLenum srcRGB = 0x%X, GLenum dstRGB = 0x%X, GLenum srcAlpha = 0x%X, GLenum dstAlpha = 0x%X)",
- srcRGB, dstRGB, srcAlpha, dstAlpha);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (srcRGB)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (dstRGB)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- break;
-
- case GL_SRC_ALPHA_SATURATE:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (srcAlpha)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- case GL_SRC_ALPHA_SATURATE:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (dstAlpha)
- {
- case GL_ZERO:
- case GL_ONE:
- case GL_SRC_COLOR:
- case GL_ONE_MINUS_SRC_COLOR:
- case GL_DST_COLOR:
- case GL_ONE_MINUS_DST_COLOR:
- case GL_SRC_ALPHA:
- case GL_ONE_MINUS_SRC_ALPHA:
- case GL_DST_ALPHA:
- case GL_ONE_MINUS_DST_ALPHA:
- case GL_CONSTANT_COLOR:
- case GL_ONE_MINUS_CONSTANT_COLOR:
- case GL_CONSTANT_ALPHA:
- case GL_ONE_MINUS_CONSTANT_ALPHA:
- break;
-
- case GL_SRC_ALPHA_SATURATE:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- bool constantColorUsed = (srcRGB == GL_CONSTANT_COLOR || srcRGB == GL_ONE_MINUS_CONSTANT_COLOR ||
- dstRGB == GL_CONSTANT_COLOR || dstRGB == GL_ONE_MINUS_CONSTANT_COLOR);
-
- bool constantAlphaUsed = (srcRGB == GL_CONSTANT_ALPHA || srcRGB == GL_ONE_MINUS_CONSTANT_ALPHA ||
- dstRGB == GL_CONSTANT_ALPHA || dstRGB == GL_ONE_MINUS_CONSTANT_ALPHA);
-
- if (constantColorUsed && constantAlphaUsed)
- {
- ERR("Simultaneous use of GL_CONSTANT_ALPHA/GL_ONE_MINUS_CONSTANT_ALPHA and GL_CONSTANT_COLOR/GL_ONE_MINUS_CONSTANT_COLOR invalid under WebGL");
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->getState().setBlendFactors(srcRGB, dstRGB, srcAlpha, dstAlpha);
- }
+ return gl::BlendFuncSeparate(srcRGB, dstRGB, srcAlpha, dstAlpha);
}
void GL_APIENTRY glBufferData(GLenum target, GLsizeiptr size, const GLvoid* data, GLenum usage)
{
- EVENT("(GLenum target = 0x%X, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p, GLenum usage = %d)",
- target, size, data, usage);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (size < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (usage)
- {
- case GL_STREAM_DRAW:
- case GL_STATIC_DRAW:
- case GL_DYNAMIC_DRAW:
- break;
-
- case GL_STREAM_READ:
- case GL_STREAM_COPY:
- case GL_STATIC_READ:
- case GL_STATIC_COPY:
- case GL_DYNAMIC_READ:
- case GL_DYNAMIC_COPY:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Error error = buffer->bufferData(data, size, usage);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::BufferData(target, size, data, usage);
}
void GL_APIENTRY glBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size, const GLvoid* data)
{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr size = %d, const GLvoid* data = 0x%0.8p)",
- target, offset, size, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (size < 0 || offset < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (data == NULL)
- {
- return;
- }
-
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (buffer->isMapped())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Check for possible overflow of size + offset
- if (!rx::IsUnsignedAdditionSafe<size_t>(size, offset))
- {
- context->recordError(gl::Error(GL_OUT_OF_MEMORY));
- return;
- }
-
- if (size + offset > buffer->getSize())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Error error = buffer->bufferSubData(data, size, offset);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::BufferSubData(target, offset, size, data);
}
GLenum GL_APIENTRY glCheckFramebufferStatus(GLenum target)
{
- EVENT("(GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidFramebufferTarget(target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return 0;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- return framebuffer->completeness(context->getData());
- }
-
- return 0;
+ return gl::CheckFramebufferStatus(target);
}
void GL_APIENTRY glClear(GLbitfield mask)
{
- EVENT("(GLbitfield mask = 0x%X)", mask);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Framebuffer *framebufferObject = context->getState().getDrawFramebuffer();
- ASSERT(framebufferObject);
-
- if (framebufferObject->completeness(context->getData()) != GL_FRAMEBUFFER_COMPLETE)
- {
- context->recordError(gl::Error(GL_INVALID_FRAMEBUFFER_OPERATION));
- return;
- }
-
- if ((mask & ~(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)) != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Error error = context->clear(mask);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::Clear(mask);
}
-void GL_APIENTRY glClearColor(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha)
+void GL_APIENTRY glClearColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{
- EVENT("(GLclampf red = %f, GLclampf green = %f, GLclampf blue = %f, GLclampf alpha = %f)",
- red, green, blue, alpha);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setClearColor(red, green, blue, alpha);
- }
+ return gl::ClearColor(red, green, blue, alpha);
}
-void GL_APIENTRY glClearDepthf(GLclampf depth)
+void GL_APIENTRY glClearDepthf(GLfloat depth)
{
- EVENT("(GLclampf depth = %f)", depth);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setClearDepth(depth);
- }
+ return gl::ClearDepthf(depth);
}
void GL_APIENTRY glClearStencil(GLint s)
{
- EVENT("(GLint s = %d)", s);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setClearStencil(s);
- }
+ return gl::ClearStencil(s);
}
void GL_APIENTRY glColorMask(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha)
{
- EVENT("(GLboolean red = %d, GLboolean green = %u, GLboolean blue = %u, GLboolean alpha = %u)",
- red, green, blue, alpha);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setColorMask(red == GL_TRUE, green == GL_TRUE, blue == GL_TRUE, alpha == GL_TRUE);
- }
+ return gl::ColorMask(red, green, blue, alpha);
}
void GL_APIENTRY glCompileShader(GLuint shader)
{
- EVENT("(GLuint shader = %d)", shader);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- if (context->getProgram(shader))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- shaderObject->compile(context->getData());
- }
-}
-
-void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height,
- GLint border, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLint border = %d, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, internalformat, width, height, border, imageSize, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, internalformat, true, false,
- 0, 0, width, height, border, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
- 0, 0, 0, width, height, 1, border, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->setCompressedImage(level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->setCompressedImage(target, level, internalformat, width, height, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLsizei imageSize, const GLvoid* data)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, "
- "GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, imageSize, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, GL_NONE, true, true,
- xoffset, yoffset, width, height, 0, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
- xoffset, yoffset, 0, width, height, 1, 0, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->subImageCompressed(target, level, xoffset, yoffset, width, height, format, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::CompileShader(shader);
+}
+
+void GL_APIENTRY glCompressedTexImage2D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLint border, GLsizei imageSize, const GLvoid* data)
+{
+ return gl::CompressedTexImage2D(target, level, internalformat, width, height, border, imageSize, data);
+}
+
+void GL_APIENTRY glCompressedTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, const GLvoid* data)
+{
+ return gl::CompressedTexSubImage2D(target, level, xoffset, yoffset, width, height, format, imageSize, data);
}
void GL_APIENTRY glCopyTexImage2D(GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
- "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, GLint border = %d)",
- target, level, internalformat, x, y, width, height, border);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2CopyTexImageParameters(context, target, level, internalformat, false,
- 0, 0, x, y, width, height, border))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3CopyTexImageParameters(context, target, level, internalformat, false,
- 0, 0, 0, x, y, width, height, border))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->copyImage(level, internalformat, x, y, width, height, framebuffer);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->copyImage(target, level, internalformat, x, y, width, height, framebuffer);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::CopyTexImage2D(target, level, internalformat, x, y, width, height, border);
}
void GL_APIENTRY glCopyTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, level, xoffset, yoffset, x, y, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2CopyTexImageParameters(context, target, level, GL_NONE, true,
- xoffset, yoffset, x, y, width, height, 0))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true,
- xoffset, yoffset, 0, x, y, width, height, 0))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, 0, x, y, width, height, framebuffer);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::CopyTexSubImage2D(target, level, xoffset, yoffset, x, y, width, height);
}
GLuint GL_APIENTRY glCreateProgram(void)
{
- EVENT("()");
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- return context->createProgram();
- }
-
- return 0;
+ return gl::CreateProgram();
}
GLuint GL_APIENTRY glCreateShader(GLenum type)
{
- EVENT("(GLenum type = 0x%X)", type);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (type)
- {
- case GL_FRAGMENT_SHADER:
- case GL_VERTEX_SHADER:
- return context->createShader(type);
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return 0;
- }
- }
-
- return 0;
+ return gl::CreateShader(type);
}
void GL_APIENTRY glCullFace(GLenum mode)
{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (mode)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setCullMode(mode);
- }
+ return gl::CullFace(mode);
}
void GL_APIENTRY glDeleteBuffers(GLsizei n, const GLuint* buffers)
{
- EVENT("(GLsizei n = %d, const GLuint* buffers = 0x%0.8p)", n, buffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteBuffer(buffers[i]);
- }
- }
-}
-
-void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
-{
- EVENT("(GLsizei n = %d, const GLuint* fences = 0x%0.8p)", n, fences);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteFenceNV(fences[i]);
- }
- }
+ return gl::DeleteBuffers(n, buffers);
}
void GL_APIENTRY glDeleteFramebuffers(GLsizei n, const GLuint* framebuffers)
{
- EVENT("(GLsizei n = %d, const GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- if (framebuffers[i] != 0)
- {
- context->deleteFramebuffer(framebuffers[i]);
- }
- }
- }
+ return gl::DeleteFramebuffers(n, framebuffers);
}
void GL_APIENTRY glDeleteProgram(GLuint program)
{
- EVENT("(GLuint program = %d)", program);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (program == 0)
- {
- return;
- }
-
- if (!context->getProgram(program))
- {
- if(context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- context->deleteProgram(program);
- }
-}
-
-void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
-{
- EVENT("(GLsizei n = %d, const GLuint *ids = 0x%0.8p)", n, ids);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteQuery(ids[i]);
- }
- }
+ return gl::DeleteProgram(program);
}
void GL_APIENTRY glDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers)
{
- EVENT("(GLsizei n = %d, const GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- context->deleteRenderbuffer(renderbuffers[i]);
- }
- }
+ return gl::DeleteRenderbuffers(n, renderbuffers);
}
void GL_APIENTRY glDeleteShader(GLuint shader)
{
- EVENT("(GLuint shader = %d)", shader);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (shader == 0)
- {
- return;
- }
-
- if (!context->getShader(shader))
- {
- if(context->getProgram(shader))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- context->deleteShader(shader);
- }
+ return gl::DeleteShader(shader);
}
void GL_APIENTRY glDeleteTextures(GLsizei n, const GLuint* textures)
{
- EVENT("(GLsizei n = %d, const GLuint* textures = 0x%0.8p)", n, textures);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- if (textures[i] != 0)
- {
- context->deleteTexture(textures[i]);
- }
- }
- }
+ return gl::DeleteTextures(n, textures);
}
void GL_APIENTRY glDepthFunc(GLenum func)
{
- EVENT("(GLenum func = 0x%X)", func);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GREATER:
- case GL_GEQUAL:
- case GL_NOTEQUAL:
- context->getState().setDepthFunc(func);
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::DepthFunc(func);
}
void GL_APIENTRY glDepthMask(GLboolean flag)
{
- EVENT("(GLboolean flag = %u)", flag);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setDepthMask(flag != GL_FALSE);
- }
+ return gl::DepthMask(flag);
}
-void GL_APIENTRY glDepthRangef(GLclampf zNear, GLclampf zFar)
+void GL_APIENTRY glDepthRangef(GLfloat n, GLfloat f)
{
- EVENT("(GLclampf zNear = %f, GLclampf zFar = %f)", zNear, zFar);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setDepthRange(zNear, zFar);
- }
+ return gl::DepthRangef(n, f);
}
void GL_APIENTRY glDetachShader(GLuint program, GLuint shader)
{
- EVENT("(GLuint program = %d, GLuint shader = %d)", program, shader);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!programObject)
- {
- gl::Shader *shaderByProgramHandle;
- shaderByProgramHandle = context->getShader(program);
- if (!shaderByProgramHandle)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
-
- if (!shaderObject)
- {
- gl::Program *programByShaderHandle = context->getProgram(shader);
- if (!programByShaderHandle)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
-
- if (!programObject->detachShader(shaderObject))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
+ return gl::DetachShader(program, shader);
}
void GL_APIENTRY glDisable(GLenum cap)
{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setEnableFeature(cap, false);
- }
+ return gl::Disable(cap);
}
void GL_APIENTRY glDisableVertexAttribArray(GLuint index)
{
- EVENT("(GLuint index = %d)", index);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setEnableVertexAttribArray(index, false);
- }
+ return gl::DisableVertexAttribArray(index);
}
void GL_APIENTRY glDrawArrays(GLenum mode, GLint first, GLsizei count)
{
- EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d)", mode, first, count);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateDrawArrays(context, mode, first, count, 0))
- {
- return;
- }
-
- gl::Error error = context->drawArrays(mode, first, count, 0);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
-{
- EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei primcount = %d)", mode, first, count, primcount);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateDrawArraysInstancedANGLE(context, mode, first, count, primcount))
- {
- return;
- }
-
- gl::Error error = context->drawArrays(mode, first, count, primcount);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::DrawArrays(mode, first, count);
}
void GL_APIENTRY glDrawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices)
{
- EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p)",
- mode, count, type, indices);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- rx::RangeUI indexRange;
- if (!ValidateDrawElements(context, mode, count, type, indices, 0, &indexRange))
- {
- return;
- }
-
- gl::Error error = context->drawElements(mode, count, type, indices, 0, indexRange);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices, GLsizei primcount)
-{
- EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei primcount = %d)",
- mode, count, type, indices, primcount);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- rx::RangeUI indexRange;
- if (!ValidateDrawElementsInstancedANGLE(context, mode, count, type, indices, primcount, &indexRange))
- {
- return;
- }
-
- gl::Error error = context->drawElements(mode, count, type, indices, primcount, indexRange);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::DrawElements(mode, count, type, indices);
}
void GL_APIENTRY glEnable(GLenum cap)
{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- context->getState().setEnableFeature(cap, true);
- }
+ return gl::Enable(cap);
}
void GL_APIENTRY glEnableVertexAttribArray(GLuint index)
{
- EVENT("(GLuint index = %d)", index);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setEnableVertexAttribArray(index, true);
- }
-}
-
-void GL_APIENTRY glEndQueryEXT(GLenum target)
-{
- EVENT("GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateEndQuery(context, target))
- {
- return;
- }
-
- gl::Error error = context->endQuery(target);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glFinishFenceNV(GLuint fence)
-{
- EVENT("(GLuint fence = %d)", fence);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::FenceNV *fenceObject = context->getFenceNV(fence);
-
- if (fenceObject == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (fenceObject->isFence() != GL_TRUE)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- fenceObject->finishFence();
- }
+ return gl::EnableVertexAttribArray(index);
}
void GL_APIENTRY glFinish(void)
{
- EVENT("()");
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Error error = context->sync(true);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::Finish();
}
void GL_APIENTRY glFlush(void)
{
- EVENT("()");
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Error error = context->sync(false);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::Flush();
}
void GL_APIENTRY glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum renderbuffertarget = 0x%X, "
- "GLuint renderbuffer = %d)", target, attachment, renderbuffertarget, renderbuffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidFramebufferTarget(target) || (renderbuffertarget != GL_RENDERBUFFER && renderbuffer != 0))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!gl::ValidateFramebufferRenderbufferParameters(context, target, attachment, renderbuffertarget, renderbuffer))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (renderbuffer != 0)
- {
- gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
- framebuffer->setRenderbufferAttachment(attachment, renderbufferObject);
- }
- else
- {
- framebuffer->setNULLAttachment(attachment);
- }
- }
+ return gl::FramebufferRenderbuffer(target, attachment, renderbuffertarget, renderbuffer);
}
void GL_APIENTRY glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum textarget = 0x%X, "
- "GLuint texture = %d, GLint level = %d)", target, attachment, textarget, texture, level);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateFramebufferTexture2D(context, target, attachment, textarget, texture, level))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (texture != 0)
- {
- gl::Texture *textureObj = context->getTexture(texture);
- gl::ImageIndex index(textarget, level, gl::ImageIndex::ENTIRE_LEVEL);
- framebuffer->setTextureAttachment(attachment, textureObj, index);
- }
- else
- {
- framebuffer->setNULLAttachment(attachment);
- }
- }
+ return gl::FramebufferTexture2D(target, attachment, textarget, texture, level);
}
void GL_APIENTRY glFrontFace(GLenum mode)
{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (mode)
- {
- case GL_CW:
- case GL_CCW:
- context->getState().setFrontFace(mode);
- break;
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::FrontFace(mode);
}
void GL_APIENTRY glGenBuffers(GLsizei n, GLuint* buffers)
{
- EVENT("(GLsizei n = %d, GLuint* buffers = 0x%0.8p)", n, buffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- buffers[i] = context->createBuffer();
- }
- }
+ return gl::GenBuffers(n, buffers);
}
void GL_APIENTRY glGenerateMipmap(GLenum target)
{
- EVENT("(GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidTextureTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Texture *texture = context->getTargetTexture(target);
-
- if (texture == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- GLenum internalFormat = texture->getBaseLevelInternalFormat();
- const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalFormat);
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalFormat);
-
- // GenerateMipmap should not generate an INVALID_OPERATION for textures created with
- // unsized formats or that are color renderable and filterable. Since we do not track if
- // the texture was created with sized or unsized format (only sized formats are stored),
- // it is not possible to make sure the the LUMA formats can generate mipmaps (they should
- // be able to) because they aren't color renderable. Simply do a special case for LUMA
- // textures since they're the only texture format that can be created with unsized formats
- // that is not color renderable. New unsized formats are unlikely to be added, since ES2
- // was the last version to use add them.
- bool isLUMA = internalFormat == GL_LUMINANCE8_EXT ||
- internalFormat == GL_LUMINANCE8_ALPHA8_EXT ||
- internalFormat == GL_ALPHA8_EXT;
-
- if (formatInfo.depthBits > 0 || formatInfo.stencilBits > 0 || !formatCaps.filterable ||
- (!formatCaps.renderable && !isLUMA) || formatInfo.compressed)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // GL_EXT_sRGB does not support mipmap generation on sRGB textures
- if (context->getClientVersion() == 2 && formatInfo.colorEncoding == GL_SRGB)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Non-power of 2 ES2 check
- if (!context->getExtensions().textureNPOT && (!gl::isPow2(texture->getBaseLevelWidth()) || !gl::isPow2(texture->getBaseLevelHeight())))
- {
- ASSERT(context->getClientVersion() <= 2 && (target == GL_TEXTURE_2D || target == GL_TEXTURE_CUBE_MAP));
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Cube completeness check
- if (target == GL_TEXTURE_CUBE_MAP)
- {
- gl::TextureCubeMap *textureCube = static_cast<gl::TextureCubeMap *>(texture);
- if (!textureCube->isCubeComplete())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
-
- gl::Error error = texture->generateMipmaps();
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
-{
- EVENT("(GLsizei n = %d, GLuint* fences = 0x%0.8p)", n, fences);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- fences[i] = context->createFenceNV();
- }
- }
+ return gl::GenerateMipmap(target);
}
void GL_APIENTRY glGenFramebuffers(GLsizei n, GLuint* framebuffers)
{
- EVENT("(GLsizei n = %d, GLuint* framebuffers = 0x%0.8p)", n, framebuffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- framebuffers[i] = context->createFramebuffer();
- }
- }
+ return gl::GenFramebuffers(n, framebuffers);
}
-void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint* ids)
+void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (GLsizei i = 0; i < n; i++)
- {
- ids[i] = context->createQuery();
- }
- }
+ return gl::GenRenderbuffers(n, renderbuffers);
}
-void GL_APIENTRY glGenRenderbuffers(GLsizei n, GLuint* renderbuffers)
+void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
{
- EVENT("(GLsizei n = %d, GLuint* renderbuffers = 0x%0.8p)", n, renderbuffers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- renderbuffers[i] = context->createRenderbuffer();
- }
- }
+ return gl::GenTextures(n, textures);
}
-void GL_APIENTRY glGenTextures(GLsizei n, GLuint* textures)
+void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
{
- EVENT("(GLsizei n = %d, GLuint* textures = 0x%0.8p)", n, textures);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < n; i++)
- {
- textures[i] = context->createTexture();
- }
- }
-}
-
-void GL_APIENTRY glGetActiveAttrib(GLuint program, GLuint index, GLsizei bufsize, GLsizei *length, GLint *size, GLenum *type, GLchar *name)
-{
- EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, GLsizei *length = 0x%0.8p, "
- "GLint *size = 0x%0.8p, GLenum *type = %0.8p, GLchar *name = %0.8p)",
- program, index, bufsize, length, size, type, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (index >= (GLuint)programObject->getActiveAttributeCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getActiveAttribute(index, bufsize, length, size, type, name);
- }
+ return gl::GetActiveAttrib(program, index, bufsize, length, size, type, name);
}
void GL_APIENTRY glGetActiveUniform(GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, GLint* size, GLenum* type, GLchar* name)
{
- EVENT("(GLuint program = %d, GLuint index = %d, GLsizei bufsize = %d, "
- "GLsizei* length = 0x%0.8p, GLint* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
- program, index, bufsize, length, size, type, name);
-
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (index >= (GLuint)programObject->getActiveUniformCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getActiveUniform(index, bufsize, length, size, type, name);
- }
+ return gl::GetActiveUniform(program, index, bufsize, length, size, type, name);
}
void GL_APIENTRY glGetAttachedShaders(GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders)
{
- EVENT("(GLuint program = %d, GLsizei maxcount = %d, GLsizei* count = 0x%0.8p, GLuint* shaders = 0x%0.8p)",
- program, maxcount, count, shaders);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (maxcount < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- return programObject->getAttachedShaders(maxcount, count, shaders);
- }
+ return gl::GetAttachedShaders(program, maxcount, count, shaders);
}
GLint GL_APIENTRY glGetAttribLocation(GLuint program, const GLchar* name)
{
- EVENT("(GLuint program = %d, const GLchar* name = %s)", program, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return -1;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programObject->isLinked() || !programBinary)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programBinary->getAttributeLocation(name);
- }
-
- return -1;
+ return gl::GetAttribLocation(program, name);
}
void GL_APIENTRY glGetBooleanv(GLenum pname, GLboolean* params)
{
- EVENT("(GLenum pname = 0x%X, GLboolean* params = 0x%0.8p)", pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_BOOL)
- {
- context->getBooleanv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
+ return gl::GetBooleanv(pname, params);
}
void GL_APIENTRY glGetBufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!gl::ValidBufferParameter(context, pname))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- // A null buffer means that "0" is bound to the requested buffer target
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (pname)
- {
- case GL_BUFFER_USAGE:
- *params = static_cast<GLint>(buffer->getUsage());
- break;
- case GL_BUFFER_SIZE:
- *params = gl::clampCast<GLint>(buffer->getSize());
- break;
- case GL_BUFFER_ACCESS_FLAGS:
- *params = buffer->getAccessFlags();
- break;
- case GL_BUFFER_MAPPED:
- *params = static_cast<GLint>(buffer->isMapped());
- break;
- case GL_BUFFER_MAP_OFFSET:
- *params = gl::clampCast<GLint>(buffer->getMapOffset());
- break;
- case GL_BUFFER_MAP_LENGTH:
- *params = gl::clampCast<GLint>(buffer->getMapLength());
- break;
- default: UNREACHABLE(); break;
- }
- }
+ return gl::GetBufferParameteriv(target, pname, params);
}
GLenum GL_APIENTRY glGetError(void)
{
- EVENT("()");
-
- gl::Context *context = gl::getContext();
-
- if (context)
- {
- return context->getError();
- }
-
- return GL_NO_ERROR;
-}
-
-void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
-{
- EVENT("(GLuint fence = %d, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", fence, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::FenceNV *fenceObject = context->getFenceNV(fence);
-
- if (fenceObject == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (fenceObject->isFence() != GL_TRUE)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (pname)
- {
- case GL_FENCE_STATUS_NV:
- {
- // GL_NV_fence spec:
- // Once the status of a fence has been finished (via FinishFenceNV) or tested and the returned status is TRUE (via either TestFenceNV
- // or GetFenceivNV querying the FENCE_STATUS_NV), the status remains TRUE until the next SetFenceNV of the fence.
- GLboolean status = GL_TRUE;
- if (fenceObject->getStatus() != GL_TRUE)
- {
- gl::Error error = fenceObject->testFence(&status);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- *params = status;
- break;
- }
-
- case GL_FENCE_CONDITION_NV:
- {
- *params = fenceObject->getCondition();
- break;
- }
-
- default:
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
- }
+ return gl::GetError();
}
void GL_APIENTRY glGetFloatv(GLenum pname, GLfloat* params)
{
- EVENT("(GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_FLOAT)
- {
- context->getFloatv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
+ return gl::GetFloatv(pname, params);
}
void GL_APIENTRY glGetFramebufferAttachmentParameteriv(GLenum target, GLenum attachment, GLenum pname, GLint* params)
{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- target, attachment, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidFramebufferTarget(target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- int clientVersion = context->getClientVersion();
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- if (clientVersion < 3 && !context->getExtensions().sRGB)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
- if (clientVersion < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- // Determine if the attachment is a valid enum
- switch (attachment)
- {
- case GL_BACK:
- case GL_FRONT:
- case GL_DEPTH:
- case GL_STENCIL:
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (clientVersion < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
-
- default:
- if (attachment < GL_COLOR_ATTACHMENT0_EXT ||
- (attachment - GL_COLOR_ATTACHMENT0_EXT) >= context->getCaps().maxColorAttachments)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
- }
-
- GLuint framebufferHandle = context->getState().getTargetFramebuffer(target)->id();
- gl::Framebuffer *framebuffer = context->getFramebuffer(framebufferHandle);
- ASSERT(framebuffer);
-
- if (framebufferHandle == 0)
- {
- if (clientVersion < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (attachment)
- {
- case GL_BACK:
- case GL_DEPTH:
- case GL_STENCIL:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
- else
- {
- if (attachment >= GL_COLOR_ATTACHMENT0_EXT && attachment <= GL_COLOR_ATTACHMENT15_EXT)
- {
- // Valid attachment query
- }
- else
- {
- switch (attachment)
- {
- case GL_DEPTH_ATTACHMENT:
- case GL_STENCIL_ATTACHMENT:
- break;
-
- case GL_DEPTH_STENCIL_ATTACHMENT:
- if (framebuffer->hasValidDepthStencil())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
- }
-
- GLenum attachmentType = GL_NONE;
- GLuint attachmentHandle = 0;
- GLuint attachmentLevel = 0;
- GLuint attachmentLayer = 0;
-
- const gl::FramebufferAttachment *attachmentObject = framebuffer->getAttachment(attachment);
-
- if (attachmentObject)
- {
- attachmentType = attachmentObject->type();
- attachmentHandle = attachmentObject->id();
- attachmentLevel = attachmentObject->mipLevel();
- attachmentLayer = attachmentObject->layer();
- }
-
- GLenum attachmentObjectType; // Type category
- if (framebufferHandle == 0)
- {
- attachmentObjectType = GL_FRAMEBUFFER_DEFAULT;
- }
- else if (attachmentType == GL_NONE || attachmentType == GL_RENDERBUFFER)
- {
- attachmentObjectType = attachmentType;
- }
- else if (gl::ValidTexture2DDestinationTarget(context, attachmentType))
- {
- attachmentObjectType = GL_TEXTURE;
- }
- else
- {
- UNREACHABLE();
- return;
- }
-
- if (attachmentObjectType == GL_NONE)
- {
- // ES 2.0.25 spec pg 127 states that if the value of FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE
- // is NONE, then querying any other pname will generate INVALID_ENUM.
-
- // ES 3.0.2 spec pg 235 states that if the attachment type is none,
- // GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME will return zero and be an
- // INVALID_OPERATION for all other pnames
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- *params = attachmentObjectType;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- if (clientVersion < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = 0;
- break;
-
- default:
- if (clientVersion < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
- }
- else
- {
- ASSERT(attachmentObjectType == GL_RENDERBUFFER || attachmentObjectType == GL_TEXTURE ||
- attachmentObjectType == GL_FRAMEBUFFER_DEFAULT);
- ASSERT(attachmentObject != NULL);
-
- switch (pname)
- {
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE:
- *params = attachmentObjectType;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME:
- if (attachmentObjectType != GL_RENDERBUFFER && attachmentObjectType != GL_TEXTURE)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentHandle;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL:
- if (attachmentObjectType != GL_TEXTURE)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentLevel;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE:
- if (attachmentObjectType != GL_TEXTURE)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = gl::IsCubemapTextureTarget(attachmentType) ? attachmentType : 0;
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE:
- *params = attachmentObject->getRedSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE:
- *params = attachmentObject->getGreenSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE:
- *params = attachmentObject->getBlueSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE:
- *params = attachmentObject->getAlphaSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE:
- *params = attachmentObject->getDepthSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE:
- *params = attachmentObject->getStencilSize();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE:
- if (attachment == GL_DEPTH_STENCIL_ATTACHMENT)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- *params = attachmentObject->getComponentType();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING:
- *params = attachmentObject->getColorEncoding();
- break;
-
- case GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LAYER:
- if (attachmentObjectType != GL_TEXTURE)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = attachmentLayer;
- break;
-
- default:
- UNREACHABLE();
- break;
- }
- }
- }
-}
-
-GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
-{
- EVENT("()");
-
- gl::Context *context = gl::getContext();
-
- if (context)
- {
- return context->getResetStatus();
- }
-
- return GL_NO_ERROR;
+ return gl::GetFramebufferAttachmentParameteriv(target, attachment, pname, params);
}
void GL_APIENTRY glGetIntegerv(GLenum pname, GLint* params)
{
- EVENT("(GLenum pname = 0x%X, GLint* params = 0x%0.8p)", pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- GLenum nativeType;
- unsigned int numParams = 0;
-
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_INT)
- {
- context->getIntegerv(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
+ return gl::GetIntegerv(pname, params);
}
void GL_APIENTRY glGetProgramiv(GLuint program, GLenum pname, GLint* params)
{
- EVENT("(GLuint program = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", program, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (context->getClientVersion() < 3)
- {
- switch (pname)
- {
- case GL_ACTIVE_UNIFORM_BLOCKS:
- case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
- case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
- case GL_TRANSFORM_FEEDBACK_VARYINGS:
- case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-
- switch (pname)
- {
- case GL_DELETE_STATUS:
- *params = programObject->isFlaggedForDeletion();
- return;
- case GL_LINK_STATUS:
- *params = programObject->isLinked();
- return;
- case GL_VALIDATE_STATUS:
- *params = programObject->isValidated();
- return;
- case GL_INFO_LOG_LENGTH:
- *params = programObject->getInfoLogLength();
- return;
- case GL_ATTACHED_SHADERS:
- *params = programObject->getAttachedShadersCount();
- return;
- case GL_ACTIVE_ATTRIBUTES:
- *params = programObject->getActiveAttributeCount();
- return;
- case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
- *params = programObject->getActiveAttributeMaxLength();
- return;
- case GL_ACTIVE_UNIFORMS:
- *params = programObject->getActiveUniformCount();
- return;
- case GL_ACTIVE_UNIFORM_MAX_LENGTH:
- *params = programObject->getActiveUniformMaxLength();
- return;
- case GL_PROGRAM_BINARY_LENGTH_OES:
- *params = programObject->getProgramBinaryLength();
- return;
- case GL_ACTIVE_UNIFORM_BLOCKS:
- *params = programObject->getActiveUniformBlockCount();
- return;
- case GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH:
- *params = programObject->getActiveUniformBlockMaxLength();
- break;
- case GL_TRANSFORM_FEEDBACK_BUFFER_MODE:
- *params = programObject->getTransformFeedbackBufferMode();
- break;
- case GL_TRANSFORM_FEEDBACK_VARYINGS:
- *params = programObject->getTransformFeedbackVaryingCount();
- break;
- case GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH:
- *params = programObject->getTransformFeedbackVaryingMaxLength();
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetProgramiv(program, pname, params);
}
void GL_APIENTRY glGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
- EVENT("(GLuint program = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
- program, bufsize, length, infolog);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getInfoLog(bufsize, length, infolog);
- }
-}
-
-void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
-{
- EVENT("GLenum target = 0x%X, GLenum pname = 0x%X, GLint *params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidQueryType(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_CURRENT_QUERY_EXT:
- params[0] = context->getState().getActiveQueryId(target);
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
-{
- EVENT("(GLuint id = %d, GLenum pname = 0x%X, GLuint *params = 0x%0.8p)", id, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-
- if (!queryObject)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (context->getState().getActiveQueryId(queryObject->getType()) == id)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch(pname)
- {
- case GL_QUERY_RESULT_EXT:
- {
- gl::Error error = queryObject->getResult(params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_QUERY_RESULT_AVAILABLE_EXT:
- {
- gl::Error error = queryObject->isResultAvailable(params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetProgramInfoLog(program, bufsize, length, infolog);
}
void GL_APIENTRY glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (context->getState().getRenderbufferId() == 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Renderbuffer *renderbuffer = context->getRenderbuffer(context->getState().getRenderbufferId());
-
- switch (pname)
- {
- case GL_RENDERBUFFER_WIDTH: *params = renderbuffer->getWidth(); break;
- case GL_RENDERBUFFER_HEIGHT: *params = renderbuffer->getHeight(); break;
- case GL_RENDERBUFFER_INTERNAL_FORMAT: *params = renderbuffer->getInternalFormat(); break;
- case GL_RENDERBUFFER_RED_SIZE: *params = renderbuffer->getRedSize(); break;
- case GL_RENDERBUFFER_GREEN_SIZE: *params = renderbuffer->getGreenSize(); break;
- case GL_RENDERBUFFER_BLUE_SIZE: *params = renderbuffer->getBlueSize(); break;
- case GL_RENDERBUFFER_ALPHA_SIZE: *params = renderbuffer->getAlphaSize(); break;
- case GL_RENDERBUFFER_DEPTH_SIZE: *params = renderbuffer->getDepthSize(); break;
- case GL_RENDERBUFFER_STENCIL_SIZE: *params = renderbuffer->getStencilSize(); break;
-
- case GL_RENDERBUFFER_SAMPLES_ANGLE:
- if (!context->getExtensions().framebufferMultisample)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = renderbuffer->getSamples();
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetRenderbufferParameteriv(target, pname, params);
}
void GL_APIENTRY glGetShaderiv(GLuint shader, GLenum pname, GLint* params)
{
- EVENT("(GLuint shader = %d, GLenum pname = %d, GLint* params = 0x%0.8p)", shader, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_SHADER_TYPE:
- *params = shaderObject->getType();
- return;
- case GL_DELETE_STATUS:
- *params = shaderObject->isFlaggedForDeletion();
- return;
- case GL_COMPILE_STATUS:
- *params = shaderObject->isCompiled() ? GL_TRUE : GL_FALSE;
- return;
- case GL_INFO_LOG_LENGTH:
- *params = shaderObject->getInfoLogLength();
- return;
- case GL_SHADER_SOURCE_LENGTH:
- *params = shaderObject->getSourceLength();
- return;
- case GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE:
- *params = shaderObject->getTranslatedSourceLength();
- return;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetShaderiv(shader, pname, params);
}
void GL_APIENTRY glGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* infolog)
{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* infolog = 0x%0.8p)",
- shader, bufsize, length, infolog);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- shaderObject->getInfoLog(bufsize, length, infolog);
- }
+ return gl::GetShaderInfoLog(shader, bufsize, length, infolog);
}
void GL_APIENTRY glGetShaderPrecisionFormat(GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision)
{
- EVENT("(GLenum shadertype = 0x%X, GLenum precisiontype = 0x%X, GLint* range = 0x%0.8p, GLint* precision = 0x%0.8p)",
- shadertype, precisiontype, range, precision);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (shadertype)
- {
- case GL_VERTEX_SHADER:
- case GL_FRAGMENT_SHADER:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (precisiontype)
- {
- case GL_LOW_FLOAT:
- case GL_MEDIUM_FLOAT:
- case GL_HIGH_FLOAT:
- // Assume IEEE 754 precision
- range[0] = 127;
- range[1] = 127;
- *precision = 23;
- break;
-
- case GL_LOW_INT:
- case GL_MEDIUM_INT:
- case GL_HIGH_INT:
- // Some (most) hardware only supports single-precision floating-point numbers,
- // which can accurately represent integers up to +/-16777216
- range[0] = 24;
- range[1] = 24;
- *precision = 0;
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetShaderPrecisionFormat(shadertype, precisiontype, range, precision);
}
void GL_APIENTRY glGetShaderSource(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
- shader, bufsize, length, source);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- shaderObject->getSource(bufsize, length, source);
- }
-}
-
-void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei* length, GLchar* source)
-{
- EVENT("(GLuint shader = %d, GLsizei bufsize = %d, GLsizei* length = 0x%0.8p, GLchar* source = 0x%0.8p)",
- shader, bufsize, length, source);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (bufsize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Only returns extra info if ANGLE_GENERATE_SHADER_DEBUG_INFO is defined
- shaderObject->getTranslatedSourceWithDebugInfo(bufsize, length, source);
- }
+ return gl::GetShaderSource(shader, bufsize, length, source);
}
const GLubyte* GL_APIENTRY glGetString(GLenum name)
{
- EVENT("(GLenum name = 0x%X)", name);
-
- gl::Context *context = gl::getNonLostContext();
-
- switch (name)
- {
- case GL_VENDOR:
- return (GLubyte*)"Google Inc.";
-
- case GL_RENDERER:
- return (GLubyte*)((context != NULL) ? context->getRendererString().c_str() : "ANGLE");
-
- case GL_VERSION:
- if (context->getClientVersion() == 2)
- {
- return (GLubyte*)"OpenGL ES 2.0 (ANGLE " ANGLE_VERSION_STRING ")";
- }
- else
- {
- return (GLubyte*)"OpenGL ES 3.0 (ANGLE " ANGLE_VERSION_STRING ")";
- }
-
- case GL_SHADING_LANGUAGE_VERSION:
- if (context->getClientVersion() == 2)
- {
- return (GLubyte*)"OpenGL ES GLSL ES 1.00 (ANGLE " ANGLE_VERSION_STRING ")";
- }
- else
- {
- return (GLubyte*)"OpenGL ES GLSL ES 3.00 (ANGLE " ANGLE_VERSION_STRING ")";
- }
-
- case GL_EXTENSIONS:
- return (GLubyte*)((context != NULL) ? context->getExtensionString().c_str() : "");
-
- default:
- if (context)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- }
- return NULL;
- }
+ return gl::GetString(name);
}
void GL_APIENTRY glGetTexParameterfv(GLenum target, GLenum pname, GLfloat* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_MAG_FILTER:
- *params = (GLfloat)texture->getSamplerState().magFilter;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = (GLfloat)texture->getSamplerState().minFilter;
- break;
- case GL_TEXTURE_WRAP_S:
- *params = (GLfloat)texture->getSamplerState().wrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = (GLfloat)texture->getSamplerState().wrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().wrapR;
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT:
- // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
- *params = (GLfloat)(texture->isImmutable() ? GL_TRUE : GL_FALSE);
- break;
- case GL_TEXTURE_IMMUTABLE_LEVELS:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->immutableLevelCount();
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = (GLfloat)texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->getExtensions().textureFilterAnisotropic)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().maxAnisotropy;
- break;
- case GL_TEXTURE_SWIZZLE_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().swizzleRed;
- break;
- case GL_TEXTURE_SWIZZLE_G:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().swizzleGreen;
- break;
- case GL_TEXTURE_SWIZZLE_B:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().swizzleBlue;
- break;
- case GL_TEXTURE_SWIZZLE_A:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().swizzleAlpha;
- break;
- case GL_TEXTURE_BASE_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().baseLevel;
- break;
- case GL_TEXTURE_MAX_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLfloat)texture->getSamplerState().maxLevel;
- break;
- case GL_TEXTURE_MIN_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().minLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().maxLod;
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetTexParameterfv(target, pname, params);
}
void GL_APIENTRY glGetTexParameteriv(GLenum target, GLenum pname, GLint* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_MAG_FILTER:
- *params = texture->getSamplerState().magFilter;
- break;
- case GL_TEXTURE_MIN_FILTER:
- *params = texture->getSamplerState().minFilter;
- break;
- case GL_TEXTURE_WRAP_S:
- *params = texture->getSamplerState().wrapS;
- break;
- case GL_TEXTURE_WRAP_T:
- *params = texture->getSamplerState().wrapT;
- break;
- case GL_TEXTURE_WRAP_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().wrapR;
- break;
- case GL_TEXTURE_IMMUTABLE_FORMAT:
- // Exposed to ES2.0 through EXT_texture_storage, no client version validation.
- *params = texture->isImmutable() ? GL_TRUE : GL_FALSE;
- break;
- case GL_TEXTURE_IMMUTABLE_LEVELS:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = static_cast<GLint>(texture->immutableLevelCount());
- break;
- case GL_TEXTURE_USAGE_ANGLE:
- *params = texture->getUsage();
- break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT:
- if (!context->getExtensions().textureFilterAnisotropic)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getSamplerState().maxAnisotropy;
- break;
- case GL_TEXTURE_SWIZZLE_R:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().swizzleRed;
- break;
- case GL_TEXTURE_SWIZZLE_G:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().swizzleGreen;
- break;
- case GL_TEXTURE_SWIZZLE_B:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().swizzleBlue;
- break;
- case GL_TEXTURE_SWIZZLE_A:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().swizzleAlpha;
- break;
- case GL_TEXTURE_BASE_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().baseLevel;
- break;
- case GL_TEXTURE_MAX_LEVEL:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = texture->getSamplerState().maxLevel;
- break;
- case GL_TEXTURE_MIN_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getSamplerState().minLod;
- break;
- case GL_TEXTURE_MAX_LOD:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- *params = (GLint)texture->getSamplerState().maxLod;
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, GLfloat* params)
-{
- EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLfloat* params = 0x%0.8p)",
- program, location, bufSize, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateGetnUniformfvEXT(context, program, location, bufSize, params))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- ASSERT(programBinary);
-
- programBinary->getUniformfv(location, params);
- }
+ return gl::GetTexParameteriv(target, pname, params);
}
void GL_APIENTRY glGetUniformfv(GLuint program, GLint location, GLfloat* params)
{
- EVENT("(GLuint program = %d, GLint location = %d, GLfloat* params = 0x%0.8p)", program, location, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateGetUniformfv(context, program, location, params))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- ASSERT(programBinary);
-
- programBinary->getUniformfv(location, params);
- }
-}
-
-void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint* params)
-{
- EVENT("(GLuint program = %d, GLint location = %d, GLsizei bufSize = %d, GLint* params = 0x%0.8p)",
- program, location, bufSize, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateGetnUniformivEXT(context, program, location, bufSize, params))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- ASSERT(programBinary);
-
- programBinary->getUniformiv(location, params);
- }
+ return gl::GetUniformfv(program, location, params);
}
void GL_APIENTRY glGetUniformiv(GLuint program, GLint location, GLint* params)
{
- EVENT("(GLuint program = %d, GLint location = %d, GLint* params = 0x%0.8p)", program, location, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateGetUniformiv(context, program, location, params))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- ASSERT(programBinary);
-
- programBinary->getUniformiv(location, params);
- }
+ return gl::GetUniformiv(program, location, params);
}
GLint GL_APIENTRY glGetUniformLocation(GLuint program, const GLchar* name)
{
- EVENT("(GLuint program = %d, const GLchar* name = 0x%0.8p)", program, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (strstr(name, "gl_") == name)
- {
- return -1;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return -1;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programObject->isLinked() || !programBinary)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programBinary->getUniformLocation(name);
- }
-
- return -1;
+ return gl::GetUniformLocation(program, name);
}
void GL_APIENTRY glGetVertexAttribfv(GLuint index, GLenum pname, GLfloat* params)
{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", index, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
- if (!gl::ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.FloatValues[i];
- }
- }
- else
- {
- *params = gl::QuerySingleVertexAttributeParameter<GLfloat>(attribState, pname);
- }
- }
+ return gl::GetVertexAttribfv(index, pname, params);
}
void GL_APIENTRY glGetVertexAttribiv(GLuint index, GLenum pname, GLint* params)
{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", index, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
-
- if (!gl::ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- float currentValue = currentValueData.FloatValues[i];
- params[i] = gl::iround<GLint>(currentValue);
- }
- }
- else
- {
- *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
- }
- }
+ return gl::GetVertexAttribiv(index, pname, params);
}
void GL_APIENTRY glGetVertexAttribPointerv(GLuint index, GLenum pname, GLvoid** pointer)
{
- EVENT("(GLuint index = %d, GLenum pname = 0x%X, GLvoid** pointer = 0x%0.8p)", index, pname, pointer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (pname != GL_VERTEX_ATTRIB_ARRAY_POINTER)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- *pointer = const_cast<GLvoid*>(context->getState().getVertexAttribPointer(index));
- }
+ return gl::GetVertexAttribPointerv(index, pname, pointer);
}
void GL_APIENTRY glHint(GLenum target, GLenum mode)
{
- EVENT("(GLenum target = 0x%X, GLenum mode = 0x%X)", target, mode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (mode)
- {
- case GL_FASTEST:
- case GL_NICEST:
- case GL_DONT_CARE:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_GENERATE_MIPMAP_HINT:
- context->getState().setGenerateMipmapHint(mode);
- break;
-
- case GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES:
- context->getState().setFragmentShaderDerivativeHint(mode);
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::Hint(target, mode);
}
GLboolean GL_APIENTRY glIsBuffer(GLuint buffer)
{
- EVENT("(GLuint buffer = %d)", buffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && buffer)
- {
- gl::Buffer *bufferObject = context->getBuffer(buffer);
-
- if (bufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
+ return gl::IsBuffer(buffer);
}
GLboolean GL_APIENTRY glIsEnabled(GLenum cap)
{
- EVENT("(GLenum cap = 0x%X)", cap);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidCap(context, cap))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return GL_FALSE;
- }
-
- return context->getState().getEnableFeature(cap);
- }
-
- return false;
-}
-
-GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
-{
- EVENT("(GLuint fence = %d)", fence);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::FenceNV *fenceObject = context->getFenceNV(fence);
-
- if (fenceObject == NULL)
- {
- return GL_FALSE;
- }
-
- return fenceObject->isFence();
- }
-
- return GL_FALSE;
+ return gl::IsEnabled(cap);
}
GLboolean GL_APIENTRY glIsFramebuffer(GLuint framebuffer)
{
- EVENT("(GLuint framebuffer = %d)", framebuffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && framebuffer)
- {
- gl::Framebuffer *framebufferObject = context->getFramebuffer(framebuffer);
-
- if (framebufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
+ return gl::IsFramebuffer(framebuffer);
}
GLboolean GL_APIENTRY glIsProgram(GLuint program)
{
- EVENT("(GLuint program = %d)", program);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && program)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (programObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
-}
-
-GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
-{
- EVENT("(GLuint id = %d)", id);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
- }
-
- return GL_FALSE;
+ return gl::IsProgram(program);
}
GLboolean GL_APIENTRY glIsRenderbuffer(GLuint renderbuffer)
{
- EVENT("(GLuint renderbuffer = %d)", renderbuffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && renderbuffer)
- {
- gl::Renderbuffer *renderbufferObject = context->getRenderbuffer(renderbuffer);
-
- if (renderbufferObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
+ return gl::IsRenderbuffer(renderbuffer);
}
GLboolean GL_APIENTRY glIsShader(GLuint shader)
{
- EVENT("(GLuint shader = %d)", shader);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && shader)
- {
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (shaderObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
+ return gl::IsShader(shader);
}
GLboolean GL_APIENTRY glIsTexture(GLuint texture)
{
- EVENT("(GLuint texture = %d)", texture);
-
- gl::Context *context = gl::getNonLostContext();
- if (context && texture)
- {
- gl::Texture *textureObject = context->getTexture(texture);
-
- if (textureObject)
- {
- return GL_TRUE;
- }
- }
-
- return GL_FALSE;
+ return gl::IsTexture(texture);
}
void GL_APIENTRY glLineWidth(GLfloat width)
{
- EVENT("(GLfloat width = %f)", width);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (width <= 0.0f)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setLineWidth(width);
- }
+ return gl::LineWidth(width);
}
void GL_APIENTRY glLinkProgram(GLuint program)
{
- EVENT("(GLuint program = %d)", program);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- gl::Error error = context->linkProgram(program);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::LinkProgram(program);
}
void GL_APIENTRY glPixelStorei(GLenum pname, GLint param)
{
- EVENT("(GLenum pname = 0x%X, GLint param = %d)", pname, param);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (pname)
- {
- case GL_UNPACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setUnpackAlignment(param);
- break;
-
- case GL_PACK_ALIGNMENT:
- if (param != 1 && param != 2 && param != 4 && param != 8)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setPackAlignment(param);
- break;
-
- case GL_PACK_REVERSE_ROW_ORDER_ANGLE:
- context->getState().setPackReverseRowOrder(param != 0);
- break;
-
- case GL_UNPACK_IMAGE_HEIGHT:
- case GL_UNPACK_SKIP_IMAGES:
- case GL_UNPACK_ROW_LENGTH:
- case GL_UNPACK_SKIP_ROWS:
- case GL_UNPACK_SKIP_PIXELS:
- case GL_PACK_ROW_LENGTH:
- case GL_PACK_SKIP_ROWS:
- case GL_PACK_SKIP_PIXELS:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- UNIMPLEMENTED();
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::PixelStorei(pname, param);
}
void GL_APIENTRY glPolygonOffset(GLfloat factor, GLfloat units)
{
- EVENT("(GLfloat factor = %f, GLfloat units = %f)", factor, units);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- context->getState().setPolygonOffsetParams(factor, units);
- }
-}
-
-void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei bufSize,
- GLvoid *data)
-{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, GLsizei bufSize = 0x%d, GLvoid *data = 0x%0.8p)",
- x, y, width, height, format, type, bufSize, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (width < 0 || height < 0 || bufSize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
- format, type, &bufSize, data))
- {
- return;
- }
-
- gl::Error error = context->readPixels(x, y, width, height, format, type, &bufSize, data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLvoid* pixels)
-{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, GLvoid* pixels = 0x%0.8p)",
- x, y, width, height, format, type, pixels);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (width < 0 || height < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!gl::ValidateReadPixelsParameters(context, x, y, width, height,
- format, type, NULL, pixels))
- {
- return;
- }
-
- gl::Error error = context->readPixels(x, y, width, height, format, type, NULL, pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::PolygonOffset(factor, units);
}
-void GL_APIENTRY glReleaseShaderCompiler(void)
+void GL_APIENTRY glReadPixels(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid* pixels)
{
- EVENT("()");
-
- gl::Context *context = gl::getNonLostContext();
-
- if (context)
- {
- context->releaseShaderCompiler();
- }
+ return gl::ReadPixels(x, y, width, height, format, type, pixels);
}
-void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glReleaseShaderCompiler(void)
{
- EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, samples, internalformat, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
- width, height, true))
- {
- return;
- }
-
- gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- gl::Error error = renderbuffer->setStorage(width, height, internalformat, samples);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::ReleaseShaderCompiler();
}
void GL_APIENTRY glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
{
- glRenderbufferStorageMultisampleANGLE(target, 0, internalformat, width, height);
+ return gl::RenderbufferStorage(target, internalformat, width, height);
}
-void GL_APIENTRY glSampleCoverage(GLclampf value, GLboolean invert)
+void GL_APIENTRY glSampleCoverage(GLfloat value, GLboolean invert)
{
- EVENT("(GLclampf value = %f, GLboolean invert = %u)", value, invert);
-
- gl::Context* context = gl::getNonLostContext();
-
- if (context)
- {
- context->getState().setSampleCoverageParams(gl::clamp01(value), invert == GL_TRUE);
- }
-}
-
-void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
-{
- EVENT("(GLuint fence = %d, GLenum condition = 0x%X)", fence, condition);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (condition != GL_ALL_COMPLETED_NV)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::FenceNV *fenceObject = context->getFenceNV(fence);
-
- if (fenceObject == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Error error = fenceObject->setFence(condition);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::SampleCoverage(value, invert);
}
void GL_APIENTRY glScissor(GLint x, GLint y, GLsizei width, GLsizei height)
{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-
- gl::Context* context = gl::getNonLostContext();
- if (context)
- {
- if (width < 0 || height < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setScissorParams(x, y, width, height);
- }
+ return gl::Scissor(x, y, width, height);
}
void GL_APIENTRY glShaderBinary(GLsizei n, const GLuint* shaders, GLenum binaryformat, const GLvoid* binary, GLsizei length)
{
- EVENT("(GLsizei n = %d, const GLuint* shaders = 0x%0.8p, GLenum binaryformat = 0x%X, "
- "const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
- n, shaders, binaryformat, binary, length);
-
- gl::Context* context = gl::getNonLostContext();
- if (context)
- {
- const std::vector<GLenum> &shaderBinaryFormats = context->getCaps().shaderBinaryFormats;
- if (std::find(shaderBinaryFormats.begin(), shaderBinaryFormats.end(), binaryformat) == shaderBinaryFormats.end())
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- // No binary shader formats are supported.
- UNIMPLEMENTED();
- }
+ return gl::ShaderBinary(n, shaders, binaryformat, binary, length);
}
void GL_APIENTRY glShaderSource(GLuint shader, GLsizei count, const GLchar* const* string, const GLint* length)
{
- EVENT("(GLuint shader = %d, GLsizei count = %d, const GLchar** string = 0x%0.8p, const GLint* length = 0x%0.8p)",
- shader, count, string, length);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (count < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Shader *shaderObject = context->getShader(shader);
-
- if (!shaderObject)
- {
- if (context->getProgram(shader))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- shaderObject->setSource(count, string, length);
- }
+ return gl::ShaderSource(shader, count, string, length);
}
void GL_APIENTRY glStencilFunc(GLenum func, GLint ref, GLuint mask)
{
- glStencilFuncSeparate(GL_FRONT_AND_BACK, func, ref, mask);
+ return gl::StencilFunc(func, ref, mask);
}
void GL_APIENTRY glStencilFuncSeparate(GLenum face, GLenum func, GLint ref, GLuint mask)
{
- EVENT("(GLenum face = 0x%X, GLenum func = 0x%X, GLint ref = %d, GLuint mask = %d)", face, func, ref, mask);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (func)
- {
- case GL_NEVER:
- case GL_ALWAYS:
- case GL_LESS:
- case GL_LEQUAL:
- case GL_EQUAL:
- case GL_GEQUAL:
- case GL_GREATER:
- case GL_NOTEQUAL:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilParams(func, ref, mask);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackParams(func, ref, mask);
- }
- }
+ return gl::StencilFuncSeparate(face, func, ref, mask);
}
void GL_APIENTRY glStencilMask(GLuint mask)
{
- glStencilMaskSeparate(GL_FRONT_AND_BACK, mask);
+ return gl::StencilMask(mask);
}
void GL_APIENTRY glStencilMaskSeparate(GLenum face, GLuint mask)
{
- EVENT("(GLenum face = 0x%X, GLuint mask = %d)", face, mask);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilWritemask(mask);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackWritemask(mask);
- }
- }
+ return gl::StencilMaskSeparate(face, mask);
}
void GL_APIENTRY glStencilOp(GLenum fail, GLenum zfail, GLenum zpass)
{
- glStencilOpSeparate(GL_FRONT_AND_BACK, fail, zfail, zpass);
+ return gl::StencilOp(fail, zfail, zpass);
}
void GL_APIENTRY glStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail, GLenum zpass)
{
- EVENT("(GLenum face = 0x%X, GLenum fail = 0x%X, GLenum zfail = 0x%X, GLenum zpas = 0x%Xs)",
- face, fail, zfail, zpass);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- switch (face)
- {
- case GL_FRONT:
- case GL_BACK:
- case GL_FRONT_AND_BACK:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (fail)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (zfail)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (zpass)
- {
- case GL_ZERO:
- case GL_KEEP:
- case GL_REPLACE:
- case GL_INCR:
- case GL_DECR:
- case GL_INVERT:
- case GL_INCR_WRAP:
- case GL_DECR_WRAP:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (face == GL_FRONT || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilOperations(fail, zfail, zpass);
- }
-
- if (face == GL_BACK || face == GL_FRONT_AND_BACK)
- {
- context->getState().setStencilBackOperations(fail, zfail, zpass);
- }
- }
+ return gl::StencilOpSeparate(face, fail, zfail, zpass);
}
-GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
+void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
- EVENT("(GLuint fence = %d)", fence);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::FenceNV *fenceObject = context->getFenceNV(fence);
-
- if (fenceObject == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_TRUE;
- }
-
- if (fenceObject->isFence() != GL_TRUE)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_TRUE;
- }
-
- GLboolean result;
- gl::Error error = fenceObject->testFence(&result);
- if (error.isError())
- {
- context->recordError(error);
- return GL_TRUE;
- }
-
- return result;
- }
-
- return GL_TRUE;
-}
-
-void GL_APIENTRY glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height,
- GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, GLsizei height = %d, "
- "GLint border = %d, GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, border, format, type, pixels);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, width, height, border, format, type, pixels))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, 0, width, height, 1, border, format, type, pixels))
- {
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->setImage(level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->setImage(target, level, width, height, internalformat, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default: UNREACHABLE();
- }
- }
+ return gl::TexImage2D(target, level, internalformat, width, height, border, format, type, pixels);
}
void GL_APIENTRY glTexParameterf(GLenum target, GLenum pname, GLfloat param)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %f)", target, pname, param);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
- {
- return;
- }
-
- gl::Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_USAGE_ANGLE: texture->setUsage(gl::uiround<GLenum>(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<GLenum>(param); break;
- case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = gl::uiround<GLenum>(param); break;
- case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = gl::iround<GLint>(param); break;
- case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = gl::iround<GLint>(param); break;
- case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = param; break;
- case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = param; break;
- default: UNREACHABLE(); break;
- }
- }
+ return gl::TexParameterf(target, pname, param);
}
void GL_APIENTRY glTexParameterfv(GLenum target, GLenum pname, const GLfloat* params)
{
- glTexParameterf(target, pname, (GLfloat)*params);
+ return gl::TexParameterfv(target, pname, params);
}
void GL_APIENTRY glTexParameteri(GLenum target, GLenum pname, GLint param)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint param = %d)", target, pname, param);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateTexParamParameters(context, pname, param))
- {
- return;
- }
-
- gl::Texture *texture = context->getTargetTexture(target);
-
- if (!texture)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_TEXTURE_WRAP_S: texture->getSamplerState().wrapS = (GLenum)param; break;
- case GL_TEXTURE_WRAP_T: texture->getSamplerState().wrapT = (GLenum)param; break;
- case GL_TEXTURE_WRAP_R: texture->getSamplerState().wrapR = (GLenum)param; break;
- case GL_TEXTURE_MIN_FILTER: texture->getSamplerState().minFilter = (GLenum)param; break;
- case GL_TEXTURE_MAG_FILTER: texture->getSamplerState().magFilter = (GLenum)param; break;
- case GL_TEXTURE_USAGE_ANGLE: texture->setUsage((GLenum)param); break;
- case GL_TEXTURE_MAX_ANISOTROPY_EXT: texture->getSamplerState().maxAnisotropy = std::min((float)param, context->getExtensions().maxTextureAnisotropy); break;
- case GL_TEXTURE_COMPARE_MODE: texture->getSamplerState().compareMode = (GLenum)param; break;
- case GL_TEXTURE_COMPARE_FUNC: texture->getSamplerState().compareFunc = (GLenum)param; break;
- case GL_TEXTURE_SWIZZLE_R: texture->getSamplerState().swizzleRed = (GLenum)param; break;
- case GL_TEXTURE_SWIZZLE_G: texture->getSamplerState().swizzleGreen = (GLenum)param; break;
- case GL_TEXTURE_SWIZZLE_B: texture->getSamplerState().swizzleBlue = (GLenum)param; break;
- case GL_TEXTURE_SWIZZLE_A: texture->getSamplerState().swizzleAlpha = (GLenum)param; break;
- case GL_TEXTURE_BASE_LEVEL: texture->getSamplerState().baseLevel = param; break;
- case GL_TEXTURE_MAX_LEVEL: texture->getSamplerState().maxLevel = param; break;
- case GL_TEXTURE_MIN_LOD: texture->getSamplerState().minLod = (GLfloat)param; break;
- case GL_TEXTURE_MAX_LOD: texture->getSamplerState().maxLod = (GLfloat)param; break;
- default: UNREACHABLE(); break;
- }
- }
+ return gl::TexParameteri(target, pname, param);
}
void GL_APIENTRY glTexParameteriv(GLenum target, GLenum pname, const GLint* params)
{
- glTexParameteri(target, pname, *params);
+ return gl::TexParameteriv(target, pname, params);
}
-void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid* pixels)
{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, levels, internalformat, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!context->getExtensions().textureStorage)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexStorageParameters(context, target, levels, internalformat, width, height))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
- {
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture2d = context->getTexture2D();
- gl::Error error = texture2d->storage(levels, internalformat, width, height);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP:
- {
- gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
- gl::Error error = textureCube->storage(levels, internalformat, width);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-void GL_APIENTRY glTexSubImage2D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height,
- GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLsizei width = %d, GLsizei height = %d, GLenum format = 0x%X, GLenum type = 0x%X, "
- "const GLvoid* pixels = 0x%0.8p)",
- target, level, xoffset, yoffset, width, height, format, type, pixels);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3 &&
- !ValidateES2TexImageParameters(context, target, level, GL_NONE, false, true,
- xoffset, yoffset, width, height, 0, format, type, pixels))
- {
- return;
- }
-
- if (context->getClientVersion() >= 3 &&
- !ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
- xoffset, yoffset, 0, width, height, 1, 0, format, type, pixels))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0)
- {
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture = context->getTexture2D();
- gl::Error error = texture->subImage(level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP_POSITIVE_X:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:
- case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:
- case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:
- {
- gl::TextureCubeMap *texture = context->getTextureCubeMap();
- gl::Error error = texture->subImage(target, level, xoffset, yoffset, width, height, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- UNREACHABLE();
- }
- }
+ return gl::TexSubImage2D(target, level, xoffset, yoffset, width, height, format, type, pixels);
}
void GL_APIENTRY glUniform1f(GLint location, GLfloat x)
{
- glUniform1fv(location, 1, &x);
+ return gl::Uniform1f(location, x);
}
void GL_APIENTRY glUniform1fv(GLint location, GLsizei count, const GLfloat* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform1fv(location, count, v);
- }
+ return gl::Uniform1fv(location, count, v);
}
void GL_APIENTRY glUniform1i(GLint location, GLint x)
{
- glUniform1iv(location, 1, &x);
+ return gl::Uniform1i(location, x);
}
void GL_APIENTRY glUniform1iv(GLint location, GLsizei count, const GLint* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform1iv(location, count, v);
- }
+ return gl::Uniform1iv(location, count, v);
}
void GL_APIENTRY glUniform2f(GLint location, GLfloat x, GLfloat y)
{
- GLfloat xy[2] = {x, y};
-
- glUniform2fv(location, 1, xy);
+ return gl::Uniform2f(location, x, y);
}
void GL_APIENTRY glUniform2fv(GLint location, GLsizei count, const GLfloat* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC2, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform2fv(location, count, v);
- }
+ return gl::Uniform2fv(location, count, v);
}
void GL_APIENTRY glUniform2i(GLint location, GLint x, GLint y)
{
- GLint xy[2] = {x, y};
-
- glUniform2iv(location, 1, xy);
+ return gl::Uniform2i(location, x, y);
}
void GL_APIENTRY glUniform2iv(GLint location, GLsizei count, const GLint* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC2, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform2iv(location, count, v);
- }
+ return gl::Uniform2iv(location, count, v);
}
void GL_APIENTRY glUniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z)
{
- GLfloat xyz[3] = {x, y, z};
-
- glUniform3fv(location, 1, xyz);
+ return gl::Uniform3f(location, x, y, z);
}
void GL_APIENTRY glUniform3fv(GLint location, GLsizei count, const GLfloat* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC3, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform3fv(location, count, v);
- }
+ return gl::Uniform3fv(location, count, v);
}
void GL_APIENTRY glUniform3i(GLint location, GLint x, GLint y, GLint z)
{
- GLint xyz[3] = {x, y, z};
-
- glUniform3iv(location, 1, xyz);
+ return gl::Uniform3i(location, x, y, z);
}
void GL_APIENTRY glUniform3iv(GLint location, GLsizei count, const GLint* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC3, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform3iv(location, count, v);
- }
+ return gl::Uniform3iv(location, count, v);
}
void GL_APIENTRY glUniform4f(GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
- GLfloat xyzw[4] = {x, y, z, w};
-
- glUniform4fv(location, 1, xyzw);
+ return gl::Uniform4f(location, x, y, z, w);
}
void GL_APIENTRY glUniform4fv(GLint location, GLsizei count, const GLfloat* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLfloat* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_FLOAT_VEC4, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform4fv(location, count, v);
- }
+ return gl::Uniform4fv(location, count, v);
}
void GL_APIENTRY glUniform4i(GLint location, GLint x, GLint y, GLint z, GLint w)
{
- GLint xyzw[4] = {x, y, z, w};
-
- glUniform4iv(location, 1, xyzw);
+ return gl::Uniform4i(location, x, y, z, w);
}
void GL_APIENTRY glUniform4iv(GLint location, GLsizei count, const GLint* v)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLint* v = 0x%0.8p)", location, count, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_INT_VEC4, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform4iv(location, count, v);
- }
+ return gl::Uniform4iv(location, count, v);
}
void GL_APIENTRY glUniformMatrix2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix2fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix2fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix3fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix3fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix4fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix4fv(location, count, transpose, value);
}
void GL_APIENTRY glUseProgram(GLuint program)
{
- EVENT("(GLuint program = %d)", program);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject && program != 0)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- if (program != 0 && !programObject->isLinked())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->useProgram(program);
- }
+ return gl::UseProgram(program);
}
void GL_APIENTRY glValidateProgram(GLuint program)
{
- EVENT("(GLuint program = %d)", program);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- programObject->validate(context->getCaps());
- }
+ return gl::ValidateProgram(program);
}
-void GL_APIENTRY glVertexAttrib1f(GLuint index, GLfloat x)
+void GL_APIENTRY glVertexAttrib1f(GLuint indx, GLfloat x)
{
- EVENT("(GLuint index = %d, GLfloat x = %f)", index, x);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, 0, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib1f(indx, x);
}
-void GL_APIENTRY glVertexAttrib1fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib1fv(GLuint indx, const GLfloat* values)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], 0, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib1fv(indx, values);
}
-void GL_APIENTRY glVertexAttrib2f(GLuint index, GLfloat x, GLfloat y)
+void GL_APIENTRY glVertexAttrib2f(GLuint indx, GLfloat x, GLfloat y)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f)", index, x, y);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib2f(indx, x, y);
}
-void GL_APIENTRY glVertexAttrib2fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib2fv(GLuint indx, const GLfloat* values)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], values[1], 0, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib2fv(indx, values);
}
-void GL_APIENTRY glVertexAttrib3f(GLuint index, GLfloat x, GLfloat y, GLfloat z)
+void GL_APIENTRY glVertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f)", index, x, y, z);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, z, 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib3f(indx, x, y, z);
}
-void GL_APIENTRY glVertexAttrib3fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib3fv(GLuint indx, const GLfloat* values)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { values[0], values[1], values[2], 1 };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib3fv(indx, values);
}
-void GL_APIENTRY glVertexAttrib4f(GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+void GL_APIENTRY glVertexAttrib4f(GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
{
- EVENT("(GLuint index = %d, GLfloat x = %f, GLfloat y = %f, GLfloat z = %f, GLfloat w = %f)", index, x, y, z, w);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLfloat vals[4] = { x, y, z, w };
- context->getState().setVertexAttribf(index, vals);
- }
+ return gl::VertexAttrib4f(indx, x, y, z, w);
}
-void GL_APIENTRY glVertexAttrib4fv(GLuint index, const GLfloat* values)
+void GL_APIENTRY glVertexAttrib4fv(GLuint indx, const GLfloat* values)
{
- EVENT("(GLuint index = %d, const GLfloat* values = 0x%0.8p)", index, values);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribf(index, values);
- }
+ return gl::VertexAttrib4fv(indx, values);
}
-void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+void GL_APIENTRY glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
{
- EVENT("(GLuint index = %d, GLuint divisor = %d)", index, divisor);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->setVertexAttribDivisor(index, divisor);
- }
-}
-
-void GL_APIENTRY glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid* ptr)
-{
- EVENT("(GLuint index = %d, GLint size = %d, GLenum type = 0x%X, "
- "GLboolean normalized = %u, GLsizei stride = %d, const GLvoid* ptr = 0x%0.8p)",
- index, size, type, normalized, stride, ptr);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (size < 1 || size > 4)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (type)
- {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_FIXED:
- case GL_FLOAT:
- break;
-
- case GL_HALF_FLOAT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_INT_2_10_10_10_REV:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (stride < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // [OpenGL ES 3.0.2] Section 2.8 page 24:
- // An INVALID_OPERATION error is generated when a non-zero vertex array object
- // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
- // and the pointer argument is not NULL.
- if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && ptr != NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type,
- normalized == GL_TRUE, false, stride, ptr);
- }
+ return gl::VertexAttribPointer(indx, size, type, normalized, stride, ptr);
}
void GL_APIENTRY glViewport(GLint x, GLint y, GLsizei width, GLsizei height)
{
- EVENT("(GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)", x, y, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (width < 0 || height < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setViewportParams(x, y, width, height);
- }
+ return gl::Viewport(x, y, width, height);
}
-// OpenGL ES 3.0 functions
-
void GL_APIENTRY glReadBuffer(GLenum mode)
{
- EVENT("(GLenum mode = 0x%X)", mode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // glReadBuffer
- UNIMPLEMENTED();
- }
+ return gl::ReadBuffer(mode);
}
void GL_APIENTRY glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid* indices)
{
- EVENT("(GLenum mode = 0x%X, GLuint start = %u, GLuint end = %u, GLsizei count = %d, GLenum type = 0x%X, "
- "const GLvoid* indices = 0x%0.8p)", mode, start, end, count, type, indices);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // glDrawRangeElements
- UNIMPLEMENTED();
- }
+ return gl::DrawRangeElements(mode, start, end, count, type, indices);
}
void GL_APIENTRY glTexImage3D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* pixels)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint internalformat = %d, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLenum format = 0x%X, "
- "GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, format, type, pixels);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImageParameters(context, target, level, internalformat, false, false,
- 0, 0, 0, width, height, depth, border, format, type, pixels))
- {
- return;
- }
-
- switch(target)
- {
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture = context->getTexture3D();
- gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture = context->getTexture2DArray();
- gl::Error error = texture->setImage(level, width, height, depth, internalformat, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::TexImage3D(target, level, internalformat, width, height, depth, border, format, type, pixels);
}
void GL_APIENTRY glTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const GLvoid* pixels)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%X, const GLvoid* pixels = 0x%0.8p)",
- target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, false, true,
- xoffset, yoffset, zoffset, width, height, depth, 0,
- format, type, pixels))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0 || depth == 0)
- {
- return;
- }
-
- switch(target)
- {
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture = context->getTexture3D();
- gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture = context->getTexture2DArray();
- gl::Error error = texture->subImage(level, xoffset, yoffset, zoffset, width, height, depth, format, type, context->getState().getUnpackState(), pixels);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::TexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, type, pixels);
}
void GL_APIENTRY glCopyTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLint x = %d, GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, level, xoffset, yoffset, zoffset, x, y, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3CopyTexImageParameters(context, target, level, GL_NONE, true, xoffset, yoffset, zoffset,
- x, y, width, height, 0))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getReadFramebuffer();
- gl::Texture *texture = NULL;
- switch (target)
- {
- case GL_TEXTURE_3D:
- texture = context->getTexture3D();
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- texture = context->getTexture2DArray();
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Error error = texture->copySubImage(target, level, xoffset, yoffset, zoffset, x, y, width, height, framebuffer);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::CopyTexSubImage3D(target, level, xoffset, yoffset, zoffset, x, y, width, height);
}
void GL_APIENTRY glCompressedTexImage3D(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLsizei imageSize, const GLvoid* data)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d, GLint border = %d, GLsizei imageSize = %d, "
- "const GLvoid* data = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, imageSize, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(internalformat);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImageParameters(context, target, level, internalformat, true, false,
- 0, 0, 0, width, height, depth, border, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- switch(target)
- {
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture = context->getTexture3D();
- gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture = context->getTexture2DArray();
- gl::Error error = texture->setCompressedImage(level, internalformat, width, height, depth, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::CompressedTexImage3D(target, level, internalformat, width, height, depth, border, imageSize, data);
}
void GL_APIENTRY glCompressedTexSubImage3D(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const GLvoid* data)
{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLint xoffset = %d, GLint yoffset = %d, "
- "GLint zoffset = %d, GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, "
- "GLenum format = 0x%X, GLsizei imageSize = %d, const GLvoid* data = 0x%0.8p)",
- target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::InternalFormat &formatInfo = gl::GetInternalFormatInfo(format);
- if (imageSize < 0 || static_cast<GLuint>(imageSize) != formatInfo.computeBlockSize(GL_UNSIGNED_BYTE, width, height))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!data)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- // validateES3TexImageFormat sets the error code if there is an error
- if (!ValidateES3TexImageParameters(context, target, level, GL_NONE, true, true,
- 0, 0, 0, width, height, depth, 0, GL_NONE, GL_NONE, data))
- {
- return;
- }
-
- // Zero sized uploads are valid but no-ops
- if (width == 0 || height == 0)
- {
- return;
- }
-
- switch(target)
- {
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture = context->getTexture3D();
- gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
- format, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture = context->getTexture2DArray();
- gl::Error error = texture->subImageCompressed(level, xoffset, yoffset, zoffset, width, height, depth,
- format, imageSize, context->getState().getUnpackState(), data);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::CompressedTexSubImage3D(target, level, xoffset, yoffset, zoffset, width, height, depth, format, imageSize, data);
}
void GL_APIENTRY glGenQueries(GLsizei n, GLuint* ids)
{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (GLsizei i = 0; i < n; i++)
- {
- ids[i] = context->createQuery();
- }
- }
+ return gl::GenQueries(n, ids);
}
void GL_APIENTRY glDeleteQueries(GLsizei n, const GLuint* ids)
{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (GLsizei i = 0; i < n; i++)
- {
- context->deleteQuery(ids[i]);
- }
- }
+ return gl::DeleteQueries(n, ids);
}
GLboolean GL_APIENTRY glIsQuery(GLuint id)
{
- EVENT("(GLuint id = %u)", id);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return (context->getQuery(id, false, GL_NONE) != NULL) ? GL_TRUE : GL_FALSE;
- }
-
- return GL_FALSE;
+ return gl::IsQuery(id);
}
void GL_APIENTRY glBeginQuery(GLenum target, GLuint id)
{
- EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateBeginQuery(context, target, id))
- {
- return;
- }
-
- gl::Error error = context->beginQuery(target, id);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::BeginQuery(target, id);
}
void GL_APIENTRY glEndQuery(GLenum target)
{
- EVENT("(GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateEndQuery(context, target))
- {
- return;
- }
-
- gl::Error error = context->endQuery(target);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::EndQuery(target);
}
void GL_APIENTRY glGetQueryiv(GLenum target, GLenum pname, GLint* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidQueryType(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (pname)
- {
- case GL_CURRENT_QUERY:
- params[0] = static_cast<GLint>(context->getState().getActiveQueryId(target));
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetQueryiv(target, pname, params);
}
void GL_APIENTRY glGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params)
{
- EVENT("(GLuint id = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", id, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Query *queryObject = context->getQuery(id, false, GL_NONE);
-
- if (!queryObject)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (context->getState().getActiveQueryId(queryObject->getType()) == id)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch(pname)
- {
- case GL_QUERY_RESULT_EXT:
- {
- gl::Error error = queryObject->getResult(params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_QUERY_RESULT_AVAILABLE_EXT:
- {
- gl::Error error = queryObject->isResultAvailable(params);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetQueryObjectuiv(id, pname, params);
}
GLboolean GL_APIENTRY glUnmapBuffer(GLenum target)
{
- EVENT("(GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return glUnmapBufferOES(target);
- }
-
- return GL_FALSE;
+ return gl::UnmapBuffer(target);
}
void GL_APIENTRY glGetBufferPointerv(GLenum target, GLenum pname, GLvoid** params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- glGetBufferPointervOES(target, pname, params);
- }
+ return gl::GetBufferPointerv(target, pname, params);
}
void GL_APIENTRY glDrawBuffers(GLsizei n, const GLenum* bufs)
{
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- glDrawBuffersEXT(n, bufs);
- }
+ return gl::DrawBuffers(n, bufs);
}
void GL_APIENTRY glUniformMatrix2x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x3, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix2x3fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix2x3fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix3x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x2, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix3x2fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix3x2fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix2x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT2x4, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix2x4fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix2x4fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix4x2fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x2, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix4x2fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix4x2fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix3x4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT3x4, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix3x4fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix3x4fv(location, count, transpose, value);
}
void GL_APIENTRY glUniformMatrix4x3fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, GLboolean transpose = %u, const GLfloat* value = 0x%0.8p)",
- location, count, transpose, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniformMatrix(context, GL_FLOAT_MAT4x3, location, count, transpose))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniformMatrix4x3fv(location, count, transpose, value);
- }
+ return gl::UniformMatrix4x3fv(location, count, transpose, value);
}
void GL_APIENTRY glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
- EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, GLint dstX0 = %d, "
- "GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
- srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter,
- false))
- {
- return;
- }
-
- gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
- mask, filter);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::BlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
void GL_APIENTRY glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLsizei samples = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, samples, internalformat, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateRenderbufferStorageParameters(context, target, samples, internalformat,
- width, height, false))
- {
- return;
- }
-
- gl::Renderbuffer *renderbuffer = context->getState().getCurrentRenderbuffer();
- renderbuffer->setStorage(width, height, internalformat, samples);
- }
+ return gl::RenderbufferStorageMultisample(target, samples, internalformat, width, height);
}
void GL_APIENTRY glFramebufferTextureLayer(GLenum target, GLenum attachment, GLuint texture, GLint level, GLint layer)
{
- EVENT("(GLenum target = 0x%X, GLenum attachment = 0x%X, GLuint texture = %u, GLint level = %d, GLint layer = %d)",
- target, attachment, texture, level, layer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateFramebufferTextureLayer(context, target, attachment, texture,
- level, layer))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (texture != 0)
- {
- gl::Texture *textureObject = context->getTexture(texture);
- gl::ImageIndex index(textureObject->getTarget(), level, layer);
- framebuffer->setTextureAttachment(attachment, textureObject, index);
- }
- else
- {
- framebuffer->setNULLAttachment(attachment);
- }
- }
+ return gl::FramebufferTextureLayer(target, attachment, texture, level, layer);
}
GLvoid* GL_APIENTRY glMapBufferRange(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
- target, offset, length, access);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- return glMapBufferRangeEXT(target, offset, length, access);
- }
-
- return NULL;
+ return gl::MapBufferRange(target, offset, length, access);
}
void GL_APIENTRY glFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length)
{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- glFlushMappedBufferRangeEXT(target, offset, length);
- }
+ return gl::FlushMappedBufferRange(target, offset, length);
}
void GL_APIENTRY glBindVertexArray(GLuint array)
{
- EVENT("(GLuint array = %u)", array);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::VertexArray *vao = context->getVertexArray(array);
-
- if (!vao)
- {
- // The default VAO should always exist
- ASSERT(array != 0);
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->bindVertexArray(array);
- }
+ return gl::BindVertexArray(array);
}
void GL_APIENTRY glDeleteVertexArrays(GLsizei n, const GLuint* arrays)
{
- EVENT("(GLsizei n = %d, const GLuint* arrays = 0x%0.8p)", n, arrays);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- if (arrays[arrayIndex] != 0)
- {
- context->deleteVertexArray(arrays[arrayIndex]);
- }
- }
- }
+ return gl::DeleteVertexArrays(n, arrays);
}
void GL_APIENTRY glGenVertexArrays(GLsizei n, GLuint* arrays)
{
- EVENT("(GLsizei n = %d, GLuint* arrays = 0x%0.8p)", n, arrays);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (n < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int arrayIndex = 0; arrayIndex < n; arrayIndex++)
- {
- arrays[arrayIndex] = context->createVertexArray();
- }
- }
+ return gl::GenVertexArrays(n, arrays);
}
GLboolean GL_APIENTRY glIsVertexArray(GLuint array)
{
- EVENT("(GLuint array = %u)", array);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- if (array == 0)
- {
- return GL_FALSE;
- }
-
- gl::VertexArray *vao = context->getVertexArray(array);
-
- return (vao != NULL ? GL_TRUE : GL_FALSE);
- }
-
- return GL_FALSE;
+ return gl::IsVertexArray(array);
}
void GL_APIENTRY glGetIntegeri_v(GLenum target, GLuint index, GLint* data)
{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint* data = 0x%0.8p)",
- target, index, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER_START:
- case GL_UNIFORM_BUFFER_SIZE:
- case GL_UNIFORM_BUFFER_BINDING:
- if (index >= caps.maxCombinedUniformBlocks)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!(context->getIndexedIntegerv(target, index, data)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (numParams == 0)
- {
- return; // it is known that pname is valid, but there are no parameters to return
- }
-
- if (nativeType == GL_INT_64_ANGLEX)
- {
- GLint64 minIntValue = static_cast<GLint64>(std::numeric_limits<int>::min());
- GLint64 maxIntValue = static_cast<GLint64>(std::numeric_limits<int>::max());
- GLint64 *int64Params = new GLint64[numParams];
-
- context->getIndexedInteger64v(target, index, int64Params);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- GLint64 clampedValue = std::max(std::min(int64Params[i], maxIntValue), minIntValue);
- data[i] = static_cast<GLint>(clampedValue);
- }
-
- delete [] int64Params;
- }
- else
- {
- UNREACHABLE();
- }
- }
- }
+ return gl::GetIntegeri_v(target, index, data);
}
void GL_APIENTRY glBeginTransformFeedback(GLenum primitiveMode)
{
- EVENT("(GLenum primitiveMode = 0x%X)", primitiveMode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (primitiveMode)
- {
- case GL_TRIANGLES:
- case GL_LINES:
- case GL_POINTS:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- if (transformFeedback->isStarted())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (transformFeedback->isPaused())
- {
- transformFeedback->resume();
- }
- else
- {
- transformFeedback->start(primitiveMode);
- }
- }
+ return gl::BeginTransformFeedback(primitiveMode);
}
void GL_APIENTRY glEndTransformFeedback(void)
{
- EVENT("(void)");
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
-
- if (!transformFeedback->isStarted())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- transformFeedback->stop();
- }
+ return gl::EndTransformFeedback();
}
void GL_APIENTRY glBindBufferRange(GLenum target, GLuint index, GLuint buffer, GLintptr offset, GLsizeiptr size)
{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u, GLintptr offset = %d, GLsizeiptr size = %d)",
- target, index, buffer, offset, size);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (buffer != 0 && size <= 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
-
- // size and offset must be a multiple of 4
- if (buffer != 0 && ((offset % 4) != 0 || (size % 4) != 0))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->bindIndexedTransformFeedbackBuffer(buffer, index, offset, size);
- context->bindGenericTransformFeedbackBuffer(buffer);
- break;
-
- case GL_UNIFORM_BUFFER:
-
- // it is an error to bind an offset not a multiple of the alignment
- if (buffer != 0 && (offset % caps.uniformBufferOffsetAlignment) != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->bindIndexedUniformBuffer(buffer, index, offset, size);
- context->bindGenericUniformBuffer(buffer);
- break;
-
- default:
- UNREACHABLE();
- }
- }
+ return gl::BindBufferRange(target, index, buffer, offset, size);
}
void GL_APIENTRY glBindBufferBase(GLenum target, GLuint index, GLuint buffer)
{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLuint buffer = %u)",
- target, index, buffer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER:
- context->bindIndexedTransformFeedbackBuffer(buffer, index, 0, 0);
- context->bindGenericTransformFeedbackBuffer(buffer);
- break;
-
- case GL_UNIFORM_BUFFER:
- context->bindIndexedUniformBuffer(buffer, index, 0, 0);
- context->bindGenericUniformBuffer(buffer);
- break;
-
- default:
- UNREACHABLE();
- }
- }
+ return gl::BindBufferBase(target, index, buffer);
}
void GL_APIENTRY glTransformFeedbackVaryings(GLuint program, GLsizei count, const GLchar* const* varyings, GLenum bufferMode)
{
- EVENT("(GLuint program = %u, GLsizei count = %d, const GLchar* const* varyings = 0x%0.8p, GLenum bufferMode = 0x%X)",
- program, count, varyings, bufferMode);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- const gl::Caps &caps = context->getCaps();
- switch (bufferMode)
- {
- case GL_INTERLEAVED_ATTRIBS:
- break;
- case GL_SEPARATE_ATTRIBS:
- if (static_cast<GLuint>(count) > caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!gl::ValidProgram(context, program))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
-
- programObject->setTransformFeedbackVaryings(count, varyings, bufferMode);
- }
+ return gl::TransformFeedbackVaryings(program, count, varyings, bufferMode);
}
void GL_APIENTRY glGetTransformFeedbackVarying(GLuint program, GLuint index, GLsizei bufSize, GLsizei* length, GLsizei* size, GLenum* type, GLchar* name)
{
- EVENT("(GLuint program = %u, GLuint index = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, "
- "GLsizei* size = 0x%0.8p, GLenum* type = 0x%0.8p, GLchar* name = 0x%0.8p)",
- program, index, bufSize, length, size, type, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!gl::ValidProgram(context, program))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
-
- if (index >= static_cast<GLuint>(programObject->getTransformFeedbackVaryingCount()))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->getTransformFeedbackVarying(index, bufSize, length, size, type, name);
- }
+ return gl::GetTransformFeedbackVarying(program, index, bufSize, length, size, type, name);
}
void GL_APIENTRY glVertexAttribIPointer(GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid* pointer)
{
- EVENT("(GLuint index = %u, GLint size = %d, GLenum type = 0x%X, GLsizei stride = %d, const GLvoid* pointer = 0x%0.8p)",
- index, size, type, stride, pointer);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (size < 1 || size > 4)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (type)
- {
- case GL_BYTE:
- case GL_UNSIGNED_BYTE:
- case GL_SHORT:
- case GL_UNSIGNED_SHORT:
- case GL_INT:
- case GL_UNSIGNED_INT:
- case GL_INT_2_10_10_10_REV:
- case GL_UNSIGNED_INT_2_10_10_10_REV:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (stride < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if ((type == GL_INT_2_10_10_10_REV || type == GL_UNSIGNED_INT_2_10_10_10_REV) && size != 4)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // [OpenGL ES 3.0.2] Section 2.8 page 24:
- // An INVALID_OPERATION error is generated when a non-zero vertex array object
- // is bound, zero is bound to the ARRAY_BUFFER buffer object binding point,
- // and the pointer argument is not NULL.
- if (context->getState().getVertexArray()->id() != 0 && context->getState().getArrayBufferId() == 0 && pointer != NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->getState().setVertexAttribState(index, context->getState().getTargetBuffer(GL_ARRAY_BUFFER), size, type, false, true,
- stride, pointer);
- }
+ return gl::VertexAttribIPointer(index, size, type, stride, pointer);
}
void GL_APIENTRY glGetVertexAttribIiv(GLuint index, GLenum pname, GLint* params)
{
- EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- index, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
-
- if (!gl::ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.IntValues[i];
- }
- }
- else
- {
- *params = gl::QuerySingleVertexAttributeParameter<GLint>(attribState, pname);
- }
- }
+ return gl::GetVertexAttribIiv(index, pname, params);
}
void GL_APIENTRY glGetVertexAttribIuiv(GLuint index, GLenum pname, GLuint* params)
{
- EVENT("(GLuint index = %u, GLenum pname = 0x%X, GLuint* params = 0x%0.8p)",
- index, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- const gl::VertexAttribute &attribState = context->getState().getVertexAttribState(index);
-
- if (!gl::ValidateGetVertexAttribParameters(context, pname))
- {
- return;
- }
-
- if (pname == GL_CURRENT_VERTEX_ATTRIB)
- {
- const gl::VertexAttribCurrentValueData &currentValueData = context->getState().getVertexAttribCurrentValue(index);
- for (int i = 0; i < 4; ++i)
- {
- params[i] = currentValueData.UnsignedIntValues[i];
- }
- }
- else
- {
- *params = gl::QuerySingleVertexAttributeParameter<GLuint>(attribState, pname);
- }
- }
+ return gl::GetVertexAttribIuiv(index, pname, params);
}
void GL_APIENTRY glVertexAttribI4i(GLuint index, GLint x, GLint y, GLint z, GLint w)
{
- EVENT("(GLuint index = %u, GLint x = %d, GLint y = %d, GLint z = %d, GLint w = %d)",
- index, x, y, z, w);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLint vals[4] = { x, y, z, w };
- context->getState().setVertexAttribi(index, vals);
- }
+ return gl::VertexAttribI4i(index, x, y, z, w);
}
void GL_APIENTRY glVertexAttribI4ui(GLuint index, GLuint x, GLuint y, GLuint z, GLuint w)
{
- EVENT("(GLuint index = %u, GLuint x = %u, GLuint y = %u, GLuint z = %u, GLuint w = %u)",
- index, x, y, z, w);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- GLuint vals[4] = { x, y, z, w };
- context->getState().setVertexAttribu(index, vals);
- }
+ return gl::VertexAttribI4ui(index, x, y, z, w);
}
void GL_APIENTRY glVertexAttribI4iv(GLuint index, const GLint* v)
{
- EVENT("(GLuint index = %u, const GLint* v = 0x%0.8p)", index, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribi(index, v);
- }
+ return gl::VertexAttribI4iv(index, v);
}
void GL_APIENTRY glVertexAttribI4uiv(GLuint index, const GLuint* v)
{
- EVENT("(GLuint index = %u, const GLuint* v = 0x%0.8p)", index, v);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->getState().setVertexAttribu(index, v);
- }
+ return gl::VertexAttribI4uiv(index, v);
}
void GL_APIENTRY glGetUniformuiv(GLuint program, GLint location, GLuint* params)
{
- EVENT("(GLuint program = %u, GLint location = %d, GLuint* params = 0x%0.8p)",
- program, location, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateGetUniformuiv(context, program, location, params))
- {
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- ASSERT(programObject);
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- ASSERT(programBinary);
-
- programBinary->getUniformuiv(location, params);
- }
+ return gl::GetUniformuiv(program, location, params);
}
GLint GL_APIENTRY glGetFragDataLocation(GLuint program, const GLchar *name)
{
- EVENT("(GLuint program = %u, const GLchar *name = 0x%0.8p)",
- program, name);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- if (program == 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return -1;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return -1;
- }
-
- return programBinary->getFragDataLocation(name);
- }
-
- return 0;
+ return gl::GetFragDataLocation(program, name);
}
void GL_APIENTRY glUniform1ui(GLint location, GLuint v0)
{
- glUniform1uiv(location, 1, &v0);
+ return gl::Uniform1ui(location, v0);
}
void GL_APIENTRY glUniform2ui(GLint location, GLuint v0, GLuint v1)
{
- const GLuint xy[] = { v0, v1 };
- glUniform2uiv(location, 1, xy);
+ return gl::Uniform2ui(location, v0, v1);
}
void GL_APIENTRY glUniform3ui(GLint location, GLuint v0, GLuint v1, GLuint v2)
{
- const GLuint xyz[] = { v0, v1, v2 };
- glUniform3uiv(location, 1, xyz);
+ return gl::Uniform3ui(location, v0, v1, v2);
}
void GL_APIENTRY glUniform4ui(GLint location, GLuint v0, GLuint v1, GLuint v2, GLuint v3)
{
- const GLuint xyzw[] = { v0, v1, v2, v3 };
- glUniform4uiv(location, 1, xyzw);
+ return gl::Uniform4ui(location, v0, v1, v2, v3);
}
void GL_APIENTRY glUniform1uiv(GLint location, GLsizei count, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform1uiv(location, count, value);
- }
+ return gl::Uniform1uiv(location, count, value);
}
void GL_APIENTRY glUniform2uiv(GLint location, GLsizei count, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC2, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform2uiv(location, count, value);
- }
+ return gl::Uniform2uiv(location, count, value);
}
void GL_APIENTRY glUniform3uiv(GLint location, GLsizei count, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value)",
- location, count, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC3, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform3uiv(location, count, value);
- }
+ return gl::Uniform3uiv(location, count, value);
}
void GL_APIENTRY glUniform4uiv(GLint location, GLsizei count, const GLuint* value)
{
- EVENT("(GLint location = %d, GLsizei count = %d, const GLuint* value = 0x%0.8p)",
- location, count, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateUniform(context, GL_UNSIGNED_INT_VEC4, location, count))
- {
- return;
- }
-
- gl::ProgramBinary *programBinary = context->getState().getCurrentProgramBinary();
- programBinary->setUniform4uiv(location, count, value);
- }
+ return gl::Uniform4uiv(location, count, value);
}
void GL_APIENTRY glClearBufferiv(GLenum buffer, GLint drawbuffer, const GLint* value)
{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLint* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateClearBuffer(context))
- {
- return;
- }
-
- switch (buffer)
- {
- case GL_COLOR:
- if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_STENCIL:
- if (drawbuffer != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Error error = context->clearBufferiv(buffer, drawbuffer, value);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::ClearBufferiv(buffer, drawbuffer, value);
}
void GL_APIENTRY glClearBufferuiv(GLenum buffer, GLint drawbuffer, const GLuint* value)
{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLuint* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateClearBuffer(context))
- {
- return;
- }
-
- switch (buffer)
- {
- case GL_COLOR:
- if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Error error = context->clearBufferuiv(buffer, drawbuffer, value);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::ClearBufferuiv(buffer, drawbuffer, value);
}
void GL_APIENTRY glClearBufferfv(GLenum buffer, GLint drawbuffer, const GLfloat* value)
{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, const GLfloat* value = 0x%0.8p)",
- buffer, drawbuffer, value);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateClearBuffer(context))
- {
- return;
- }
-
- switch (buffer)
- {
- case GL_COLOR:
- if (drawbuffer < 0 || static_cast<GLuint>(drawbuffer) >= context->getCaps().maxDrawBuffers)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_DEPTH:
- if (drawbuffer != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Error error = context->clearBufferfv(buffer, drawbuffer, value);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::ClearBufferfv(buffer, drawbuffer, value);
}
void GL_APIENTRY glClearBufferfi(GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil)
{
- EVENT("(GLenum buffer = 0x%X, GLint drawbuffer = %d, GLfloat depth, GLint stencil = %d)",
- buffer, drawbuffer, depth, stencil);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateClearBuffer(context))
- {
- return;
- }
-
- switch (buffer)
- {
- case GL_DEPTH_STENCIL:
- if (drawbuffer != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Error error = context->clearBufferfi(buffer, drawbuffer, depth, stencil);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::ClearBufferfi(buffer, drawbuffer, depth, stencil);
}
const GLubyte* GL_APIENTRY glGetStringi(GLenum name, GLuint index)
{
- EVENT("(GLenum name = 0x%X, GLuint index = %u)", name, index);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if (name != GL_EXTENSIONS)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (index >= context->getExtensionStringCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- return reinterpret_cast<const GLubyte*>(context->getExtensionString(index).c_str());
- }
-
- return NULL;
+ return gl::GetStringi(name, index);
}
void GL_APIENTRY glCopyBufferSubData(GLenum readTarget, GLenum writeTarget, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size)
{
- EVENT("(GLenum readTarget = 0x%X, GLenum writeTarget = 0x%X, GLintptr readOffset = %d, GLintptr writeOffset = %d, GLsizeiptr size = %d)",
- readTarget, writeTarget, readOffset, writeOffset, size);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!gl::ValidBufferTarget(context, readTarget) || !gl::ValidBufferTarget(context, writeTarget))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *readBuffer = context->getState().getTargetBuffer(readTarget);
- gl::Buffer *writeBuffer = context->getState().getTargetBuffer(writeTarget);
-
- if (!readBuffer || !writeBuffer)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Verify that readBuffer and writeBuffer are not currently mapped
- if (readBuffer->isMapped() || writeBuffer->isMapped())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (readOffset < 0 || writeOffset < 0 || size < 0 ||
- static_cast<unsigned int>(readOffset + size) > readBuffer->getSize() ||
- static_cast<unsigned int>(writeOffset + size) > writeBuffer->getSize())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (readBuffer == writeBuffer && std::abs(readOffset - writeOffset) < size)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- // if size is zero, the copy is a successful no-op
- if (size > 0)
- {
- gl::Error error = writeBuffer->copyBufferSubData(readBuffer, readOffset, writeOffset, size);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- }
+ return gl::CopyBufferSubData(readTarget, writeTarget, readOffset, writeOffset, size);
}
void GL_APIENTRY glGetUniformIndices(GLuint program, GLsizei uniformCount, const GLchar* const* uniformNames, GLuint* uniformIndices)
{
- EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLchar* const* uniformNames = 0x%0.8p, GLuint* uniformIndices = 0x%0.8p)",
- program, uniformCount, uniformNames, uniformIndices);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformCount < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programObject->isLinked() || !programBinary)
- {
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- uniformIndices[uniformId] = GL_INVALID_INDEX;
- }
- }
- else
- {
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- uniformIndices[uniformId] = programBinary->getUniformIndex(uniformNames[uniformId]);
- }
- }
- }
+ return gl::GetUniformIndices(program, uniformCount, uniformNames, uniformIndices);
}
void GL_APIENTRY glGetActiveUniformsiv(GLuint program, GLsizei uniformCount, const GLuint* uniformIndices, GLenum pname, GLint* params)
{
- EVENT("(GLuint program = %u, GLsizei uniformCount = %d, const GLuint* uniformIndices = 0x%0.8p, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- program, uniformCount, uniformIndices, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformCount < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- switch (pname)
- {
- case GL_UNIFORM_TYPE:
- case GL_UNIFORM_SIZE:
- case GL_UNIFORM_NAME_LENGTH:
- case GL_UNIFORM_BLOCK_INDEX:
- case GL_UNIFORM_OFFSET:
- case GL_UNIFORM_ARRAY_STRIDE:
- case GL_UNIFORM_MATRIX_STRIDE:
- case GL_UNIFORM_IS_ROW_MAJOR:
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- if (!programBinary && uniformCount > 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- const GLuint index = uniformIndices[uniformId];
-
- if (index >= (GLuint)programBinary->getActiveUniformCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- for (int uniformId = 0; uniformId < uniformCount; uniformId++)
- {
- const GLuint index = uniformIndices[uniformId];
- params[uniformId] = programBinary->getActiveUniformi(index, pname);
- }
- }
+ return gl::GetActiveUniformsiv(program, uniformCount, uniformIndices, pname, params);
}
GLuint GL_APIENTRY glGetUniformBlockIndex(GLuint program, const GLchar* uniformBlockName)
{
- EVENT("(GLuint program = %u, const GLchar* uniformBlockName = 0x%0.8p)", program, uniformBlockName);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_INVALID_INDEX;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_INVALID_INDEX;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return GL_INVALID_INDEX;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
- if (!programBinary)
- {
- return GL_INVALID_INDEX;
- }
-
- return programBinary->getUniformBlockIndex(uniformBlockName);
- }
-
- return 0;
+ return gl::GetUniformBlockIndex(program, uniformBlockName);
}
void GL_APIENTRY glGetActiveUniformBlockiv(GLuint program, GLuint uniformBlockIndex, GLenum pname, GLint* params)
{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)",
- program, uniformBlockIndex, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_UNIFORM_BLOCK_BINDING:
- *params = static_cast<GLint>(programObject->getUniformBlockBinding(uniformBlockIndex));
- break;
-
- case GL_UNIFORM_BLOCK_DATA_SIZE:
- case GL_UNIFORM_BLOCK_NAME_LENGTH:
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS:
- case GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES:
- case GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER:
- case GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER:
- programBinary->getActiveUniformBlockiv(uniformBlockIndex, pname, params);
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetActiveUniformBlockiv(program, uniformBlockIndex, pname, params);
}
void GL_APIENTRY glGetActiveUniformBlockName(GLuint program, GLuint uniformBlockIndex, GLsizei bufSize, GLsizei* length, GLchar* uniformBlockName)
{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLchar* uniformBlockName = 0x%0.8p)",
- program, uniformBlockIndex, bufSize, length, uniformBlockName);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programBinary->getActiveUniformBlockName(uniformBlockIndex, bufSize, length, uniformBlockName);
- }
+ return gl::GetActiveUniformBlockName(program, uniformBlockIndex, bufSize, length, uniformBlockName);
}
void GL_APIENTRY glUniformBlockBinding(GLuint program, GLuint uniformBlockIndex, GLuint uniformBlockBinding)
{
- EVENT("(GLuint program = %u, GLuint uniformBlockIndex = %u, GLuint uniformBlockBinding = %u)",
- program, uniformBlockIndex, uniformBlockBinding);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (uniformBlockBinding >= context->getCaps().maxUniformBufferBindings)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject)
- {
- if (context->getShader(program))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- else
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- // if never linked, there won't be any uniform blocks
- if (!programBinary || uniformBlockIndex >= programBinary->getActiveUniformBlockCount())
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- programObject->bindUniformBlock(uniformBlockIndex, uniformBlockBinding);
- }
+ return gl::UniformBlockBinding(program, uniformBlockIndex, uniformBlockBinding);
}
void GL_APIENTRY glDrawArraysInstanced(GLenum mode, GLint first, GLsizei count, GLsizei instanceCount)
{
- EVENT("(GLenum mode = 0x%X, GLint first = %d, GLsizei count = %d, GLsizei instanceCount = %d)",
- mode, first, count, instanceCount);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // glDrawArraysInstanced
- UNIMPLEMENTED();
- }
+ return gl::DrawArraysInstanced(mode, first, count, instanceCount);
}
void GL_APIENTRY glDrawElementsInstanced(GLenum mode, GLsizei count, GLenum type, const GLvoid* indices, GLsizei instanceCount)
{
- EVENT("(GLenum mode = 0x%X, GLsizei count = %d, GLenum type = 0x%X, const GLvoid* indices = 0x%0.8p, GLsizei instanceCount = %d)",
- mode, count, type, indices, instanceCount);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // glDrawElementsInstanced
- UNIMPLEMENTED();
- }
+ return gl::DrawElementsInstanced(mode, count, type, indices, instanceCount);
}
GLsync GL_APIENTRY glFenceSync(GLenum condition, GLbitfield flags)
{
- EVENT("(GLenum condition = 0x%X, GLbitfield flags = 0x%X)", condition, flags);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return 0;
- }
-
- if (condition != GL_SYNC_GPU_COMMANDS_COMPLETE)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return 0;
- }
-
- if (flags != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return 0;
- }
-
- GLsync fenceSync = context->createFenceSync();
-
- gl::FenceSync *fenceSyncObject = context->getFenceSync(fenceSync);
- gl::Error error = fenceSyncObject->set(condition);
- if (error.isError())
- {
- context->deleteFenceSync(fenceSync);
- context->recordError(error);
- return NULL;
- }
-
- return fenceSync;
- }
-
- return NULL;
+ return gl::FenceSync_(condition, flags);
}
GLboolean GL_APIENTRY glIsSync(GLsync sync)
{
- EVENT("(GLsync sync = 0x%0.8p)", sync);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return (context->getFenceSync(sync) != NULL);
- }
-
- return GL_FALSE;
+ return gl::IsSync(sync);
}
void GL_APIENTRY glDeleteSync(GLsync sync)
{
- EVENT("(GLsync sync = 0x%0.8p)", sync);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (sync != static_cast<GLsync>(0) && !context->getFenceSync(sync))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->deleteFenceSync(sync);
- }
+ return gl::DeleteSync(sync);
}
GLenum GL_APIENTRY glClientWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
{
- EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
- sync, flags, timeout);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_WAIT_FAILED;
- }
-
- if ((flags & ~(GL_SYNC_FLUSH_COMMANDS_BIT)) != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return GL_WAIT_FAILED;
- }
-
- gl::FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return GL_WAIT_FAILED;
- }
-
- GLenum result = GL_WAIT_FAILED;
- gl::Error error = fenceSync->clientWait(flags, timeout, &result);
- if (error.isError())
- {
- context->recordError(error);
- return GL_WAIT_FAILED;
- }
-
- return result;
- }
-
- return GL_FALSE;
+ return gl::ClientWaitSync(sync, flags, timeout);
}
void GL_APIENTRY glWaitSync(GLsync sync, GLbitfield flags, GLuint64 timeout)
{
- EVENT("(GLsync sync = 0x%0.8p, GLbitfield flags = 0x%X, GLuint64 timeout = %llu)",
- sync, flags, timeout);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (flags != 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (timeout != GL_TIMEOUT_IGNORED)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::Error error = fenceSync->serverWait(flags, timeout);
- if (error.isError())
- {
- context->recordError(error);
- }
- }
+ return gl::WaitSync(sync, flags, timeout);
}
void GL_APIENTRY glGetInteger64v(GLenum pname, GLint64* params)
{
- EVENT("(GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
- pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!ValidateStateQuery(context, pname, &nativeType, &numParams))
- {
- return;
- }
-
- if (nativeType == GL_INT_64_ANGLEX)
- {
- context->getInteger64v(pname, params);
- }
- else
- {
- CastStateValues(context, nativeType, pname, numParams, params);
- }
- }
+ return gl::GetInteger64v(pname, params);
}
void GL_APIENTRY glGetSynciv(GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length, GLint* values)
{
- EVENT("(GLsync sync = 0x%0.8p, GLenum pname = 0x%X, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLint* values = 0x%0.8p)",
- sync, pname, bufSize, length, values);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- gl::FenceSync *fenceSync = context->getFenceSync(sync);
-
- if (!fenceSync)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_OBJECT_TYPE: values[0] = static_cast<GLint>(GL_SYNC_FENCE); break;
- case GL_SYNC_CONDITION: values[0] = static_cast<GLint>(fenceSync->getCondition()); break;
- case GL_SYNC_FLAGS: values[0] = 0; break;
-
- case GL_SYNC_STATUS:
- {
- gl::Error error = fenceSync->getStatus(values);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- break;
- }
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::GetSynciv(sync, pname, bufSize, length, values);
}
void GL_APIENTRY glGetInteger64i_v(GLenum target, GLuint index, GLint64* data)
{
- EVENT("(GLenum target = 0x%X, GLuint index = %u, GLint64* data = 0x%0.8p)",
- target, index, data);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::Caps &caps = context->getCaps();
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK_BUFFER_START:
- case GL_TRANSFORM_FEEDBACK_BUFFER_SIZE:
- case GL_TRANSFORM_FEEDBACK_BUFFER_BINDING:
- if (index >= caps.maxTransformFeedbackSeparateAttributes)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- case GL_UNIFORM_BUFFER_START:
- case GL_UNIFORM_BUFFER_SIZE:
- case GL_UNIFORM_BUFFER_BINDING:
- if (index >= caps.maxUniformBufferBindings)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!(context->getIndexedInteger64v(target, index, data)))
- {
- GLenum nativeType;
- unsigned int numParams = 0;
- if (!context->getIndexedQueryParameterInfo(target, &nativeType, &numParams))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (numParams == 0)
- return; // it is known that pname is valid, but there are no parameters to return
-
- if (nativeType == GL_INT)
- {
- GLint *intParams = new GLint[numParams];
-
- context->getIndexedIntegerv(target, index, intParams);
-
- for (unsigned int i = 0; i < numParams; ++i)
- {
- data[i] = static_cast<GLint64>(intParams[i]);
- }
-
- delete [] intParams;
- }
- else
- {
- UNREACHABLE();
- }
- }
- }
+ return gl::GetInteger64i_v(target, index, data);
}
void GL_APIENTRY glGetBufferParameteri64v(GLenum target, GLenum pname, GLint64* params)
{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLint64* params = 0x%0.8p)",
- target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (!gl::ValidBufferParameter(context, pname))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer)
- {
- // A null buffer means that "0" is bound to the requested buffer target
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (pname)
- {
- case GL_BUFFER_USAGE:
- *params = static_cast<GLint64>(buffer->getUsage());
- break;
- case GL_BUFFER_SIZE:
- *params = buffer->getSize();
- break;
- case GL_BUFFER_ACCESS_FLAGS:
- *params = static_cast<GLint64>(buffer->getAccessFlags());
- break;
- case GL_BUFFER_MAPPED:
- *params = static_cast<GLint64>(buffer->isMapped());
- break;
- case GL_BUFFER_MAP_OFFSET:
- *params = buffer->getMapOffset();
- break;
- case GL_BUFFER_MAP_LENGTH:
- *params = buffer->getMapLength();
- break;
- default: UNREACHABLE(); break;
- }
- }
+ return gl::GetBufferParameteri64v(target, pname, params);
}
void GL_APIENTRY glGenSamplers(GLsizei count, GLuint* samplers)
{
- EVENT("(GLsizei count = %d, GLuint* samplers = 0x%0.8p)", count, samplers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < count; i++)
- {
- samplers[i] = context->createSampler();
- }
- }
+ return gl::GenSamplers(count, samplers);
}
void GL_APIENTRY glDeleteSamplers(GLsizei count, const GLuint* samplers)
{
- EVENT("(GLsizei count = %d, const GLuint* samplers = 0x%0.8p)", count, samplers);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (count < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- for (int i = 0; i < count; i++)
- {
- context->deleteSampler(samplers[i]);
- }
- }
+ return gl::DeleteSamplers(count, samplers);
}
GLboolean GL_APIENTRY glIsSampler(GLuint sampler)
{
- EVENT("(GLuint sampler = %u)", sampler);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- return context->isSampler(sampler);
- }
-
- return GL_FALSE;
+ return gl::IsSampler(sampler);
}
void GL_APIENTRY glBindSampler(GLuint unit, GLuint sampler)
{
- EVENT("(GLuint unit = %u, GLuint sampler = %u)", unit, sampler);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (sampler != 0 && !context->isSampler(sampler))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (unit >= context->getCaps().maxCombinedTextureImageUnits)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- context->bindSampler(unit, sampler);
- }
+ return gl::BindSampler(unit, sampler);
}
void GL_APIENTRY glSamplerParameteri(GLuint sampler, GLenum pname, GLint param)
{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint param = %d)", sampler, pname, param);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!gl::ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!gl::ValidateTexParamParameters(context, pname, param))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->samplerParameteri(sampler, pname, param);
- }
+ return gl::SamplerParameteri(sampler, pname, param);
}
void GL_APIENTRY glSamplerParameteriv(GLuint sampler, GLenum pname, const GLint* param)
{
- glSamplerParameteri(sampler, pname, *param);
+ return gl::SamplerParameteriv(sampler, pname, param);
}
void GL_APIENTRY glSamplerParameterf(GLuint sampler, GLenum pname, GLfloat param)
{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLfloat param = %g)", sampler, pname, param);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!gl::ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
-
- if (!gl::ValidateTexParamParameters(context, pname, static_cast<GLint>(param)))
- {
- return;
- }
-
- if (!context->isSampler(sampler))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->samplerParameterf(sampler, pname, param);
- }
+ return gl::SamplerParameterf(sampler, pname, param);
}
void GL_APIENTRY glSamplerParameterfv(GLuint sampler, GLenum pname, const GLfloat* param)
{
- glSamplerParameterf(sampler, pname, *param);
+ return gl::SamplerParameterfv(sampler, pname, param);
}
void GL_APIENTRY glGetSamplerParameteriv(GLuint sampler, GLenum pname, GLint* params)
{
- EVENT("(GLuint sampler = %u, GLenum pname = 0x%X, GLint* params = 0x%0.8p)", sampler, pname, params);
+ return gl::GetSamplerParameteriv(sampler, pname, params);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+{
+ return gl::GetSamplerParameterfv(sampler, pname, params);
+}
- if (!gl::ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
+void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
+{
+ return gl::VertexAttribDivisor(index, divisor);
+}
- if (!context->isSampler(sampler))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
+{
+ return gl::BindTransformFeedback(target, id);
+}
- *params = context->getSamplerParameteri(sampler, pname);
- }
+void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+{
+ return gl::DeleteTransformFeedbacks(n, ids);
}
-void GL_APIENTRY glGetSamplerParameterfv(GLuint sampler, GLenum pname, GLfloat* params)
+void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids)
{
- EVENT("(GLuint sample = %ur, GLenum pname = 0x%X, GLfloat* params = 0x%0.8p)", sampler, pname, params);
+ return gl::GenTransformFeedbacks(n, ids);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
+{
+ return gl::IsTransformFeedback(id);
+}
- if (!gl::ValidateSamplerObjectParameter(context, pname))
- {
- return;
- }
+void GL_APIENTRY glPauseTransformFeedback(void)
+{
+ return gl::PauseTransformFeedback();
+}
- if (!context->isSampler(sampler))
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glResumeTransformFeedback(void)
+{
+ return gl::ResumeTransformFeedback();
+}
- *params = context->getSamplerParameterf(sampler, pname);
- }
+void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+{
+ return gl::GetProgramBinary(program, bufSize, length, binaryFormat, binary);
}
-void GL_APIENTRY glVertexAttribDivisor(GLuint index, GLuint divisor)
+void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
{
- EVENT("(GLuint index = %u, GLuint divisor = %u)", index, divisor);
+ return gl::ProgramBinary(program, binaryFormat, binary, length);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
+{
+ return gl::ProgramParameteri(program, pname, value);
+}
- if (index >= gl::MAX_VERTEX_ATTRIBS)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
+void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+{
+ return gl::InvalidateFramebuffer(target, numAttachments, attachments);
+}
- context->setVertexAttribDivisor(index, divisor);
- }
+void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+{
+ return gl::InvalidateSubFramebuffer(target, numAttachments, attachments, x, y, width, height);
}
-void GL_APIENTRY glBindTransformFeedback(GLenum target, GLuint id)
+void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
{
- EVENT("(GLenum target = 0x%X, GLuint id = %u)", target, id);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- switch (target)
- {
- case GL_TRANSFORM_FEEDBACK:
- {
- // Cannot bind a transform feedback object if the current one is started and not paused (3.0.2 pg 85 section 2.14.1)
- gl::TransformFeedback *curTransformFeedback = context->getState().getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Cannot bind a transform feedback object that does not exist (3.0.2 pg 85 section 2.14.1)
- if (context->getTransformFeedback(id) == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- context->bindTransformFeedback(id);
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::TexStorage2D(target, levels, internalformat, width, height);
}
-void GL_APIENTRY glDeleteTransformFeedbacks(GLsizei n, const GLuint* ids)
+void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
{
- EVENT("(GLsizei n = %d, const GLuint* ids = 0x%0.8p)", n, ids);
+ return gl::TexStorage3D(target, levels, internalformat, width, height, depth);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+{
+ return gl::GetInternalformativ(target, internalformat, pname, bufSize, params);
+}
- for (int i = 0; i < n; i++)
- {
- context->deleteTransformFeedback(ids[i]);
- }
- }
+void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
+{
+ return gl::BlitFramebufferANGLE(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
}
-void GL_APIENTRY glGenTransformFeedbacks(GLsizei n, GLuint* ids)
+void GL_APIENTRY glRenderbufferStorageMultisampleANGLE(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
{
- EVENT("(GLsizei n = %d, GLuint* ids = 0x%0.8p)", n, ids);
+ return gl::RenderbufferStorageMultisampleANGLE(target, samples, internalformat, width, height);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glDeleteFencesNV(GLsizei n, const GLuint* fences)
+{
+ return gl::DeleteFencesNV(n, fences);
+}
- for (int i = 0; i < n; i++)
- {
- ids[i] = context->createTransformFeedback();
- }
- }
+void GL_APIENTRY glGenFencesNV(GLsizei n, GLuint* fences)
+{
+ return gl::GenFencesNV(n, fences);
}
-GLboolean GL_APIENTRY glIsTransformFeedback(GLuint id)
+GLboolean GL_APIENTRY glIsFenceNV(GLuint fence)
{
- EVENT("(GLuint id = %u)", id);
+ return gl::IsFenceNV(fence);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
+GLboolean GL_APIENTRY glTestFenceNV(GLuint fence)
+{
+ return gl::TestFenceNV(fence);
+}
- return ((context->getTransformFeedback(id) != NULL) ? GL_TRUE : GL_FALSE);
- }
+void GL_APIENTRY glGetFenceivNV(GLuint fence, GLenum pname, GLint *params)
+{
+ return gl::GetFenceivNV(fence, pname, params);
+}
- return GL_FALSE;
+void GL_APIENTRY glFinishFenceNV(GLuint fence)
+{
+ return gl::FinishFenceNV(fence);
}
-void GL_APIENTRY glPauseTransformFeedback(void)
+void GL_APIENTRY glSetFenceNV(GLuint fence, GLenum condition)
{
- EVENT("(void)");
+ return gl::SetFenceNV(fence, condition);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glGetTranslatedShaderSourceANGLE(GLuint shader, GLsizei bufsize, GLsizei *length, GLchar *source)
+{
+ return gl::GetTranslatedShaderSourceANGLE(shader, bufsize, length, source);
+}
- gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
+void GL_APIENTRY glTexStorage2DEXT(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+{
+ return gl::TexStorage2DEXT(target, levels, internalformat, width, height);
+}
- // Current transform feedback must be started and not paused in order to pause (3.0.2 pg 86)
- if (!transformFeedback->isStarted() || transformFeedback->isPaused())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+GLenum GL_APIENTRY glGetGraphicsResetStatusEXT(void)
+{
+ return gl::GetGraphicsResetStatusEXT();
+}
- transformFeedback->pause();
- }
+void GL_APIENTRY glReadnPixelsEXT(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLsizei bufSize, void *data)
+{
+ return gl::ReadnPixelsEXT(x, y, width, height, format, type, bufSize, data);
}
-void GL_APIENTRY glResumeTransformFeedback(void)
+void GL_APIENTRY glGetnUniformfvEXT(GLuint program, GLint location, GLsizei bufSize, float *params)
{
- EVENT("(void)");
+ return gl::GetnUniformfvEXT(program, location, bufSize, params);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glGetnUniformivEXT(GLuint program, GLint location, GLsizei bufSize, GLint *params)
+{
+ return gl::GetnUniformivEXT(program, location, bufSize, params);
+}
- gl::TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
- ASSERT(transformFeedback != NULL);
+void GL_APIENTRY glGenQueriesEXT(GLsizei n, GLuint *ids)
+{
+ return gl::GenQueriesEXT(n, ids);
+}
- // Current transform feedback must be started and paused in order to resume (3.0.2 pg 86)
- if (!transformFeedback->isStarted() || !transformFeedback->isPaused())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glDeleteQueriesEXT(GLsizei n, const GLuint *ids)
+{
+ return gl::DeleteQueriesEXT(n, ids);
+}
- transformFeedback->resume();
- }
+GLboolean GL_APIENTRY glIsQueryEXT(GLuint id)
+{
+ return gl::IsQueryEXT(id);
}
-void GL_APIENTRY glGetProgramBinary(GLuint program, GLsizei bufSize, GLsizei* length, GLenum* binaryFormat, GLvoid* binary)
+void GL_APIENTRY glBeginQueryEXT(GLenum target, GLuint id)
{
- EVENT("(GLuint program = %u, GLsizei bufSize = %d, GLsizei* length = 0x%0.8p, GLenum* binaryFormat = 0x%0.8p, GLvoid* binary = 0x%0.8p)",
- program, bufSize, length, binaryFormat, binary);
+ return gl::BeginQueryEXT(target, id);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glEndQueryEXT(GLenum target)
+{
+ return gl::EndQueryEXT(target);
+}
- // glGetProgramBinary
- UNIMPLEMENTED();
- }
+void GL_APIENTRY glGetQueryivEXT(GLenum target, GLenum pname, GLint *params)
+{
+ return gl::GetQueryivEXT(target, pname, params);
}
-void GL_APIENTRY glProgramBinary(GLuint program, GLenum binaryFormat, const GLvoid* binary, GLsizei length)
+void GL_APIENTRY glGetQueryObjectuivEXT(GLuint id, GLenum pname, GLuint *params)
{
- EVENT("(GLuint program = %u, GLenum binaryFormat = 0x%X, const GLvoid* binary = 0x%0.8p, GLsizei length = %d)",
- program, binaryFormat, binary, length);
+ return gl::GetQueryObjectuivEXT(id, pname, params);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
+{
+ return gl::DrawBuffersEXT(n, bufs);
+}
- // glProgramBinary
- UNIMPLEMENTED();
- }
+void GL_APIENTRY glDrawArraysInstancedANGLE(GLenum mode, GLint first, GLsizei count, GLsizei primcount)
+{
+ return gl::DrawArraysInstancedANGLE(mode, first, count, primcount);
}
-void GL_APIENTRY glProgramParameteri(GLuint program, GLenum pname, GLint value)
+void GL_APIENTRY glDrawElementsInstancedANGLE(GLenum mode, GLsizei count, GLenum type, const void *indices, GLsizei primcount)
{
- EVENT("(GLuint program = %u, GLenum pname = 0x%X, GLint value = %d)",
- program, pname, value);
+ return gl::DrawElementsInstancedANGLE(mode, count, type, indices, primcount);
+}
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
+void GL_APIENTRY glVertexAttribDivisorANGLE(GLuint index, GLuint divisor)
+{
+ return gl::VertexAttribDivisorANGLE(index, divisor);
+}
- // glProgramParameteri
- UNIMPLEMENTED();
- }
+void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary)
+{
+ return gl::GetProgramBinaryOES(program, bufSize, length, binaryFormat, binary);
}
-void GL_APIENTRY glInvalidateFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments)
+void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length)
{
- EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p)",
- target, numAttachments, attachments);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
- {
- gl::Error error = framebuffer->invalidate(context->getCaps(), numAttachments, attachments);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- }
+ return gl::ProgramBinaryOES(program, binaryFormat, binary, length);
}
-void GL_APIENTRY glInvalidateSubFramebuffer(GLenum target, GLsizei numAttachments, const GLenum* attachments, GLint x, GLint y, GLsizei width, GLsizei height)
+void* GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
{
- EVENT("(GLenum target = 0x%X, GLsizei numAttachments = %d, const GLenum* attachments = 0x%0.8p, GLint x = %d, "
- "GLint y = %d, GLsizei width = %d, GLsizei height = %d)",
- target, numAttachments, attachments, x, y, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateInvalidateFramebufferParameters(context, target, numAttachments, attachments))
- {
- return;
- }
-
- gl::Framebuffer *framebuffer = context->getState().getTargetFramebuffer(target);
- ASSERT(framebuffer);
-
- if (framebuffer->completeness(context->getData()) == GL_FRAMEBUFFER_COMPLETE)
- {
- gl::Error error = framebuffer->invalidateSub(numAttachments, attachments, x, y, width, height);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- }
+ return gl::MapBufferOES(target, access);
}
-void GL_APIENTRY glTexStorage2D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height)
+GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target)
{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, GLsizei height = %d)",
- target, levels, internalformat, width, height);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, 1))
- {
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *texture2d = context->getTexture2D();
- gl::Error error = texture2d->storage(levels, internalformat, width, height);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP:
- {
- gl::TextureCubeMap *textureCube = context->getTextureCubeMap();
- gl::Error error = textureCube->storage(levels, internalformat, width);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
+ return gl::UnmapBufferOES(target);
}
-void GL_APIENTRY glTexStorage3D(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth)
+void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, GLvoid **params)
{
- EVENT("(GLenum target = 0x%X, GLsizei levels = %d, GLenum internalformat = 0x%X, GLsizei width = %d, "
- "GLsizei height = %d, GLsizei depth = %d)",
- target, levels, internalformat, width, height, depth);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!ValidateES3TexStorageParameters(context, target, levels, internalformat, width, height, depth))
- {
- return;
- }
-
- switch (target)
- {
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *texture3d = context->getTexture3D();
- gl::Error error = texture3d->storage(levels, internalformat, width, height, depth);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *texture2darray = context->getTexture2DArray();
- gl::Error error = texture2darray->storage(levels, internalformat, width, height, depth);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
- break;
-
- default:
- UNREACHABLE();
- }
- }
+ return gl::GetBufferPointervOES(target, pname, params);
}
-void GL_APIENTRY glGetInternalformativ(GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, GLint* params)
+void* GL_APIENTRY glMapBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
{
- EVENT("(GLenum target = 0x%X, GLenum internalformat = 0x%X, GLenum pname = 0x%X, GLsizei bufSize = %d, "
- "GLint* params = 0x%0.8p)",
- target, internalformat, pname, bufSize, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (context->getClientVersion() < 3)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- const gl::TextureCaps &formatCaps = context->getTextureCaps().get(internalformat);
- if (!formatCaps.renderable)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (target != GL_RENDERBUFFER)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (bufSize < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- switch (pname)
- {
- case GL_NUM_SAMPLE_COUNTS:
- if (bufSize != 0)
- {
- *params = formatCaps.sampleCounts.size();
- }
- break;
-
- case GL_SAMPLES:
- std::copy_n(formatCaps.sampleCounts.rbegin(), std::min<size_t>(bufSize, formatCaps.sampleCounts.size()), params);
- break;
-
- default:
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
- }
-}
-
-// Extension functions
-
-void GL_APIENTRY glBlitFramebufferANGLE(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- EVENT("(GLint srcX0 = %d, GLint srcY0 = %d, GLint srcX1 = %d, GLint srcY1 = %d, "
- "GLint dstX0 = %d, GLint dstY0 = %d, GLint dstX1 = %d, GLint dstY1 = %d, "
- "GLbitfield mask = 0x%X, GLenum filter = 0x%X)",
- srcX0, srcY0, srcX1, srcX1, dstX0, dstY0, dstX1, dstY1, mask, filter);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!ValidateBlitFramebufferParameters(context, srcX0, srcY0, srcX1, srcY1,
- dstX0, dstY0, dstX1, dstY1, mask, filter,
- true))
- {
- return;
- }
-
- gl::Error error = context->blitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
- mask, filter);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glTexImage3DOES(GLenum target, GLint level, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth,
- GLint border, GLenum format, GLenum type, const GLvoid* pixels)
-{
- EVENT("(GLenum target = 0x%X, GLint level = %d, GLenum internalformat = 0x%X, "
- "GLsizei width = %d, GLsizei height = %d, GLsizei depth = %d, GLint border = %d, "
- "GLenum format = 0x%X, GLenum type = 0x%x, const GLvoid* pixels = 0x%0.8p)",
- target, level, internalformat, width, height, depth, border, format, type, pixels);
-
- UNIMPLEMENTED(); // FIXME
-}
-
-void GL_APIENTRY glGetProgramBinaryOES(GLuint program, GLsizei bufSize, GLsizei *length,
- GLenum *binaryFormat, void *binary)
-{
- EVENT("(GLenum program = 0x%X, bufSize = %d, length = 0x%0.8p, binaryFormat = 0x%0.8p, binary = 0x%0.8p)",
- program, bufSize, length, binaryFormat, binary);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Program *programObject = context->getProgram(program);
-
- if (!programObject || !programObject->isLinked())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- if (!programBinary)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Error error = programBinary->save(binaryFormat, binary, bufSize, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
-}
-
-void GL_APIENTRY glProgramBinaryOES(GLuint program, GLenum binaryFormat,
- const void *binary, GLint length)
-{
- EVENT("(GLenum program = 0x%X, binaryFormat = 0x%x, binary = 0x%0.8p, length = %d)",
- program, binaryFormat, binary, length);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- const std::vector<GLenum> &programBinaryFormats = context->getCaps().programBinaryFormats;
- if (std::find(programBinaryFormats.begin(), programBinaryFormats.end(), binaryFormat) == programBinaryFormats.end())
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Program *programObject = context->getProgram(program);
- if (!programObject)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- gl::Error error = context->setProgramBinary(program, binaryFormat, binary, length);
- if (error.isError())
- {
- context->recordError(error);
- return;
- }
- }
+ return gl::MapBufferRangeEXT(target, offset, length, access);
}
-void GL_APIENTRY glDrawBuffersEXT(GLsizei n, const GLenum *bufs)
+void GL_APIENTRY glFlushMappedBufferRangeEXT(GLenum target, GLintptr offset, GLsizeiptr length)
{
- EVENT("(GLenum n = %d, bufs = 0x%0.8p)", n, bufs);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (n < 0 || static_cast<GLuint>(n) > context->getCaps().maxDrawBuffers)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- ASSERT(context->getState().getDrawFramebuffer());
-
- if (context->getState().getDrawFramebuffer()->id() == 0)
- {
- if (n != 1)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (bufs[0] != GL_NONE && bufs[0] != GL_BACK)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
- else
- {
- for (int colorAttachment = 0; colorAttachment < n; colorAttachment++)
- {
- const GLenum attachment = GL_COLOR_ATTACHMENT0_EXT + colorAttachment;
- if (bufs[colorAttachment] != GL_NONE && bufs[colorAttachment] != attachment)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
- }
- }
-
- gl::Framebuffer *framebuffer = context->getState().getDrawFramebuffer();
- ASSERT(framebuffer);
-
- for (unsigned int colorAttachment = 0; colorAttachment < static_cast<unsigned int>(n); colorAttachment++)
- {
- framebuffer->setDrawBufferState(colorAttachment, bufs[colorAttachment]);
- }
-
- for (unsigned int colorAttachment = n; colorAttachment < context->getCaps().maxDrawBuffers; colorAttachment++)
- {
- framebuffer->setDrawBufferState(colorAttachment, GL_NONE);
- }
- }
-}
-
-void GL_APIENTRY glGetBufferPointervOES(GLenum target, GLenum pname, void** params)
-{
- EVENT("(GLenum target = 0x%X, GLenum pname = 0x%X, GLvoid** params = 0x%0.8p)", target, pname, params);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- if (pname != GL_BUFFER_MAP_POINTER)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (!buffer || !buffer->isMapped())
- {
- *params = NULL;
- }
- else
- {
- *params = buffer->getMapPointer();
- }
- }
-}
-
-void * GL_APIENTRY glMapBufferOES(GLenum target, GLenum access)
-{
- EVENT("(GLenum target = 0x%X, GLbitfield access = 0x%X)", target, access);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if (access != GL_WRITE_ONLY_OES)
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (buffer->isMapped())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- gl::Error error = buffer->mapRange(0, buffer->getSize(), GL_MAP_WRITE_BIT);
- if (error.isError())
- {
- context->recordError(error);
- return NULL;
- }
-
- return buffer->getMapPointer();
- }
-
- return NULL;
+ return gl::FlushMappedBufferRangeEXT(target, offset, length);
}
-GLboolean GL_APIENTRY glUnmapBufferOES(GLenum target)
+void GL_APIENTRY SetTraceFunctionPointers(GetCategoryEnabledFlagFunc getCategoryEnabledFlag,
+ AddTraceEventFunc addTraceEvent)
{
- EVENT("(GLenum target = 0x%X)", target);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return GL_FALSE;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL || !buffer->isMapped())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return GL_FALSE;
- }
-
- // TODO: detect if we had corruption. if so, throw an error and return false.
-
- gl::Error error = buffer->unmap();
- if (error.isError())
- {
- context->recordError(error);
- return GL_FALSE;
- }
-
- return GL_TRUE;
- }
-
- return GL_FALSE;
-}
-
-void* GL_APIENTRY glMapBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length, GLbitfield access)
-{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d, GLbitfield access = 0x%X)",
- target, offset, length, access);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return NULL;
- }
-
- if (offset < 0 || length < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- // Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
-
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getSize()))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- // Check for invalid bits in the mask
- GLbitfield allAccessBits = GL_MAP_READ_BIT |
- GL_MAP_WRITE_BIT |
- GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_INVALIDATE_BUFFER_BIT |
- GL_MAP_FLUSH_EXPLICIT_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT;
-
- if (access & ~(allAccessBits))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return NULL;
- }
-
- if (length == 0 || buffer->isMapped())
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- // Check for invalid bit combinations
- if ((access & (GL_MAP_READ_BIT | GL_MAP_WRITE_BIT)) == 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- GLbitfield writeOnlyBits = GL_MAP_INVALIDATE_RANGE_BIT |
- GL_MAP_INVALIDATE_BUFFER_BIT |
- GL_MAP_UNSYNCHRONIZED_BIT;
-
- if ((access & GL_MAP_READ_BIT) != 0 && (access & writeOnlyBits) != 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- if ((access & GL_MAP_WRITE_BIT) == 0 && (access & GL_MAP_FLUSH_EXPLICIT_BIT) != 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return NULL;
- }
-
- gl::Error error = buffer->mapRange(offset, length, access);
- if (error.isError())
- {
- context->recordError(error);
- return NULL;
- }
-
- return buffer->getMapPointer();
- }
-
- return NULL;
-}
-
-void GL_APIENTRY glFlushMappedBufferRangeEXT (GLenum target, GLintptr offset, GLsizeiptr length)
-{
- EVENT("(GLenum target = 0x%X, GLintptr offset = %d, GLsizeiptr length = %d)", target, offset, length);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- if (offset < 0 || length < 0)
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- if (!gl::ValidBufferTarget(context, target))
- {
- context->recordError(gl::Error(GL_INVALID_ENUM));
- return;
- }
-
- gl::Buffer *buffer = context->getState().getTargetBuffer(target);
-
- if (buffer == NULL)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- if (!buffer->isMapped() || (buffer->getAccessFlags() & GL_MAP_FLUSH_EXPLICIT_BIT) == 0)
- {
- context->recordError(gl::Error(GL_INVALID_OPERATION));
- return;
- }
-
- // Check for buffer overflow
- size_t offsetSize = static_cast<size_t>(offset);
- size_t lengthSize = static_cast<size_t>(length);
-
- if (!rx::IsUnsignedAdditionSafe(offsetSize, lengthSize) ||
- offsetSize + lengthSize > static_cast<size_t>(buffer->getMapLength()))
- {
- context->recordError(gl::Error(GL_INVALID_VALUE));
- return;
- }
-
- // We do not currently support a non-trivial implementation of FlushMappedBufferRange
- }
-}
-
-__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname)
-{
- struct Extension
- {
- const char *name;
- __eglMustCastToProperFunctionPointerType address;
- };
-
- static const Extension glExtensions[] =
- {
- {"glTexImage3DOES", (__eglMustCastToProperFunctionPointerType)glTexImage3DOES},
- {"glBlitFramebufferANGLE", (__eglMustCastToProperFunctionPointerType)glBlitFramebufferANGLE},
- {"glRenderbufferStorageMultisampleANGLE", (__eglMustCastToProperFunctionPointerType)glRenderbufferStorageMultisampleANGLE},
- {"glDeleteFencesNV", (__eglMustCastToProperFunctionPointerType)glDeleteFencesNV},
- {"glGenFencesNV", (__eglMustCastToProperFunctionPointerType)glGenFencesNV},
- {"glIsFenceNV", (__eglMustCastToProperFunctionPointerType)glIsFenceNV},
- {"glTestFenceNV", (__eglMustCastToProperFunctionPointerType)glTestFenceNV},
- {"glGetFenceivNV", (__eglMustCastToProperFunctionPointerType)glGetFenceivNV},
- {"glFinishFenceNV", (__eglMustCastToProperFunctionPointerType)glFinishFenceNV},
- {"glSetFenceNV", (__eglMustCastToProperFunctionPointerType)glSetFenceNV},
- {"glGetTranslatedShaderSourceANGLE", (__eglMustCastToProperFunctionPointerType)glGetTranslatedShaderSourceANGLE},
- {"glTexStorage2DEXT", (__eglMustCastToProperFunctionPointerType)glTexStorage2DEXT},
- {"glGetGraphicsResetStatusEXT", (__eglMustCastToProperFunctionPointerType)glGetGraphicsResetStatusEXT},
- {"glReadnPixelsEXT", (__eglMustCastToProperFunctionPointerType)glReadnPixelsEXT},
- {"glGetnUniformfvEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformfvEXT},
- {"glGetnUniformivEXT", (__eglMustCastToProperFunctionPointerType)glGetnUniformivEXT},
- {"glGenQueriesEXT", (__eglMustCastToProperFunctionPointerType)glGenQueriesEXT},
- {"glDeleteQueriesEXT", (__eglMustCastToProperFunctionPointerType)glDeleteQueriesEXT},
- {"glIsQueryEXT", (__eglMustCastToProperFunctionPointerType)glIsQueryEXT},
- {"glBeginQueryEXT", (__eglMustCastToProperFunctionPointerType)glBeginQueryEXT},
- {"glEndQueryEXT", (__eglMustCastToProperFunctionPointerType)glEndQueryEXT},
- {"glGetQueryivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryivEXT},
- {"glGetQueryObjectuivEXT", (__eglMustCastToProperFunctionPointerType)glGetQueryObjectuivEXT},
- {"glDrawBuffersEXT", (__eglMustCastToProperFunctionPointerType)glDrawBuffersEXT},
- {"glVertexAttribDivisorANGLE", (__eglMustCastToProperFunctionPointerType)glVertexAttribDivisorANGLE},
- {"glDrawArraysInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawArraysInstancedANGLE},
- {"glDrawElementsInstancedANGLE", (__eglMustCastToProperFunctionPointerType)glDrawElementsInstancedANGLE},
- {"glGetProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glGetProgramBinaryOES},
- {"glProgramBinaryOES", (__eglMustCastToProperFunctionPointerType)glProgramBinaryOES},
- {"glGetBufferPointervOES", (__eglMustCastToProperFunctionPointerType)glGetBufferPointervOES},
- {"glMapBufferOES", (__eglMustCastToProperFunctionPointerType)glMapBufferOES},
- {"glUnmapBufferOES", (__eglMustCastToProperFunctionPointerType)glUnmapBufferOES},
- {"glMapBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glMapBufferRangeEXT},
- {"glFlushMappedBufferRangeEXT", (__eglMustCastToProperFunctionPointerType)glFlushMappedBufferRangeEXT}, };
-
- for (unsigned int ext = 0; ext < ArraySize(glExtensions); ext++)
- {
- if (strcmp(procname, glExtensions[ext].name) == 0)
- {
- return (__eglMustCastToProperFunctionPointerType)glExtensions[ext].address;
- }
- }
-
- return NULL;
-}
-
-// Non-public functions used by EGL
-
-bool EGLAPIENTRY glBindTexImage(egl::Surface *surface)
-{
- EVENT("(egl::Surface* surface = 0x%0.8p)",
- surface);
-
- gl::Context *context = gl::getNonLostContext();
- if (context)
- {
- gl::Texture2D *textureObject = context->getTexture2D();
- ASSERT(textureObject != NULL);
-
- if (textureObject->isImmutable())
- {
- return false;
- }
-
- textureObject->bindTexImage(surface);
- }
-
- return true;
+ gl::g_getCategoryEnabledFlag = getCategoryEnabledFlag;
+ gl::g_addTraceEvent = addTraceEvent;
}
}
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
index 33557eb1c9..9c6dc497d0 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
@@ -144,7 +144,6 @@ EXPORTS
glViewport @142
; Extensions
- glTexImage3DOES @143
glBlitFramebufferANGLE @149
glRenderbufferStorageMultisampleANGLE @150
glDeleteFencesNV @151
@@ -285,12 +284,5 @@ EXPORTS
glTexStorage3D @282
glGetInternalformativ @283
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress @148 NONAME
- glBindTexImage @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers @284
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc b/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc
deleted file mode 100644
index 76cd05566e..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.rc
+++ /dev/null
@@ -1,103 +0,0 @@
-// Microsoft Visual C++ generated resource script.
-//
-#include "resource.h"
-
-#define APSTUDIO_READONLY_SYMBOLS
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 2 resource.
-//
-#include <windows.h>
-#include "../common/version.h"
-
-/////////////////////////////////////////////////////////////////////////////
-#undef APSTUDIO_READONLY_SYMBOLS
-
-/////////////////////////////////////////////////////////////////////////////
-// English (U.S.) resources
-
-#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
-#ifdef _WIN32
-LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
-#pragma code_page(1252)
-#endif //_WIN32
-
-#ifdef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// TEXTINCLUDE
-//
-
-1 TEXTINCLUDE
-BEGIN
- "resource.h\0"
-END
-
-2 TEXTINCLUDE
-BEGIN
- "#include ""afxres.h""\r\n"
- "#include ""../common/version.h""\0"
-END
-
-3 TEXTINCLUDE
-BEGIN
- "\r\n"
- "\0"
-END
-
-#endif // APSTUDIO_INVOKED
-
-
-/////////////////////////////////////////////////////////////////////////////
-//
-// Version
-//
-
-VS_VERSION_INFO VERSIONINFO
- FILEVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0
- PRODUCTVERSION ANGLE_MAJOR_VERSION,ANGLE_MINOR_VERSION,0,0
- FILEFLAGSMASK 0x17L
-#ifdef _DEBUG
- FILEFLAGS 0x1L
-#else
- FILEFLAGS 0x0L
-#endif
- FILEOS 0x4L
- FILETYPE 0x2L
- FILESUBTYPE 0x0L
-BEGIN
- BLOCK "StringFileInfo"
- BEGIN
- BLOCK "040904b0"
- BEGIN
- VALUE "FileDescription", "ANGLE libGLESv2 Dynamic Link Library"
- VALUE "FileVersion", ANGLE_VERSION_STRING
- VALUE "InternalName", "libGLESv2"
- VALUE "LegalCopyright", "Copyright (C) 2011 Google Inc."
- VALUE "OriginalFilename", "libGLESv2.dll"
- VALUE "PrivateBuild", ANGLE_VERSION_STRING
- VALUE "ProductName", "ANGLE libGLESv2 Dynamic Link Library"
- VALUE "ProductVersion", ANGLE_VERSION_STRING
- VALUE "Comments", "Build Date: " ANGLE_COMMIT_DATE
- END
- END
- BLOCK "VarFileInfo"
- BEGIN
- VALUE "Translation", 0x409, 1200
- END
-END
-
-#endif // English (U.S.) resources
-/////////////////////////////////////////////////////////////////////////////
-
-
-
-#ifndef APSTUDIO_INVOKED
-/////////////////////////////////////////////////////////////////////////////
-//
-// Generated from the TEXTINCLUDE 3 resource.
-//
-
-
-/////////////////////////////////////////////////////////////////////////////
-#endif // not APSTUDIO_INVOKED
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
index 18ffcf6a0d..e02b85bcf2 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2_mingw32.def
@@ -144,7 +144,6 @@ EXPORTS
glViewport@16 @142
; Extensions
- glTexImage3DOES@40 @143
glBlitFramebufferANGLE@40 @149
glRenderbufferStorageMultisampleANGLE@20 @150
glDeleteFencesNV@8 @151
@@ -285,12 +284,5 @@ EXPORTS
glTexStorage3D@24 @282
glGetInternalformativ@20 @283
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress@4 @148 NONAME
- glBindTexImage@4 @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers@8 @284
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
index 120371e013..d35309c6ce 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d.def
@@ -144,7 +144,6 @@ EXPORTS
glViewport @142
; Extensions
- glTexImage3DOES @143
glBlitFramebufferANGLE @149
glRenderbufferStorageMultisampleANGLE @150
glDeleteFencesNV @151
@@ -285,12 +284,5 @@ EXPORTS
glTexStorage3D @282
glGetInternalformativ @283
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress @148 NONAME
- glBindTexImage @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers @284
diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
index 8c1306a703..e2b2c333a1 100644
--- a/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2d_mingw32.def
@@ -144,7 +144,6 @@ EXPORTS
glViewport@16 @142
; Extensions
- glTexImage3DOES@40 @143
glBlitFramebufferANGLE@40 @149
glRenderbufferStorageMultisampleANGLE@20 @150
glDeleteFencesNV@8 @151
@@ -285,12 +284,5 @@ EXPORTS
glTexStorage3D@24 @282
glGetInternalformativ@20 @283
- ; EGL dependencies
- glCreateContext @144 NONAME
- glDestroyContext @145 NONAME
- glMakeCurrent @146 NONAME
- glGetCurrentContext @147 NONAME
- glGetProcAddress@4 @148 NONAME
- glBindTexImage@4 @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
+ ; Setting up TRACE macro callbacks
+ SetTraceFunctionPointers@8 @284
diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
deleted file mode 100644
index 00f63ae079..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/main.cpp
+++ /dev/null
@@ -1,186 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.cpp: DLL entry point and management of thread-local data.
-
-#include "libGLESv2/main.h"
-#include "libGLESv2/Context.h"
-
-#include "common/tls.h"
-
-static TLSIndex currentTLS = TLS_INVALID_INDEX;
-
-namespace gl
-{
-
-// TODO(kbr): figure out how these are going to be managed on
-// non-Windows platforms. These routines would need to be exported
-// from ANGLE and called cooperatively when users create and destroy
-// threads -- or the initialization of the TLS index, and allocation
-// of thread-local data, will have to be done lazily. Will have to use
-// destructor function with pthread_create_key on POSIX platforms to
-// clean up thread-local data.
-
-// Call this exactly once at process startup.
-bool CreateThreadLocalIndex()
-{
- currentTLS = CreateTLSIndex();
- if (currentTLS == TLS_INVALID_INDEX)
- {
- return false;
- }
- return true;
-}
-
-// Call this exactly once at process shutdown.
-void DestroyThreadLocalIndex()
-{
- DestroyTLSIndex(currentTLS);
- currentTLS = TLS_INVALID_INDEX;
-}
-
-// Call this upon thread startup.
-Current *AllocateCurrent()
-{
- ASSERT(currentTLS != TLS_INVALID_INDEX);
- if (currentTLS == TLS_INVALID_INDEX)
- {
- return NULL;
- }
-
- Current *current = new Current();
- current->context = NULL;
- current->display = NULL;
-
- if (!SetTLSValue(currentTLS, current))
- {
- ERR("Could not set thread local storage.");
- return NULL;
- }
-
- return current;
-}
-
-// Call this upon thread shutdown.
-void DeallocateCurrent()
-{
- Current *current = reinterpret_cast<Current*>(GetTLSValue(currentTLS));
- SafeDelete(current);
- SetTLSValue(currentTLS, NULL);
-}
-
-}
-
-#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
-extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
-{
- switch (reason)
- {
- case DLL_PROCESS_ATTACH:
- {
- if (!gl::CreateThreadLocalIndex())
- {
- return FALSE;
- }
-
-#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
- gl::InitializeDebugAnnotations();
-#endif
- }
- // Fall through to initialize index
- case DLL_THREAD_ATTACH:
- {
- gl::AllocateCurrent();
- }
- break;
- case DLL_THREAD_DETACH:
- {
- gl::DeallocateCurrent();
- }
- break;
- case DLL_PROCESS_DETACH:
- {
- gl::DeallocateCurrent();
- gl::DestroyThreadLocalIndex();
-
-#ifdef ANGLE_ENABLE_DEBUG_ANNOTATIONS
- gl::UninitializeDebugAnnotations();
-#endif
- }
- break;
- default:
- break;
- }
-
- return TRUE;
-}
-#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC
-
-namespace gl
-{
-
-Current *GetCurrentData()
-{
-#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
- Current *current = reinterpret_cast<Current*>(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 &current;
-#endif
-}
-
-void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
-{
- Current *current = GetCurrentData();
-
- current->context = context;
- current->display = display;
-
- if (context && display && surface)
- {
- context->makeCurrent(surface);
- }
-}
-
-Context *getContext()
-{
- Current *current = GetCurrentData();
-
- return current->context;
-}
-
-Context *getNonLostContext()
-{
- Context *context = getContext();
-
- if (context)
- {
- if (context->isContextLost())
- {
- context->recordError(Error(GL_OUT_OF_MEMORY, "Context has been lost."));
- return NULL;
- }
- else
- {
- return context;
- }
- }
- return NULL;
-}
-
-egl::Display *getDisplay()
-{
- Current *current = GetCurrentData();
-
- return current->display;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/main.h b/src/3rdparty/angle/src/libGLESv2/main.h
deleted file mode 100644
index dff02787f5..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/main.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//
-// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// main.h: Management of thread-local data.
-
-#ifndef LIBGLESV2_MAIN_H_
-#define LIBGLESV2_MAIN_H_
-
-#include "common/debug.h"
-
-#include <GLES2/gl2.h>
-#include <EGL/egl.h>
-
-namespace egl
-{
-class Display;
-class Surface;
-class AttributeMap;
-}
-
-namespace gl
-{
-class Context;
-
-struct Current
-{
- Context *context;
- egl::Display *display;
-};
-
-void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface);
-
-Context *getContext();
-Context *getNonLostContext();
-egl::Display *getDisplay();
-
-}
-
-namespace rx
-{
-class Renderer;
-}
-
-extern "C"
-{
-// Exported functions for use by EGL
-gl::Context *glCreateContext(int clientVersion, const gl::Context *shareContext, rx::Renderer *renderer, bool notifyResets, bool robustAccess);
-void glDestroyContext(gl::Context *context);
-void glMakeCurrent(gl::Context *context, egl::Display *display, egl::Surface *surface);
-gl::Context *glGetCurrentContext();
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap);
-void glDestroyRenderer(rx::Renderer *renderer);
-
-__eglMustCastToProperFunctionPointerType EGLAPIENTRY glGetProcAddress(const char *procname);
-bool EGLAPIENTRY glBindTexImage(egl::Surface *surface);
-}
-
-#endif // LIBGLESV2_MAIN_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
deleted file mode 100644
index 1dd46785d9..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/FenceImpl.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// FenceImpl.h: Defines the rx::FenceNVImpl and rx::FenceSyncImpl classes.
-
-#ifndef LIBGLESV2_RENDERER_FENCEIMPL_H_
-#define LIBGLESV2_RENDERER_FENCEIMPL_H_
-
-#include "libGLESv2/Error.h"
-
-#include "common/angleutils.h"
-
-#include "angle_gl.h"
-
-namespace rx
-{
-
-class FenceNVImpl
-{
- public:
- FenceNVImpl() { };
- virtual ~FenceNVImpl() { };
-
- virtual gl::Error set() = 0;
- virtual gl::Error test(bool flushCommandBuffer, GLboolean *outFinished) = 0;
- virtual gl::Error finishFence(GLboolean *outFinished) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FenceNVImpl);
-};
-
-class FenceSyncImpl
-{
- public:
- FenceSyncImpl() { };
- virtual ~FenceSyncImpl() { };
-
- virtual gl::Error set() = 0;
- virtual gl::Error clientWait(GLbitfield flags, GLuint64 timeout, GLenum *outResult) = 0;
- virtual gl::Error serverWait(GLbitfield flags, GLuint64 timeout) = 0;
- virtual gl::Error getStatus(GLint *outResult) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FenceSyncImpl);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_FENCEIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
deleted file mode 100644
index 5b9b75f562..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Image.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Implements the rx::Image class, an abstract base class for the
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#include "libGLESv2/renderer/Image.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/main.h"
-
-namespace rx
-{
-
-Image::Image()
-{
- mWidth = 0;
- mHeight = 0;
- mDepth = 0;
- mInternalFormat = GL_NONE;
- mActualFormat = GL_NONE;
- mTarget = GL_NONE;
- mRenderable = false;
- mDirty = false;
-}
-
-gl::Error Image::copy(GLint xoffset, GLint yoffset, GLint zoffset, const gl::Rectangle &area, gl::Framebuffer *source)
-{
- gl::FramebufferAttachment *colorbuffer = source->getReadColorbuffer();
- ASSERT(colorbuffer);
-
- RenderTarget *renderTarget = NULL;
- gl::Error error = GetAttachmentRenderTarget(colorbuffer, &renderTarget);
- if (error.isError())
- {
- return error;
- }
-
- ASSERT(renderTarget);
- return copy(xoffset, yoffset, zoffset, area, renderTarget);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp
deleted file mode 100644
index 857fdc9dae..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget.cpp: Implements serial handling for rx::RenderTarget
-
-#include "libGLESv2/renderer/RenderTarget.h"
-
-namespace rx
-{
-unsigned int RenderTarget::mCurrentSerial = 1;
-
-RenderTarget::RenderTarget()
- : mSerial(issueSerials(1))
-{
-}
-
-RenderTarget::~RenderTarget()
-{
-}
-
-unsigned int RenderTarget::getSerial() const
-{
- return mSerial;
-}
-
-unsigned int RenderTarget::issueSerials(unsigned int count)
-{
- unsigned int firstSerial = mCurrentSerial;
- mCurrentSerial += count;
- return firstSerial;
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
deleted file mode 100644
index 3bdfb0cc98..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderTarget.h
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderTarget.h: Defines an abstract wrapper class to manage IDirect3DSurface9
-// and ID3D11View objects belonging to renderbuffers.
-
-#ifndef LIBGLESV2_RENDERER_RENDERTARGET_H_
-#define LIBGLESV2_RENDERER_RENDERTARGET_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/angletypes.h"
-
-namespace rx
-{
-class RenderTarget
-{
- public:
- RenderTarget();
- virtual ~RenderTarget();
-
- virtual GLsizei getWidth() const = 0;
- virtual GLsizei getHeight() const = 0;
- virtual GLsizei getDepth() const = 0;
- virtual GLenum getInternalFormat() const = 0;
- virtual GLenum getActualFormat() const = 0;
- virtual GLsizei getSamples() const = 0;
- gl::Extents getExtents() const { return gl::Extents(getWidth(), getHeight(), getDepth()); }
-
- virtual void invalidate(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
-
- virtual unsigned int getSerial() const;
- static unsigned int issueSerials(unsigned int count);
-
- struct Desc {
- GLsizei width;
- GLsizei height;
- GLsizei depth;
- GLenum format;
- };
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderTarget);
-
- const unsigned int mSerial;
- static unsigned int mCurrentSerial;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERTARGET_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h
deleted file mode 100644
index 52e070f1d3..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/RenderbufferImpl.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderbufferImpl.h: Defines the abstract class gl::RenderbufferImpl
-
-#ifndef LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
-#define LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
-
-#include "angle_gl.h"
-
-#include "libGLESv2/Error.h"
-
-#include "common/angleutils.h"
-
-namespace rx
-{
-
-class RenderbufferImpl
-{
- public:
- RenderbufferImpl();
- virtual ~RenderbufferImpl() = 0;
-
- virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) = 0;
-
- virtual GLsizei getWidth() const = 0;
- virtual GLsizei getHeight() const = 0;
- virtual GLenum getInternalFormat() const = 0;
- virtual GLenum getActualFormat() const = 0;
- virtual GLsizei getSamples() const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferImpl);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERBUFFERIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
deleted file mode 100644
index df3dae1e38..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.cpp
+++ /dev/null
@@ -1,172 +0,0 @@
-//
-// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.cpp: Implements EGL dependencies for creating and destroying Renderer instances.
-
-#include "common/utilities.h"
-#include "libEGL/AttributeMap.h"
-#include "libGLESv2/main.h"
-#include "libGLESv2/renderer/Renderer.h"
-
-#include <EGL/eglext.h>
-
-#if defined (ANGLE_ENABLE_D3D9)
-#include "libGLESv2/renderer/d3d/d3d9/Renderer9.h"
-#endif // ANGLE_ENABLE_D3D9
-
-#if defined (ANGLE_ENABLE_D3D11)
-#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-#endif // ANGLE_ENABLE_D3D11
-
-#if defined (ANGLE_TEST_CONFIG)
-#define ANGLE_DEFAULT_D3D11 1
-#endif
-
-#if !defined(ANGLE_DEFAULT_D3D11)
-// Enables use of the Direct3D 11 API for a default display, when available
-#define ANGLE_DEFAULT_D3D11 0
-#endif
-
-namespace rx
-{
-
-Renderer::Renderer()
- : mCapsInitialized(false),
- mWorkaroundsInitialized(false)
-{
-}
-
-Renderer::~Renderer()
-{
-}
-
-const gl::Caps &Renderer::getRendererCaps() const
-{
- if (!mCapsInitialized)
- {
- generateCaps(&mCaps, &mTextureCaps, &mExtensions);
- mCapsInitialized = true;
- }
-
- return mCaps;
-}
-
-const gl::TextureCapsMap &Renderer::getRendererTextureCaps() const
-{
- if (!mCapsInitialized)
- {
- generateCaps(&mCaps, &mTextureCaps, &mExtensions);
- mCapsInitialized = true;
- }
-
- return mTextureCaps;
-}
-
-const gl::Extensions &Renderer::getRendererExtensions() const
-{
- if (!mCapsInitialized)
- {
- generateCaps(&mCaps, &mTextureCaps, &mExtensions);
- mCapsInitialized = true;
- }
-
- return mExtensions;
-}
-
-const Workarounds &Renderer::getWorkarounds() const
-{
- if (!mWorkaroundsInitialized)
- {
- mWorkarounds = generateWorkarounds();
- mWorkaroundsInitialized = true;
- }
-
- return mWorkarounds;
-}
-
-typedef Renderer *(*CreateRendererFunction)(egl::Display*, EGLNativeDisplayType, const egl::AttributeMap &);
-
-template <typename RendererType>
-Renderer *CreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attributes)
-{
- return new RendererType(display, nativeDisplay, attributes);
-}
-
-}
-
-extern "C"
-{
-
-rx::Renderer *glCreateRenderer(egl::Display *display, EGLNativeDisplayType nativeDisplay, const egl::AttributeMap &attribMap)
-{
- std::vector<rx::CreateRendererFunction> rendererCreationFunctions;
-
- EGLint requestedDisplayType = attribMap.get(EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE);
-
-# if defined(ANGLE_ENABLE_D3D11)
- if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
- nativeDisplay == EGL_D3D11_ONLY_DISPLAY_ANGLE ||
- requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE)
- {
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
- }
-# endif
-
-# if defined(ANGLE_ENABLE_D3D9)
- if (nativeDisplay == EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE ||
- requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE)
- {
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
- }
-# endif
-
- if (nativeDisplay != EGL_D3D11_ELSE_D3D9_DISPLAY_ANGLE &&
- nativeDisplay != EGL_D3D11_ONLY_DISPLAY_ANGLE &&
- requestedDisplayType == EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE)
- {
- // The default display is requested, try the D3D9 and D3D11 renderers, order them using
- // the definition of ANGLE_DEFAULT_D3D11
-# if ANGLE_DEFAULT_D3D11
-# if defined(ANGLE_ENABLE_D3D11)
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
-# endif
-# if defined(ANGLE_ENABLE_D3D9)
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
-# endif
-# else
-# if defined(ANGLE_ENABLE_D3D9)
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer9>);
-# endif
-# if defined(ANGLE_ENABLE_D3D11)
- rendererCreationFunctions.push_back(rx::CreateRenderer<rx::Renderer11>);
-# endif
-# endif
- }
-
- for (size_t i = 0; i < rendererCreationFunctions.size(); i++)
- {
- rx::Renderer *renderer = rendererCreationFunctions[i](display, nativeDisplay, attribMap);
- if (renderer->initialize() == EGL_SUCCESS)
- {
- return renderer;
- }
- else
- {
- // Failed to create the renderer, try the next
- SafeDelete(renderer);
- }
- }
-
- return NULL;
-}
-
-void glDestroyRenderer(rx::Renderer *renderer)
-{
- ASSERT(renderer);
- SafeDelete(renderer);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h b/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
deleted file mode 100644
index b85895a938..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Renderer.h
+++ /dev/null
@@ -1,193 +0,0 @@
-//
-// Copyright (c) 2012-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Renderer.h: Defines a back-end specific class that hides the details of the
-// implementation-specific renderer.
-
-#ifndef LIBGLESV2_RENDERER_RENDERER_H_
-#define LIBGLESV2_RENDERER_RENDERER_H_
-
-#include "libGLESv2/Caps.h"
-#include "libGLESv2/Error.h"
-#include "libGLESv2/Uniform.h"
-#include "libGLESv2/angletypes.h"
-#include "libGLESv2/renderer/Workarounds.h"
-#include "common/NativeWindow.h"
-#include "common/mathutil.h"
-
-#include <cstdint>
-
-#include <EGL/egl.h>
-
-#if !defined(ANGLE_COMPILE_OPTIMIZATION_LEVEL)
-// WARNING: D3DCOMPILE_OPTIMIZATION_LEVEL3 may lead to a DX9 shader compiler hang.
-// It should only be used selectively to work around specific bugs.
-#define ANGLE_COMPILE_OPTIMIZATION_LEVEL D3DCOMPILE_OPTIMIZATION_LEVEL1
-#endif
-
-namespace egl
-{
-class Display;
-}
-
-namespace gl
-{
-class Buffer;
-class Framebuffer;
-struct Data;
-}
-
-namespace rx
-{
-class QueryImpl;
-class FenceNVImpl;
-class FenceSyncImpl;
-class BufferImpl;
-class VertexArrayImpl;
-class ShaderImpl;
-class ProgramImpl;
-class TextureImpl;
-class TransformFeedbackImpl;
-class RenderbufferImpl;
-struct TranslatedIndexData;
-struct Workarounds;
-class SwapChain;
-
-struct ConfigDesc
-{
- GLenum renderTargetFormat;
- GLenum depthStencilFormat;
- GLint multiSample;
- bool fastConfig;
- bool es3Capable;
-};
-
-class Renderer
-{
- public:
- Renderer();
- virtual ~Renderer();
-
- virtual EGLint initialize() = 0;
- virtual bool resetDevice() = 0;
-
- virtual int generateConfigs(ConfigDesc **configDescList) = 0;
- virtual void deleteConfigs(ConfigDesc *configDescList) = 0;
-
- virtual gl::Error sync(bool block) = 0;
-
- virtual gl::Error drawArrays(const gl::Data &data, GLenum mode,
- GLint first, GLsizei count, GLsizei instances) = 0;
- virtual gl::Error drawElements(const gl::Data &data, GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei instances,
- const RangeUI &indexRange) = 0;
-
- virtual gl::Error clear(const gl::Data &data, GLbitfield mask) = 0;
- virtual gl::Error clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values) = 0;
- virtual gl::Error clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values) = 0;
- virtual gl::Error clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values) = 0;
- virtual gl::Error clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer, GLfloat depth, GLint stencil) = 0;
-
- virtual gl::Error readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, void* pixels) = 0;
-
- virtual gl::Error blitFramebuffer(const gl::Data &data,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter) = 0;
-
- // TODO(jmadill): caps? and virtual for egl::Display
- virtual bool getShareHandleSupport() const = 0;
- virtual bool getPostSubBufferSupport() const = 0;
-
- // Shader creation
- virtual ShaderImpl *createShader(const gl::Data &data, GLenum type) = 0;
- virtual ProgramImpl *createProgram() = 0;
-
- // Shader operations
- virtual void releaseShaderCompiler() = 0;
-
- // Texture creation
- virtual TextureImpl *createTexture(GLenum target) = 0;
-
- // Renderbuffer creation
- virtual RenderbufferImpl *createRenderbuffer() = 0;
- virtual RenderbufferImpl *createRenderbuffer(SwapChain *swapChain, bool depth) = 0;
-
- // Buffer creation
- virtual BufferImpl *createBuffer() = 0;
-
- // Vertex Array creation
- virtual VertexArrayImpl *createVertexArray() = 0;
-
- // Query and Fence creation
- virtual QueryImpl *createQuery(GLenum type) = 0;
- virtual FenceNVImpl *createFenceNV() = 0;
- virtual FenceSyncImpl *createFenceSync() = 0;
-
- // Transform Feedback creation
- virtual TransformFeedbackImpl *createTransformFeedback() = 0;
-
- // lost device
- //TODO(jmadill): investigate if this stuff is necessary in GL
- virtual void notifyDeviceLost() = 0;
- virtual bool isDeviceLost() = 0;
- virtual bool testDeviceLost(bool notify) = 0;
- virtual bool testDeviceResettable() = 0;
-
- virtual DWORD getAdapterVendor() const = 0;
- virtual std::string getRendererDescription() const = 0;
- virtual GUID getAdapterIdentifier() const = 0;
-
- // Renderer capabilities (virtual because of egl::Display)
- virtual const gl::Caps &getRendererCaps() const;
- const gl::TextureCapsMap &getRendererTextureCaps() const;
- virtual const gl::Extensions &getRendererExtensions() const;
- const Workarounds &getWorkarounds() const;
-
- // TODO(jmadill): needed by egl::Display, probably should be removed
- virtual int getMajorShaderModel() const = 0;
- virtual int getMinSwapInterval() const = 0;
- virtual int getMaxSwapInterval() const = 0;
- virtual bool getLUID(LUID *adapterLuid) const = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Renderer);
-
- virtual void generateCaps(gl::Caps *outCaps, gl::TextureCapsMap* outTextureCaps, gl::Extensions *outExtensions) const = 0;
- virtual Workarounds generateWorkarounds() const = 0;
-
- mutable bool mCapsInitialized;
- mutable gl::Caps mCaps;
- mutable gl::TextureCapsMap mTextureCaps;
- mutable gl::Extensions mExtensions;
-
- mutable bool mWorkaroundsInitialized;
- mutable Workarounds mWorkarounds;
-};
-
-struct dx_VertexConstants
-{
- float depthRange[4];
- float viewAdjust[4];
-};
-
-struct dx_PixelConstants
-{
- float depthRange[4];
- float viewCoords[4];
- float depthFront[4];
-};
-
-enum ShaderType
-{
- SHADER_VERTEX,
- SHADER_PIXEL,
- SHADER_GEOMETRY
-};
-
-}
-#endif // LIBGLESV2_RENDERER_RENDERER_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h b/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
deleted file mode 100644
index f1a96d74fb..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/ShaderExecutable.h
+++ /dev/null
@@ -1,78 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// ShaderExecutable.h: Defines a renderer-agnostic class to contain shader
-// executable implementation details.
-
-#ifndef LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
-#define LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
-
-#include "common/angleutils.h"
-#include "common/debug.h"
-
-#include <vector>
-#include <cstdint>
-
-namespace rx
-{
-
-class ShaderExecutable
-{
- public:
- ShaderExecutable(const void *function, size_t length)
- : mFunctionBuffer(length)
- {
- memcpy(mFunctionBuffer.data(), function, length);
- }
-
- virtual ~ShaderExecutable() {}
-
- const uint8_t *getFunction() const
- {
- return mFunctionBuffer.data();
- }
-
- size_t getLength() const
- {
- return mFunctionBuffer.size();
- }
-
- const std::string &getDebugInfo() const
- {
- return mDebugInfo;
- }
-
- void appendDebugInfo(const std::string &info)
- {
- mDebugInfo += info;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ShaderExecutable);
-
- std::vector<uint8_t> mFunctionBuffer;
- std::string mDebugInfo;
-};
-
-class UniformStorage
-{
- public:
- UniformStorage(size_t initialSize)
- : mSize(initialSize)
- {
- }
-
- virtual ~UniformStorage() {}
-
- size_t size() const { return mSize; }
-
- private:
- size_t mSize;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_SHADEREXECUTABLE_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h b/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
deleted file mode 100644
index 3e662557e4..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/TextureImpl.h
+++ /dev/null
@@ -1,64 +0,0 @@
-//
-// Copyright 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// TextureImpl.h: Defines the abstract rx::TextureImpl classes.
-
-#ifndef LIBGLESV2_RENDERER_TEXTUREIMPL_H_
-#define LIBGLESV2_RENDERER_TEXTUREIMPL_H_
-
-#include "common/angleutils.h"
-#include "libGLESv2/Error.h"
-
-#include "angle_gl.h"
-
-#include "libGLESv2/ImageIndex.h"
-
-namespace egl
-{
-class Surface;
-}
-
-namespace gl
-{
-class Framebuffer;
-struct PixelUnpackState;
-struct SamplerState;
-}
-
-namespace rx
-{
-
-class Image;
-
-class TextureImpl
-{
- public:
- virtual ~TextureImpl() {};
-
- // Deprecated in favour of the ImageIndex method
- virtual Image *getImage(int level, int layer) const = 0;
- virtual Image *getImage(const gl::ImageIndex &index) const = 0;
- virtual GLsizei getLayerCount(int level) const = 0;
-
- virtual void setUsage(GLenum usage) = 0;
-
- virtual gl::Error setImage(GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth, GLenum internalFormat, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
- virtual gl::Error setCompressedImage(GLenum target, GLint level, GLenum format, GLsizei width, GLsizei height, GLsizei depth, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
- virtual gl::Error subImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLenum type, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
- virtual gl::Error subImageCompressed(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLsizei width, GLsizei height, GLsizei depth, GLenum format, GLsizei imageSize, const gl::PixelUnpackState &unpack, const void *pixels) = 0;
- virtual gl::Error copyImage(GLenum target, GLint level, GLenum format, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
- virtual gl::Error copySubImage(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint zoffset, GLint x, GLint y, GLsizei width, GLsizei height, gl::Framebuffer *source) = 0;
- virtual gl::Error storage(GLenum target, GLsizei levels, GLenum internalformat, GLsizei width, GLsizei height, GLsizei depth) = 0;
-
- virtual gl::Error generateMipmaps() = 0;
-
- virtual void bindTexImage(egl::Surface *surface) = 0;
- virtual void releaseTexImage() = 0;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_TEXTUREIMPL_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h b/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h
deleted file mode 100644
index 20a166fb7a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/Workarounds.h
+++ /dev/null
@@ -1,39 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// angletypes.h: Workarounds for driver bugs and other issues.
-
-#ifndef LIBGLESV2_RENDERER_WORKAROUNDS_H_
-#define LIBGLESV2_RENDERER_WORKAROUNDS_H_
-
-// TODO(jmadill,zmo,geofflang): make a workarounds library that can operate
-// independent of ANGLE's renderer. Workarounds should also be accessible
-// outside of the Renderer.
-
-namespace rx
-{
-
-enum D3DWorkaroundType
-{
- ANGLE_D3D_WORKAROUND_NONE,
- ANGLE_D3D_WORKAROUND_SKIP_OPTIMIZATION,
- ANGLE_D3D_WORKAROUND_MAX_OPTIMIZATION
-};
-
-struct Workarounds
-{
- Workarounds()
- : mrtPerfWorkaround(false),
- setDataFasterThanImageUpload(false)
- {}
-
- bool mrtPerfWorkaround;
- bool setDataFasterThanImageUpload;
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_WORKAROUNDS_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h b/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h
deleted file mode 100644
index e0e8af166b..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/copyvertex.h
+++ /dev/null
@@ -1,35 +0,0 @@
-//
-// Copyright (c) 2013-2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// copyvertex.h: Defines vertex buffer copying and conversion functions
-
-#ifndef LIBGLESV2_RENDERER_COPYVERTEX_H_
-#define LIBGLESV2_RENDERER_COPYVERTEX_H_
-
-#include "common/mathutil.h"
-
-namespace rx
-{
-
-// 'widenDefaultValueBits' gives the default value for the alpha channel (4th component)
-// the sentinel value 0 means we do not want to widen the input or add an alpha channel
-template <typename T, size_t componentCount, uint32_t widenDefaultValueBits>
-inline void CopyNativeVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
-
-template <size_t componentCount>
-inline void Copy32FixedTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
-
-template <typename T, size_t componentCount, bool normalized>
-inline void CopyTo32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
-
-template <bool isSigned, bool normalized, bool toFloat>
-inline void CopyXYZ10W2ToXYZW32FVertexData(const uint8_t *input, size_t stride, size_t count, uint8_t *output);
-
-}
-
-#include "copyvertex.inl"
-
-#endif // LIBGLESV2_RENDERER_COPYVERTEX_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
deleted file mode 100644
index 12b919ab5a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Implements the rx::Image class, an abstract base class for the
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#include "libGLESv2/renderer/d3d/ImageD3D.h"
-
-namespace rx
-{
-
-ImageD3D::ImageD3D()
-{
-}
-
-ImageD3D *ImageD3D::makeImageD3D(Image *img)
-{
- ASSERT(HAS_DYNAMIC_TYPE(ImageD3D*, img));
- return static_cast<ImageD3D*>(img);
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
deleted file mode 100644
index 554ca0cee0..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/ImageD3D.h
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (c) 2002-2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// Image.h: Defines the rx::Image class, an abstract base class for the
-// renderer-specific classes which will define the interface to the underlying
-// surfaces or resources.
-
-#ifndef LIBGLESV2_RENDERER_IMAGED3D_H_
-#define LIBGLESV2_RENDERER_IMAGED3D_H_
-
-#include "common/debug.h"
-#include "libGLESv2/renderer/Image.h"
-
-namespace gl
-{
-class Framebuffer;
-struct ImageIndex;
-struct Box;
-}
-
-namespace rx
-{
-class TextureStorage;
-
-class ImageD3D : public Image
-{
- public:
- ImageD3D();
- virtual ~ImageD3D() {};
-
- static ImageD3D *makeImageD3D(Image *img);
-
- virtual bool isDirty() const = 0;
-
- virtual gl::Error setManagedSurface2D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurfaceCube(TextureStorage *storage, int face, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurface3D(TextureStorage *storage, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error setManagedSurface2DArray(TextureStorage *storage, int layer, int level) { return gl::Error(GL_NO_ERROR); };
- virtual gl::Error copyToStorage(TextureStorage *storage, const gl::ImageIndex &index, const gl::Box &region) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ImageD3D);
-};
-
-}
-
-#endif // LIBGLESV2_RENDERER_IMAGED3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h
deleted file mode 100644
index 9440a449f2..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RenderbufferD3D.h
+++ /dev/null
@@ -1,51 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RenderbufferD3d.h: Defines the RenderbufferD3D class which implements RenderbufferImpl.
-
-#ifndef LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
-#define LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
-
-#include "angle_gl.h"
-
-#include "common/angleutils.h"
-#include "libGLESv2/renderer/RenderbufferImpl.h"
-
-namespace rx
-{
-class RendererD3D;
-class RenderTarget;
-class SwapChain;
-
-class RenderbufferD3D : public RenderbufferImpl
-{
- public:
- RenderbufferD3D(RendererD3D *renderer);
- virtual ~RenderbufferD3D();
-
- static RenderbufferD3D *makeRenderbufferD3D(RenderbufferImpl *renderbuffer);
-
- virtual gl::Error setStorage(GLsizei width, GLsizei height, GLenum internalformat, GLsizei samples) override;
- gl::Error setStorage(SwapChain *swapChain, bool depth);
-
- virtual GLsizei getWidth() const;
- virtual GLsizei getHeight() const;
- virtual GLenum getInternalFormat() const;
- virtual GLenum getActualFormat() const;
- virtual GLsizei getSamples() const;
-
- RenderTarget *getRenderTarget();
- unsigned int getRenderTargetSerial() const;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RenderbufferD3D);
-
- RendererD3D *mRenderer;
- RenderTarget *mRenderTarget;
-};
-}
-
-#endif // LIBGLESV2_RENDERER_RENDERBUFFERD3D_H_
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
deleted file mode 100644
index 5cddd8ab5e..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
+++ /dev/null
@@ -1,801 +0,0 @@
-//
-// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// RendererD3D.cpp: Implementation of the base D3D Renderer.
-
-#include "libGLESv2/renderer/d3d/RendererD3D.h"
-
-#include "libGLESv2/renderer/d3d/IndexDataManager.h"
-#include "libGLESv2/Framebuffer.h"
-#include "libGLESv2/FramebufferAttachment.h"
-#include "libGLESv2/ResourceManager.h"
-#include "libGLESv2/State.h"
-#include "libGLESv2/VertexArray.h"
-#include "libGLESv2/formatutils.h"
-#include "common/utilities.h"
-
-namespace rx
-{
-
-RendererD3D::RendererD3D(egl::Display *display)
- : mDisplay(display)
-{
-}
-
-RendererD3D::~RendererD3D()
-{
- cleanup();
-}
-
-void RendererD3D::cleanup()
-{
- for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i)
- {
- i->second.set(NULL);
- }
- mIncompleteTextures.clear();
-}
-
-// static
-RendererD3D *RendererD3D::makeRendererD3D(Renderer *renderer)
-{
- ASSERT(HAS_DYNAMIC_TYPE(RendererD3D*, renderer));
- return static_cast<RendererD3D*>(renderer);
-}
-
-gl::Error RendererD3D::drawElements(const gl::Data &data,
- GLenum mode, GLsizei count, GLenum type,
- const GLvoid *indices, GLsizei instances,
- const RangeUI &indexRange)
-{
- ASSERT(data.state->getCurrentProgramId() != 0);
-
- gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
- programBinary->updateSamplerMapping();
-
- gl::Error error = generateSwizzles(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!applyPrimitiveType(mode, count))
- {
- return gl::Error(GL_NO_ERROR);
- }
-
- error = applyRenderTarget(data, mode, false);
- if (error.isError())
- {
- return error;
- }
-
- error = applyState(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- gl::VertexArray *vao = data.state->getVertexArray();
- TranslatedIndexData indexInfo;
- indexInfo.indexRange = indexRange;
- error = applyIndexBuffer(indices, vao->getElementArrayBuffer(), count, mode, type, &indexInfo);
- if (error.isError())
- {
- return error;
- }
-
- GLsizei vertexCount = indexInfo.indexRange.length() + 1;
- error = applyVertexBuffer(*data.state, indexInfo.indexRange.start, vertexCount, instances);
- if (error.isError())
- {
- return error;
- }
-
- bool transformFeedbackActive = applyTransformFeedbackBuffers(data);
- // Transform feedback is not allowed for DrawElements, this error should have been caught at the API validation
- // layer.
- ASSERT(!transformFeedbackActive);
-
- error = applyShaders(data, transformFeedbackActive);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data);
- if (error.isError())
- {
- return error;
- }
-
- error = applyUniformBuffers(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!skipDraw(data, mode))
- {
- error = drawElements(mode, count, type, indices, vao->getElementArrayBuffer(), indexInfo, instances);
- if (error.isError())
- {
- return error;
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::drawArrays(const gl::Data &data,
- GLenum mode, GLint first,
- GLsizei count, GLsizei instances)
-{
- ASSERT(data.state->getCurrentProgramId() != 0);
-
- gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
- programBinary->updateSamplerMapping();
-
- gl::Error error = generateSwizzles(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!applyPrimitiveType(mode, count))
- {
- return gl::Error(GL_NO_ERROR);
- }
-
- error = applyRenderTarget(data, mode, false);
- if (error.isError())
- {
- return error;
- }
-
- error = applyState(data, mode);
- if (error.isError())
- {
- return error;
- }
-
- error = applyVertexBuffer(*data.state, first, count, instances);
- if (error.isError())
- {
- return error;
- }
-
- bool transformFeedbackActive = applyTransformFeedbackBuffers(data);
-
- error = applyShaders(data, transformFeedbackActive);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data);
- if (error.isError())
- {
- return error;
- }
-
- error = applyUniformBuffers(data);
- if (error.isError())
- {
- return error;
- }
-
- if (!skipDraw(data, mode))
- {
- error = drawArrays(mode, count, instances, transformFeedbackActive);
- if (error.isError())
- {
- return error;
- }
-
- if (transformFeedbackActive)
- {
- markTransformFeedbackUsage(data);
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::generateSwizzles(const gl::Data &data, gl::SamplerType type)
-{
- gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
-
- size_t samplerRange = programBinary->getUsedSamplerRange(type);
-
- for (size_t i = 0; i < samplerRange; i++)
- {
- GLenum textureType = programBinary->getSamplerTextureType(type, i);
- GLint textureUnit = programBinary->getSamplerMapping(type, i, *data.caps);
- if (textureUnit != -1)
- {
- gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
- ASSERT(texture);
- if (texture->getSamplerState().swizzleRequired())
- {
- gl::Error error = generateSwizzle(texture);
- if (error.isError())
- {
- return error;
- }
- }
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::generateSwizzles(const gl::Data &data)
-{
- gl::Error error = generateSwizzles(data, gl::SAMPLER_VERTEX);
- if (error.isError())
- {
- return error;
- }
-
- error = generateSwizzles(data, gl::SAMPLER_PIXEL);
- if (error.isError())
- {
- return error;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-// Applies the render target surface, depth stencil surface, viewport rectangle and
-// scissor rectangle to the renderer
-gl::Error RendererD3D::applyRenderTarget(const gl::Data &data, GLenum drawMode, bool ignoreViewport)
-{
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- ASSERT(framebufferObject && framebufferObject->completeness(data) == GL_FRAMEBUFFER_COMPLETE);
-
- gl::Error error = applyRenderTarget(framebufferObject);
- if (error.isError())
- {
- return error;
- }
-
- float nearZ, farZ;
- data.state->getDepthRange(&nearZ, &farZ);
- setViewport(data.state->getViewport(), nearZ, farZ, drawMode,
- data.state->getRasterizerState().frontFace, ignoreViewport);
-
- setScissorRectangle(data.state->getScissor(), data.state->isScissorTestEnabled());
-
- return gl::Error(GL_NO_ERROR);
-}
-
-// Applies the fixed-function state (culling, depth test, alpha blending, stenciling, etc) to the Direct3D device
-gl::Error RendererD3D::applyState(const gl::Data &data, GLenum drawMode)
-{
- const gl::Framebuffer *framebufferObject = data.state->getDrawFramebuffer();
- int samples = framebufferObject->getSamples(data);
-
- gl::RasterizerState rasterizer = data.state->getRasterizerState();
- rasterizer.pointDrawMode = (drawMode == GL_POINTS);
- rasterizer.multiSample = (samples != 0);
-
- gl::Error error = setRasterizerState(rasterizer);
- if (error.isError())
- {
- return error;
- }
-
- unsigned int mask = 0;
- if (data.state->isSampleCoverageEnabled())
- {
- GLclampf coverageValue;
- bool coverageInvert = false;
- data.state->getSampleCoverageParams(&coverageValue, &coverageInvert);
- if (coverageValue != 0)
- {
- float threshold = 0.5f;
-
- for (int i = 0; i < samples; ++i)
- {
- mask <<= 1;
-
- if ((i + 1) * coverageValue >= threshold)
- {
- threshold += 1.0f;
- mask |= 1;
- }
- }
- }
-
- if (coverageInvert)
- {
- mask = ~mask;
- }
- }
- else
- {
- mask = 0xFFFFFFFF;
- }
- error = setBlendState(framebufferObject, data.state->getBlendState(), data.state->getBlendColor(), mask);
- if (error.isError())
- {
- return error;
- }
-
- error = setDepthStencilState(data.state->getDepthStencilState(), data.state->getStencilRef(),
- data.state->getStencilBackRef(), rasterizer.frontFace == GL_CCW);
- if (error.isError())
- {
- return error;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-bool RendererD3D::applyTransformFeedbackBuffers(const gl::Data &data)
-{
- gl::TransformFeedback *curTransformFeedback = data.state->getCurrentTransformFeedback();
- if (curTransformFeedback && curTransformFeedback->isStarted() && !curTransformFeedback->isPaused())
- {
- applyTransformFeedbackBuffers(*data.state);
- return true;
- }
- else
- {
- return false;
- }
-}
-
-// Applies the shaders and shader constants to the Direct3D device
-gl::Error RendererD3D::applyShaders(const gl::Data &data, bool transformFeedbackActive)
-{
- gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
-
- gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS];
- gl::VertexFormat::GetInputLayout(inputLayout, programBinary, *data.state);
-
- const gl::Framebuffer *fbo = data.state->getDrawFramebuffer();
-
- gl::Error error = applyShaders(programBinary, inputLayout, fbo, data.state->getRasterizerState().rasterizerDiscard, transformFeedbackActive);
- if (error.isError())
- {
- return error;
- }
-
- return programBinary->applyUniforms();
-}
-
-// For each Direct3D sampler of either the pixel or vertex stage,
-// looks up the corresponding OpenGL texture image unit and texture type,
-// and sets the texture and its addressing/filtering state (or NULL when inactive).
-gl::Error RendererD3D::applyTextures(const gl::Data &data, gl::SamplerType shaderType,
- const FramebufferTextureSerialArray &framebufferSerials, size_t framebufferSerialCount)
-{
- gl::ProgramBinary *programBinary = data.state->getCurrentProgramBinary();
-
- size_t samplerRange = programBinary->getUsedSamplerRange(shaderType);
- for (size_t samplerIndex = 0; samplerIndex < samplerRange; samplerIndex++)
- {
- GLenum textureType = programBinary->getSamplerTextureType(shaderType, samplerIndex);
- GLint textureUnit = programBinary->getSamplerMapping(shaderType, samplerIndex, *data.caps);
- if (textureUnit != -1)
- {
- gl::Texture *texture = data.state->getSamplerTexture(textureUnit, textureType);
- ASSERT(texture);
- gl::SamplerState sampler = texture->getSamplerState();
-
- gl::Sampler *samplerObject = data.state->getSampler(textureUnit);
- if (samplerObject)
- {
- samplerObject->getState(&sampler);
- }
-
- // TODO: std::binary_search may become unavailable using older versions of GCC
- if (texture->isSamplerComplete(sampler, *data.textureCaps, *data.extensions, data.clientVersion) &&
- !std::binary_search(framebufferSerials.begin(), framebufferSerials.begin() + framebufferSerialCount, texture->getTextureSerial()))
- {
- gl::Error error = setSamplerState(shaderType, samplerIndex, texture, sampler);
- if (error.isError())
- {
- return error;
- }
-
- error = setTexture(shaderType, samplerIndex, texture);
- if (error.isError())
- {
- return error;
- }
- }
- else
- {
- // Texture is not sampler complete or it is in use by the framebuffer. Bind the incomplete texture.
- gl::Texture *incompleteTexture = getIncompleteTexture(textureType);
- gl::Error error = setTexture(shaderType, samplerIndex, incompleteTexture);
- if (error.isError())
- {
- return error;
- }
- }
- }
- else
- {
- // No texture bound to this slot even though it is used by the shader, bind a NULL texture
- gl::Error error = setTexture(shaderType, samplerIndex, NULL);
- if (error.isError())
- {
- return error;
- }
- }
- }
-
- // Set all the remaining textures to NULL
- size_t samplerCount = (shaderType == gl::SAMPLER_PIXEL) ? data.caps->maxTextureImageUnits
- : data.caps->maxVertexTextureImageUnits;
- for (size_t samplerIndex = samplerRange; samplerIndex < samplerCount; samplerIndex++)
- {
- gl::Error error = setTexture(shaderType, samplerIndex, NULL);
- if (error.isError())
- {
- return error;
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::applyTextures(const gl::Data &data)
-{
- FramebufferTextureSerialArray framebufferSerials;
- size_t framebufferSerialCount = getBoundFramebufferTextureSerials(data, &framebufferSerials);
-
- gl::Error error = applyTextures(data, gl::SAMPLER_VERTEX, framebufferSerials, framebufferSerialCount);
- if (error.isError())
- {
- return error;
- }
-
- error = applyTextures(data, gl::SAMPLER_PIXEL, framebufferSerials, framebufferSerialCount);
- if (error.isError())
- {
- return error;
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::applyUniformBuffers(const gl::Data &data)
-{
- gl::Program *programObject = data.resourceManager->getProgram(data.state->getCurrentProgramId());
- gl::ProgramBinary *programBinary = programObject->getProgramBinary();
-
- std::vector<gl::Buffer*> boundBuffers;
-
- for (unsigned int uniformBlockIndex = 0; uniformBlockIndex < programBinary->getActiveUniformBlockCount(); uniformBlockIndex++)
- {
- GLuint blockBinding = programObject->getUniformBlockBinding(uniformBlockIndex);
-
- if (data.state->getIndexedUniformBuffer(blockBinding)->id() == 0)
- {
- // undefined behaviour
- return gl::Error(GL_INVALID_OPERATION, "It is undefined behaviour to have a used but unbound uniform buffer.");
- }
- else
- {
- gl::Buffer *uniformBuffer = data.state->getIndexedUniformBuffer(blockBinding);
- ASSERT(uniformBuffer);
- boundBuffers.push_back(uniformBuffer);
- }
- }
-
- return programBinary->applyUniformBuffers(boundBuffers, *data.caps);
-}
-
-bool RendererD3D::skipDraw(const gl::Data &data, GLenum drawMode)
-{
- if (drawMode == GL_POINTS)
- {
- // ProgramBinary assumes non-point rendering if gl_PointSize isn't written,
- // which affects varying interpolation. Since the value of gl_PointSize is
- // undefined when not written, just skip drawing to avoid unexpected results.
- if (!data.state->getCurrentProgramBinary()->usesPointSize())
- {
- // This is stictly speaking not an error, but developers should be
- // notified of risking undefined behavior.
- ERR("Point rendering without writing to gl_PointSize.");
-
- return true;
- }
- }
- else if (gl::IsTriangleMode(drawMode))
- {
- if (data.state->getRasterizerState().cullFace && data.state->getRasterizerState().cullMode == GL_FRONT_AND_BACK)
- {
- return true;
- }
- }
-
- return false;
-}
-
-void RendererD3D::markTransformFeedbackUsage(const gl::Data &data)
-{
- for (size_t i = 0; i < data.caps->maxTransformFeedbackSeparateAttributes; i++)
- {
- gl::Buffer *buffer = data.state->getIndexedTransformFeedbackBuffer(i);
- if (buffer)
- {
- buffer->markTransformFeedbackUsage();
- }
- }
-}
-
-size_t RendererD3D::getBoundFramebufferTextureSerials(const gl::Data &data,
- FramebufferTextureSerialArray *outSerialArray)
-{
- size_t serialCount = 0;
-
- const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
- for (unsigned int i = 0; i < gl::IMPLEMENTATION_MAX_DRAW_BUFFERS; i++)
- {
- gl::FramebufferAttachment *attachment = drawFramebuffer->getColorbuffer(i);
- if (attachment && attachment->isTexture())
- {
- gl::Texture *texture = attachment->getTexture();
- (*outSerialArray)[serialCount++] = texture->getTextureSerial();
- }
- }
-
- gl::FramebufferAttachment *depthStencilAttachment = drawFramebuffer->getDepthOrStencilbuffer();
- if (depthStencilAttachment && depthStencilAttachment->isTexture())
- {
- gl::Texture *depthStencilTexture = depthStencilAttachment->getTexture();
- (*outSerialArray)[serialCount++] = depthStencilTexture->getTextureSerial();
- }
-
- std::sort(outSerialArray->begin(), outSerialArray->begin() + serialCount);
-
- return serialCount;
-}
-
-gl::Texture *RendererD3D::getIncompleteTexture(GLenum type)
-{
- if (mIncompleteTextures.find(type) == mIncompleteTextures.end())
- {
- const GLubyte color[] = { 0, 0, 0, 255 };
- const gl::PixelUnpackState incompleteUnpackState(1);
-
- gl::Texture* t = NULL;
- switch (type)
- {
- default:
- UNREACHABLE();
- // default falls through to TEXTURE_2D
-
- case GL_TEXTURE_2D:
- {
- gl::Texture2D *incomplete2d = new gl::Texture2D(createTexture(GL_TEXTURE_2D), gl::Texture::INCOMPLETE_TEXTURE_ID);
- incomplete2d->setImage(0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- t = incomplete2d;
- }
- break;
-
- case GL_TEXTURE_CUBE_MAP:
- {
- gl::TextureCubeMap *incompleteCube = new gl::TextureCubeMap(createTexture(GL_TEXTURE_CUBE_MAP), gl::Texture::INCOMPLETE_TEXTURE_ID);
-
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_X, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_POSITIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
- incompleteCube->setImage(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z, 0, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
- t = incompleteCube;
- }
- break;
-
- case GL_TEXTURE_3D:
- {
- gl::Texture3D *incomplete3d = new gl::Texture3D(createTexture(GL_TEXTURE_3D), gl::Texture::INCOMPLETE_TEXTURE_ID);
- incomplete3d->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
- t = incomplete3d;
- }
- break;
-
- case GL_TEXTURE_2D_ARRAY:
- {
- gl::Texture2DArray *incomplete2darray = new gl::Texture2DArray(createTexture(GL_TEXTURE_2D_ARRAY), gl::Texture::INCOMPLETE_TEXTURE_ID);
- incomplete2darray->setImage(0, 1, 1, 1, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, incompleteUnpackState, color);
-
- t = incomplete2darray;
- }
- break;
- }
-
- mIncompleteTextures[type].set(t);
- }
-
- return mIncompleteTextures[type].get();
-}
-
-gl::Error RendererD3D::clear(const gl::Data &data, GLbitfield mask)
-{
- gl::ClearParameters clearParams = data.state->getClearParameters(mask);
-
- // Clips the clear to the scissor rectangle but not the viewport
- gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
- if (error.isError())
- {
- return error;
- }
-
- return clear(clearParams, data.state->getDrawFramebuffer());
-}
-
-gl::Error RendererD3D::clearBufferfv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLfloat *values)
-{
- // glClearBufferfv can be called to clear the color buffer or depth buffer
- gl::ClearParameters clearParams = data.state->getClearParameters(0);
-
- if (buffer == GL_COLOR)
- {
- for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
- {
- clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
- }
- clearParams.colorFClearValue = gl::ColorF(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_FLOAT;
- }
-
- if (buffer == GL_DEPTH)
- {
- clearParams.clearDepth = true;
- clearParams.depthClearValue = values[0];
- }
-
- // Clips the clear to the scissor rectangle but not the viewport
- gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
- if (error.isError())
- {
- return error;
- }
-
- return clear(clearParams, data.state->getDrawFramebuffer());
-}
-
-gl::Error RendererD3D::clearBufferuiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLuint *values)
-{
- // glClearBufferuiv can only be called to clear a color buffer
- gl::ClearParameters clearParams = data.state->getClearParameters(0);
- for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
- {
- clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
- }
- clearParams.colorUIClearValue = gl::ColorUI(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_UNSIGNED_INT;
-
- // Clips the clear to the scissor rectangle but not the viewport
- gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
- if (error.isError())
- {
- return error;
- }
-
- return clear(clearParams, data.state->getDrawFramebuffer());
-}
-
-gl::Error RendererD3D::clearBufferiv(const gl::Data &data, GLenum buffer, GLint drawbuffer, const GLint *values)
-{
- // glClearBufferiv can be called to clear the color buffer or stencil buffer
- gl::ClearParameters clearParams = data.state->getClearParameters(0);
-
- if (buffer == GL_COLOR)
- {
- for (unsigned int i = 0; i < ArraySize(clearParams.clearColor); i++)
- {
- clearParams.clearColor[i] = (drawbuffer == static_cast<int>(i));
- }
- clearParams.colorIClearValue = gl::ColorI(values[0], values[1], values[2], values[3]);
- clearParams.colorClearType = GL_INT;
- }
-
- if (buffer == GL_STENCIL)
- {
- clearParams.clearStencil = true;
- clearParams.stencilClearValue = values[1];
- }
-
- // Clips the clear to the scissor rectangle but not the viewport
- gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
- if (error.isError())
- {
- return error;
- }
-
- return clear(clearParams, data.state->getDrawFramebuffer());
-}
-
-gl::Error RendererD3D::clearBufferfi(const gl::Data &data, GLenum buffer, GLint drawbuffer,
- GLfloat depth, GLint stencil)
-{
- if (data.state->isRasterizerDiscardEnabled())
- {
- return gl::Error(GL_NO_ERROR);
- }
-
- // glClearBufferfi can only be called to clear a depth stencil buffer
- gl::ClearParameters clearParams = data.state->getClearParameters(0);
- clearParams.clearDepth = true;
- clearParams.depthClearValue = depth;
- clearParams.clearStencil = true;
- clearParams.stencilClearValue = stencil;
-
- // Clips the clear to the scissor rectangle but not the viewport
- gl::Error error = applyRenderTarget(data, GL_TRIANGLES, true);
- if (error.isError())
- {
- return error;
- }
-
- return clear(clearParams, data.state->getDrawFramebuffer());
-}
-
-gl::Error RendererD3D::blitFramebuffer(const gl::Data &data,
- GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
- GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
- GLbitfield mask, GLenum filter)
-{
- const gl::Framebuffer *readFramebuffer = data.state->getReadFramebuffer();
- const gl::Framebuffer *drawFramebuffer = data.state->getDrawFramebuffer();
-
- bool blitRenderTarget = false;
- bool blitDepth = false;
- bool blitStencil = false;
- if ((mask & GL_COLOR_BUFFER_BIT) && readFramebuffer->getReadColorbuffer() && drawFramebuffer->getFirstColorbuffer())
- {
- blitRenderTarget = true;
- }
- if ((mask & GL_STENCIL_BUFFER_BIT) && readFramebuffer->getStencilbuffer() && drawFramebuffer->getStencilbuffer())
- {
- blitStencil = true;
- }
- if ((mask & GL_DEPTH_BUFFER_BIT) && readFramebuffer->getDepthbuffer() && drawFramebuffer->getDepthbuffer())
- {
- blitDepth = true;
- }
-
- gl::Rectangle srcRect(srcX0, srcY0, srcX1 - srcX0, srcY1 - srcY0);
- gl::Rectangle dstRect(dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0);
- if (blitRenderTarget || blitDepth || blitStencil)
- {
- const gl::Rectangle *scissor = data.state->isScissorTestEnabled() ? &data.state->getScissor() : NULL;
- gl::Error error = blitRect(readFramebuffer, srcRect, drawFramebuffer, dstRect, scissor,
- blitRenderTarget, blitDepth, blitStencil, filter);
- if (error.isError())
- {
- return error;
- }
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-gl::Error RendererD3D::readPixels(const gl::Data &data, GLint x, GLint y, GLsizei width, GLsizei height,
- GLenum format, GLenum type, GLsizei *bufSize, void* pixels)
-{
- const gl::Framebuffer *framebuffer = data.state->getReadFramebuffer();
-
- GLenum sizedInternalFormat = gl::GetSizedInternalFormat(format, type);
- const gl::InternalFormat &sizedFormatInfo = gl::GetInternalFormatInfo(sizedInternalFormat);
- GLuint outputPitch = sizedFormatInfo.computeRowPitch(type, width, data.state->getPackAlignment());
-
- return readPixels(framebuffer, x, y, width, height, format, type, outputPitch, data.state->getPackState(),
- reinterpret_cast<uint8_t*>(pixels));
-}
-
-}
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
deleted file mode 100644
index ff90a6a69a..0000000000
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
+++ /dev/null
@@ -1,255 +0,0 @@
-//
-// Copyright (c) 2012 The ANGLE Project Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-//
-
-// InputLayoutCache.cpp: Defines InputLayoutCache, a class that builds and caches
-// D3D11 input layouts.
-
-#include "libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h"
-#include "libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h"
-#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
-#include "libGLESv2/renderer/d3d/ProgramD3D.h"
-#include "libGLESv2/renderer/d3d/VertexDataManager.h"
-#include "libGLESv2/ProgramBinary.h"
-#include "libGLESv2/VertexAttribute.h"
-
-#include "third_party/murmurhash/MurmurHash3.h"
-
-namespace rx
-{
-
-static void GetInputLayout(const TranslatedAttribute translatedAttributes[gl::MAX_VERTEX_ATTRIBS],
- gl::VertexFormat inputLayout[gl::MAX_VERTEX_ATTRIBS])
-{
- for (unsigned int attributeIndex = 0; attributeIndex < gl::MAX_VERTEX_ATTRIBS; attributeIndex++)
- {
- const TranslatedAttribute &translatedAttribute = translatedAttributes[attributeIndex];
-
- if (translatedAttributes[attributeIndex].active)
- {
- inputLayout[attributeIndex] = gl::VertexFormat(*translatedAttribute.attribute,
- translatedAttribute.currentValueType);
- }
- }
-}
-
-const unsigned int InputLayoutCache::kMaxInputLayouts = 1024;
-
-InputLayoutCache::InputLayoutCache() : mInputLayoutMap(kMaxInputLayouts, hashInputLayout, compareInputLayouts)
-{
- mCounter = 0;
- mDevice = NULL;
- mDeviceContext = NULL;
- mCurrentIL = NULL;
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- mCurrentBuffers[i] = NULL;
- mCurrentVertexStrides[i] = -1;
- mCurrentVertexOffsets[i] = -1;
- }
-}
-
-InputLayoutCache::~InputLayoutCache()
-{
- clear();
-}
-
-void InputLayoutCache::initialize(ID3D11Device *device, ID3D11DeviceContext *context)
-{
- clear();
- mDevice = device;
- mDeviceContext = context;
-}
-
-void InputLayoutCache::clear()
-{
- for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
- {
- SafeRelease(i->second.inputLayout);
- }
- mInputLayoutMap.clear();
- markDirty();
-}
-
-void InputLayoutCache::markDirty()
-{
- mCurrentIL = NULL;
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- mCurrentBuffers[i] = NULL;
- mCurrentVertexStrides[i] = -1;
- mCurrentVertexOffsets[i] = -1;
- }
-}
-
-gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::MAX_VERTEX_ATTRIBS],
- gl::ProgramBinary *programBinary)
-{
- int sortedSemanticIndices[gl::MAX_VERTEX_ATTRIBS];
- programBinary->sortAttributesByLayout(attributes, sortedSemanticIndices);
-
- if (!mDevice || !mDeviceContext)
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Internal input layout cache is not initialized.");
- }
-
- InputLayoutKey ilKey = { 0 };
-
- static const char* semanticName = "TEXCOORD";
-
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- if (attributes[i].active)
- {
- D3D11_INPUT_CLASSIFICATION inputClass = attributes[i].divisor > 0 ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA;
-
- gl::VertexFormat vertexFormat(*attributes[i].attribute, attributes[i].currentValueType);
- const d3d11::VertexFormat &vertexFormatInfo = d3d11::GetVertexFormatInfo(vertexFormat);
-
- // Record the type of the associated vertex shader vector in our key
- // This will prevent mismatched vertex shaders from using the same input layout
- GLint attributeSize;
- programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
-
- ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
- ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i;
- ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat;
- ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
- ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
- ilKey.elements[ilKey.elementCount].desc.InputSlotClass = inputClass;
- ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
- ilKey.elementCount++;
- }
- }
-
- ID3D11InputLayout *inputLayout = NULL;
-
- InputLayoutMap::iterator keyIter = mInputLayoutMap.find(ilKey);
- if (keyIter != mInputLayoutMap.end())
- {
- inputLayout = keyIter->second.inputLayout;
- keyIter->second.lastUsedTime = mCounter++;
- }
- else
- {
- gl::VertexFormat shaderInputLayout[gl::MAX_VERTEX_ATTRIBS];
- GetInputLayout(attributes, shaderInputLayout);
- ProgramD3D *programD3D = ProgramD3D::makeProgramD3D(programBinary->getImplementation());
-
- ShaderExecutable *shader = NULL;
- gl::Error error = programD3D->getVertexExecutableForInputLayout(shaderInputLayout, &shader);
- if (error.isError())
- {
- return error;
- }
-
- ShaderExecutable *shader11 = ShaderExecutable11::makeShaderExecutable11(shader);
-
- D3D11_INPUT_ELEMENT_DESC descs[gl::MAX_VERTEX_ATTRIBS];
- for (unsigned int j = 0; j < ilKey.elementCount; ++j)
- {
- descs[j] = ilKey.elements[j].desc;
- }
-
- HRESULT result = mDevice->CreateInputLayout(descs, ilKey.elementCount, shader11->getFunction(), shader11->getLength(), &inputLayout);
- if (FAILED(result))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal input layout, HRESULT: 0x%08x", result);
- }
-
- if (mInputLayoutMap.size() >= kMaxInputLayouts)
- {
- TRACE("Overflowed the limit of %u input layouts, removing the least recently used "
- "to make room.", kMaxInputLayouts);
-
- InputLayoutMap::iterator leastRecentlyUsed = mInputLayoutMap.begin();
- for (InputLayoutMap::iterator i = mInputLayoutMap.begin(); i != mInputLayoutMap.end(); i++)
- {
- if (i->second.lastUsedTime < leastRecentlyUsed->second.lastUsedTime)
- {
- leastRecentlyUsed = i;
- }
- }
- SafeRelease(leastRecentlyUsed->second.inputLayout);
- mInputLayoutMap.erase(leastRecentlyUsed);
- }
-
- InputLayoutCounterPair inputCounterPair;
- inputCounterPair.inputLayout = inputLayout;
- inputCounterPair.lastUsedTime = mCounter++;
-
- mInputLayoutMap.insert(std::make_pair(ilKey, inputCounterPair));
- }
-
- if (inputLayout != mCurrentIL)
- {
- mDeviceContext->IASetInputLayout(inputLayout);
- mCurrentIL = inputLayout;
- }
-
- bool dirtyBuffers = false;
- size_t minDiff = gl::MAX_VERTEX_ATTRIBS;
- size_t maxDiff = 0;
- for (unsigned int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
- {
- ID3D11Buffer *buffer = NULL;
-
- if (attributes[i].active)
- {
- VertexBuffer11 *vertexBuffer = VertexBuffer11::makeVertexBuffer11(attributes[i].vertexBuffer);
- Buffer11 *bufferStorage = attributes[i].storage ? Buffer11::makeBuffer11(attributes[i].storage) : NULL;
-
- buffer = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK)
- : vertexBuffer->getBuffer();
- }
-
- UINT vertexStride = attributes[i].stride;
- UINT vertexOffset = attributes[i].offset;
-
- if (buffer != mCurrentBuffers[i] || vertexStride != mCurrentVertexStrides[i] ||
- vertexOffset != mCurrentVertexOffsets[i])
- {
- dirtyBuffers = true;
- minDiff = std::min(minDiff, static_cast<size_t>(i));
- maxDiff = std::max(maxDiff, static_cast<size_t>(i));
-
- mCurrentBuffers[i] = buffer;
- mCurrentVertexStrides[i] = vertexStride;
- mCurrentVertexOffsets[i] = vertexOffset;
- }
- }
-
- if (dirtyBuffers)
- {
- ASSERT(minDiff <= maxDiff && maxDiff < gl::MAX_VERTEX_ATTRIBS);
- mDeviceContext->IASetVertexBuffers(minDiff, maxDiff - minDiff + 1, mCurrentBuffers + minDiff,
- mCurrentVertexStrides + minDiff, mCurrentVertexOffsets + minDiff);
- }
-
- return gl::Error(GL_NO_ERROR);
-}
-
-std::size_t InputLayoutCache::hashInputLayout(const InputLayoutKey &inputLayout)
-{
- static const unsigned int seed = 0xDEADBEEF;
-
- std::size_t hash = 0;
- MurmurHash3_x86_32(inputLayout.begin(), inputLayout.end() - inputLayout.begin(), seed, &hash);
- return hash;
-}
-
-bool InputLayoutCache::compareInputLayouts(const InputLayoutKey &a, const InputLayoutKey &b)
-{
- if (a.elementCount != b.elementCount)
- {
- return false;
- }
-
- return std::equal(a.begin(), a.end(), b.begin());
-}
-
-}
diff --git a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
index 30bb7e3b94..27917e6eec 100644
--- a/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
+++ b/src/3rdparty/angle/src/third_party/compiler/ArrayBoundsClamper.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
-#define THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+#ifndef THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
+#define THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
@@ -57,4 +57,4 @@ private:
bool mArrayBoundsClampDefinitionNeeded;
};
-#endif // THIRD_PARTY_COMPILER_ARRAY_BOUNDS_CLAMPER_H_
+#endif // THIRD_PARTY_COMPILER_ARRAYBOUNDSCLAMPER_H_
diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp
index dd86292649..a599c26502 100644
--- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp
+++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.cpp
@@ -29,6 +29,8 @@
#else // defined(_MSC_VER)
+// Ignore GCC force inline warnings
+#pragma GCC diagnostic ignored "-Wattributes"
#define FORCE_INLINE __attribute__((always_inline))
inline uint32_t rotl32 ( uint32_t x, int8_t r )
diff --git a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h
index adb52004e2..bb02cd508f 100644
--- a/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h
+++ b/src/3rdparty/angle/src/third_party/murmurhash/MurmurHash3.h
@@ -20,4 +20,4 @@ void MurmurHash3_x64_128 ( const void * key, int len, uint32_t seed, void * out
//-----------------------------------------------------------------------------
-#endif // _MURMURHASH3_H_ \ No newline at end of file
+#endif // _MURMURHASH3_H_
diff --git a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h
index 65005ee9c6..226085fbd3 100644
--- a/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h
+++ b/src/3rdparty/angle/src/third_party/systeminfo/SystemInfo.h
@@ -23,8 +23,8 @@
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef SystemInfo_h
-#define SystemInfo_h
+#ifndef THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
+#define THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
namespace rx {
@@ -32,4 +32,4 @@ bool isWindowsVistaOrGreater();
} // namespace rx
-#endif // SystemInfo_h
+#endif // THIRD_PARTY_SYSTEMINFO_SYSTEMINFO_H_
diff --git a/src/3rdparty/angle/src/third_party/trace_event/trace_event.h b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
new file mode 100644
index 0000000000..af59dcfcc3
--- /dev/null
+++ b/src/3rdparty/angle/src/third_party/trace_event/trace_event.h
@@ -0,0 +1,795 @@
+// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Trace events are for tracking application performance and resource usage.
+// Macros are provided to track:
+// Begin and end of function calls
+// Counters
+//
+// Events are issued against categories. Whereas LOG's
+// categories are statically defined, TRACE categories are created
+// implicitly with a string. For example:
+// TRACE_EVENT_INSTANT0("MY_SUBSYSTEM", "SomeImportantEvent")
+//
+// Events can be INSTANT, or can be pairs of BEGIN and END in the same scope:
+// TRACE_EVENT_BEGIN0("MY_SUBSYSTEM", "SomethingCostly")
+// doSomethingCostly()
+// TRACE_EVENT_END0("MY_SUBSYSTEM", "SomethingCostly")
+// Note: our tools can't always determine the correct BEGIN/END pairs unless
+// these are used in the same scope. Use ASYNC_BEGIN/ASYNC_END macros if you need them
+// to be in separate scopes.
+//
+// A common use case is to trace entire function scopes. This
+// issues a trace BEGIN and END automatically:
+// void doSomethingCostly() {
+// TRACE_EVENT0("MY_SUBSYSTEM", "doSomethingCostly");
+// ...
+// }
+//
+// Additional parameters can be associated with an event:
+// void doSomethingCostly2(int howMuch) {
+// TRACE_EVENT1("MY_SUBSYSTEM", "doSomethingCostly",
+// "howMuch", howMuch);
+// ...
+// }
+//
+// The trace system will automatically add to this information the
+// current process id, thread id, and a timestamp in microseconds.
+//
+// To trace an asynchronous procedure such as an IPC send/receive, use ASYNC_BEGIN and
+// ASYNC_END:
+// [single threaded sender code]
+// static int send_count = 0;
+// ++send_count;
+// TRACE_EVENT_ASYNC_BEGIN0("ipc", "message", send_count);
+// Send(new MyMessage(send_count));
+// [receive code]
+// void OnMyMessage(send_count) {
+// TRACE_EVENT_ASYNC_END0("ipc", "message", send_count);
+// }
+// The third parameter is a unique ID to match ASYNC_BEGIN/ASYNC_END pairs.
+// ASYNC_BEGIN and ASYNC_END can occur on any thread of any traced process. Pointers can
+// be used for the ID parameter, and they will be mangled internally so that
+// the same pointer on two different processes will not match. For example:
+// class MyTracedClass {
+// public:
+// MyTracedClass() {
+// TRACE_EVENT_ASYNC_BEGIN0("category", "MyTracedClass", this);
+// }
+// ~MyTracedClass() {
+// TRACE_EVENT_ASYNC_END0("category", "MyTracedClass", this);
+// }
+// }
+//
+// Trace event also supports counters, which is a way to track a quantity
+// as it varies over time. Counters are created with the following macro:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter", g_myCounterValue);
+//
+// Counters are process-specific. The macro itself can be issued from any
+// thread, however.
+//
+// Sometimes, you want to track two counters at once. You can do this with two
+// counter macros:
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter0", g_myCounterValue[0]);
+// TRACE_COUNTER1("MY_SUBSYSTEM", "myCounter1", g_myCounterValue[1]);
+// Or you can do it with a combined macro:
+// TRACE_COUNTER2("MY_SUBSYSTEM", "myCounter",
+// "bytesPinned", g_myCounterValue[0],
+// "bytesAllocated", g_myCounterValue[1]);
+// This indicates to the tracing UI that these counters should be displayed
+// in a single graph, as a summed area chart.
+//
+// Since counters are in a global namespace, you may want to disembiguate with a
+// unique ID, by using the TRACE_COUNTER_ID* variations.
+//
+// By default, trace collection is compiled in, but turned off at runtime.
+// Collecting trace data is the responsibility of the embedding
+// application. In Chrome's case, navigating to about:tracing will turn on
+// tracing and display data collected across all active processes.
+//
+//
+// Memory scoping note:
+// Tracing copies the pointers, not the string content, of the strings passed
+// in for category, name, and arg_names. Thus, the following code will
+// cause problems:
+// char* str = strdup("impprtantName");
+// TRACE_EVENT_INSTANT0("SUBSYSTEM", str); // BAD!
+// free(str); // Trace system now has dangling pointer
+//
+// To avoid this issue with the |name| and |arg_name| parameters, use the
+// TRACE_EVENT_COPY_XXX overloads of the macros at additional runtime overhead.
+// Notes: The category must always be in a long-lived char* (i.e. static const).
+// The |arg_values|, when used, are always deep copied with the _COPY
+// macros.
+//
+// When are string argument values copied:
+// const char* arg_values are only referenced by default:
+// TRACE_EVENT1("category", "name",
+// "arg1", "literal string is only referenced");
+// Use TRACE_STR_COPY to force copying of a const char*:
+// TRACE_EVENT1("category", "name",
+// "arg1", TRACE_STR_COPY("string will be copied"));
+// std::string arg_values are always copied:
+// TRACE_EVENT1("category", "name",
+// "arg1", std::string("string will be copied"));
+//
+//
+// Thread Safety:
+// A thread safe singleton and mutex are used for thread safety. Category
+// enabled flags are used to limit the performance impact when the system
+// is not enabled.
+//
+// TRACE_EVENT macros first cache a pointer to a category. The categories are
+// statically allocated and safe at all times, even after exit. Fetching a
+// category is protected by the TraceLog::lock_. Multiple threads initializing
+// the static variable is safe, as they will be serialized by the lock and
+// multiple calls will return the same pointer to the category.
+//
+// Then the category_enabled flag is checked. This is a unsigned char, and
+// not intended to be multithread safe. It optimizes access to addTraceEvent
+// which is threadsafe internally via TraceLog::lock_. The enabled flag may
+// cause some threads to incorrectly call or skip calling addTraceEvent near
+// the time of the system being enabled or disabled. This is acceptable as
+// we tolerate some data loss while the system is being enabled/disabled and
+// because addTraceEvent is threadsafe internally and checks the enabled state
+// again under lock.
+//
+// Without the use of these static category pointers and enabled flags all
+// trace points would carry a significant performance cost of aquiring a lock
+// and resolving the category.
+
+#ifndef COMMON_TRACE_EVENT_H_
+#define COMMON_TRACE_EVENT_H_
+
+#include <string>
+
+#include "common/event_tracer.h"
+
+// By default, const char* argument values are assumed to have long-lived scope
+// and will not be copied. Use this macro to force a const char* to be copied.
+#define TRACE_STR_COPY(str) \
+ WebCore::TraceEvent::TraceStringWithCopy(str)
+
+// Records a pair of begin and end events called "name" for the current
+// scope, with 0, 1 or 2 associated arguments. If the category is not
+// enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name)
+#define TRACE_EVENT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val)
+#define TRACE_EVENT2(category, name, arg1_name, arg1_val, arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_INSTANT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_INSTANT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_INSTANT2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_INSTANT0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_INSTANT1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_INSTANT2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_INSTANT, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_BEGIN0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_BEGIN1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_BEGIN2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_BEGIN0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_BEGIN1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_BEGIN2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_BEGIN, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records a single END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_EVENT_END0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_END1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_END2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_END0(category, name) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_END1(category, name, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_END2(category, name, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_END, \
+ category, name, TRACE_EVENT_FLAG_COPY, arg1_name, arg1_val, \
+ arg2_name, arg2_val)
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER1(category, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER1(category, name, value) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+#define TRACE_COUNTER2(category, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER2(category, name, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Records the value of a counter called "name" immediately. Value
+// must be representable as a 32 bit integer.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID1(category, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ "value", static_cast<int>(value))
+#define TRACE_COPY_COUNTER_ID1(category, name, id, value) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ "value", static_cast<int>(value))
+
+// Records the values of a multi-parted counter called "name" immediately.
+// The UI will treat value1 and value2 as parts of a whole, displaying their
+// values as a stacked-bar chart.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to disambiguate counters with the same name. It must either
+// be a pointer or an integer value up to 64 bits. If it's a pointer, the bits
+// will be xored with a hash of the process ID so that the same pointer on
+// two different processes will not collide.
+#define TRACE_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+#define TRACE_COPY_COUNTER_ID2(category, name, id, value1_name, value1_val, \
+ value2_name, value2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_COUNTER, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ value1_name, static_cast<int>(value1_val), \
+ value2_name, static_cast<int>(value2_val))
+
+// Records a single ASYNC_BEGIN event called "name" immediately, with 0, 1 or 2
+// associated arguments. If the category is not enabled, then this
+// does nothing.
+// - category and name strings must have application lifetime (statics or
+// literals). They may not include " chars.
+// - |id| is used to match the ASYNC_BEGIN event with the ASYNC_END event. ASYNC
+// events are considered to match if their category, name and id values all
+// match. |id| must either be a pointer or an integer value up to 64 bits. If
+// it's a pointer, the bits will be xored with a hash of the process ID so
+// that the same pointer on two different processes will not collide.
+// An asynchronous operation can consist of multiple phases. The first phase is
+// defined by the ASYNC_BEGIN calls. Additional phases can be defined using the
+// ASYNC_STEP_BEGIN macros. When the operation completes, call ASYNC_END.
+// An async operation can span threads and processes, but all events in that
+// operation must use the same |name| and |id|. Each event can have its own
+// args.
+#define TRACE_EVENT_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_BEGIN2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_BEGIN, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Records a single ASYNC_STEP event for |step| immediately. If the category
+// is not enabled, then this does nothing. The |name| and |id| must match the
+// ASYNC_BEGIN event above. The |step| param identifies this step within the
+// async event. This should be called at the beginning of the next phase of an
+// asynchronous operation.
+#define TRACE_EVENT_ASYNC_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step)
+#define TRACE_EVENT_ASYNC_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, "step", step, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_STEP0(category, name, id, step) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step)
+#define TRACE_EVENT_COPY_ASYNC_STEP1(category, name, id, step, \
+ arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_STEP, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, "step", step, \
+ arg1_name, arg1_val)
+
+// Records a single ASYNC_END event for "name" immediately. If the category
+// is not enabled, then this does nothing.
+#define TRACE_EVENT_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE)
+#define TRACE_EVENT_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, arg1_name, arg1_val)
+#define TRACE_EVENT_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_NONE, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+#define TRACE_EVENT_COPY_ASYNC_END0(category, name, id) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY)
+#define TRACE_EVENT_COPY_ASYNC_END1(category, name, id, arg1_name, arg1_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val)
+#define TRACE_EVENT_COPY_ASYNC_END2(category, name, id, arg1_name, arg1_val, \
+ arg2_name, arg2_val) \
+ INTERNAL_TRACE_EVENT_ADD_WITH_ID(TRACE_EVENT_PHASE_ASYNC_END, \
+ category, name, id, TRACE_EVENT_FLAG_COPY, \
+ arg1_name, arg1_val, arg2_name, arg2_val)
+
+// Creates a scope of a sampling state with the given category and name (both must
+// be constant strings). These states are intended for a sampling profiler.
+// Implementation note: we store category and name together because we don't
+// want the inconsistency/expense of storing two pointers.
+// |thread_bucket| is [0..2] and is used to statically isolate samples in one
+// thread from others.
+//
+// { // The sampling state is set within this scope.
+// TRACE_EVENT_SAMPLING_STATE_SCOPE_FOR_BUCKET(0, "category", "name");
+// ...;
+// }
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+ TraceEvent::SamplingStateScope<bucket_number> traceEventSamplingScope(category "\0" name);
+
+// Returns a current sampling state of the given bucket.
+// The format of the returned string is "category\0name".
+#define TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(bucket_number) \
+ TraceEvent::SamplingStateScope<bucket_number>::current()
+
+// Sets a current sampling state of the given bucket.
+// |category| and |name| have to be constant strings.
+#define TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(bucket_number, category, name) \
+ TraceEvent::SamplingStateScope<bucket_number>::set(category "\0" name)
+
+// Sets a current sampling state of the given bucket.
+// |categoryAndName| doesn't need to be a constant string.
+// The format of the string is "category\0name".
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(bucket_number, categoryAndName) \
+ TraceEvent::SamplingStateScope<bucket_number>::set(categoryAndName)
+
+// Syntactic sugars for the sampling tracing in the main thread.
+#define TRACE_EVENT_SCOPED_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SCOPED_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_GET_SAMPLING_STATE() \
+ TRACE_EVENT_GET_SAMPLING_STATE_FOR_BUCKET(0)
+#define TRACE_EVENT_SET_SAMPLING_STATE(category, name) \
+ TRACE_EVENT_SET_SAMPLING_STATE_FOR_BUCKET(0, category, name)
+#define TRACE_EVENT_SET_NONCONST_SAMPLING_STATE(categoryAndName) \
+ TRACE_EVENT_SET_NONCONST_SAMPLING_STATE_FOR_BUCKET(0, categoryAndName)
+
+////////////////////////////////////////////////////////////////////////////////
+// Implementation specific tracing API definitions.
+
+// Get a pointer to the enabled state of the given trace category. Only
+// long-lived literal strings should be given as the category name. The returned
+// pointer can be held permanently in a local static for example. If the
+// unsigned char is non-zero, tracing is enabled. If tracing is enabled,
+// TRACE_EVENT_API_ADD_TRACE_EVENT can be called. It's OK if tracing is disabled
+// between the load of the tracing state and the call to
+// TRACE_EVENT_API_ADD_TRACE_EVENT, because this flag only provides an early out
+// for best performance when tracing is disabled.
+// const unsigned char*
+// TRACE_EVENT_API_GET_CATEGORY_ENABLED(const char* category_name)
+#define TRACE_EVENT_API_GET_CATEGORY_ENABLED \
+ gl::TraceGetTraceCategoryEnabledFlag
+
+// Add a trace event to the platform tracing system.
+// void TRACE_EVENT_API_ADD_TRACE_EVENT(
+// char phase,
+// const unsigned char* category_enabled,
+// const char* name,
+// unsigned long long id,
+// int num_args,
+// const char** arg_names,
+// const unsigned char* arg_types,
+// const unsigned long long* arg_values,
+// unsigned char flags)
+#define TRACE_EVENT_API_ADD_TRACE_EVENT \
+ gl::TraceAddTraceEvent
+
+////////////////////////////////////////////////////////////////////////////////
+
+// Implementation detail: trace event macros create temporary variables
+// to keep instrumentation overhead low. These macros give each temporary
+// variable a unique name based on the line number to prevent name collissions.
+#define INTERNAL_TRACE_EVENT_UID3(a, b) \
+ trace_event_unique_##a##b
+#define INTERNAL_TRACE_EVENT_UID2(a, b) \
+ INTERNAL_TRACE_EVENT_UID3(a, b)
+#define INTERNALTRACEEVENTUID(name_prefix) \
+ INTERNAL_TRACE_EVENT_UID2(name_prefix, __LINE__)
+
+// Implementation detail: internal macro to create static category.
+#define INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category) \
+ static const unsigned char* INTERNALTRACEEVENTUID(catstatic) = 0; \
+ if (!INTERNALTRACEEVENTUID(catstatic)) \
+ INTERNALTRACEEVENTUID(catstatic) = \
+ TRACE_EVENT_API_GET_CATEGORY_ENABLED(category);
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD(phase, category, name, flags, ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ gl::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), name, \
+ gl::TraceEvent::noEventId, flags, ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Implementation detail: internal macro to create static category and add begin
+// event if the category is enabled. Also adds the end event when the scope
+// ends.
+#define INTERNAL_TRACE_EVENT_ADD_SCOPED(category, name, ...) \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ gl::TraceEvent::TraceEndOnScopeClose \
+ INTERNALTRACEEVENTUID(profileScope); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ gl::TraceEvent::addTraceEvent( \
+ TRACE_EVENT_PHASE_BEGIN, \
+ INTERNALTRACEEVENTUID(catstatic), \
+ name, gl::TraceEvent::noEventId, \
+ TRACE_EVENT_FLAG_NONE, ##__VA_ARGS__); \
+ INTERNALTRACEEVENTUID(profileScope).initialize( \
+ INTERNALTRACEEVENTUID(catstatic), name); \
+ }
+
+// Implementation detail: internal macro to create static category and add
+// event if the category is enabled.
+#define INTERNAL_TRACE_EVENT_ADD_WITH_ID(phase, category, name, id, flags, \
+ ...) \
+ do { \
+ INTERNAL_TRACE_EVENT_GET_CATEGORY_INFO(category); \
+ if (*INTERNALTRACEEVENTUID(catstatic)) { \
+ unsigned char traceEventFlags = flags | TRACE_EVENT_FLAG_HAS_ID; \
+ gl::TraceEvent::TraceID traceEventTraceID( \
+ id, &traceEventFlags); \
+ gl::TraceEvent::addTraceEvent( \
+ phase, INTERNALTRACEEVENTUID(catstatic), \
+ name, traceEventTraceID.data(), traceEventFlags, \
+ ##__VA_ARGS__); \
+ } \
+ } while (0)
+
+// Notes regarding the following definitions:
+// New values can be added and propagated to third party libraries, but existing
+// definitions must never be changed, because third party libraries may use old
+// definitions.
+
+// Phase indicates the nature of an event entry. E.g. part of a begin/end pair.
+#define TRACE_EVENT_PHASE_BEGIN ('B')
+#define TRACE_EVENT_PHASE_END ('E')
+#define TRACE_EVENT_PHASE_INSTANT ('I')
+#define TRACE_EVENT_PHASE_ASYNC_BEGIN ('S')
+#define TRACE_EVENT_PHASE_ASYNC_STEP ('T')
+#define TRACE_EVENT_PHASE_ASYNC_END ('F')
+#define TRACE_EVENT_PHASE_METADATA ('M')
+#define TRACE_EVENT_PHASE_COUNTER ('C')
+#define TRACE_EVENT_PHASE_SAMPLE ('P')
+
+// Flags for changing the behavior of TRACE_EVENT_API_ADD_TRACE_EVENT.
+#define TRACE_EVENT_FLAG_NONE (static_cast<unsigned char>(0))
+#define TRACE_EVENT_FLAG_COPY (static_cast<unsigned char>(1 << 0))
+#define TRACE_EVENT_FLAG_HAS_ID (static_cast<unsigned char>(1 << 1))
+#define TRACE_EVENT_FLAG_MANGLE_ID (static_cast<unsigned char>(1 << 2))
+
+// Type values for identifying types in the TraceValue union.
+#define TRACE_VALUE_TYPE_BOOL (static_cast<unsigned char>(1))
+#define TRACE_VALUE_TYPE_UINT (static_cast<unsigned char>(2))
+#define TRACE_VALUE_TYPE_INT (static_cast<unsigned char>(3))
+#define TRACE_VALUE_TYPE_DOUBLE (static_cast<unsigned char>(4))
+#define TRACE_VALUE_TYPE_POINTER (static_cast<unsigned char>(5))
+#define TRACE_VALUE_TYPE_STRING (static_cast<unsigned char>(6))
+#define TRACE_VALUE_TYPE_COPY_STRING (static_cast<unsigned char>(7))
+
+
+namespace gl {
+
+namespace TraceEvent {
+
+// Specify these values when the corresponding argument of addTraceEvent is not
+// used.
+const int zeroNumArgs = 0;
+const unsigned long long noEventId = 0;
+
+// TraceID encapsulates an ID that can either be an integer or pointer. Pointers
+// are mangled with the Process ID so that they are unlikely to collide when the
+// same pointer is used on different processes.
+class TraceID {
+public:
+ explicit TraceID(const void* id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(reinterpret_cast<uintptr_t>(id)))
+ {
+ *flags |= TRACE_EVENT_FLAG_MANGLE_ID;
+ }
+ explicit TraceID(unsigned long long id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned long id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned int id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned short id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(unsigned char id, unsigned char* flags) : m_data(id) { (void)flags; }
+ explicit TraceID(long long id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(long id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(int id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(short id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+ explicit TraceID(signed char id, unsigned char* flags) :
+ m_data(static_cast<unsigned long long>(id)) { (void)flags; }
+
+ unsigned long long data() const { return m_data; }
+
+private:
+ unsigned long long m_data;
+};
+
+// Simple union to store various types as unsigned long long.
+union TraceValueUnion {
+ bool m_bool;
+ unsigned long long m_uint;
+ long long m_int;
+ double m_double;
+ const void* m_pointer;
+ const char* m_string;
+};
+
+// Simple container for const char* that should be copied instead of retained.
+class TraceStringWithCopy {
+public:
+ explicit TraceStringWithCopy(const char* str) : m_str(str) { }
+ operator const char* () const { return m_str; }
+private:
+ const char* m_str;
+};
+
+// Define setTraceValue for each allowed type. It stores the type and
+// value in the return arguments. This allows this API to avoid declaring any
+// structures so that it is portable to third_party libraries.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE(actual_type, \
+ union_member, \
+ value_type_id) \
+ static inline void setTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ TraceValueUnion typeValue; \
+ typeValue.union_member = arg; \
+ *type = value_type_id; \
+ *value = typeValue.m_uint; \
+ }
+// Simpler form for int types that can be safely casted.
+#define INTERNAL_DECLARE_SET_TRACE_VALUE_INT(actual_type, \
+ value_type_id) \
+ static inline void setTraceValue(actual_type arg, \
+ unsigned char* type, \
+ unsigned long long* value) { \
+ *type = value_type_id; \
+ *value = static_cast<unsigned long long>(arg); \
+ }
+
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned long long, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned int, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned short, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(unsigned char, TRACE_VALUE_TYPE_UINT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(long long, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(int, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(short, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE_INT(signed char, TRACE_VALUE_TYPE_INT)
+INTERNAL_DECLARE_SET_TRACE_VALUE(bool, m_bool, TRACE_VALUE_TYPE_BOOL)
+INTERNAL_DECLARE_SET_TRACE_VALUE(double, m_double, TRACE_VALUE_TYPE_DOUBLE)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const void*, m_pointer,
+ TRACE_VALUE_TYPE_POINTER)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const char*, m_string,
+ TRACE_VALUE_TYPE_STRING)
+INTERNAL_DECLARE_SET_TRACE_VALUE(const TraceStringWithCopy&, m_string,
+ TRACE_VALUE_TYPE_COPY_STRING)
+
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE
+#undef INTERNAL_DECLARE_SET_TRACE_VALUE_INT
+
+static inline void setTraceValue(const std::string& arg,
+ unsigned char* type,
+ unsigned long long* value) {
+ TraceValueUnion typeValue;
+ typeValue.m_string = arg.data();
+ *type = TRACE_VALUE_TYPE_COPY_STRING;
+ *value = typeValue.m_uint;
+}
+
+// These addTraceEvent template functions are defined here instead of in the
+// macro, because the arg values could be temporary string objects. In order to
+// store pointers to the internal c_str and pass through to the tracing API, the
+// arg values must live throughout these procedures.
+
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ zeroNumArgs, 0, 0, 0,
+ flags);
+}
+
+template<class ARG1_TYPE>
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1Name,
+ const ARG1_TYPE& arg1Val) {
+ const int numArgs = 1;
+ unsigned char argTypes[1];
+ unsigned long long argValues[1];
+ setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ numArgs, &arg1Name, argTypes, argValues,
+ flags);
+}
+
+template<class ARG1_TYPE, class ARG2_TYPE>
+static inline void addTraceEvent(char phase,
+ const unsigned char* categoryEnabled,
+ const char* name,
+ unsigned long long id,
+ unsigned char flags,
+ const char* arg1Name,
+ const ARG1_TYPE& arg1Val,
+ const char* arg2Name,
+ const ARG2_TYPE& arg2Val) {
+ const int numArgs = 2;
+ const char* argNames[2] = { arg1Name, arg2Name };
+ unsigned char argTypes[2];
+ unsigned long long argValues[2];
+ setTraceValue(arg1Val, &argTypes[0], &argValues[0]);
+ setTraceValue(arg2Val, &argTypes[1], &argValues[1]);
+ return TRACE_EVENT_API_ADD_TRACE_EVENT(
+ phase, categoryEnabled, name, id,
+ numArgs, argNames, argTypes, argValues,
+ flags);
+}
+
+// Used by TRACE_EVENTx macro. Do not use directly.
+class TraceEndOnScopeClose {
+public:
+ // Note: members of m_data intentionally left uninitialized. See initialize.
+ TraceEndOnScopeClose() : m_pdata(0) { }
+ ~TraceEndOnScopeClose()
+ {
+ if (m_pdata)
+ addEventIfEnabled();
+ }
+
+ void initialize(const unsigned char* categoryEnabled,
+ const char* name)
+ {
+ m_data.categoryEnabled = categoryEnabled;
+ m_data.name = name;
+ m_pdata = &m_data;
+ }
+
+private:
+ // Add the end event if the category is still enabled.
+ void addEventIfEnabled()
+ {
+ // Only called when m_pdata is non-null.
+ if (*m_pdata->categoryEnabled) {
+ TRACE_EVENT_API_ADD_TRACE_EVENT(
+ TRACE_EVENT_PHASE_END,
+ m_pdata->categoryEnabled,
+ m_pdata->name, noEventId,
+ zeroNumArgs, 0, 0, 0,
+ TRACE_EVENT_FLAG_NONE);
+ }
+ }
+
+ // This Data struct workaround is to avoid initializing all the members
+ // in Data during construction of this object, since this object is always
+ // constructed, even when tracing is disabled. If the members of Data were
+ // members of this class instead, compiler warnings occur about potential
+ // uninitialized accesses.
+ struct Data {
+ const unsigned char* categoryEnabled;
+ const char* name;
+ };
+ Data* m_pdata;
+ Data m_data;
+};
+
+} // namespace TraceEvent
+
+} // namespace gl
+
+#endif
diff --git a/src/3rdparty/libpng.pri b/src/3rdparty/libpng.pri
index ae71032e8c..f8516bd5db 100644
--- a/src/3rdparty/libpng.pri
+++ b/src/3rdparty/libpng.pri
@@ -1,4 +1,5 @@
DEFINES *= QT_USE_BUNDLED_LIBPNG
+DEFINES += PNG_ARM_NEON_OPT=0
INCLUDEPATH += $$PWD/libpng
SOURCES += $$PWD/libpng/png.c \
$$PWD/libpng/pngerror.c \
diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE
index dbc2ed1730..131e0aa369 100644
--- a/src/3rdparty/libpng/ANNOUNCE
+++ b/src/3rdparty/libpng/ANNOUNCE
@@ -1,5 +1,4 @@
-
-Libpng 1.5.10 - March 29, 2012
+Libpng 1.6.17 - March 26, 2015
This is a public release of libpng, intended for use in production codes.
@@ -8,52 +7,61 @@ Files available for download:
Source files with LF line endings (for Unix/Linux) and with a
"configure" script
- libpng-1.5.10.tar.xz (LZMA-compressed, recommended)
- libpng-1.5.10.tar.gz
- libpng-1.5.10.tar.bz2
+ libpng-1.6.17.tar.xz (LZMA-compressed, recommended)
+ libpng-1.6.17.tar.gz
Source files with CRLF line endings (for Windows), without the
"configure" script
- lpng1510.7z (LZMA-compressed, recommended)
- lpng1510.zip
+ lpng1617.7z (LZMA-compressed, recommended)
+ lpng1617.zip
Other information:
- libpng-1.5.10-README.txt
- libpng-1.5.10-LICENSE.txt
+ libpng-1.6.17-README.txt
+ libpng-1.6.17-LICENSE.txt
+ libpng-1.6.17-*.asc (armored detached GPG signatures)
-Changes since the last public release (1.5.9):
+Changes since the last public release (1.6.16):
- Removed two useless #ifdef directives from pngread.c and one from pngrutil.c
- Always put the CMAKE_LIBRARY in "lib" (removed special WIN32 case).
- Removed empty vstudio/pngstest directory (Clifford Yapp).
- Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from
- pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c;
- now that png_ptr->buffer is inaccessible to applications, the special
- handling is no longer useful.
- Fixed bug with png_handle_hIST with odd chunk length (Frank Busse).
- Added PNG_SAFE_LIMITS feature to pnglibconf.dfa and code in pngconf.h
- to reset the user limits to safe ones if PNG_SAFE_LIMITS is defined.
- To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED" on the configure
- command or put "#define PNG_SAFE_LIMITS_SUPPORTED" in pnglibconf.h.
- Revised the SAFE_LIMITS feature to be the same as the feature in libpng16.
- Added information about the new limits in the manual.
- Updated Makefile.in
- Removed unused "current_text" members of png_struct and the png_free()
- of png_ptr->current_text from pngread.c
- Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
- Fixed CMF optimization of non-IDAT compressed chunks, which was added at
- libpng-1.5.4. It sometimes produced too small of a window.
- Reject all iCCP chunks after the first, even if the first one is invalid.
- Added palette-index checking. Issue a png_benign_error() if an invalid
- index is found.
- Revised example.c to put text strings in a temporary character array
- instead of directly assigning string constants to png_textp members.
- This avoids compiler warnings when -Wwrite-strings is enabled.
- Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
- Revised png_set_text_2() to avoid potential memory corruption (fixes
- CVE-2011-3048).
+ Removed duplicate PNG_SAFE_LIMITS_SUPPORTED handling from pngconf.h
+ Corrected the width limit calculation in png_check_IHDR().
+ Removed user limits from pngfix. Also pass NULL pointers to
+ png_read_row to skip the unnecessary row de-interlace stuff.
+ Added testing of png_set_packing() to pngvalid.c
+ Regenerated configure scripts in the *.tar distributions with libtool-2.4.4
+ Implement previously untested cases of libpng transforms in pngvalid.c
+ Fixed byte order in 2-byte filler, in png_do_read_filler().
+ Made the check for out-of-range values in png_set_tRNS() detect
+ values that are exactly 2^bit_depth, and work on 16-bit platforms.
+ Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47.
+ Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and
+ pngset.c to avoid warnings about dead code.
+ Do not build png_product2() when it is unused.
+ Display user limits in the output from pngtest.
+ Eliminated the PNG_SAFE_LIMITS macro and restored the 1-million-column
+ and 1-million-row default limits in pnglibconf.dfa, that can be reset
+ by the user at build time or run time. This provides a more robust
+ defense against DOS and as-yet undiscovered overflows.
+ Added PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED macro, on by default.
+ Allow user to call png_get_IHDR() with NULL arguments (Reuben Hawkins).
+ Rebuilt configure scripts with automake-1.15 and libtool-2.4.6
+ Moved png_set_filter() prototype into a PNG_WRITE_SUPPORTED block
+ of png.h.
+ Avoid runtime checks when converting integer to png_byte with
+ Visual Studio (Sergey Kosarevsky)
+ Removed some comments that the configure script did not handle
+ properly from scripts/pnglibconf.dfa and pnglibconf.h.prebuilt.
+ Free the unknown_chunks structure even when it contains no data.
+ Updated CMakeLists.txt to add OSX framework, change YES/NO to ON/OFF
+ for consistency, and remove some useless tests (Alexey Petruchik).
+ Remove pnglibconf.h, pnglibconf.c, pnglibconf.pre, pnglibconf.dfn,
+ and pnglibconf.out instead of pnglibconf.* in "make clean" (Cosmin).
+ Fixed simplified 8-bit-linear to sRGB alpha. The calculated alpha
+ value was wrong. It's not clear if this affected the final stored
+ value; in the obvious code path the upper and lower 8-bits of the
+ alpha value were identical and the alpha was truncated to 8-bits
+ rather than dividing by 257 (John Bowler).
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES
index 70af8273e7..1be09e9385 100644
--- a/src/3rdparty/libpng/CHANGES
+++ b/src/3rdparty/libpng/CHANGES
@@ -1,4 +1,4 @@
-#if 0
+
CHANGES - changes for libpng
Version 0.2
@@ -2102,7 +2102,7 @@ Version 1.4.0beta24 [July 25, 2008]
png_decompress_chunk(), and remove "chunkdata" from parameter list.
Put a call to png_check_chunk_name() in png_read_chunk_header().
Revised png_check_chunk_name() to reject a name with a lowercase 3rd byte.
- Removed two calls to png_check_chunk_name() occuring later in the process.
+ Removed two calls to png_check_chunk_name() occurring later in the process.
Define PNG_NO_ERROR_NUMBERS by default in pngconf.h
Version 1.4.0beta25 [July 30, 2008]
@@ -3672,7 +3672,8 @@ Version 1.5.6 [November 3, 2011]
No changes.
Version 1.5.7beta01 [November 4, 2011]
- Added support for ARM processor (Mans Rullgard)
+ Added support for ARM processor, when decoding all PNG up-filtered rows
+ and any other-filtered rows with 3 or 4 bytes per pixel (Mans Rullgard).
Fixed bug in pngvalid on early allocation failure; fixed type cast in
pngmem.c; pngvalid would attempt to call png_error() if the allocation
of a png_struct or png_info failed. This would probably have led to a
@@ -3775,84 +3776,1434 @@ Version 1.5.7rc03 [December 7, 2011]
Version 1.5.7 [December 15, 2011]
Minor fixes to pngvalid.c for gcc 4.6.2 compatibility to remove warnings
reported by earlier versions.
-
-Version 1.5.8beta01 [January 15, 2011]
- Removed '#include config.h"' from contrib/libtests/pngvalid.c. It's not
- needed and causes trouble for VPATH building.
+ Fixed minor memset/sizeof errors in pngvalid.c.
+
+Version 1.6.0beta01 [December 15, 2011]
+ Removed machine-generated configure files from the GIT repository (they will
+ continue to appear in the tarball distributions and in the libpng15 and
+ earlier GIT branches).
+ Restored the new 'simplified' API, which was started in libpng-1.5.7beta02
+ but later deleted from libpng-1.5.7beta05.
+ Added example programs for the new 'simplified' API.
+ Added ANSI-C (C90) headers and require them, and take advantage of the
+ change. Also fixed some of the projects/* and contrib/* files that needed
+ updates for libpng16 and the move of pngvalid.c.
+ With this change the required ANSI-C header files are assumed to exist: the
+ implementation must provide float.h, limits.h, stdarg.h and stddef.h and
+ libpng relies on limits.h and stddef.h existing and behaving as defined
+ (the other two required headers aren't used). Non-ANSI systems that don't
+ have stddef.h or limits.h will have to provide an appropriate fake
+ containing the relevant types and #defines.
+ The use of FAR/far has been eliminated and the definition of png_alloc_size_t
+ is now controlled by a flag so that 'small size_t' systems can select it
+ if necessary. Libpng 1.6 may not currently work on such systems -- it
+ seems likely that it will ask 'malloc' for more than 65535 bytes with any
+ image that has a sufficiently large row size (rather than simply failing
+ to read such images).
+ New tools directory containing tools used to generate libpng code.
+ Fixed race conditions in parallel make builds. With higher degrees of
+ parallelism during 'make' the use of the same temporary file names such
+ as 'dfn*' can result in a race where a temporary file from one arm of the
+ build is deleted or overwritten in another arm. This changes the
+ temporary files for suffix rules to always use $* and ensures that the
+ non-suffix rules use unique file names.
+
+Version 1.6.0beta02 [December 21, 2011]
+ Correct configure builds where build and source directories are separate.
+ The include path of 'config.h' was erroneously made relative in pngvalid.c
+ in libpng 1.5.7.
+
+Version 1.6.0beta03 [December 22, 2011]
+ Start-up code size improvements, error handler flexibility. These changes
+ alter how the tricky allocation of the initial png_struct and png_info
+ structures are handled. png_info is now handled in pretty much the same
+ way as everything else, except that the allocations handle NULL return
+ silently. png_struct is changed in a similar way on allocation and on
+ deallocation a 'safety' error handler is put in place (which should never
+ be required). The error handler itself is changed to permit mismatches
+ in the application and libpng error buffer size; however, this means a
+ silent change to the API to return the jmp_buf if the size doesn't match
+ the size from the libpng compilation; libpng now allocates the memory and
+ this may fail. Overall these changes result in slight code size
+ reductions; however, this is a reduction in code that is always executed
+ so is particularly valuable. Overall on a 64-bit system the libpng DLL
+ decreases in code size by 1733 bytes. pngerror.o increases in size by
+ about 465 bytes because of the new functionality.
+ Added png_convert_to_rfc1123_buffer() and deprecated png_convert_to_rfc1123()
+ to avoid including a spurious buffer in the png_struct.
+
+Version 1.6.0beta04 [December 30, 2011]
+ Regenerated configure scripts with automake-1.11.2
+ Eliminated png_info_destroy(). It is now used only in png.c and only calls
+ one other internal function and memset().
+ Enabled png_get_sCAL_fixed() if floating point APIs are enabled. Previously
+ it was disabled whenever internal fixed point arithmetic was selected,
+ which meant it didn't exist even on systems where FP was available but not
+ preferred.
+ Added pngvalid.c compile time checks for const APIs.
+ Implemented 'restrict' for png_info and png_struct. Because of the way
+ libpng works both png_info and png_struct are always accessed via a
+ single pointer. This means adding C99 'restrict' to the pointer gives
+ the compiler some opportunity to optimize the code. This change allows
+ that.
Moved AC_MSG_CHECKING([if libraries can be versioned]) later to the proper
location in configure.ac (Gilles Espinasse).
+ Changed png_memcpy to C assignment where appropriate. Changed all those
+ uses of png_memcpy that were doing a simple assignment to assignments
+ (all those cases where the thing being copied is a non-array C L-value).
+ Added some error checking to png_set_*() routines.
+ Removed the reference to the non-exported function png_memcpy() from
+ example.c.
+ Fixed the Visual C 64-bit build - it requires jmp_buf to be aligned, but
+ it had become misaligned.
+ Revised contrib/pngminus/pnm2png.c to avoid warnings when png_uint_32
+ and unsigned long are of different sizes.
+
+Version 1.6.0beta05 [January 15, 2012]
+ Updated manual with description of the simplified API (copied from png.h)
Fix bug in pngerror.c: some long warnings were being improperly truncated
(CVE-2011-3464, bug introduced in libpng-1.5.3beta05).
-Version 1.5.8rc01 [January 21, 2012]
- No changes.
-
-Version 1.5.8rc02 [January 25, 2012]
+Version 1.6.0beta06 [January 24, 2012]
+ Added palette support to the simplified APIs. This commit
+ changes some of the macro definitions in png.h, app code
+ may need corresponding changes.
+ Increased the formatted warning buffer to 192 bytes.
+ Added color-map support to simplified API. This is an initial version for
+ review; the documentation has not yet been updated.
Fixed Min/GW uninstall to remove libpng.dll.a
- Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt
-
-Version 1.5.8 [February 1, 2012]
- No changes.
-
-Version 1.5.9beta01 [February 3, 2012]
- Rebuilt configure scripts in the tar distributions.
-Version 1.5.9beta02 [February 16, 2012]
- Removed two unused definitions from scripts/pnglibconf.h.prebuilt
+Version 1.6.0beta07 [January 28, 2012]
+ Eliminated Intel icc/icl compiler warnings. The Intel (GCC derived)
+ compiler issues slightly different warnings from those issued by the
+ current vesions of GCC. This eliminates those warnings by
+ adding/removing casts and small code rewrites.
+ Updated configure.ac from autoupdate: added --enable-werror option.
+ Also some layout regularization and removal of introduced tab characters
+ (replaced with 3-character indentation). Obsolete macros identified by
+ autoupdate have been removed; the replacements are all in 2.59 so
+ the pre-req hasn't been changed. --enable-werror checks for support
+ for -Werror (or the given argument) in the compiler. This mimics the
+ gcc configure option by allowing -Werror to be turned on safely; without
+ the option the tests written in configure itself fail compilation because
+ they cause compiler warnings.
+ Rewrote autogen.sh to run autoreconf instead of running tools one-by-one.
+ Conditionalize the install rules for MINGW and CYGWIN in CMakeLists.txt and
+ set CMAKE_LIBRARY_OUTPUT_DIRECTORY to "lib" on all platforms (C. Yapp).
+ Freeze libtool files in the 'scripts' directory. This version of autogen.sh
+ attempts to dissuade people from running it when it is not, or should not,
+ be necessary. In fact, autogen.sh does not work when run in a libpng
+ directory extracted from a tar distribution anymore. You must run it in
+ a GIT clone instead.
+ Added two images to contrib/pngsuite (1-bit and 2-bit transparent grayscale),
+ and renamed three whose names were inconsistent with those in
+ pngsuite/README.txt.
+
+Version 1.6.0beta08 [February 1, 2012]
+ Fixed Image::colormap misalignment in pngstest.c
+ Check libtool/libtoolize version number (2.4.2) in configure.ac
+ Divide test-pngstest.sh into separate pngstest runs for basic and
+ transparent images.
+ Moved automake options to AM_INIT_AUTOMAKE in configure.ac
+ Added color-tests, silent-rules (Not yet implemented in Makefile.am) and
+ version checking to configure.ac
+ Improved pngstest speed by not doing redundant tests and add const to
+ the background parameter of png_image_finish_read. The --background
+ option is now done automagically only when required, so that commandline
+ option no longer exists.
+ Cleaned up pngpriv.h to consistently declare all functions and data.
+ Also eliminated PNG_CONST_DATA, which is apparently not needed but we
+ can't be sure until it is gone.
+ Added symbol prefixing that allows all the libpng external symbols
+ to be prefixed (suggested by Reuben Hawkins).
+ Updated "ftbb*.png" list in the owatcom and vstudio projects.
+ Fixed 'prefix' builds on clean systems. The generation of pngprefix.h
+ should not require itself.
+ Updated INSTALL to explain that autogen.sh must be run in a GIT clone,
+ not in a libpng directory extracted from a tar distribution.
+
+Version 1.6.0beta09 [February 1, 2012]
+ Reverted the prebuilt configure files to libpng-1.6.0beta05 condition.
+
+Version 1.6.0beta10 [February 3, 2012]
+ Added Z_SOLO for zlib-1.2.6+ and correct pngstest tests
+ Updated list of test images in CMakeLists.txt
+ Updated the prebuilt configure files to current condition.
+ Revised INSTALL information about autogen.sh; it works in tar distributions.
+
+Version 1.6.0beta11 [February 16, 2012]
+ Fix character count in pngstest command in projects/owatcom/pngstest.tgt
+ Revised test-pngstest.sh to report PASS/FAIL for each image.
+ Updated documentation about the simplified API.
+ Corrected estimate of error in libpng png_set_rgb_to_gray API. The API is
+ extremely inaccurate for sRGB conversions because it uses an 8-bit
+ intermediate linear value and it does not use the sRGB transform, so it
+ suffers from the known instability in gamma transforms for values close
+ to 0 (see Poynton). The net result is that the calculation has a maximum
+ error of 14.99/255; 0.5/255^(1/2.2). pngstest now uses 15 for the
+ permitted 8-bit error. This may still not be enough because of arithmetic
+ error.
Removed some unused arrays (with #ifdef) from png_read_push_finish_row().
+ Fixed a memory overwrite bug in simplified read of RGB PNG with
+ non-linear gamma Also bugs in the error checking in pngread.c and changed
+ quite a lot of the checks in pngstest.c to be correct; either correctly
+ written or not over-optimistic. The pngstest changes are insufficient to
+ allow all possible RGB transforms to be passed; pngstest cmppixel needs
+ to be rewritten to make it clearer which errors it allows and then changed
+ to permit known inaccuracies.
Removed tests for no-longer-used *_EMPTY_PLTE_SUPPORTED from pngstruct.h
-
-Version 1.5.9rc01 [February 17, 2012]
+ Fixed fixed/float API export conditionals. 1) If FIXED_POINT or
+ FLOATING_POINT options were switched off, png.h ended up with lone ';'
+ characters. This is not valid ANSI-C outside a function. The ';'
+ characters have been moved inside the definition of PNG_FP_EXPORT and
+ PNG_FIXED_EXPORT. 2) If either option was switched off, the declaration
+ of the corresponding functions were completely omitted, even though some
+ of them are still used internally. The result is still valid, but
+ produces warnings from gcc with some warning options (including -Wall). The
+ fix is to cause png.h to declare the functions with PNG_INTERNAL_FUNCTION
+ when png.h is included from pngpriv.h.
+ Check for invalid palette index while reading paletted PNG. When one is
+ found, issue a warning and increase png_ptr->num_palette accordingly.
+ Apps are responsible for checking to see if that happened.
+
+Version 1.6.0beta12 [February 18, 2012]
+ Do not increase num_palette on invalid_index.
+ Relocated check for invalid palette index to pngrtran.c, after unpacking
+ the sub-8-bit pixels.
Fixed CVE-2011-3026 buffer overrun bug. This bug was introduced when
iCCP chunk support was added at libpng-1.0.6. Deal more correctly with the
test on iCCP chunk length. Also removed spurious casts that may hide
problems on 16-bit systems.
-Version 1.5.9 [February 18, 2012]
- No changes.
-
-Version 1.5.10beta01 [February 24, 2012]
- Removed two useless #ifdef directives from pngread.c and one from pngrutil.c
- Always put the CMAKE_LIBRARY in "lib" (removed special WIN32 case).
- Removed empty vstudio/pngstest directory (Clifford Yapp).
+Version 1.6.0beta13 [February 24, 2012]
Eliminated redundant png_push_read_tEXt|zTXt|iTXt|unknown code from
pngpread.c and use the sequential png_handle_tEXt, etc., in pngrutil.c;
now that png_ptr->buffer is inaccessible to applications, the special
handling is no longer useful.
- Fixed bug with png_handle_hIST with odd chunk length (Frank Busse).
- Added PNG_SAFE_LIMITS feature to pnglibconf.dfa and code in pngconf.h
- to reset the user limits to safe ones if PNG_SAFE_LIMITS is defined.
- To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED" on the configure
- command or put "#define PNG_SAFE_LIMITS_SUPPORTED" in pnglibconf.h.
- Revised the SAFE_LIMITS feature to be the same as the feature in libpng16.
- Added information about the new limits in the manual.
+ Added PNG_SAFE_LIMITS feature to pnglibconf.dfa, pngpriv.h, and new
+ pngusr.dfa to reset the user limits to safe ones if PNG_SAFE_LIMITS is
+ defined. To enable, use "CPPFLAGS=-DPNG_SAFE_LIMITS_SUPPORTED=1" on the
+ configure command or put #define PNG_SAFE_LIMITS_SUPPORTED in
+ pnglibconf.h.prebuilt and pnglibconf.h.
-Version 1.5.10beta02 [February 27, 2012]
+Version 1.6.0beta14 [February 27, 2012]
+ Added information about the new limits in the manual.
Updated Makefile.in
-Version 1.5.10beta03 [March 6, 2012]
+Version 1.6.0beta15 [March 2, 2012]
Removed unused "current_text" members of png_struct and the png_free()
of png_ptr->current_text from pngread.c
- Added palette-index checking. Issue a png_warning() if an invalid index is
- found.
-
-Version 1.5.10beta04 [March 10, 2012]
- Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
- Fixed CMF optimization of non-IDAT compressed chunks, which was added at
- libpng-1.5.4. It sometimes produced too small of a window.
-
-Version 1.5.10beta05 [March 10, 2012]
+ Rewrote pngstest.c for substantial speed improvement.
+ Fixed transparent pixel and 16-bit rgb tests in pngstest and removed a
+ spurious check in pngwrite.c
+ Added PNG_IMAGE_FLAG_FAST for the benefit of applications that store
+ intermediate files, or intermediate in-memory data, while processing
+ image data with the simplified API. The option makes the files larger
+ but faster to write and read. pngstest now uses this by default; this
+ can be disabled with the --slow option.
+ Improved pngstest fine tuning of error numbers, new test file generator.
+ The generator generates images that test the full range of sample values,
+ allow the error numbers in pngstest to be tuned and checked. makepng
+ also allows generation of images with extra chunks, although this is
+ still work-in-progress.
+ Added check for invalid palette index while reading.
+ Fixed some bugs in ICC profile writing. The code should now accept
+ all potentially valid ICC profiles and reject obviously invalid ones.
+ It now uses png_error() to do so rather than casually writing a PNG
+ without the necessary color data.
+ Removed whitespace from the end of lines in all source files and scripts.
+
+Version 1.6.0beta16 [March 6, 2012]
+ Relocated palette-index checking function from pngrutil.c to pngtrans.c
+ Added palette-index checking while writing.
+ Changed png_inflate() and calling routines to avoid overflow problems.
+ This is an intermediate check-in that solves the immediate problems and
+ introduces one performance improvement (avoiding a copy via png_ptr->zbuf.)
+ Further changes will be made to make ICC profile handling more secure.
+ Fixed build warnings (MSVC, GCC, GCC v3). Cygwin GCC with default options
+ declares 'index' as a global, causing a warning if it is used as a local
+ variable. GCC 64-bit warns about assigning a (size_t) (unsigned 64-bit)
+ to an (int) (signed 32-bit). MSVC, however, warns about using the
+ unary '-' operator on an unsigned value (even though it is well defined
+ by ANSI-C to be ~x+1). The padding calculation was changed to use a
+ different method. Removed the tests on png_ptr->pass.
+ Added contrib/libtests/tarith.c to test internal arithmetic functions from
+ png.c. This is a libpng maintainer program used to validate changes to the
+ internal arithmetic functions.
+ Made read 'inflate' handling like write 'deflate' handling. The read
+ code now claims and releases png_ptr->zstream, like the write code.
+ The bug whereby the progressive reader failed to release the zstream
+ is now fixed, all initialization is delayed, and the code checks for
+ changed parameters on deflate rather than always calling
+ deflatedEnd/deflateInit.
+ Validate the zTXt strings in pngvalid.
+ Added code to validate the windowBits value passed to deflateInit2().
+ If the call to deflateInit2() is wrong a png_warning will be issued
+ (in fact this is harmless, but the PNG data produced may be sub-optimal).
+
+Version 1.6.0beta17 [March 10, 2012]
+ Fixed PNG_LIBPNG_BUILD_BASE_TYPE definition.
Reject all iCCP chunks after the first, even if the first one is invalid.
+ Deflate/inflate was reworked to move common zlib calls into single
+ functions [rw]util.c. A new shared keyword check routine was also added
+ and the 'zbuf' is no longer allocated on progressive read. It is now
+ possible to call png_inflate() incrementally. A warning is no longer
+ issued if the language tag or translated keyword in the iTXt chunk
+ has zero length.
+ If benign errors are disabled use maximum window on ancilliary inflate.
+ This works round a bug introduced in 1.5.4 where compressed ancillary
+ chunks could end up with a too-small windowBits value in the deflate
+ header.
+
+Version 1.6.0beta18 [March 16, 2012]
Issue a png_benign_error() instead of png_warning() about bad palette index.
+ In pngtest, treat benign errors as errors if "-strict" is present.
Fixed an off-by-one error in the palette index checking function.
+ Fixed a compiler warning under Cygwin (Windows-7, 32-bit system)
Revised example.c to put text strings in a temporary character array
instead of directly assigning string constants to png_textp members.
This avoids compiler warnings when -Wwrite-strings is enabled.
-
-Version 1.5.10 [March 29, 2012]
+ Added output flushing to aid debugging under Visual Studio. Unfortunately
+ this is necessary because the VS2010 output window otherwise simply loses
+ the error messages on error (they weren't flushed to the window before
+ the process exited, apparently!)
+ Added configuration support for benign errors and changed the read
+ default. Also changed some warnings in the iCCP and sRGB handling
+ from to benign errors. Configuration now makes read benign
+ errors warnings and write benign errors to errors by default (thus
+ changing the behavior on read). The simplified API always forces
+ read benign errors to warnings (regardless of the system default, unless
+ this is disabled in which case the simplified API can't be built.)
+
+Version 1.6.0beta19 [March 18, 2012]
+ Work around for duplicate row start calls; added warning messages.
+ This turns on PNG_FLAG_DETECT_UNINITIALIZED to detect app code that
+ fails to call one of the 'start' routines (not enabled in libpng-1.5
+ because it is technically an API change, since it did normally work
+ before.) It also makes duplicate calls to png_read_start_row (an
+ internal function called at the start of the image read) benign, as
+ they were before changes to use png_inflate_claim. Somehow webkit is
+ causing this to happen; this is probably a mis-feature in the zlib
+ changes so this commit is only a work-round.
+ Removed erroneous setting of DETECT_UNINITIALIZED and added more
+ checks. The code now does a png_error if an attempt is made to do the
+ row initialization twice; this is an application error and it has
+ serious consequences because the transform data in png_struct is
+ changed by each call.
+ Added application error reporting and added chunk names to read
+ benign errors; also added --strict to pngstest - not enabled
+ yet because a warning is produced.
+ Avoid the double gamma correction warning in the simplified API.
+ This allows the --strict option to pass in the pngstest checks
+
+Version 1.6.0beta20 [March 29, 2012]
+ Changed chunk handler warnings into benign errors, incrementally load iCCP
+ Added checksum-icc.c to contrib/tools
Prevent PNG_EXPAND+PNG_SHIFT doing the shift twice.
+ Recognize known sRGB ICC profiles while reading; prefer writing the
+ iCCP profile over writing the sRGB chunk, controlled by the
+ PNG_sRGB_PROFILE_CHECKS option.
Revised png_set_text_2() to avoid potential memory corruption (fixes
- CVE-2011-3048).
+ CVE-2011-3048, also known as CVE-2012-3425).
+
+Version 1.6.0beta21 [April 27, 2012]
+ Revised scripts/makefile.darwin: use system zlib; remove quotes around
+ architecture list; add missing ppc architecture; add architecture options
+ to shared library link; don't try to create a shared lib based on missing
+ RELEASE variable.
+ Enable png_set_check_for_invalid_index() for both read and write.
+ Removed #ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED in pngpriv.h around
+ declaration of png_handle_unknown().
+ Added -lssp_nonshared in a comment in scripts/makefile.freebsd
+ and changed deprecated NOOBJ and NOPROFILE to NO_OBJ and NO_PROFILE.
+
+Version 1.6.0beta22 [May 23, 2012]
+ Removed need for -Wno-cast-align with clang. clang correctly warns on
+ alignment increasing pointer casts when -Wcast-align is passed. This
+ fixes the cases that clang warns about either by eliminating the
+ casts from png_bytep to png_uint_16p (pngread.c), or, for pngrutil.c
+ where the cast is previously verified or pngstest.c where it is OK, by
+ introducing new png_aligncast macros to do the cast in a way that clang
+ accepts.
+
+Version 1.6.0beta23 [June 6, 2012]
+ Revised CMakeLists.txt to not attempt to make a symlink under mingw.
+ Made fixes for new optimization warnings from gcc 4.7.0. The compiler
+ performs an optimization which is safe; however it then warns about it.
+ Changing the type of 'palette_number' in pngvalid.c removes the warning.
+ Do not depend upon a GCC feature macro being available for use in generating
+ the linker mapfile symbol prefix.
+ Improved performance of new do_check_palette_indexes() function (only
+ update the value when it actually increases, move test for whether
+ the check is wanted out of the function.
+
+Version 1.6.0beta24 [June 7, 2012]
+ Don't check palette indexes if num_palette is 0 (as it can be in MNG files).
+
+Version 1.6.0beta25 [June 16, 2012]
+ Revised png_set_keep_unknown_chunks() so num_chunks < 0 means ignore all
+ unknown chunks and all known chunks except for IHDR, PLTE, tRNS, IDAT,
+ and IEND. Previously it only meant ignore all unknown chunks, the
+ same as num_chunks == 0. Revised png_image_skip_unused_chunks() to
+ provide a list of chunks to be processed instead of a list of chunks to
+ ignore. Revised contrib/gregbook/readpng2.c accordingly.
+
+Version 1.6.0beta26 [July 10, 2012]
+ Removed scripts/makefile.cegcc from the *.zip and *.7z distributions; it
+ depends on configure, which is not included in those archives.
+ Moved scripts/chkfmt to contrib/tools.
+ Changed "a+w" to "u+w" in Makefile.in to fix CVE-2012-3386.
+
+Version 1.6.0beta27 [August 11, 2012]
+ Do not compile PNG_DEPRECATED, PNG_ALLOC and PNG_PRIVATE when __GNUC__ < 3.
+ Do not use __restrict when GNUC is <= 3.1
+ Removed references to png_zalloc() and png_zfree() from the manual.
+ Fixed configurations where floating point is completely disabled. Because
+ of the changes to support symbol prefixing PNG_INTERNAL_FUNCTION declares
+ floating point APIs during libpng builds even if they are completely
+ disabled. This requires the png floating point types (png_double*) to be
+ declared even though the functions are never actually defined. This
+ change provides a dummy definition so that the declarations work, yet any
+ implementation will fail to compile because of an incomplete type.
+ Re-eliminated the use of strcpy() in pngtest.c. An unncessary use of
+ strcpy() was accidentally re-introduced in libpng16; this change replaces
+ it with strncpy().
+ Eliminated use of png_sizeof(); use sizeof() instead.
+ Use a consistent style for (sizeof type) and (sizeof (array))
+ Cleanup of png_set_filler(). This function does very different things on
+ read and write. In libpng 1.6 the two cases can be distinguished and
+ considerable code cleanup, and extra error checking, is possible. This
+ makes calls on the write side that have no effect be ignored with a
+ png_app_error(), which can be disabled in the app using
+ png_set_benign_errors(), and removes the spurious use of usr_channels
+ on the read side.
+ Insist on autotools 1.12.1 for git builds because there are security issues
+ with 1.12 and insisting on anything less would allow 1.12 to be used.
+ Removed info_ptr->signature[8] from WRITE-only builds.
+ Add some conditions for compiling png_fixed(). This is a small function
+ but it requires "-lm" on some platforms.
+ Cause pngtest --strict to fail on any warning from libpng (not just errors)
+ and cause it not to fail at the comparison step if libpng lacks support
+ for writing chunks that it reads from the input (currently only implemented
+ for compressed text chunks).
+ Make all three "make check" test programs work without READ or WRITE support.
+ Now "make check" will succeed even if libpng is compiled with -DPNG_NO_READ
+ or -DPNG_NO_WRITE. The tests performed are reduced, but the basic reading
+ and writing of a PNG file is always tested by one or more of the tests.
+ Consistently use strlen(), memset(), memcpy(), and memcmp() instead of the
+ png_strlen(), png_memset(), png_memcpy(), and png_memcmp() macros.
+ Removed the png_sizeof(), png_strlen(), png_memset(), png_memcpy(), and
+ png_memcmp() macros.
+ Work around gcc 3.x and Microsoft Visual Studio 2010 complaints. Both object
+ to the split initialization of num_chunks.
+
+Version 1.6.0beta28 [August 29, 2012]
+ Unknown handling fixes and clean up. This adds more correct option
+ control of the unknown handling, corrects the pre-existing bug where
+ the per-chunk 'keep' setting is ignored and makes it possible to skip
+ IDAT chunks in the sequential reader (broken in earlier 1.6 versions).
+ There is a new test program, test-unknown.c, which is a work in progress
+ (not currently part of the test suite). Comments in the header files now
+ explain how the unknown handling works.
+ Allow fine grain control of unknown chunk APIs. This change allows
+ png_set_keep_unknown_chunks() to be turned off if not required and causes
+ both read and write to behave appropriately (on read this is only possible
+ if the user callback is used to handle unknown chunks). The change
+ also removes the support for storing unknown chunks in the info_struct
+ if the only unknown handling enabled is via the callback, allowing libpng
+ to be configured with callback reading and none of the unnecessary code.
+ Corrected fix for unknown handling in pngtest. This reinstates the
+ libpng handling of unknown chunks other than vpAg and sTER (including
+ unsafe-to-copy chunks which were dropped before) and eliminates the
+ repositioning of vpAg and sTER in pngtest.png by changing pngtest.png
+ (so the chunks are where libpng would put them).
+ Added "tunknown" test and corrected a logic error in png_handle_unknown()
+ when SAVE support is absent. Moved the shell test scripts for
+ contrib/libtests from the libpng top directory to contrib/libtests.
+ png_handle_unknown() must always read or skip the chunk, if
+ SAVE_UNKNOWN_CHUNKS is turned off *and* the application does not set
+ a user callback an unknown chunk will not be read, leading to a read
+ error, which was revealed by the "tunknown" test.
+ Cleaned up and corrected ICC profile handling.
+ contrib/libtests/makepng: corrected 'rgb' and 'gray' cases. profile_error
+ messages could be truncated; made a correct buffer size calculation and
+ adjusted pngerror.c appropriately. png_icc_check_* checking improved;
+ changed the functions to receive the correct color type of the PNG on read
+ or write and check that it matches the color space of the profile (despite
+ what the comments said before, there is danger in assuming the app will
+ cope correctly with an RGB profile on a grayscale image and, since it
+ violates the PNG spec, allowing it is certain to produce inconsistent
+ app behavior and might even cause app crashes.) Check that profiles
+ contain the tags needed to process the PNG (tags all required by the ICC
+ spec). Removed unused PNG_STATIC from pngpriv.h.
+
+Version 1.6.0beta29 [September 4, 2012]
+ Fixed the simplified API example programs to add the *colormap parameter
+ to several of he API and improved the error message if the version field
+ is not set.
+ Added contrib/examples/* to the *.zip and *.7z distributions.
+ Updated simplified API synopses and description of the png_image structure
+ in the manual.
+ Made makepng and pngtest produce identical PNGs, add "--relaxed" option
+ to pngtest. The "--relaxed" option turns off the benign errors that are
+ enabled by default in pre-RC builds. makepng can now write ICC profiles
+ where the length has not been extended to a multiple of 4, and pngtest
+ now intercepts all libpng errors, allowing the previously-introduced
+ "--strict test" on no warnings to actually work.
+ Improved ICC profile handling including cHRM chunk generation and fixed
+ Cygwin+MSVC build errors. The ICC profile handling now includes more
+ checking. Several errors that caused rejection of the profile are now
+ handled with a warning in such a way that the invalid profiles will be
+ read by default in release (but not pre-RC) builds but will not be
+ written by default. The easy part of handling the cHRM chunk is written,
+ where the ICC profile contains the required data. The more difficult
+ part plus guessing a gAMA value requires code to pass selected RGB values
+ through the profile.
+
+Version 1.6.0beta30 [October 24, 2012]
+ Changed ICC profile matrix/vector types to not depend on array type rules.
+ By the ANSI-C standard the new types should be identical to the previous
+ versions, and all known versions of gcc tested with the previous versions
+ except for GCC-4.2.1 work with this version. The change makes the ANSI-C
+ rule that const applied to an array of elements applies instead to the
+ elements in the array moot by explicitly applying const to the base
+ elements of the png_icc_matrix and png_icc_vector types. The accidental
+ (harmless) 'const' previously applied to the parameters of two of the
+ functions have also been removed.
+ Added a work around for GCC 4.2 optimization bug.
+ Marked the broken (bad white point) original HP sRGB profiles correctly and
+ correct comments.
+ Added -DZ_SOLO to contrib/pngminim/*/makefile to work with zlib-1.2.7
+ Use /MDd for vstudio debug builds. Also added pngunkown to the vstudio
+ builds, fixed build errors and corrected a minor exit code error in
+ pngvalid if the 'touch' file name is invalid.
+ Add updated WARNING file to projects/vstudio from libpng 1.5/vstudio
+ Fixed build when using #define PNG_NO_READ_GAMMA in png_do_compose() in
+ pngrtran.c (Domani Hannes).
+
+Version 1.6.0beta31 [November 1, 2012]
+ Undid the erroneous change to vstudio/pngvalid build in libpng-1.6.0beta30.
+ Made pngvalid so that it will build outside the libpng source tree.
+ Made builds -DPNG_NO_READ_GAMMA compile (the unit tests still fail).
+ Made PNG_NO_READ_GAMMA switch off interfaces that depend on READ_GAMMA.
+ Prior to 1.6.0 switching off READ_GAMMA did unpredictable things to the
+ interfaces that use it (specifically, png_do_background in 1.4 would
+ simply display composite for grayscale images but do composition
+ with the incorrect arithmetic for color ones). In 1.6 the semantic
+ of -DPNG_NO_READ_GAMMA is changed to simply disable any interface that
+ depends on it; this obliges people who set it to consider whether they
+ really want it off if they happen to use any of the interfaces in
+ question (typically most users who disable it won't).
+ Fixed GUIDs in projects/vstudio. Some were duplicated or missing,
+ resulting in VS2010 having to update the files.
+ Removed non-working ICC profile support code that was mostly added to
+ libpng-1.6.0beta29 and beta30. There was too much code for too little
+ gain; implementing full ICC color correction may be desireable but is left
+ up to applications.
+
+Version 1.6.0beta32 [November 25, 2012]
+ Fixed an intermittent SEGV in pngstest due to an uninitialized array element.
+ Added the ability for contrib/libtests/makepng.c to make a PNG with just one
+ color. This is useful for debugging pngstest color inaccuracy reports.
+ Fixed error checking in the simplified write API (Olaf van der Spek)
+ Made png_user_version_check() ok to use with libpng version 1.10.x and later.
+
+Version 1.6.0beta33 [December 15, 2012]
+ Fixed typo in png.c (PNG_SET_CHUNK_MALLOC_MAX should be PNG_CHUNK_MALLOC_MAX)
+ that causes the MALLOC_MAX limit not to work (John Bowler)
+ Change png_warning() to png_app_error() in pngwrite.c and comment the
+ fall-through condition.
+ Change png_warning() to png_app_warning() in png_write_tRNS().
+ Rearranged the ARM-NEON optimizations: Isolated the machine specific code
+ to the hardware subdirectory and added comments to pngrutil.c so that
+ implementors of other optimizations know what to do.
+ Fixed cases of unquoted DESTDIR in Makefile.am
+ Rebuilt Makefile.in, etc., with autoconf-2.69 and automake-1.12.5.
+
+Version 1.6.0beta34 [December 19, 2012]
+ Cleaned up whitespace in the synopsis portion of the manpage "libpng.3"
+ Disassembled the version number in scripts/options.awk (necessary for
+ building on SunOs).
+
+Version 1.6.0beta35 [December 23, 2012]
+ Made default Zlib compression settings be configurable. This adds #defines to
+ pnglibconf.h to control the defaults.
+ Fixed Windows build issues, enabled ARM compilation. Various warnings issued
+ by earlier versions of GCC fixed for Cygwin and Min/GW (which both use old
+ GCCs.) ARM support is enabled by default in zlib.props (unsupported by
+ Microsoft) and ARM compilation is made possible by deleting the check for
+ x86. The test programs cannot be run because they are not signed.
+
+Version 1.6.0beta36 [January 2, 2013]
+ Discontinued distributing libpng-1.x.x.tar.bz2.
+ Discontinued distributing libpng-1.7.0-1.6.0-diff.txt and similar.
+ Rebuilt configure with autoconf-2.69 (inadvertently not done in beta33)
+ Fixed 'make distcheck' on SUN OS - libpng.so was not being removed
+
+Version 1.6.0beta37 [January 10, 2013]
+ Fixed conceivable but difficult to repro overflow. Also added two test
+ programs to generate and test a PNG which should have the problem.
+
+Version 1.6.0beta39 [January 19, 2013]
+ Again corrected attempt at overflow detection in png_set_unknown_chunks()
+ (CVE-2013-7353). Added overflow detection in png_set_sPLT() and
+ png_set_text_2() (CVE-2013-7354).
+
+Version 1.6.0beta40 [January 20, 2013]
+ Use consistent handling of overflows in text, sPLT and unknown png_set_* APIs
+
+Version 1.6.0rc01 [January 26, 2013]
+ No changes.
+
+Version 1.6.0rc02 [February 4, 2013]
+ Added png_get_palette_max() function.
+
+Version 1.6.0rc03 [February 5, 2013]
+ Fixed the png_get_palette_max API.
+
+Version 1.6.0rc04 [February 7, 2013]
+ Turn serial tests back on (recently turned off by autotools upgrade).
+
+Version 1.6.0rc05 [February 8, 2013]
+ Update manual about png_get_palette_max().
+
+Version 1.6.0rc06 [February 9, 2013]
+ Fixed missing dependency in --prefix builds The intermediate
+ internal 'prefix.h' file can only be generated correctly after
+ pnglibconf.h, however the dependency was not in Makefile.am. The
+ symptoms are unpredictable depending on the order make chooses to
+ build pngprefix.h and pnglibconf.h, often the error goes unnoticed
+ because there is a system pnglibconf.h to use instead.
+
+Version 1.6.0rc07 [February 10, 2013]
+ Enclosed the new png_get_palette_max in #ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+ block, and revised pnglibconf.h and pnglibconf.h.prebuilt accordingly.
+
+Version 1.6.0rc08 [February 10, 2013]
+ Fix typo in png.h #ifdef
+
+Version 1.6.0 [February 14, 2013]
+ No changes.
+
+Version 1.6.1beta01 [February 16, 2013]
+ Made symbol prefixing work with the ARM neon optimizations. Also allow
+ pngpriv.h to be included for preprocessor definitions only, so it can
+ be used in non-C/C++ files. Back ported from libpng 1.7.
+ Made sRGB check numbers consistent.
+ Ported libpng 1.5 options.awk/dfn file handling to 1.6, fixed one bug.
+ Removed cc -E workround, corrected png_get_palette_max API Tested on
+ SUN OS cc 5.9, which demonstrates the tokenization problem previously
+ avoided by using /lib/cpp. Since all .dfn output is now protected in
+ double quotes unless it is to be macro substituted the fix should
+ work everywhere.
+ Enabled parallel tests - back ported from libpng-1.7.
+ scripts/pnglibconf.dfa formatting improvements back ported from libpng17.
+ Fixed a race condition in the creation of the build 'scripts' directory
+ while building with a parallel make.
+ Use approved/supported Android method to check for NEON, use Linux/POSIX
+ 1003.1 API to check /proc/self/auxv avoiding buffer allocation and other
+ library calls (ported from libpng15).
+
+Version 1.6.1beta02 [February 19, 2013]
+ Use parentheses more consistently in "#if defined(MACRO)" tests.
+ Folded long lines.
+ Reenabled code to allow zero length PLTE chunks for MNG.
+
+Version 1.6.1beta03 [February 22, 2013]
+ Fixed ALIGNED_MEMORY support.
+ Allow run-time ARM NEON checking to be disabled. A new configure option:
+ --enable-arm-neon=always will stop the run-time checks. New checks
+ within arm/arm_init.c will cause the code not to be compiled unless
+ __ARM_NEON__ is set. This should make it fail safe (if someone asks
+ for it on then the build will fail if it can't be done.)
+ Updated the INSTALL document.
+
+Version 1.6.1beta04 [February 27, 2013]
+ Revised INSTALL to recommend using CPPFLAGS instead of INCLUDES.
+ Revised scripts/makefile.freebsd to respect ZLIBLIB and ZLIBINC.
+ Revised scripts/dfn.awk to work with the buggy MSYS awk that has trouble
+ with CRLF line endings.
+
+Version 1.6.1beta05 [March 1, 2013]
+ Avoid a possible memory leak in contrib/gregbook/readpng.c
+
+Version 1.6.1beta06 [March 4, 2013]
+ Better documentation of unknown handling API interactions.
+ Corrected Android builds and corrected libpng.vers with symbol
+ prefixing. This adds an API to set optimization options externally,
+ providing an alternative and general solution for the non-portable
+ run-time tests used by the ARM Neon code. It also makes those tests
+ compile and link on Android.
+ The order of settings vs options in pnglibconf.h is reversed to allow
+ settings to depend on options and options can now set (or override) the
+ defaults for settings.
+
+Version 1.6.1beta07 [March 7, 2013]
+ Corrected simplified API default gamma for color-mapped output, added
+ a flag to change default. In 1.6.0 when the simplified API was used
+ to produce color-mapped output from an input image with no gamma
+ information the gamma assumed for the input could be different from
+ that assumed for non-color-mapped output. In particular 16-bit depth
+ input files were assumed to be sRGB encoded, whereas in the 'direct'
+ case they were assumed to have linear data. This was an error. The
+ fix makes the simplified API treat all input files the same way and
+ adds a new flag to the png_image::flags member to allow the
+ application/user to specify that 16-bit files contain sRGB data
+ rather than the default linear.
+ Fixed bugs in the pngpixel and makepng test programs.
+
+Version 1.6.1beta08 [March 7, 2013]
+ Fixed CMakelists.txt to allow building a single variant of the library
+ (Claudio Bley):
+ Introduced a PNG_LIB_TARGETS variable that lists all activated library
+ targets. It is an error if this variable ends up empty, ie. you have
+ to build at least one library variant.
+ Made the *_COPY targets only depend on library targets actually being build.
+ Use PNG_LIB_TARGETS to unify a code path.
+ Changed the CREATE_SYMLINK macro to expect the full path to a file as the
+ first argument. When symlinking the filename component of that path is
+ determined and used as the link target.
+ Use copy_if_different in the CREATE_SYMLINK macro.
+
+Version 1.6.1beta09 [March 13, 2013]
+ Eliminated two warnings from the Intel C compiler. The warnings are
+ technically valid, although a reasonable treatment of division would
+ show it to be incorrect.
+
+Version 1.6.1rc01 [March 21, 2013]
+ No changes.
+
+Version 1.6.1 [March 28, 2013]
+ No changes.
+
+Version 1.6.2beta01 [April 14, 2013]
+ Updated documentation of 1.5.x to 1.6.x changes in iCCP chunk handling.
+ Fixed incorrect warning of excess deflate data. End condition - the
+ warning would be produced if the end of the deflate stream wasn't read
+ in the last row. The warning is harmless.
+ Corrected the test on user transform changes on read. It was in the
+ png_set of the transform function, but that doesn't matter unless the
+ transform function changes the rowbuf size, and that is only valid if
+ transform_info is called.
+ Corrected a misplaced closing bracket in contrib/libtests/pngvalid.c
+ (Flavio Medeiros).
+ Corrected length written to uncompressed iTXt chunks (Samuli Suominen).
+ Bug was introduced in libpng-1.6.0.
+
+Version 1.6.2rc01 [April 18, 2013]
+ Added contrib/tools/fixitxt.c, to repair the erroneous iTXt chunk length
+ written by libpng-1.6.0 and 1.6.1.
+ Disallow storing sRGB information when the sRGB is not supported.
+
+Version 1.6.2rc02 [April 18, 2013]
+ Merge pngtest.c with libpng-1.7.0
+
+Version 1.6.2rc03 [April 22, 2013]
+ Trivial spelling cleanup.
+
+Version 1.6.2rc04 and 1.6.2rc05 [omitted]
+
+Version 1.6.2rc06 [April 24, 2013]
+ Reverted to version 1.6.2rc03. Recent changes to arm/neon support
+ have been ported to libpng-1.7.0beta09 and will reappear in version
+ 1.6.3beta01.
+
+Version 1.6.2 [April 25, 2013]
+ No changes.
+
+Version 1.6.3beta01 [April 25, 2013]
+ Revised stack marking in arm/filter_neon.S and configure.ac.
+ Ensure that NEON filter stuff is completely disabled when switched 'off'.
+ Previously the ARM NEON specific files were still built if the option
+ was switched 'off' as opposed to being explicitly disabled.
+
+Version 1.6.3beta02 [April 26, 2013]
+ Test for 'arm*' not just 'arm' in the host_cpu configure variable.
+ Rebuilt the configure scripts.
+
+Version 1.6.3beta03 [April 30, 2013]
+ Expanded manual paragraph about writing private chunks, particularly
+ the need to call png_set_keep_unknown_chunks() when writing them.
+ Avoid dereferencing NULL pointer possibly returned from
+ png_create_write_struct() (Andrew Church).
+
+Version 1.6.3beta05 [May 9, 2013]
+ Calculate our own zlib windowBits when decoding rather than trusting the
+ CMF bytes in the PNG datastream.
+ Added an option to force maximum window size for inflating, which was
+ the behavior of libpng15 and earlier.
+ Added png-fix-itxt and png-fix-too-far-back to the built programs and
+ removed warnings from the source code and timepng that are revealed as
+ a result.
+ Detect wrong libpng versions linked to png-fix-too-far-back, which currently
+ only works with libpng versions that can be made to reliably fail when
+ the deflate data contains an out-of-window reference. This means only
+ 1.6 and later.
+ Fixed gnu issues: g++ needs a static_cast, gcc 4.4.7 has a broken warning
+ message which it is easier to work round than ignore.
+ Updated contrib/pngminus/pnm2png.c (Paul Stewart):
+ Check for EOF
+ Ignore "#" delimited comments in input file to pnm2png.c.
+ Fixed whitespace handling
+ Added a call to png_set_packing()
+ Initialize dimension values so if sscanf fails at least we have known
+ invalid values.
+ Attempt to detect configuration issues with png-fix-too-far-back, which
+ requires both the correct libpng and the correct zlib to function
+ correctly.
+ Check ZLIB_VERNUM for mismatches, enclose #error in quotes
+ Added information in the documentation about problems with and fixes for
+ the bad CRC and bad iTXt chunk situations.
+
+Version 1.6.3beta06 [May 12, 2013]
+ Allow contrib/pngminus/pnm2png.c to compile without WRITE_INVERT and
+ WRITE_PACK supported (writes error message that it can't read P1 or
+ P4 PBM files).
+ Improved png-fix-too-far-back usage message, added --suffix option.
+ Revised contrib/pngminim/*/makefile to generate pnglibconf.h with the
+ right zlib header files.
+ Separated CPPFLAGS and CFLAGS in contrib/pngminim/*/makefile
+
+Version 1.6.3beta07 [June 8, 2013]
+ Removed a redundant test in png_set_IHDR().
+ Added set(CMAKE_CONFIGURATION_TYPES ...) to CMakeLists.txt (Andrew Hundt)
+ Deleted set(CMAKE_BUILD_TYPE) block from CMakeLists.txt
+ Enclose the prototypes for the simplified write API in
+ #ifdef PNG_STDIO_SUPPORTED/#endif
+ Make ARM NEON support work at compile time (not just configure time).
+ This moves the test on __ARM_NEON__ into pngconf.h to avoid issues when
+ using a compiler that compiles for multiple architectures at one time.
+ Removed PNG_FILTER_OPTIMIZATIONS and PNG_ARM_NEON_SUPPORTED from
+ pnglibconf.h, allowing more of the decisions to be made internally
+ (pngpriv.h) during the compile. Without this, symbol prefixing is broken
+ under certain circumstances on ARM platforms. Now only the API parts of
+ the optimizations ('check' vs 'api') are exposed in the public header files
+ except that the new setting PNG_ARM_NEON_OPT documents how libpng makes the
+ decision about whether or not to use the optimizations.
+ Protect symbol prefixing against CC/CPPFLAGS/CFLAGS useage.
+ Previous iOS/Xcode fixes for the ARM NEON optimizations moved the test
+ on __ARM_NEON__ from configure time to compile time. This breaks symbol
+ prefixing because the definition of the special png_init_filter_functions
+ call was hidden at configure time if the relevant compiler arguments are
+ passed in CFLAGS as opposed to CC. This change attempts to avoid all
+ the confusion that would result by declaring the init function even when
+ it is not used, so that it will always get prefixed.
+
+Version 1.6.3beta08 [June 18, 2013]
+ Revised libpng.3 so that "doclifter" can process it.
+
+Version 1.6.3beta09 [June 27, 2013]
+ Revised example.c to illustrate use of PNG_DEFAULT_sRGB and PNG_GAMMA_MAC_18
+ as parameters for png_set_gamma(). These have been available since
+ libpng-1.5.4.
+ Renamed contrib/tools/png-fix-too-far-back.c to pngfix.c and revised it
+ to check all compressed chunks known to libpng.
+
+Version 1.6.3beta10 [July 5, 2013]
+ Updated documentation to show default behavior of benign errors correctly.
+ Only compile ARM code when PNG_READ_SUPPORTED is defined.
+ Fixed undefined behavior in contrib/tools/pngfix.c and added new strip
+ option. pngfix relied on undefined behavior and even a simple change from
+ gcc to g++ caused it to fail. The new strip option 'unsafe' has been
+ implemented and is the default if --max is given. Option names have
+ been clarified, with --strip=transform now stripping the bKGD chunk,
+ which was stripped previously with --strip=unused.
+ Added all documented chunk types to pngpriv.h
+ Unified pngfix.c source with libpng17.
+
+Version 1.6.3rc01 [July 11, 2013]
+ No changes.
+
+Version 1.6.3 [July 18, 2013]
+ Revised manual about changes in iTXt chunk handling made in libpng-1.6.0.
+ Added "/* SAFE */" comments in pngrutil.c and pngrtran.c where warnings
+ may be erroneously issued by code-checking applications.
+
+Version 1.6.4beta01 [August 21, 2013]
+ Added information about png_set_options() to the manual.
+ Delay calling png_init_filter_functions() until a row with nonzero filter
+ is found.
+
+Version 1.6.4beta02 [August 30, 2013]
+ Fixed inconsistent conditional compilation of png_chunk_unknown_handling()
+ prototype, definition, and usage. Made it depend on
+ PNG_HANDLE_AS_UNKNOWN_SUPPORTED everywhere.
+
+Version 1.6.4rc01 [September 5, 2013]
+ No changes.
+
+Version 1.6.4 [September 12, 2013]
+ No changes.
+
+Version 1.6.5 [September 14, 2013]
+ Removed two stray lines of code from arm/arm_init.c.
+
+Version 1.6.6 [September 16, 2013]
+ Removed two stray lines of code from arm/arm_init.c, again.
+
+Version 1.6.7beta01 [September 30, 2013]
+ Revised unknown chunk code to correct several bugs in the NO_SAVE_/NO_WRITE
+ combination
+ Allow HANDLE_AS_UNKNOWN to work when other options are configured off. Also
+ fixed the pngminim makefiles to work when $(MAKEFLAGS) contains stuff
+ which terminates the make options (as by default in recent versions of
+ Gentoo).
+ Avoid up-cast warnings in pngvalid.c. On ARM the alignment requirements of
+ png_modifier are greater than that of png_store and as a consequence
+ compilation of pngvalid.c results in a warning about increased alignment
+ requirements because of the bare cast to (png_modifier*). The code is safe,
+ because the pointer is known to point to a stack allocated png_modifier,
+ but this change avoids the warning.
+ Fixed default behavior of ARM_NEON_API. If the ARM NEON API option was
+ compiled without the CHECK option it defaulted to on, not off.
+ Check user callback behavior in pngunknown.c. Previous versions compiled
+ if SAVE_UNKNOWN was not available but did nothing since the callback
+ was never implemented.
+ Merged pngunknown.c with 1.7 version and back ported 1.7 improvements/fixes
+
+Version 1.6.7beta02 [October 12, 2013]
+ Made changes for compatibility with automake 1.14:
+ 1) Added the 'compile' program to the list of programs that must be cleaned
+ in autogen.sh
+ 2) Added 'subdir-objects' which causes .c files in sub-directories to be
+ compiled such that the corresponding .o files are also in the
+ sub-directory. This is because automake 1.14 warns that the
+ current behavior of compiling to the top level directory may be removed
+ in the future.
+ 3) Updated dependencies on pnglibconf.h to match the new .o locations and
+ added all the files in contrib/libtests and contrib/tools that depend
+ on pnglibconf.h
+ 4) Added 'BUILD_SOURCES = pnglibconf.h'; this is the automake recommended
+ way of handling the dependencies of sources that are machine generated;
+ unfortunately it only works if the user does 'make all' or 'make check',
+ so the dependencies (3) are still required.
+ Cleaned up (char*) casts of zlib messages. The latest version of the Intel C
+ compiler complains about casting a string literal as (char*), so copied the
+ treatment of z_const from the library code into pngfix.c
+ Simplified error message code in pngunknown. The simplification has the
+ useful side effect of avoiding a bogus warning generated by the latest
+ version of the Intel C compiler (it objects to
+ condition ? string-literal : string-literal).
+ Make autogen.sh work with automake 1.13 as well as 1.14. Do this by always
+ removing the 1.14 'compile' script but never checking for it.
+
+Version 1.6.7beta03 [October 19, 2013]
+ Added ARMv8 support (James Yu <james.yu at linaro.org>). Added file
+ arm/filter_neon_intrinsics.c; enable with -mfpu=neon.
+ Revised pngvalid to generate size images with as many filters as it can
+ manage, limited by the number of rows.
+ Cleaned up ARM NEON compilation handling. The tests are now in pngpriv.h
+ and detect the broken GCC compilers.
+
+Version 1.6.7beta04 [October 26, 2013]
+ Allow clang derived from older GCC versions to use ARM intrinsics. This
+ causes all clang builds that use -mfpu=neon to use the intrinsics code,
+ not the assembler code. This has only been tested on iOS 7. It may be
+ necessary to exclude some earlier clang versions but this seems unlikely.
+ Changed NEON implementation selection mechanism. This allows assembler
+ or intrinsics to be turned on at compile time during the build by defining
+ PNG_ARM_NEON_IMPLEMENTATION to the correct value (2 or 1). This macro
+ is undefined by default and the build type is selected in pngpriv.h.
+
+Version 1.6.7rc01 [November 2, 2013]
+ No changes.
+
+Version 1.6.7rc02 [November 7, 2013]
+ Fixed #include in filter_neon_intrinsics.c and ctype macros. The ctype char
+ checking macros take an unsigned char argument, not a signed char.
+
+Version 1.6.7 [November 14, 2013]
+ No changes.
+
+Version 1.6.8beta01 [November 24, 2013]
+ Moved prototype for png_handle_unknown() in pngpriv.h outside of
+ the #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED/#endif block.
+ Added "-Wall" to CFLAGS in contrib/pngminim/*/makefile
+ Conditionally compile some unused functions reported by -Wall in
+ pngminim.
+ Fixed 'minimal' builds. Various obviously useful minimal configurations
+ don't build because of missing contrib/libtests test programs and
+ overly complex dependencies in scripts/pnglibconf.dfa. This change
+ adds contrib/conftest/*.dfa files that can be used in automatic build
+ scripts to ensure that these configurations continue to build.
+ Enabled WRITE_INVERT and WRITE_PACK in contrib/pngminim/encoder.
+ Fixed pngvalid 'fail' function declaration on the Intel C Compiler.
+ This reverts to the previous 'static' implementation and works round
+ the 'unused static function' warning by using PNG_UNUSED().
+
+Version 1.6.8beta02 [November 30, 2013]
+ Removed or marked PNG_UNUSED some harmless "dead assignments" reported
+ by clang scan-build.
+ Changed tabs to 3 spaces in png_debug macros and changed '"%s"m'
+ to '"%s" m' to improve portability among compilers.
+ Changed png_free_default() to free() in pngtest.c
+
+Version 1.6.8rc01 [December 12, 2013]
+ Tidied up pngfix inits and fixed pngtest no-write builds.
+
+Version 1.6.8rc02 [December 14, 2013]
+ Handle zero-length PLTE chunk or NULL palette with png_error()
+ instead of png_chunk_report(), which by default issues a warning
+ rather than an error, leading to later reading from a NULL pointer
+ (png_ptr->palette) in png_do_expand_palette(). This is CVE-2013-6954
+ and VU#650142. Libpng-1.6.1 through 1.6.7 are vulnerable.
+ Libpng-1.6.0 and earlier do not have this bug.
+
+Version 1.6.8 [December 19, 2013]
+ No changes.
+
+Version 1.6.9beta01 [December 26, 2013]
+ Bookkeeping: Moved functions around (no changes). Moved transform
+ function definitions before the place where they are called so that
+ they can be made static. Move the intrapixel functions and the
+ grayscale palette builder out of the png?tran.c files. The latter
+ isn't a transform function and is no longer used internally, and the
+ former MNG specific functions are better placed in pngread/pngwrite.c
+ Made transform implementation functions static. This makes the internal
+ functions called by png_do_{read|write}_transformations static. On an
+ x86-64 DLL build (Gentoo Linux) this reduces the size of the text
+ segment of the DLL by 1208 bytes, about 0.6%. It also simplifies
+ maintenance by removing the declarations from pngpriv.h and allowing
+ easier changes to the internal interfaces.
+ Rebuilt configure scripts with automake-1.14.1 and autoconf-2.69
+ in the tar distributions.
+
+Version 1.6.9beta02 [January 1, 2014]
+ Added checks for libpng 1.5 to pngvalid.c. This supports the use of
+ this version of pngvalid in libpng 1.5
+ Merged with pngvalid.c from libpng-1.7 changes to create a single
+ pngvalid.c
+ Removed #error macro from contrib/tools/pngfix.c (Thomas Klausner).
+ Merged pngrio.c, pngtrans.c, pngwio.c, and pngerror.c with libpng-1.7.0
+ Merged libpng-1.7.0 changes to make no-interlace configurations work
+ with test programs.
+ Revised pngvalid.c to support libpng 1.5, which does not support the
+ PNG_MAXIMUM_INFLATE_WINDOW option, so #define it out when appropriate in
+ pngvalid.c
+ Allow unversioned links created on install to be disabled in configure.
+ In configure builds 'make install' changes/adds links like png.h
+ and libpng.a to point to the newly installed, versioned, files (e.g.
+ libpng17/png.h and libpng17.a). Three new configure options and some
+ rearrangement of Makefile.am allow creation of these links to be disabled.
+
+Version 1.6.9beta03 [January 10, 2014]
+ Removed potentially misleading warning from png_check_IHDR().
+
+Version 1.6.9beta04 [January 20, 2014]
+ Updated scripts/makefile.* to use CPPFLAGS (Cosmin).
+ Added clang attribute support (Cosmin).
+
+Version 1.6.9rc01 [January 28, 2014]
+ No changes.
+
+Version 1.6.9rc02 [January 30, 2014]
+ Quiet an uninitialized memory warning from VC2013 in png_get_png().
+
+Version 1.6.9 [February 6, 2014]
+
+Version 1.6.10beta01 [February 9, 2014]
+ Backported changes from libpng-1.7.0beta30 and beta31:
+ Fixed a large number of instances where PNGCBAPI was omitted from
+ function definitions.
+ Added pngimage test program for png_read_png() and png_write_png()
+ with two new test scripts.
+ Removed dependence on !PNG_READ_EXPAND_SUPPORTED for calling
+ png_set_packing() in png_read_png().
+ Fixed combination of ~alpha with shift. On read invert alpha, processing
+ occurred after shift processing, which causes the final values to be
+ outside the range that should be produced by the shift. Reversing the
+ order on read makes the two transforms work together correctly and mirrors
+ the order used on write.
+ Do not read invalid sBIT chunks. Previously libpng only checked sBIT
+ values on write, so a malicious PNG writer could therefore cause
+ the read code to return an invalid sBIT chunk, which might lead to
+ application errors or crashes. Such chunks are now skipped (with
+ chunk_benign_error).
+ Make png_read_png() and png_write_png() prototypes in png.h depend
+ upon PNG_READ_SUPPORTED and PNG_WRITE_SUPPORTED.
+ Support builds with unsupported PNG_TRANSFORM_* values. All of the
+ PNG_TRANSFORM_* values are always defined in png.h and, because they
+ are used for both read and write in some cases, it is not reliable
+ to #if out ones that are totally unsupported. This change adds error
+ detection in png_read_image() and png_write_image() to do a
+ png_app_error() if the app requests something that cannot be done
+ and it adds corresponding code to pngimage.c to handle such options
+ by not attempting to test them.
+
+Version 1.6.10beta02 [February 23, 2014]
+ Moved redefines of png_error(), png_warning(), png_chunk_error(),
+ and png_chunk_warning() from pngpriv.h to png.h to make them visible
+ to libpng-calling applications.
+ Moved OS dependent code from arm/arm_init.c, to allow the included
+ implementation of the ARM NEON discovery function to be set at
+ build-time and provide sample implementations from the current code in the
+ contrib/arm-neon subdirectory. The __linux__ code has also been changed to
+ compile and link on Android by using /proc/cpuinfo, and the old linux code
+ is in contrib/arm-neon/linux-auxv.c. The new code avoids POSIX and Linux
+ dependencies apart from opening /proc/cpuinfo and is C90 compliant.
+ Check for info_ptr == NULL early in png_read_end() so we don't need to
+ run all the png_handle_*() and depend on them to return if info_ptr == NULL.
+ This improves the performance of png_read_end(png_ptr, NULL) and makes
+ it more robust against future programming errors.
+ Check for __has_extension before using it in pngconf.h, to
+ support older Clang versions (Jeremy Sequoia).
+ Treat CRC error handling with png_set_crc_action(), instead of with
+ png_set_benign_errors(), which has been the case since libpng-1.6.0beta18.
+ Use a user warning handler in contrib/gregbook/readpng2.c instead of default,
+ so warnings will be put on stderr even if libpng has CONSOLE_IO disabled.
+ Added png_ptr->process_mode = PNG_READ_IDAT_MODE in png_push_read_chunk
+ after recognizing the IDAT chunk, which avoids an infinite loop while
+ reading a datastream whose first IDAT chunk is of zero-length.
+ This fixes CERT VU#684412 and CVE-2014-0333.
+ Don't recognize known sRGB profiles as sRGB if they have been hacked,
+ but don't reject them and don't issue a copyright violation warning.
+
+Version 1.6.10beta03 [February 25, 2014]
+ Moved some documentation from png.h to libpng.3 and libpng-manual.txt
+ Minor editing of contrib/arm-neon/README and contrib/examples/*.c
+
+Version 1.6.10rc01 [February 27, 2014]
+ Fixed typos in the manual and in scripts/pnglibconf.dfa (CFLAGS -> CPPFLAGS
+ and PNG_USR_CONFIG -> PNG_USER_CONFIG).
+
+Version 1.6.10rc02 [February 28, 2014]
+ Removed unreachable return statement after png_chunk_error()
+ in pngrutil.c
+
+Version 1.6.10rc03 [March 4, 2014]
+ Un-deprecated png_data_freer().
+
+Version 1.6.10 [March 6, 2014]
+ No changes.
+
+Version 1.6.11beta01 [March 17, 2014]
+ Use "if (value != 0)" instead of "if (value)" consistently.
+ Changed ZlibSrcDir from 1.2.5 to 1.2.8 in projects/vstudio.
+ Moved configuration information from the manual to the INSTALL file.
+
+Version 1.6.11beta02 [April 6, 2014]
+ Removed #if/#else/#endif from inside two pow() calls in pngvalid.c because
+ they were handled improperly by Portland Group's PGI-14.1 - PGI-14.3
+ when using its "__builtin_pow()" function.
+ Silence 'unused parameter' build warnings (Cosmin Truta).
+ $(CP) is now used alongside $(RM_F). Also, use 'copy' instead of 'cp'
+ where applicable, and applied other minor makefile changes (Cosmin).
+ Don't warn about invalid dimensions exceeding user limits (Cosmin).
+ Allow an easy replacement of the default pre-built configuration
+ header with a custom header, via the make PNGLIBCONF_H_PREBUILT
+ macro (Cosmin).
+
+Version 1.6.11beta03 [April 6, 2014]
+ Fixed a typo in pngrutil.c, introduced in libpng-1.5.6, that interferes
+ with "blocky" expansion of sub-8-bit interlaced PNG files (Eric Huss).
+ Optionally use __builtin_bswap16() in png_do_swap().
+
+Version 1.6.11beta04 [April 19, 2014]
+ Made progressive reading of interlaced images consistent with the
+ behavior of the sequential reader and consistent with the manual, by
+ moving some code out of the PNG_READ_INTERLACING_SUPPORTED blocks. The
+ row_callback now receives the proper pass number and unexpanded rows, when
+ png_combine_row() isn't built or used, and png_set_interlace_handling()
+ is not called.
+ Allow PNG_sRGB_PROFILE_CHECKING = (-1) to mean no sRGB profile checking.
+
+Version 1.6.11beta05 [April 26, 2014]
+ Do not reject ICC V2 profiles that lack padding (Kai-Uwe Behrmann).
+ Relocated closing bracket of the sRGB profile test loop to avoid getting
+ "Not recognizing known sRGB profile that has been edited" warning for
+ ICC V2 profiles that lack the MD5 signature in the profile header.
+
+Version 1.6.11beta06 [May 19, 2014]
+ Added PNG_SKIP_sRGB_CHECK_PROFILE choice for png_set_option().
+
+Version 1.6.11rc01 [May 27, 2014]
+ No changes.
+
+Version 1.6.11rc02 [June 3, 2014]
+ Test ZLIB_VERNUM instead of PNG_ZLIB_VERNUM in contrib/tools/pngfix.c
+
+Version 1.6.11 [June 5, 2014]
+ No changes.
+
+Version 1.6.12rc01 [June 6, 2014]
+ Relocated new code from 1.6.11beta06 in png.c to a point after the
+ declarations (Max Stepin).
+
+Version 1.6.12rc02 [June 7, 2014]
+ Changed file permissions of contrib/tools/intgamma.sh,
+ test-driver, and compile from 0644 to 0755 (Cosmin).
+
+Version 1.6.12rc03 [June 8, 2014]
+ Ensure "__has_attribute()" macro exists before trying to use it with
+ old clang compilers (MacPorts Ticket #43939).
+
+Version 1.6.12 [June 12, 2014]
+ No changes.
+
+Version 1.6.13beta01 [July 4, 2014]
+ Quieted -Wsign-compare and -Wclobber compiler warnings in
+ contrib/pngminus/*.c
+ Added "(void) png_ptr;" where needed in contrib/gregbook to quiet
+ compiler complaints about unused pointers.
+ Split a long output string in contrib/gregbook/rpng2-x.c.
+ Added "PNG_SET_OPTION" requirement for sRGB chunk support to pnglibconf.dfa,
+ Needed for write-only support (John Bowler).
+ Changed "if defined(__ARM_NEON__)" to
+ "if (defined(__ARM_NEON__) || defined(__ARM_NEON))" (James Wu).
+ Fixed clang no-warning builds: png_digit was defined but never used.
+
+Version 1.6.13beta02 [July 21, 2014]
+ Fixed an incorrect separator ("/" should be "\") in scripts/makefile.vcwin32
+ (bug report from Wolfgang S. Kechel). Bug was introduced in libpng-1.6.11.
+ Also fixed makefile.bc32, makefile.bor, makefile.msc, makefile.intel, and
+ makefile.tc3 similarly.
+
+Version 1.6.13beta03 [August 3, 2014]
+ Removed scripts/makefile.elf. It has not worked since libpng-1.5.0beta14
+ due to elimination of the PNG_FUNCTION_EXPORT and PNG_DATA_EXPORT
+ definitions from pngconf.h.
+ Ensure that CMakeLists.txt makes the target "lib" directory before making
+ symbolic link into it (SourceForge bug report #226 by Rolf Timmermans).
+
+Version 1.6.13beta04 [August 8, 2014]
+ Added opinion that the ECCN (Export Control Classification Number) for
+ libpng is EAR99 to the README file.
+ Eliminated use of "$<" in makefile explicit rules, when copying
+ $PNGLIBCONF_H_PREBUILT. This does not work on some versions of make;
+ bug introduced in libpng version 1.6.11.
+
+Version 1.6.13rc01 [August 14, 2014]
+ Made "ccopts" agree with "CFLAGS" in scripts/makefile.hp* and makefile.*sunu
+
+Version 1.6.13 [August 21, 2014]
+ No changes.
+
+Version 1.6.14beta01 [September 14, 2014]
+ Guard usage of png_ptr->options with #ifdef PNG_SET_OPTION_SUPPORTED.
+ Do not build contrib/tools/pngfix.c when PNG_SETJMP_NOT_SUPPORTED,
+ to allow "make" to complete without setjmp support (bug report by
+ Claudio Fontana)
+ Add "#include <setjmp.h>" to contrib/tools/pngfix.c (John Bowler)
+
+Version 1.6.14beta02 [September 18, 2014]
+ Use nanosleep() instead of usleep() in contrib/gregbook/rpng2-x.c
+ because usleep() is deprecated.
+ Define usleep() in contrib/gregbook/rpng2-x.c if not already defined
+ in unistd.h and nanosleep() is not available; fixes error introduced
+ in libpng-1.6.13.
+ Disable floating point exception handling in pngvalid.c when
+ PNG_FLOATING_ARITHMETIC is not supported (bug report by "zootus
+ at users.sourceforge.net").
+
+Version 1.6.14beta03 [September 19, 2014]
+ Define FE_DIVBYZERO, FE_INVALID, and FE_OVERFLOW in pngvalid.c if not
+ already defined. Revert floating point exception handling in pngvalid.c
+ to version 1.6.14beta01 behavior.
+
+Version 1.6.14beta04 [September 27, 2014]
+ Fixed incorrect handling of the iTXt compression flag in pngrutil.c
+ (bug report by Shunsaku Hirata). Bug was introduced in libpng-1.6.0.
+
+Version 1.6.14beta05 [October 1, 2014]
+ Added "option READ_iCCP enables READ_COMPRESSED_TEXT" to pnglibconf.dfa
+
+Version 1.6.14beta06 [October 5, 2014]
+ Removed unused "text_len" parameter from private function png_write_zTXt().
+ Conditionally compile some code in png_deflate_claim(), when
+ PNG_WARNINGS_SUPPORTED and PNG_ERROR_TEXT_SUPPORTED are disabled.
+ Replaced repeated code in pngpread.c with PNG_PUSH_SAVE_BUFFER_IF_FULL.
+ Added "chunk iTXt enables TEXT" and "chunk zTXt enables TEXT"
+ to pnglibconf.dfa.
+ Removed "option READ_COMPRESSED_TEXT enables READ_TEXT" from pnglibconf.dfa,
+ to make it possible to configure a libpng that supports iCCP but not TEXT.
+
+Version 1.6.14beta07 [October 7, 2014]
+ Removed "option WRITE_COMPRESSED_TEXT enables WRITE_TEXT" from pnglibconf.dfa
+ Only mark text chunks as written after successfully writing them.
+
+Version 1.6.14rc01 [October 15, 2014]
+ Fixed some typos in comments.
+
+Version 1.6.14rc02 [October 17, 2014]
+ Changed png_convert_to_rfc_1123() to png_convert_to_rfc_1123_buffer()
+ in the manual, to reflect the change made in libpng-1.6.0.
+ Updated README file to explain that direct access to the png_struct
+ and info_struct members has not been permitted since libpng-1.5.0.
+
+Version 1.6.14 [October 23, 2014]
+ No changes.
+
+Version 1.6.15beta01 [October 29, 2014]
+ Changed "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)"
+ Simplified png_free_data().
+ Added missing "ptr = NULL" after some instances of png_free().
+
+Version 1.6.15beta02 [November 1, 2014]
+ Changed remaining "if (!x)" to "if (x == 0)" and "if (x)" to "if (x != 0)"
+
+Version 1.6.15beta03 [November 3, 2014]
+ Added PNG_USE_ARM_NEON configuration flag (Marcin Juszkiewicz).
+
+Version 1.6.15beta04 [November 4, 2014]
+ Removed new PNG_USE_ARM_NEON configuration flag and made a one-line
+ revision to configure.ac to support ARM on aarch64 instead (John Bowler).
+
+Version 1.6.15beta05 [November 5, 2014]
+ Use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING in
+ example.c, pngtest.c, and applications in the contrib directory.
+ Avoid out-of-bounds memory access in png_user_version_check().
+ Simplified and future-proofed png_user_version_check().
+ Fixed GCC unsigned int->float warnings. Various versions of GCC
+ seem to generate warnings when an unsigned value is implicitly
+ converted to double. This is probably a GCC bug but this change
+ avoids the issue by explicitly converting to (int) where safe.
+ Free all allocated memory in pngimage. The file buffer cache was left
+ allocated at the end of the program, harmless but it causes memory
+ leak reports from clang.
+ Fixed array size calculations to avoid warnings. At various points
+ in the code the number of elements in an array is calculated using
+ sizeof. This generates a compile time constant of type (size_t) which
+ is then typically assigned to an (unsigned int) or (int). Some versions
+ of GCC on 64-bit systems warn about the apparent narrowing, even though
+ the same compiler does apparently generate the correct, in-range,
+ numeric constant. This adds appropriate, safe, casts to make the
+ warnings go away.
+
+Version 1.6.15beta06 [November 6, 2014]
+ Reverted use png_get_libpng_ver(NULL) instead of PNG_LIBPNG_VER_STRING
+ in the manual, example.c, pngtest.c, and applications in the contrib
+ directory. It was incorrect advice.
+
+Version 1.6.15beta07 [November 7, 2014]
+ Removed #ifdef PNG_16BIT_SUPPORTED/#endif around png_product2(); it is
+ needed by png_reciprocal2().
+ Added #ifdef PNG_16BIT_SUPPORTED/#endif around png_log16bit() and
+ png_do_swap().
+ Changed all "#endif /* PNG_FEATURE_SUPPORTED */" to "#endif /* FEATURE */"
+
+Version 1.6.15beta08 [November 8, 2014]
+ More housecleaning in *.h
+
+Version 1.6.15rc01 [November 13, 2014]
+
+Version 1.6.15rc02 [November 14, 2014]
+ The macros passed in the command line to Borland make were ignored if
+ similarly-named macros were already defined in makefiles. This behavior
+ is different from POSIX make and other make programs. Surround the
+ macro definitions with ifndef guards (Cosmin).
+
+Version 1.6.15rc03 [November 16, 2014]
+ Added "-D_CRT_SECURE_NO_WARNINGS" to CFLAGS in scripts/makefile.vcwin32.
+ Removed the obsolete $ARCH variable from scripts/makefile.darwin.
+
+Version 1.6.15 [November 20, 2014]
+ No changes.
+
+Version 1.6.16beta01 [December 14, 2014]
+ Added ".align 2" to arm/filter_neon.S to support old GAS assemblers that
+ don't do alignment correctly.
+ Revised Makefile.am and scripts/symbols.dfn to work with MinGW/MSYS
+ (Bob Friesenhahn).
+
+Version 1.6.16beta02 [December 15, 2014]
+ Revised Makefile.am and scripts/*.dfn again to work with MinGW/MSYS;
+ renamed scripts/*.dfn to scripts/*.c (John Bowler).
+
+Version 1.6.16beta03 [December 21, 2014]
+ Quiet a "comparison always true" warning in pngstest.c (John Bowler).
+
+Version 1.6.16rc01 [December 21, 2014]
+ Restored a test on width that was removed from png.c at libpng-1.6.9
+ (Bug report by Alex Eubanks, CVE-2015-0973).
+
+Version 1.6.16rc02 [December 21, 2014]
+ Undid the update to pngrutil.c in 1.6.16rc01.
+
+Version 1.6.16rc03 [December 21, 2014]
+ Fixed an overflow in png_combine_row() with very wide interlaced images
+ (Bug report and fix by John Bowler, CVE-2014-9495).
+
+Version 1.6.16 [December 22, 2014]
+ No changes.
+
+Version 1.6.17beta01 [January 29, 2015]
+ Removed duplicate PNG_SAFE_LIMITS_SUPPORTED handling from pngconf.h
+ Corrected the width limit calculation in png_check_IHDR().
+ Removed user limits from pngfix. Also pass NULL pointers to
+ png_read_row to skip the unnecessary row de-interlace stuff.
+ Added testing of png_set_packing() to pngvalid.c
+ Regenerated configure scripts in the *.tar distributions with libtool-2.4.4
+ Implement previously untested cases of libpng transforms in pngvalid.c
+ Fixed byte order in 2-byte filler, in png_do_read_filler().
+ Made the check for out-of-range values in png_set_tRNS() detect
+ values that are exactly 2^bit_depth, and work on 16-bit platforms.
+ Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47.
+ Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and
+ pngset.c to avoid warnings about dead code.
+ Added "& 0xff" to many instances of expressions that are typecast
+ to (png_byte), to avoid Coverity gripes.
+
+Version 1.6.17beta02 [February 7, 2015]
+ Work around one more Coverity-scan dead-code warning.
+ Do not build png_product2() when it is unused.
+
+Version 1.6.17beta03 [February 17, 2015]
+ Display user limits in the output from pngtest.
+ Eliminated the PNG_SAFE_LIMITS macro and restored the 1-million-column
+ and 1-million-row default limits in pnglibconf.dfa, that can be reset
+ by the user at build time or run time. This provides a more robust
+ defense against DOS and as-yet undiscovered overflows.
+
+Version 1.6.17beta04 [February 21, 2015]
+ Added PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED macro, on by default.
+ Allow user to call png_get_IHDR() with NULL arguments (Reuben Hawkins).
+ Rebuilt configure scripts with automake-1.15 and libtool-2.4.6
+
+Version 1.6.17beta05 [February 25, 2015]
+ Restored compiling of png_reciprocal2 with PNG_NO_16BIT.
+
+Version 1.6.17beta06 [February 27, 2015]
+ Moved png_set_filter() prototype into a PNG_WRITE_SUPPORTED block
+ of png.h.
+ Avoid runtime checks when converting integer to png_byte with
+ Visual Studio (Sergey Kosarevsky)
+
+Version 1.6.17rc01 [March 4, 2015]
+ No changes.
+
+Version 1.6.17rc02 [March 9, 2015]
+ Removed some comments that the configure script did not handle
+ properly from scripts/pnglibconf.dfa and pnglibconf.h.prebuilt.
+ Free the unknown_chunks structure even when it contains no data.
+
+Version 1.6.17rc03 [March 12, 2015]
+ Updated CMakeLists.txt to add OSX framework, change YES/NO to ON/OFF
+ for consistency, and remove some useless tests (Alexey Petruchik).
+
+Version 1.6.17rc04 [March 16, 2015]
+ Remove pnglibconf.h, pnglibconf.c, and pnglibconf.out instead of
+ pnglibconf.* in "make clean" (Cosmin).
+ Fix bug in calculation of maxbits, in png_write_sBIT, introduced
+ in libpng-1.6.17beta01 (John Bowler).
+
+Version 1.6.17rc05 [March 21, 2015]
+ Define PNG_FILTER_* and PNG_FILTER_VALUE_* in png.h even when WRITE
+ is not supported (John Bowler). This fixes an error introduced in
+ libpng-1.6.17beta06.
+ Reverted "& 0xff" additions of version 1.6.17beta01. Libpng passes
+ the Coverity scan without them.
+
+Version 1.6.17rc06 [March 23, 2015]
+ Remove pnglibconf.dfn and pnglibconf.pre with "make clean".
+ Reformatted some "&0xff" instances to "& 0xff".
+ Fixed simplified 8-bit-linear to sRGB alpha. The calculated alpha
+ value was wrong. It's not clear if this affected the final stored
+ value; in the obvious code path the upper and lower 8-bits of the
+ alpha value were identical and the alpha was truncated to 8-bits
+ rather than dividing by 257 (John Bowler).
+
+Version 1.6.17 [March 26, 2015]
+ No changes.
Send comments/corrections/commendations to png-mng-implement at lists.sf.net
(subscription required; visit
@@ -3861,4 +5212,3 @@ to subscribe)
or to glennrp at users.sourceforge.net
Glenn R-P
-#endif
diff --git a/src/3rdparty/libpng/INSTALL b/src/3rdparty/libpng/INSTALL
index e6979c6fb0..a294ffe633 100644
--- a/src/3rdparty/libpng/INSTALL
+++ b/src/3rdparty/libpng/INSTALL
@@ -1,32 +1,69 @@
Installing libpng
+Contents
+
+ I. Simple installation
+ II. Rebuilding the configure scripts
+ III. Using scripts/makefile*
+ IV. Using cmake
+ V. Directory structure
+ VI. Building with project files
+ VII. Building with makefiles
+VIII. Configuring libpng for 16-bit platforms
+ IX. Configuring for DOS
+ X. Configuring for Medium Model
+ XI. Prepending a prefix to exported symbols
+ XII. Configuring for compiler xxx:
+XIII. Removing unwanted object code
+ XIV. Changes to the build and configuration of libpng in libpng-1.5.x
+ XV. Setjmp/longjmp issues
+ XVI. Other sources of information about libpng
+
+I. Simple installation
+
On Unix/Linux and similar systems, you can simply type
./configure [--prefix=/path]
make check
make install
-and ignore the rest of this document.
+and ignore the rest of this document. "/path" is the path to the directory
+where you want to install the libpng "lib", "include", and "bin"
+subdirectories.
+
+If you downloaded a GIT clone, you will need to run ./autogen.sh before
+running ./configure, to create "configure" and "Makefile.in" which are
+not included in the GIT repository.
+
+Note that "configure" is only included in the "*.tar" distributions and not
+in the "*.zip" or "*.7z" distributions. If you downloaded one of those
+distributions, see "Building with project files" or "Building with makefiles",
+below.
-If configure does not work on your system and you have a reasonably
-up-to-date set of tools, running ./autogen.sh before running ./configure
-may fix the problem. You can also run the individual commands in
-autogen.sh with the --force option, if supported by your version of
-the tools. To be really sure that you aren't using any of the included
-pre-built scripts, you can do this:
+II. Rebuilding the configure scripts
+
+If configure does not work on your system, or if you have a need to
+change configure.ac or Makefile.am, and you have a reasonably
+up-to-date set of tools, running ./autogen.sh in a git clone before
+running ./configure may fix the problem. To be really sure that you
+aren't using any of the included pre-built scripts, you can do this:
./configure --enable-maintainer-mode
make maintainer-clean
- ./autogen.sh
+ ./autogen.sh --maintainer --clean
+ ./autogen.sh --maintainer
./configure [--prefix=/path] [other options]
make
make install
make check
+III. Using scripts/makefile*
+
Instead, you can use one of the custom-built makefiles in the
"scripts" directory
+ cp scripts/pnglibconf.h.prebuilt pnglibconf.h
cp scripts/makefile.system makefile
make test
make install
@@ -38,8 +75,28 @@ Or you can use one of the "projects" in the "projects" directory.
Before installing libpng, you must first install zlib, if it
is not already on your system. zlib can usually be found
-wherever you got libpng. zlib can be placed in another directory,
-at the same level as libpng.
+wherever you got libpng; otherwise go to http://zlib.net. You can place
+zlib in in the same directory as libpng or in another directory.
+
+If your system already has a preinstalled zlib you will still need
+to have access to the zlib.h and zconf.h include files that
+correspond to the version of zlib that's installed.
+
+If you wish to test with a particular zlib that is not first in the
+standard library search path, put ZLIBLIB, ZLIBINC, CPPFLAGS, LDFLAGS,
+and LD_LIBRARY_PATH in your environment before running "make test"
+or "make distcheck":
+
+ZLIBLIB=/path/to/lib export ZLIBLIB
+ZLIBINC=/path/to/include export ZLIBINC
+CPPFLAGS="-I$ZLIBINC" export CPPFLAGS
+LDFLAGS="-L$ZLIBLIB" export LDFLAGS
+LD_LIBRARY_PATH="$ZLIBLIB:$LD_LIBRARY_PATH" export LD_LIBRARY_PATH
+
+If you are using one of the makefile scripts, put ZLIBLIB and ZLIBINC
+in your environment and type "make ZLIBLIB=$ZLIBLIB ZLIBINC=$ZLIBINC test".
+
+IV. Using cmake
If you want to use "cmake" (see www.cmake.org), type
@@ -47,13 +104,15 @@ If you want to use "cmake" (see www.cmake.org), type
make
make install
-If your system already has a preinstalled zlib you will still need
-to have access to the zlib.h and zconf.h include files that
-correspond to the version of zlib that's installed.
+As when using the simple configure method described above, "/path" points to
+the installation directory where you want to put the libpng "lib", "include",
+and "bin" subdirectories.
+
+V. Directory structure
You can rename the directories that you downloaded (they
-might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.5"
-or "zlib125") so that you have directories called "zlib" and "libpng".
+might be called "libpng-x.y.z" or "libpngNN" and "zlib-1.2.8"
+or "zlib128") so that you have directories called "zlib" and "libpng".
Your directory structure should look like this:
@@ -61,8 +120,7 @@ Your directory structure should look like this:
libpng (this directory)
INSTALL (this file)
README
- *.h
- *.c
+ *.h, *.c => libpng source files
CMakeLists.txt => "cmake" script
configuration files:
configure.ac, configure, Makefile.am, Makefile.in,
@@ -70,14 +128,10 @@ Your directory structure should look like this:
libpng-config.in, aclocal.m4, config.h.in, config.sub,
depcomp, install-sh, mkinstalldirs, test-pngtest.sh
contrib
- gregbook
- pngminim
- pngminus
- pngsuite
- visupng
+ arm-neon, conftest, examples, gregbook, libtests, pngminim,
+ pngminus, pngsuite, tools, visupng
projects
- visualc71
- vstudio
+ cbuilder5, owatcom, visualc71, vstudio, xcode
scripts
makefile.*
*.def (module definition files)
@@ -85,29 +139,31 @@ Your directory structure should look like this:
pngtest.png
etc.
zlib
- README
- *.h
- *.c
- contrib
- etc.
+ README, *.h, *.c contrib, etc.
If the line endings in the files look funny, you may wish to get the other
distribution of libpng. It is available in both tar.gz (UNIX style line
endings) and zip (DOS style line endings) formats.
+VI. Building with project files
+
If you are building libpng with MSVC, you can enter the
-libpng projects\visualc6 or visualc71 directory and follow the instructions
+libpng projects\visualc71 or vstudio directory and follow the instructions
in README.txt.
Otherwise enter the zlib directory and follow the instructions in zlib/README,
then come back here and run "configure" or choose the appropriate
makefile.sys in the scripts directory.
+VII. Building with makefiles
+
Copy the file (or files) that you need from the
scripts directory into this directory, for example
MSDOS example: copy scripts\makefile.msc makefile
- UNIX example: cp scripts/makefile.std makefile
+ copy scripts\pnglibconf.h.prebuilt pnglibconf.h
+ UNIX example: cp scripts/makefile.std makefile
+ cp scripts/pnglibconf.h.prebuilt pnglibconf.h
Read the makefile to see if you need to change any source or
target directories to match your preferences.
@@ -130,6 +186,202 @@ do that, run "make install" in the zlib directory first if necessary).
Some also allow you to run "make test-installed" after you have
run "make install".
+VIII. Configuring libpng for 16-bit platforms
+
+You will want to look into zconf.h to tell zlib (and thus libpng) that
+it cannot allocate more than 64K at a time. Even if you can, the memory
+won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
+
+IX. Configuring for DOS
+
+For DOS users who only have access to the lower 640K, you will
+have to limit zlib's memory usage via a png_set_compression_mem_level()
+call. See zlib.h or zconf.h in the zlib library for more information.
+
+X. Configuring for Medium Model
+
+Libpng's support for medium model has been tested on most of the popular
+compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
+defined, and FAR gets defined to far in pngconf.h, and you should be
+all set. Everything in the library (except for zlib's structure) is
+expecting far data. You must use the typedefs with the p or pp on
+the end for pointers (or at least look at them and be careful). Make
+note that the rows of data are defined as png_bytepp, which is
+an "unsigned char far * far *".
+
+XI. Prepending a prefix to exported symbols
+
+Starting with libpng-1.6.0, you can configure libpng (when using the
+"configure" script) to prefix all exported symbols by means of the
+configuration option "--with-libpng-prefix=FOO_", where FOO_ can be any
+string beginning with a letter and containing only uppercase
+and lowercase letters, digits, and the underscore (i.e., a C language
+identifier). This creates a set of macros in pnglibconf.h, so this is
+transparent to applications; their function calls get transformed by
+the macros to use the modified names.
+
+XII. Configuring for compiler xxx:
+
+All includes for libpng are in pngconf.h. If you need to add, change
+or delete an include, this is the place to do it.
+The includes that are not needed outside libpng are placed in pngpriv.h,
+which is only used by the routines inside libpng itself.
+The files in libpng proper only include pngpriv.h and png.h, which
+in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h.
+As of libpng-1.5.0, pngpriv.h also includes three other private header
+files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
+that previously appeared in the public headers.
+
+XIII. Removing unwanted object code
+
+There are a bunch of #define's in pngconf.h that control what parts of
+libpng are compiled. All the defines end in _SUPPORTED. If you are
+never going to use a capability, you can change the #define to #undef
+before recompiling libpng and save yourself code and data space, or
+you can turn off individual capabilities with defines that begin with
+PNG_NO_.
+
+In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead.
+
+You can also turn all of the transforms and ancillary chunk capabilities
+off en masse with compiler directives that define
+PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
+or all four, along with directives to turn on any of the capabilities that
+you do want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the
+extra transformations but still leave the library fully capable of reading
+and writing PNG files with all known public chunks. Use of the
+PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
+that is incapable of reading or writing ancillary chunks. If you are
+not using the progressive reading capability, you can turn that off
+with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
+capability, which you'll still have).
+
+All the reading and writing specific code are in separate files, so the
+linker should only grab the files it needs. However, if you want to
+make sure, or if you are building a stand alone library, all the
+reading files start with "pngr" and all the writing files start with "pngw".
+The files that don't match either (like png.c, pngtrans.c, etc.)
+are used for both reading and writing, and always need to be included.
+The progressive reader is in pngpread.c
+
+If you are creating or distributing a dynamically linked library (a .so
+or DLL file), you should not remove or disable any parts of the library,
+as this will cause applications linked with different versions of the
+library to fail if they call functions not available in your library.
+The size of the library itself should not be an issue, because only
+those sections that are actually used will be loaded into memory.
+
+XIV. Changes to the build and configuration of libpng in libpng-1.5.x
+
+Details of internal changes to the library code can be found in the CHANGES
+file and in the GIT repository logs. These will be of no concern to the vast
+majority of library users or builders; however, the few who configure libpng
+to a non-default feature set may need to change how this is done.
+
+There should be no need for library builders to alter build scripts if
+these use the distributed build support - configure or the makefiles -
+however, users of the makefiles may care to update their build scripts
+to build pnglibconf.h where the corresponding makefile does not do so.
+
+Building libpng with a non-default configuration has changed completely.
+The old method using pngusr.h should still work correctly even though the
+way pngusr.h is used in the build has been changed; however, library
+builders will probably want to examine the changes to take advantage of
+new capabilities and to simplify their build system.
+
+A. Specific changes to library configuration capabilities
+
+The exact mechanism used to control attributes of API functions has
+changed. A single set of operating system independent macro definitions
+is used and operating system specific directives are defined in
+pnglibconf.h
+
+As part of this the mechanism used to choose procedure call standards on
+those systems that allow a choice has been changed. At present this only
+affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems
+running on Intel processors. As before, PNGAPI is defined where required
+to control the exported API functions; however, two new macros, PNGCBAPI
+and PNGCAPI, are used instead for callback functions (PNGCBAPI) and
+(PNGCAPI) for functions that must match a C library prototype (currently
+only png_longjmp_ptr, which must match the C longjmp function.) The new
+approach is documented in pngconf.h
+
+Despite these changes, libpng 1.5.0 only supports the native C function
+calling standard on those platforms tested so far (__cdecl on Microsoft
+Windows). This is because the support requirements for alternative
+calling conventions seem to no longer exist. Developers who find it
+necessary to set PNG_API_RULE to 1 should advise the mailing list
+(png-mng-implement) of this and library builders who use Openwatcom and
+therefore set PNG_API_RULE to 2 should also contact the mailing list.
+
+B. Changes to the configuration mechanism
+
+Prior to libpng-1.5.0 library builders who needed to configure libpng
+had either to modify the exported pngconf.h header file to add system
+specific configuration or had to write feature selection macros into
+pngusr.h and cause this to be included into pngconf.h by defining
+PNG_USER_CONFIG. The latter mechanism had the disadvantage that an
+application built without PNG_USER_CONFIG defined would see the
+unmodified, default, libpng API and thus would probably fail to link.
+
+These mechanisms still work in the configure build and in any makefile
+build that builds pnglibconf.h, although the feature selection macros
+have changed somewhat as described above. In 1.5.0, however, pngusr.h is
+processed only once, at the time the exported header file pnglibconf.h is
+built. pngconf.h no longer includes pngusr.h; therefore, pngusr.h is ignored
+after the build of pnglibconf.h and it is never included in an application
+build.
+
+The formerly used alternative of adding a list of feature macros to the
+CPPFLAGS setting in the build also still works; however, the macros will be
+copied to pnglibconf.h and this may produce macro redefinition warnings
+when the individual C files are compiled.
+
+All configuration now only works if pnglibconf.h is built from
+scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan
+(the original author of awk) maintains C source code of that awk and this
+and all known later implementations (often called by subtly different
+names - nawk and gawk for example) are adequate to build pnglibconf.h.
+The Sun Microsystems (now Oracle) program 'awk' is an earlier version
+and does not work; this may also apply to other systems that have a
+functioning awk called 'nawk'.
+
+Configuration options are now documented in scripts/pnglibconf.dfa. This
+file also includes dependency information that ensures a configuration is
+consistent; that is, if a feature is switched off, dependent features are
+also switched off. As a recommended alternative to using feature macros in
+pngusr.h a system builder may also define equivalent options in pngusr.dfa
+(or, indeed, any file) and add that to the configuration by setting
+DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate
+how to do this, and also illustrate a case where pngusr.h is still required.
+
+After you have built libpng, the definitions that were recorded in
+pnglibconf.h are available to your application (pnglibconf.h is included
+in png.h and gets installed alongside png.h and pngconf.h in your
+$PREFIX/include directory). Do not edit pnglibconf.h after you have built
+libpng, because than the settings would not accurately reflect the settings
+that were used to build libpng.
+
+XV. Setjmp/longjmp issues
+
+Libpng uses setjmp()/longjmp() for error handling. Unfortunately setjmp()
+is known to be not thread-safe on some platforms and we don't know of
+any platform where it is guaranteed to be thread-safe. Therefore, if
+your application is going to be using multiple threads, you should
+configure libpng with PNG_NO_SETJMP in your pngusr.dfa file, with
+-DPNG_NO_SETJMP on your compile line, or with
+
+ #undef PNG_SETJMP_SUPPORTED
+
+in your pnglibconf.h or pngusr.h.
+
+Starting with libpng-1.6.0, the library included a "simplified API".
+This requires setjmp/longjmp, so you must either build the library
+with PNG_SETJMP_SUPPORTED defined, or with PNG_SIMPLIFIED_READ_SUPPORTED
+and PNG_SIMPLIFIED_WRITE_SUPPORTED undefined.
+
+XVI. Other sources of information about libpng:
+
Further information can be found in the README and libpng-manual.txt
files, in the individual makefiles, in png.h, and the manual pages
libpng.3 and png.5.
@@ -147,7 +399,7 @@ CFLAGS="-Wall -O -funroll-loops \
--with-pkgconfigdir=/usr/lib/pkgconfig --includedir=/usr/include
You can alternatively specify --includedir=/usr/include, /usr/local/include,
-/usr/include/libpng%NN%, or whatever.
+/usr/include/libpng16, or whatever.
If you find that the configure script is out-of-date or is not supporting
your platform properly, try running autogen.sh to regenerate "configure",
diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE
index b72d1258e3..eb4a9a9da4 100644
--- a/src/3rdparty/libpng/LICENSE
+++ b/src/3rdparty/libpng/LICENSE
@@ -10,8 +10,8 @@ this sentence.
This code is released under the libpng license.
-libpng versions 1.2.6, August 15, 2004, through 1.5.10, March 29, 2012, are
-Copyright (c) 2004, 2006-2011 Glenn Randers-Pehrson, and are
+libpng versions 1.2.6, August 15, 2004, through 1.6.17, March 26, 2015, are
+Copyright (c) 2004, 2006-2015 Glenn Randers-Pehrson, and are
distributed according to the same disclaimer and license as libpng-1.2.5
with the following individual added to the list of Contributing Authors
@@ -108,4 +108,4 @@ certification mark of the Open Source Initiative.
Glenn Randers-Pehrson
glennrp at users.sourceforge.net
-March 29, 2012
+March 26, 2015
diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README
index e821ee4c87..a158ea8a77 100644
--- a/src/3rdparty/libpng/README
+++ b/src/3rdparty/libpng/README
@@ -1,11 +1,11 @@
-README for libpng version 1.5.10 - March 29, 2012 (shared library 15.0)
+README for libpng version 1.6.17 - March 26, 2015 (shared library 16.0)
See the note about version numbers near the top of png.h
See INSTALL for instructions on how to install libpng.
-Libpng comes in several distribution formats. Get libpng-*.tar.gz,
-libpng-*.tar.xz or libpng-*.tar.bz2 if you want UNIX-style line endings
-in the text files, or lpng*.zip if you want DOS-style line endings.
+Libpng comes in several distribution formats. Get libpng-*.tar.gz or
+libpng-*.tar.xz or if you want UNIX-style line endings in the text files,
+or lpng*.7z or lpng*.zip if you want DOS-style line endings.
Version 0.89 was the first official release of libpng. Don't let the
fact that it's the first release fool you. The libpng library has been in
@@ -23,18 +23,25 @@ earlier versions if you are using a shared library. The type of the
png_uint_32, which will affect shared-library applications that use
this function.
-To avoid problems with changes to the internals of png_info_struct,
+To avoid problems with changes to the internals of png info_struct,
new APIs have been made available in 0.95 to avoid direct application
access to info_ptr. These functions are the png_set_<chunk> and
png_get_<chunk> functions. These functions should be used when
accessing/storing the info_struct data, rather than manipulating it
directly, to avoid such problems in the future.
-It is important to note that the APIs do not make current programs
+It is important to note that the APIs did not make current programs
that access the info struct directly incompatible with the new
-library. However, it is strongly suggested that new programs use
-the new APIs (as shown in example.c and pngtest.c), and older programs
-be converted to the new format, to facilitate upgrades in the future.
+library, through libpng-1.2.x. In libpng-1.4.x, which was meant to
+be a transitional release, members of the png_struct and the
+info_struct can still be accessed, but the compiler will issue a
+warning about deprecated usage. Since libpng-1.5.0, direct access
+to these structs is not allowed, and the definitions of the structs
+reside in private pngstruct.h and pnginfo.h header files that are not
+accessible to applications. It is strongly suggested that new
+programs use the new APIs (as shown in example.c and pngtest.c), and
+older programs be converted to the new format, to facilitate upgrades
+in the future.
****
Additions since 0.90 include the ability to compile libpng as a
@@ -77,17 +84,21 @@ compression library that is useful for more things than just PNG files.
You can use zlib as a drop-in replacement for fread() and fwrite() if
you are so inclined.
-zlib should be available at the same place that libpng is, or at.
-ftp://ftp.info-zip.org/pub/infozip/zlib
+zlib should be available at the same place that libpng is, or at zlib.net.
You may also want a copy of the PNG specification. It is available
as an RFC, a W3C Recommendation, and an ISO/IEC Standard. You can find
these at http://www.libpng.org/pub/png/documents/
This code is currently being archived at libpng.sf.net in the
-[DOWNLOAD] area, and on CompuServe, Lib 20 (PNG SUPPORT)
-at GO GRAPHSUP. If you can't find it in any of those places,
-e-mail me, and I'll help you find it.
+[DOWNLOAD] area, and at ftp://ftp.simplesystems.org. If you can't find it
+in any of those places, e-mail me, and I'll help you find it.
+
+I am not a lawyer, but I believe that the Export Control Classification
+Number (ECCN) for libpng is EAR99, which means not subject to export
+controls or International Traffic in Arms Regulations (ITAR) because it
+is open source, publicly available software, that does not contain any
+encryption software. See the EAR, paragraphs 734.3(b)(3) and 734.7(b).
If you have any code changes, requests, problems, etc., please e-mail
them to me. Also, I'd appreciate any make files or project files,
@@ -105,7 +116,7 @@ based in a large way on Guy's and Andreas' earlier work), and the PNG
development group.
Send comments/corrections/commendations to png-mng-implement at
-lists.sourceforge.net (subscription required; visit
+lists.sourceforge.net (subscription required; visit
https://lists.sourceforge.net/lists/listinfo/png-mng-implement
to subscribe) or to glennrp at users.sourceforge.net
@@ -123,7 +134,7 @@ and ...". If in doubt, send questions to me. I'll bounce them
to others, if necessary.
Please do not send suggestions on how to change PNG. We have
-been discussing PNG for sixteen years now, and it is official and
+been discussing PNG for nineteen years now, and it is official and
finished. If you have suggestions for libpng, however, I'll
gladly listen. Even if your suggestion is not used immediately,
it may be used later.
@@ -167,23 +178,25 @@ Files in this distribution:
pngwrite.c => High-level write functions
pngwtran.c => Write data transformations
pngwutil.c => Write utility functions
+ arm => Contains optimized code for the ARM platform
contrib => Contributions
+ examples => Example programs
gregbook => source code for PNG reading and writing, from
Greg Roelofs' "PNG: The Definitive Guide",
O'Reilly, 1999
- msvctest => Builds and runs pngtest using a MSVC workspace
- pngminus => Simple pnm2png and png2pnm programs
- pngsuite => Test images
- visupng => Contains a MSVC workspace for VisualPng
+ libtests => Test programs
+ pngminim => Minimal decoder, encoder, and progressive decoder
+ programs demonstrating use of pngusr.dfa
+ pngminus => Simple pnm2png and png2pnm programs
+ pngsuite => Test images
+ tools => Various tools
+ visupng => Contains a MSVC workspace for VisualPng
projects => Contains project files and workspaces for
building a DLL
- cbuilder5 => Contains a Borland workspace for building
- libpng and zlib
- visualc6 => Contains a Microsoft Visual C++ (MSVC)
- workspace for building libpng and zlib
+ owatcom => Contains a WATCOM project for building libpng
visualc71 => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
- xcode => Contains an Apple xcode
+ vstudio => Contains a Microsoft Visual C++ (MSVC)
workspace for building libpng and zlib
scripts => Directory containing scripts for building libpng:
(see scripts/README.txt for the list of scripts)
diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt
index d55e80a009..f0dae987f9 100644
--- a/src/3rdparty/libpng/libpng-manual.txt
+++ b/src/3rdparty/libpng/libpng-manual.txt
@@ -1,9 +1,9 @@
libpng-manual.txt - A description on how to use and modify libpng
- libpng version 1.5.10 - March 29, 2012
+ libpng version 1.6.17 - March 26, 2015
Updated and distributed by Glenn Randers-Pehrson
<glennrp at users.sourceforge.net>
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ Copyright (c) 1998-2015 Glenn Randers-Pehrson
This document is released under the libpng license.
For conditions of distribution and use, see the disclaimer
@@ -11,15 +11,15 @@ libpng-manual.txt - A description on how to use and modify libpng
Based on:
- libpng versions 0.97, January 1998, through 1.5.10 - March 29, 2012
+ libpng versions 0.97, January 1998, through 1.6.17 - March 26, 2015
Updated and distributed by Glenn Randers-Pehrson
- Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ Copyright (c) 1998-2015 Glenn Randers-Pehrson
- libpng 1.0 beta 6 version 0.96 May 28, 1997
+ libpng 1.0 beta 6 - version 0.96 - May 28, 1997
Updated and distributed by Andreas Dilger
Copyright (c) 1996, 1997 Andreas Dilger
- libpng 1.0 beta 2 - version 0.88 January 26, 1996
+ libpng 1.0 beta 2 - version 0.88 - January 26, 1996
For conditions of distribution and use, see copyright
notice in png.h. Copyright (c) 1995, 1996 Guy Eric
Schalnat, Group 42, Inc.
@@ -28,16 +28,33 @@ libpng-manual.txt - A description on how to use and modify libpng
Copyright (c) 1995, 1996 Frank J. T. Wojcik
December 18, 1995 & January 20, 1996
+ TABLE OF CONTENTS
+
+ I. Introduction
+ II. Structures
+ III. Reading
+ IV. Writing
+ V. Simplified API
+ VI. Modifying/Customizing libpng
+ VII. MNG support
+ VIII. Changes to Libpng from version 0.88
+ IX. Changes to Libpng from version 1.0.x to 1.2.x
+ X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x
+ XI. Changes to Libpng from version 1.4.x to 1.5.x
+ XII. Changes to Libpng from version 1.5.x to 1.6.x
+ XIII. Detecting libpng
+ XIV. Source code repository
+ XV. Coding style
+ XVI. Y2K Compliance in libpng
+
I. Introduction
This file describes how to use and modify the PNG reference library
-(known as libpng) for your own use. There are five sections to this
-file: introduction, structures, reading, writing, and modification and
-configuration notes for various special platforms. In addition to this
+(known as libpng) for your own use. In addition to this
file, example.c is a good starting point for using the library, as
it is heavily commented and should include everything most people
will need. We assume that libpng is already installed; see the
-INSTALL file for instructions on how to install libpng.
+INSTALL file for instructions on how to configure and install libpng.
For examples of libpng usage, see the files "example.c", "pngtest.c",
and the files in the "contrib" directory, all of which are included in
@@ -48,7 +65,7 @@ of reducing the amount of time and effort it takes to support the PNG
file format in application programs.
The PNG specification (second edition), November 2003, is available as
-a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2003 (E)) at
+a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at
<http://www.w3.org/TR/2003/REC-PNG-20031110/
The W3C and ISO documents have identical technical content.
@@ -141,8 +158,8 @@ APIs. Most of these are fairly obvious; for example types corresponding
to integers of particular sizes and types for passing color values.
One exception is how non-integral numbers are handled. For application
-convenience most APIs that take such numbers have C (double) arguments,
-however internally PNG, and libpng, use 32 bit signed integers and encode
+convenience most APIs that take such numbers have C (double) arguments;
+however, internally PNG, and libpng, use 32 bit signed integers and encode
the value by multiplying by 100,000. As of libpng 1.5.0 a convenience
macro PNG_FP_1 is defined in png.h along with a type (png_fixed_point)
which is simply (png_int_32).
@@ -257,10 +274,10 @@ This method of building a customized pnglibconf.h is illustrated in
contrib/pngminim/*. See the "$(PNGCONF):" target in the makefile and
pngusr.dfa in these directories.
-C. Configuration using PNG_USR_CONFIG
+C. Configuration using PNG_USER_CONFIG
-If -DPNG_USR_CONFIG is added to the CFLAGS when pnglibconf.h is built the file
-pngusr.h will automatically be included before the options in
+If -DPNG_USER_CONFIG is added to the CPPFLAGS when pnglibconf.h is built,
+the file pngusr.h will automatically be included before the options in
scripts/pnglibconf.dfa are processed. Your pngusr.h file should contain only
macro definitions turning features on or off or setting settings.
@@ -319,7 +336,7 @@ prediction.
If you are intending to keep the file pointer open for use in libpng,
you must ensure you don't read more than 8 bytes from the beginning
-of the file, and you also have to make a call to png_set_sig_bytes_read()
+of the file, and you also have to make a call to png_set_sig_bytes()
with the number of bytes you read from the beginning. Libpng will
then only check the bytes (if any) that your program didn't read.
@@ -327,22 +344,23 @@ then only check the bytes (if any) that your program didn't read.
to replace them with custom functions. See the discussion under
Customizing libpng.
-
FILE *fp = fopen(file_name, "rb");
if (!fp)
{
return (ERROR);
}
- fread(header, 1, number, fp);
- is_png = !png_sig_cmp(header, 0, number);
+ if (fread(header, 1, number, fp) != number)
+ {
+ return (ERROR);
+ }
+ is_png = !png_sig_cmp(header, 0, number);
if (!is_png)
{
return (NOT_PNG);
}
-
Next, png_struct and png_info need to be allocated and initialized. In
order to ensure that the size of these structures is correct even with a
dynamically linked libpng, there are functions to initialize and
@@ -508,9 +526,14 @@ you can retrieve with
png_get_user_chunk_ptr(png_ptr);
If you call the png_set_read_user_chunk_fn() function, then all unknown
-chunks will be saved when read, in case your callback function will need
-one or more of them. This behavior can be changed with the
-png_set_keep_unknown_chunks() function, described below.
+chunks which the callback does not handle will be saved when read. You can
+cause them to be discarded by returning '1' ("handled") instead of '0'. This
+behavior will change in libpng 1.7 and the default handling set by the
+png_set_keep_unknown_chunks() function, described below, will be used when the
+callback returns 0. If you want the existing behavior you should set the global
+default to PNG_HANDLE_CHUNK_IF_SAFE now; this is compatible with all current
+versions of libpng and with 1.7. Libpng 1.6 issues a warning if you keep the
+default, or PNG_HANDLE_CHUNK_NEVER, and the callback returns 0.
At this point, you can set up a callback function that will be
called after each row has been read, which you can use to control
@@ -553,6 +576,7 @@ chunk types. To change this, you can call:
png_set_keep_unknown_chunks(png_ptr, keep,
chunk_list, num_chunks);
+
keep - 0: default unknown chunk handling
1: ignore; do not keep
2: keep only if safe-to-copy
@@ -566,11 +590,16 @@ chunk types. To change this, you can call:
chunk_list - list of chunks affected (a byte string,
five bytes per chunk, NULL or '\0' if
- num_chunks is 0)
+ num_chunks is positive; ignored if
+ numchunks <= 0).
num_chunks - number of chunks affected; if 0, all
- unknown chunks are affected. If nonzero,
- only the chunks in the list are affected
+ unknown chunks are affected. If positive,
+ only the chunks in the list are affected,
+ and if negative all unknown chunks and
+ all known chunks except for the IHDR,
+ PLTE, tRNS, IDAT, and IEND chunks are
+ affected.
Unknown chunks declared in this way will be saved as raw data onto a
list of png_unknown_chunk structures. If a chunk that is normally
@@ -603,30 +632,29 @@ callback function:
...
#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED)
- /* ignore all unknown chunks: */
- png_set_keep_unknown_chunks(read_ptr, 1, NULL, 0);
+ /* ignore all unknown chunks
+ * (use global setting "2" for libpng16 and earlier):
+ */
+ png_set_keep_unknown_chunks(read_ptr, 2, NULL, 0);
/* except for vpAg: */
png_set_keep_unknown_chunks(read_ptr, 2, vpAg, 1);
/* also ignore unused known chunks: */
png_set_keep_unknown_chunks(read_ptr, 1, unused_chunks,
- (int)sizeof(unused_chunks)/5);
+ (int)(sizeof unused_chunks)/5);
#endif
User limits
The PNG specification allows the width and height of an image to be as
large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns.
-Since very few applications really need to process such large images,
-we have imposed an arbitrary 1-million limit on rows and columns.
Larger images will be rejected immediately with a png_error() call. If
-you wish to change this limit, you can use
+you wish to change these limits, you can use
png_set_user_limits(png_ptr, width_max, height_max);
-to set your own limits, or use width_max = height_max = 0x7fffffffL
-to allow all valid dimensions (libpng may reject some very large images
+to set your own limits (libpng may reject some very wide images
anyway because of potential buffer overflow conditions).
You should put this statement after you create the PNG structure and
@@ -650,9 +678,6 @@ where 0x7fffffffL means unlimited. You can retrieve this limit with
chunk_cache_max = png_get_chunk_cache_max(png_ptr);
-This limit also applies to the number of buffers that can be allocated
-by png_decompress_chunk() while decompressing iTXt, zTXt, and iCCP chunks.
-
You can also set a limit on the amount of memory that a compressed chunk
other than IDAT can occupy, with
@@ -685,11 +710,12 @@ value. You can also specify a default encoding for the PNG file in
case the required information is missing from the file. By default libpng
assumes that the PNG data matches your system, to keep this default call:
- png_set_gamma(png_ptr, screen_gamma, 1/screen_gamma/*file gamma*/);
+ png_set_gamma(png_ptr, screen_gamma, output_gamma);
or you can use the fixed point equivalent:
- png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma, PNG_FP_1/screen_gamma);
+ png_set_gamma_fixed(png_ptr, PNG_FP_1*screen_gamma,
+ PNG_FP_1*output_gamma);
If you don't know the gamma for your system it is probably 2.2 - a good
approximation to the IEC standard for display systems (sRGB). If images are
@@ -701,19 +727,86 @@ display driver, a few systems, including older Macs, change the response by
default. As of 1.5.4 three special values are available to handle common
situations:
- PNG_DEFAULT_sRGB: Indicates that the system conforms to the IEC 61966-2-1
- standard. This matches almost all systems.
- PNG_GAMMA_MAC_18: Indicates that the system is an older (pre Mac OS 10.6)
- Apple Macintosh system with the default settings.
- PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates that the
- system expects data with no gamma encoding.
+ PNG_DEFAULT_sRGB: Indicates that the system conforms to the
+ IEC 61966-2-1 standard. This matches almost
+ all systems.
+ PNG_GAMMA_MAC_18: Indicates that the system is an older
+ (pre Mac OS 10.6) Apple Macintosh system with
+ the default settings.
+ PNG_GAMMA_LINEAR: Just the fixed point value for 1.0 - indicates
+ that the system expects data with no gamma
+ encoding.
You would use the linear (unencoded) value if you need to process the pixel
-values further because this avoids the need to decode and reencode each
+values further because this avoids the need to decode and re-encode each
component value whenever arithmetic is performed. A lot of graphics software
uses linear values for this reason, often with higher precision component values
to preserve overall accuracy.
+
+The output_gamma value expresses how to decode the output values, not how
+they are encoded. The values used correspond to the normal numbers used to
+describe the overall gamma of a computer display system; for example 2.2 for
+an sRGB conformant system. The values are scaled by 100000 in the _fixed
+version of the API (so 220000 for sRGB.)
+
+The inverse of the value is always used to provide a default for the PNG file
+encoding if it has no gAMA chunk and if png_set_gamma() has not been called
+to override the PNG gamma information.
+
+When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
+opaque pixels however pixels with lower alpha values are not encoded,
+regardless of the output gamma setting.
+
+When the standard Porter Duff handling is requested with mode 1 the output
+encoding is set to be linear and the output_gamma value is only relevant
+as a default for input data that has no gamma information. The linear output
+encoding will be overridden if png_set_gamma() is called - the results may be
+highly unexpected!
+
+The following numbers are derived from the sRGB standard and the research
+behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of
+0.45455 (1/2.2) for PNG. The value implicitly includes any viewing
+correction required to take account of any differences in the color
+environment of the original scene and the intended display environment; the
+value expresses how to *decode* the image for display, not how the original
+data was *encoded*.
+
+sRGB provides a peg for the PNG standard by defining a viewing environment.
+sRGB itself, and earlier TV standards, actually use a more complex transform
+(a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is
+limited to simple power laws.) By saying that an image for direct display on
+an sRGB conformant system should be stored with a gAMA chunk value of 45455
+(11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
+makes it possible to derive values for other display systems and
+environments.
+
+The Mac value is deduced from the sRGB based on an assumption that the actual
+extra viewing correction used in early Mac display systems was implemented as
+a power 1.45 lookup table.
+
+Any system where a programmable lookup table is used or where the behavior of
+the final display device characteristics can be changed requires system
+specific code to obtain the current characteristic. However this can be
+difficult and most PNG gamma correction only requires an approximate value.
+
+By default, if png_set_alpha_mode() is not called, libpng assumes that all
+values are unencoded, linear, values and that the output device also has a
+linear characteristic. This is only very rarely correct - it is invariably
+better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
+default if you don't know what the right answer is!
+
+The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
+10.6) which used a correction table to implement a somewhat lower gamma on an
+otherwise sRGB system.
+
+Both these values are reserved (not simple gamma values) in order to allow
+more precise correction internally in the future.
+
+NOTE: the values can be passed to either the fixed or floating
+point APIs, but the floating point API will also accept floating point
+values.
+
The second thing you may need to tell libpng about is how your system handles
alpha channel information. Some, but not all, PNG files contain an alpha
channel. To display these files correctly you need to compose the data onto a
@@ -723,11 +816,11 @@ Libpng only supports composing onto a single color (using png_set_background;
see below). Otherwise you must do the composition yourself and, in this case,
you may need to call png_set_alpha_mode:
-#if PNG_LIBPNG_VER >= 10504
- png_set_alpha_mode(png_ptr, mode, screen_gamma);
-#else
- png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma);
-#endif
+ #if PNG_LIBPNG_VER >= 10504
+ png_set_alpha_mode(png_ptr, mode, screen_gamma);
+ #else
+ png_set_gamma(png_ptr, screen_gamma, 1.0/screen_gamma);
+ #endif
The screen_gamma value is the same as the argument to png_set_gamma; however,
how it affects the output depends on the mode. png_set_alpha_mode() sets the
@@ -738,11 +831,11 @@ by png_set_alpha_mode().
The mode is as follows:
- PNG_ALPHA_PNG: The data is encoded according to the PNG specification. Red,
-green and blue, or gray, components are gamma encoded color
-values and are not premultiplied by the alpha value. The
-alpha value is a linear measure of the contribution of the
-pixel to the corresponding final output pixel.
+ PNG_ALPHA_PNG: The data is encoded according to the PNG
+specification. Red, green and blue, or gray, components are
+gamma encoded color values and are not premultiplied by the
+alpha value. The alpha value is a linear measure of the
+contribution of the pixel to the corresponding final output pixel.
You should normally use this format if you intend to perform
color correction on the color values; most, maybe all, color
@@ -759,11 +852,35 @@ be used!
The remaining modes assume you don't need to do any further color correction or
that if you do, your color correction software knows all about alpha (it
-probably doesn't!)
-
- PNG_ALPHA_STANDARD: The data libpng produces
-is encoded in the standard way
-assumed by most correctly written graphics software.
+probably doesn't!). They 'associate' the alpha with the color information by
+storing color channel values that have been scaled by the alpha. The
+advantage is that the color channels can be resampled (the image can be
+scaled) in this form. The disadvantage is that normal practice is to store
+linear, not (gamma) encoded, values and this requires 16-bit channels for
+still images rather than the 8-bit channels that are just about sufficient if
+gamma encoding is used. In addition all non-transparent pixel values,
+including completely opaque ones, must be gamma encoded to produce the final
+image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+described below (the latter being the two common names for associated alpha
+color channels). Note that PNG files always contain non-associated color
+channels; png_set_alpha_mode() with one of the modes causes the decoder to
+convert the pixels to an associated form before returning them to your
+application.
+
+Since it is not necessary to perform arithmetic on opaque color values so
+long as they are not to be resampled and are in the final color space it is
+possible to optimize the handling of alpha by storing the opaque pixels in
+the PNG format (adjusted for the output color space) while storing partially
+opaque pixels in the standard, linear, format. The accuracy required for
+standard alpha composition is relatively low, because the pixels are
+isolated, therefore typically the accuracy loss in storing 8-bit linear
+values is acceptable. (This is not true if the alpha channel is used to
+simulate transparency over large areas - use 16 bits or the PNG mode in
+this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is
+treated as opaque only if the alpha value is equal to the maximum value.
+
+ PNG_ALPHA_STANDARD: The data libpng produces is encoded in the
+standard way assumed by most correctly written graphics software.
The gamma encoding will be removed by libpng and the
linear component values will be pre-multiplied by the
alpha channel.
@@ -792,14 +909,13 @@ dynamic range. To avoid problems, and if your software
supports it, use png_set_expand_16() to force all
components to 16 bits.
- PNG_ALPHA_OPTIMIZED: This mode is the same
-as PNG_ALPHA_STANDARD except that
-completely opaque pixels are gamma encoded according to
+ PNG_ALPHA_OPTIMIZED: This mode is the same as PNG_ALPHA_STANDARD
+except that completely opaque pixels are gamma encoded according to
the screen_gamma value. Pixels with alpha less than 1.0
will still have linear components.
Use this format if you have control over your
-compositing software and do don't do other arithmetic
+compositing software and so don't do other arithmetic
(such as scaling) on the data you get from libpng. Your
compositing software can simply copy opaque pixels to
the output but still has linear values for the
@@ -813,18 +929,16 @@ representation of non-opaque pixels are irrelevant.
You can also try this format if your software is broken;
it might look better.
- PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD;
-however, all component values,
-including the alpha channel are gamma encoded. This is
-an appropriate format to try if your software, or more
-likely hardware, is totally broken, i.e., if it performs
-linear arithmetic directly on gamma encoded values.
-
-In most cases of broken software or hardware the bug in the final display
-manifests as a subtle halo around composited parts of the image. You may not
-even perceive this as a halo; the composited part of the image may simply appear
-separate from the background, as though it had been cut out of paper and pasted
-on afterward.
+ PNG_ALPHA_BROKEN: This is PNG_ALPHA_STANDARD; however, all component
+values, including the alpha channel are gamma encoded. This is
+broken because, in practice, no implementation that uses this choice
+correctly undoes the encoding before handling alpha composition. Use this
+choice only if other serious errors in the software or hardware you use
+mandate it. In most cases of broken software or hardware the bug in the
+final display manifests as a subtle halo around composited parts of the
+image. You may not even perceive this as a halo; the composited part of
+the image may simply appear separate from the background, as though it had
+been cut out of paper and pasted on afterward.
If you don't have to deal with bugs in software or hardware, or if you can fix
them, there are three recommended ways of using png_set_alpha_mode():
@@ -855,6 +969,89 @@ All you can do is compose the result onto a matching output. Since this
mode is libpng-specific you also need to write your own composition
software.
+The following are examples of calls to png_set_alpha_mode to achieve the
+required overall gamma correction and, where necessary, alpha
+premultiplication.
+
+ png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB);
+
+This is the default libpng handling of the alpha channel - it is not
+pre-multiplied into the color components. In addition the call states
+that the output is for a sRGB system and causes all PNG files without gAMA
+chunks to be assumed to be encoded using sRGB.
+
+ png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC);
+
+In this case the output is assumed to be something like an sRGB conformant
+display preceeded by a power-law lookup table of power 1.45. This is how
+early Mac systems behaved.
+
+ png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_GAMMA_LINEAR);
+
+This is the classic Jim Blinn approach and will work in academic
+environments where everything is done by the book. It has the shortcoming
+of assuming that input PNG data with no gamma information is linear - this
+is unlikely to be correct unless the PNG files where generated locally.
+Most of the time the output precision will be so low as to show
+significant banding in dark areas of the image.
+
+ png_set_expand_16(pp);
+ png_set_alpha_mode(pp, PNG_ALPHA_STANDARD, PNG_DEFAULT_sRGB);
+
+This is a somewhat more realistic Jim Blinn inspired approach. PNG files
+are assumed to have the sRGB encoding if not marked with a gamma value and
+the output is always 16 bits per component. This permits accurate scaling
+and processing of the data. If you know that your input PNG files were
+generated locally you might need to replace PNG_DEFAULT_sRGB with the
+correct value for your system.
+
+ png_set_alpha_mode(pp, PNG_ALPHA_OPTIMIZED, PNG_DEFAULT_sRGB);
+
+If you just need to composite the PNG image onto an existing background
+and if you control the code that does this you can use the optimization
+setting. In this case you just copy completely opaque pixels to the
+output. For pixels that are not completely transparent (you just skip
+those) you do the composition math using png_composite or png_composite_16
+below then encode the resultant 8-bit or 16-bit values to match the output
+encoding.
+
+ Other cases
+
+If neither the PNG nor the standard linear encoding work for you because
+of the software or hardware you use then you have a big problem. The PNG
+case will probably result in halos around the image. The linear encoding
+will probably result in a washed out, too bright, image (it's actually too
+contrasty.) Try the ALPHA_OPTIMIZED mode above - this will probably
+substantially reduce the halos. Alternatively try:
+
+ png_set_alpha_mode(pp, PNG_ALPHA_BROKEN, PNG_DEFAULT_sRGB);
+
+This option will also reduce the halos, but there will be slight dark
+halos round the opaque parts of the image where the background is light.
+In the OPTIMIZED mode the halos will be light halos where the background
+is dark. Take your pick - the halos are unavoidable unless you can get
+your hardware/software fixed! (The OPTIMIZED approach is slightly
+faster.)
+
+When the default gamma of PNG files doesn't match the output gamma.
+If you have PNG files with no gamma information png_set_alpha_mode allows
+you to provide a default gamma, but it also sets the ouput gamma to the
+matching value. If you know your PNG files have a gamma that doesn't
+match the output you can take advantage of the fact that
+png_set_alpha_mode always sets the output gamma but only sets the PNG
+default if it is not already set:
+
+ png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB);
+ png_set_alpha_mode(pp, PNG_ALPHA_PNG, PNG_GAMMA_MAC);
+
+The first call sets both the default and the output gamma values, the
+second call overrides the output gamma without changing the default. This
+is easier than achieving the same effect with png_set_gamma. You must use
+PNG_ALPHA_PNG for the first call - internal checking in png_set_alpha will
+fire if more than one call to png_set_alpha_mode and png_set_background is
+made in the same read operation, however multiple calls with PNG_ALPHA_PNG
+are ignored.
+
If you don't need, or can't handle, the alpha channel you can call
png_set_background() to remove it by compositing against a fixed color. Don't
call png_set_strip_alpha() to do this - it will leave spurious pixel values in
@@ -962,7 +1159,7 @@ where row_pointers is an array of pointers to the pixel data for each row:
If you know your image size and pixel size ahead of time, you can allocate
row_pointers prior to calling png_read_png() with
- if (height > PNG_UINT_32_MAX/png_sizeof(png_byte))
+ if (height > PNG_UINT_32_MAX/(sizeof (png_byte)))
png_error (png_ptr,
"Image is too tall to process in memory");
@@ -971,7 +1168,7 @@ row_pointers prior to calling png_read_png() with
"Image is too wide to process in memory");
row_pointers = png_malloc(png_ptr,
- height*png_sizeof(png_bytep));
+ height*(sizeof (png_bytep)));
for (int i=0; i<height, i++)
row_pointers[i]=NULL; /* security precaution */
@@ -1068,13 +1265,13 @@ in until png_read_end() has read the chunk data following the image.
the PNG datastream is embedded in
a MNG-1.0 datastream)
- Any or all of interlace_type, compression_type, or
- filter_method can be NULL if you are
- not interested in their values.
+ Any of width, height, color_type, bit_depth,
+ interlace_type, compression_type, or filter_method can
+ be NULL if you are not interested in their values.
Note that png_get_IHDR() returns 32-bit data into
the application's width and height variables.
- This is an unsafe situation if these are 16-bit
+ This is an unsafe situation if these are not png_uint_32
variables. In such situations, the
png_get_image_width() and png_get_image_height()
functions described below are safer.
@@ -1130,6 +1327,15 @@ data has been read, or zero if it is missing. The parameters to the
png_get_<chunk> are set directly if they are simple data types, or a
pointer into the info_ptr is returned for any complex types.
+The colorspace data from gAMA, cHRM, sRGB, iCCP, and sBIT chunks
+is simply returned to give the application information about how the
+image was encoded. Libpng itself only does transformations using the file
+gamma when combining semitransparent pixels with the background color, and,
+since libpng-1.6.0, when converting between 8-bit sRGB and 16-bit linear pixels
+within the simplified API. Libpng also uses the file gamma when converting
+RGB to gray, beginning with libpng-1.0.5, if the application calls
+png_set_rgb_to_gray()).
+
png_get_PLTE(png_ptr, info_ptr, &palette,
&num_palette);
@@ -1147,31 +1353,36 @@ pointer into the info_ptr is returned for any complex types.
int_file_gamma - 100,000 times the gamma at which the
file is written
- png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x, &red_y,
- &green_x, &green_y, &blue_x, &blue_y)
- png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z, &green_X,
- &green_Y, &green_Z, &blue_X, &blue_Y, &blue_Z)
- png_get_cHRM_fixed(png_ptr, info_ptr, &int_white_x, &int_white_y,
- &int_red_x, &int_red_y, &int_green_x, &int_green_y,
- &int_blue_x, &int_blue_y)
+ png_get_cHRM(png_ptr, info_ptr, &white_x, &white_y, &red_x,
+ &red_y, &green_x, &green_y, &blue_x, &blue_y)
+ png_get_cHRM_XYZ(png_ptr, info_ptr, &red_X, &red_Y, &red_Z,
+ &green_X, &green_Y, &green_Z, &blue_X, &blue_Y,
+ &blue_Z)
+ png_get_cHRM_fixed(png_ptr, info_ptr, &int_white_x,
+ &int_white_y, &int_red_x, &int_red_y,
+ &int_green_x, &int_green_y, &int_blue_x,
+ &int_blue_y)
png_get_cHRM_XYZ_fixed(png_ptr, info_ptr, &int_red_X, &int_red_Y,
- &int_red_Z, &int_green_X, &int_green_Y, &int_green_Z,
- &int_blue_X, &int_blue_Y, &int_blue_Z)
+ &int_red_Z, &int_green_X, &int_green_Y,
+ &int_green_Z, &int_blue_X, &int_blue_Y,
+ &int_blue_Z)
{white,red,green,blue}_{x,y}
- A color space encoding specified using the chromaticities
- of the end points and the white point. (PNG_INFO_cHRM)
+ A color space encoding specified using the
+ chromaticities of the end points and the
+ white point. (PNG_INFO_cHRM)
{red,green,blue}_{X,Y,Z}
- A color space encoding specified using the encoding end
- points - the CIE tristimulus specification of the intended
- color of the red, green and blue channels in the PNG RGB
- data. The white point is simply the sum of the three end
- points. (PNG_INFO_cHRM)
+ A color space encoding specified using the
+ encoding end points - the CIE tristimulus
+ specification of the intended color of the red,
+ green and blue channels in the PNG RGB data.
+ The white point is simply the sum of the three
+ end points. (PNG_INFO_cHRM)
png_get_sRGB(png_ptr, info_ptr, &srgb_intent);
- file_srgb_intent - the rendering intent (PNG_INFO_sRGB)
+ srgb_intent - the rendering intent (PNG_INFO_sRGB)
The presence of the sRGB chunk
means that the pixel data is in the
sRGB color space. This chunk also
@@ -1571,17 +1782,19 @@ Within the matrix,
"A" means the transformation is obtained by png_set_add_alpha().
"X" means the transformation is obtained by png_set_expand().
"1" means the transformation is obtained by
- png_set_expand_gray_1_2_4_to_8() (and by png_set_expand() if there
- is no transparency in the original or the final format).
+ png_set_expand_gray_1_2_4_to_8() (and by png_set_expand()
+ if there is no transparency in the original or the final
+ format).
"C" means the transformation is obtained by png_set_gray_to_rgb().
"G" means the transformation is obtained by png_set_rgb_to_gray().
"P" means the transformation is obtained by
png_set_expand_palette_to_rgb().
"p" means the transformation is obtained by png_set_packing().
"Q" means the transformation is obtained by png_set_quantize().
- "T" means the transformation is obtained by png_set_tRNS_to_alpha().
- "B" means the transformation is obtained by png_set_background(), or
- png_strip_alpha().
+ "T" means the transformation is obtained by
+ png_set_tRNS_to_alpha().
+ "B" means the transformation is obtained by
+ png_set_background(), or png_strip_alpha().
When an entry has multiple transforms listed all are required to cause the
right overall transformation. When two transforms are separated by a comma
@@ -1666,8 +1879,8 @@ with alpha.
if (color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- png_set_rgb_to_gray(png_ptr, error_action, double red_weight,
- double green_weight);
+ png_set_rgb_to_gray(png_ptr, error_action,
+ double red_weight, double green_weight);
error_action = 1: silently do the conversion
@@ -1689,7 +1902,8 @@ with alpha.
In the corresponding fixed point API the red_weight and green_weight values are
simply scaled by 100,000:
- png_set_rgb_to_gray(png_ptr, error_action, png_fixed_point red_weight,
+ png_set_rgb_to_gray(png_ptr, error_action,
+ png_fixed_point red_weight,
png_fixed_point green_weight);
If you have set error_action = 1 or 2, you can
@@ -1733,7 +1947,7 @@ the current display (e.g., the background color from a web page). You
need to tell libpng how the color is represented, both the format of the
component values in the color (the number of bits) and the gamma encoding of the
color. The function takes two arguments, background_gamma_mode and need_expand
-to convey this information, however only two combinations are likely to be
+to convey this information; however, only two combinations are likely to be
useful:
png_color_16 my_background;
@@ -1780,7 +1994,7 @@ value when you call it in this position:
png_set_gamma(png_ptr, screen_gamma, 0.45455);
If you need to reduce an RGB file to a paletted file, or if a paletted
-file has more entries then will fit on your screen, png_set_quantize()
+file has more entries than will fit on your screen, png_set_quantize()
will do that. Note that this is a simple match quantization that merely
finds the closest color available. This should work fairly well with
optimized palettes, but fairly badly with linear color cubes. If you
@@ -2027,7 +2241,7 @@ the second parameter NULL.
If you don't want libpng to handle the interlacing details, just call
png_read_rows() PNG_INTERLACE_ADAM7_PASSES times to read in all the images.
-Each of the images is a valid image by itself, however you will almost
+Each of the images is a valid image by itself; however, you will almost
certainly need to distribute the pixels from each sub-image to the
correct place. This is where everything gets very tricky.
@@ -2118,10 +2332,15 @@ how pngvalid.c does it.
Finishing a sequential read
After you are finished reading the image through the
-low-level interface, you can finish reading the file. If you are
-interested in comments or time, which may be stored either before or
-after the image data, you should pass the separate png_info struct if
-you want to keep the comments from before and after the image
+low-level interface, you can finish reading the file.
+
+If you want to use a different crc action for handling CRC errors in
+chunks after the image data, you can call png_set_crc_action()
+again at this point.
+
+If you are interested in comments or time, which may be stored either
+before or after the image data, you should pass the separate png_info
+struct if you want to keep the comments from before and after the image
separate.
png_infop end_info = png_create_info_struct(png_ptr);
@@ -2137,6 +2356,9 @@ separate.
If you are not interested, you should still call png_read_end()
but you can pass NULL, avoiding the need to create an end_info structure.
+If you do this, libpng will not process any chunks after IDAT other than
+skipping over them and perhaps (depending on whether you have called
+png_set_crc_action) checking their CRCs while looking for the IEND chunk.
png_read_end(png_ptr, (png_infop)NULL);
@@ -2184,7 +2406,7 @@ sPLT, only the n'th item in the structure is freed, where n is "seq".
The default behavior is only to free data that was allocated internally
by libpng. This can be changed, so that libpng will not free the data,
or so that it will free data that was allocated by the user with png_malloc()
-or png_zalloc() and passed in via a png_set_*() function, with
+or png_calloc() and passed in via a png_set_*() function, with
png_data_freer(png_ptr, info_ptr, freer, mask)
@@ -2205,7 +2427,7 @@ or png_destroy_*() is supposed to free the data. When the user assumes
responsibility for libpng-allocated data, the application must use
png_free() to free it, and when the user transfers responsibility to libpng
for data that the user has allocated, the user must have used png_malloc()
-or png_zalloc() to allocate it.
+or png_calloc() to allocate it.
If you allocated your row_pointers in a single block, as suggested above in
the description of the high level read interface, you must not transfer
@@ -2241,7 +2463,7 @@ For a more compact example of reading a PNG image, see the file example.c.
Reading PNG files progressively
-The progressive reader is slightly different then the non-progressive
+The progressive reader is slightly different from the non-progressive
reader. Instead of calling png_read_info(), png_read_rows(), and
png_read_end(), you make one call to png_process_data(), which calls
callbacks when it has the info, a row, or the end of the image. You
@@ -2325,7 +2547,7 @@ png_infop info_ptr;
64K. The library seems to run fine with sizes
of 4K. Although you can give it much less if
necessary (I assume you can give it chunks of
- 1 byte, I haven't tried less then 256 bytes
+ 1 byte, I haven't tried less than 256 bytes
yet). When this function returns, you may
want to display any rows that were generated
in the row callback if you don't already do
@@ -2412,7 +2634,7 @@ png_infop info_ptr;
png_progressive_combine_row(png_ptr, old_row,
new_row);
- /* where old_row is what was displayed for
+ /* where old_row is what was displayed
previously for the row. Note that the first
pass (pass == 0, really) will completely cover
the old row, so the rows do not have to be
@@ -2521,6 +2743,20 @@ You can #define PNG_ABORT() to a function that does something
more useful than abort(), as long as your function does not
return.
+Checking for invalid palette index on write was added at libpng
+1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues
+a benign error. This is enabled by default because this condition is an
+error according to the PNG specification, Clause 11.3.2, but the error can
+be ignored in each png_ptr with
+
+ png_set_check_for_invalid_index(png_ptr, 0);
+
+If the error is ignored, or if png_benign_error() treats it as a warning,
+any invalid pixels are written as-is by the encoder, resulting in an
+invalid PNG datastream as output. In this case the application is
+responsible for ensuring that the pixel indexes are in range when it writes
+a PLTE chunk with fewer entries than the bit depth would allow.
+
Now you need to set up the output code. The default for libpng is to
use the C function fwrite(). If you use this, you will need to pass a
valid FILE * in the function png_init_io(). Be sure that the file is
@@ -3023,18 +3259,53 @@ tEXt chunk use RFC 1123 format dates (e.g. "22 May 1997 18:07:10 GMT"),
although this isn't a requirement. Unlike the tIME chunk, the
"Creation Time" tEXt chunk is not expected to be automatically changed
by the software. To facilitate the use of RFC 1123 dates, a function
-png_convert_to_rfc1123(png_timep) is provided to convert from PNG
-time to an RFC 1123 format string.
+png_convert_to_rfc1123_buffer(buffer, png_timep) is provided to
+convert from PNG time to an RFC 1123 format string. The caller must provide
+a writeable buffer of at least 29 bytes.
Writing unknown chunks
-You can use the png_set_unknown_chunks function to queue up chunks
-for writing. You give it a chunk name, raw data, and a size; that's
-all there is to it. The chunks will be written by the next following
-png_write_info_before_PLTE, png_write_info, or png_write_end function.
-Any chunks previously read into the info structure's unknown-chunk
-list will also be written out in a sequence that satisfies the PNG
-specification's ordering rules.
+You can use the png_set_unknown_chunks function to queue up private chunks
+for writing. You give it a chunk name, location, raw data, and a size. You
+also must use png_set_keep_unknown_chunks() to ensure that libpng will
+handle them. That's all there is to it. The chunks will be written by the
+next following png_write_info_before_PLTE, png_write_info, or png_write_end
+function, depending upon the specified location. Any chunks previously
+read into the info structure's unknown-chunk list will also be written out
+in a sequence that satisfies the PNG specification's ordering rules.
+
+Here is an example of writing two private chunks, prVt and miNE:
+
+ #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+ /* Set unknown chunk data */
+ png_unknown_chunk unk_chunk[2];
+ strcpy((char *) unk_chunk[0].name, "prVt";
+ unk_chunk[0].data = (unsigned char *) "PRIVATE DATA";
+ unk_chunk[0].size = strlen(unk_chunk[0].data)+1;
+ unk_chunk[0].location = PNG_HAVE_IHDR;
+ strcpy((char *) unk_chunk[1].name, "miNE";
+ unk_chunk[1].data = (unsigned char *) "MY CHUNK DATA";
+ unk_chunk[1].size = strlen(unk_chunk[0].data)+1;
+ unk_chunk[1].location = PNG_AFTER_IDAT;
+ png_set_unknown_chunks(write_ptr, write_info_ptr,
+ unk_chunk, 2);
+ /* Needed because miNE is not safe-to-copy */
+ png_set_keep_unknown_chunks(png, PNG_HANDLE_CHUNK_ALWAYS,
+ (png_bytep) "miNE", 1);
+ # if PNG_LIBPNG_VER < 10600
+ /* Deal with unknown chunk location bug in 1.5.x and earlier */
+ png_set_unknown_chunk_location(png, info, 0, PNG_HAVE_IHDR);
+ png_set_unknown_chunk_location(png, info, 1, PNG_AFTER_IDAT);
+ # endif
+ # if PNG_LIBPNG_VER < 10500
+ /* PNG_AFTER_IDAT writes two copies of the chunk prior to libpng-1.5.0,
+ * one before IDAT and another after IDAT, so don't use it; only use
+ * PNG_HAVE_IHDR location. This call resets the location previously
+ * set by assignment and png_set_unknown_chunk_location() for chunk 1.
+ */
+ png_set_unknown_chunk_location(png, info, 1, PNG_HAVE_IHDR);
+ # endif
+ #endif
The high-level write interface
@@ -3386,7 +3657,7 @@ png_destroy_write_struct().
The default behavior is only to free data that was allocated internally
by libpng. This can be changed, so that libpng will not free the data,
or so that it will free data that was allocated by the user with png_malloc()
-or png_zalloc() and passed in via a png_set_*() function, with
+or png_calloc() and passed in via a png_set_*() function, with
png_data_freer(png_ptr, info_ptr, freer, mask)
@@ -3422,7 +3693,7 @@ When the user assumes responsibility for libpng-allocated data, the
application must use
png_free() to free it, and when the user transfers responsibility to libpng
for data that the user has allocated, the user must have used png_malloc()
-or png_zalloc() to allocate it.
+or png_calloc() to allocate it.
If you allocated text_ptr.text, text_ptr.lang, and text_ptr.translated_keyword
separately, do not transfer responsibility for freeing text_ptr to libpng,
@@ -3432,7 +3703,374 @@ if you transfer responsibility for free'ing text_ptr from libpng to your
application, your application must not separately free those members.
For a more compact example of writing a PNG image, see the file example.c.
-V. Modifying/Customizing libpng:
+V. Simplified API
+
+The simplified API, which became available in libpng-1.6.0, hides the details
+of both libpng and the PNG file format itself.
+It allows PNG files to be read into a very limited number of
+in-memory bitmap formats or to be written from the same formats. If these
+formats do not accommodate your needs then you can, and should, use the more
+sophisticated APIs above - these support a wide variety of in-memory formats
+and a wide variety of sophisticated transformations to those formats as well
+as a wide variety of APIs to manipulate ancilliary information.
+
+To read a PNG file using the simplified API:
+
+ 1) Declare a 'png_image' structure (see below) on the
+ stack and memset() it to all zero.
+
+ 2) Call the appropriate png_image_begin_read... function.
+
+ 3) Set the png_image 'format' member to the required
+ format and allocate a buffer for the image.
+
+ 4) Call png_image_finish_read to read the image into
+ your buffer.
+
+There are no restrictions on the format of the PNG input itself; all valid
+color types, bit depths, and interlace methods are acceptable, and the
+input image is transformed as necessary to the requested in-memory format
+during the png_image_finish_read() step.
+
+To write a PNG file using the simplified API:
+
+ 1) Declare a 'png_image' structure on the stack and memset()
+ it to all zero.
+
+ 2) Initialize the members of the structure that describe the
+ image, setting the 'format' member to the format of the
+ image in memory.
+
+ 3) Call the appropriate png_image_write... function with a
+ pointer to the image to write the PNG data.
+
+png_image is a structure that describes the in-memory format of an image
+when it is being read or define the in-memory format of an image that you
+need to write. The "png_image" structure contains the following members:
+
+ png_uint_32 version Set to PNG_IMAGE_VERSION
+ png_uint_32 width Image width in pixels (columns)
+ png_uint_32 height Image height in pixels (rows)
+ png_uint_32 format Image format as defined below
+ png_uint_32 flags A bit mask containing informational flags
+ png_controlp opaque Initialize to NULL, free with png_image_free
+ png_uint_32 colormap_entries; Number of entries in the color-map
+ png_uint_32 warning_or_error;
+ char message[64];
+
+In the event of an error or warning the following field warning_or_error
+field will be set to a non-zero value and the 'message' field will contain
+a '\0' terminated string with the libpng error or warning message. If both
+warnings and an error were encountered, only the error is recorded. If there
+are multiple warnings, only the first one is recorded.
+
+The upper 30 bits of this value are reserved; the low two bits contain
+a two bit code such that a value more than 1 indicates a failure in the API
+just called:
+
+ 0 - no warning or error
+ 1 - warning
+ 2 - error
+ 3 - error preceded by warning
+
+The pixels (samples) of the image have one to four channels whose components
+have original values in the range 0 to 1.0:
+
+ 1: A single gray or luminance channel (G).
+ 2: A gray/luminance channel and an alpha channel (GA).
+ 3: Three red, green, blue color channels (RGB).
+ 4: Three color channels and an alpha channel (RGBA).
+
+The channels are encoded in one of two ways:
+
+ a) As a small integer, value 0..255, contained in a single byte. For the
+alpha channel the original value is simply value/255. For the color or
+luminance channels the value is encoded according to the sRGB specification
+and matches the 8-bit format expected by typical display devices.
+
+The color/gray channels are not scaled (pre-multiplied) by the alpha
+channel and are suitable for passing to color management software.
+
+ b) As a value in the range 0..65535, contained in a 2-byte integer, in
+the native byte order of the platform on which the application is running.
+All channels can be converted to the original value by dividing by 65535; all
+channels are linear. Color channels use the RGB encoding (RGB end-points) of
+the sRGB specification. This encoding is identified by the
+PNG_FORMAT_FLAG_LINEAR flag below.
+
+When an alpha channel is present it is expected to denote pixel coverage
+of the color or luminance channels and is returned as an associated alpha
+channel: the color/gray channels are scaled (pre-multiplied) by the alpha
+value.
+
+When a color-mapped image is used as a result of calling
+png_image_read_colormap or png_image_write_colormap the channels are encoded
+in the color-map and the descriptions above apply to the color-map entries.
+The image data is encoded as small integers, value 0..255, that index the
+entries in the color-map. One integer (one byte) is stored for each pixel.
+
+PNG_FORMAT_*
+
+The #defines to be used in png_image::format. Each #define identifies a
+particular layout of channel data and, if present, alpha values. There are
+separate defines for each of the two channel encodings.
+
+A format is built up using single bit flag values. Not all combinations are
+valid: use the bit flag values below for testing a format returned by the
+read APIs, but set formats from the derived values.
+
+When reading or writing color-mapped images the format should be set to the
+format of the entries in the color-map then png_image_{read,write}_colormap
+called to read or write the color-map and set the format correctly for the
+image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
+
+NOTE: libpng can be built with particular features disabled, if you see
+compiler errors because the definition of one of the following flags has been
+compiled out it is because libpng does not have the required support. It is
+possible, however, for the libpng configuration to enable the format on just
+read or just write; in that case you may see an error at run time. You can
+guard against this by checking for the definition of:
+
+ PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
+
+ PNG_FORMAT_FLAG_ALPHA 0x01 format with an alpha channel
+ PNG_FORMAT_FLAG_COLOR 0x02 color format: otherwise grayscale
+ PNG_FORMAT_FLAG_LINEAR 0x04 png_uint_16 channels else png_byte
+ PNG_FORMAT_FLAG_COLORMAP 0x08 libpng use only
+ PNG_FORMAT_FLAG_BGR 0x10 BGR colors, else order is RGB
+ PNG_FORMAT_FLAG_AFIRST 0x20 alpha channel comes first
+
+Supported formats are as follows. Future versions of libpng may support more
+formats; for compatibility with older versions simply check if the format
+macro is defined using #ifdef. These defines describe the in-memory layout
+of the components of the pixels of the image.
+
+First the single byte formats:
+
+ PNG_FORMAT_GRAY 0
+ PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
+ PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
+ PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR
+ PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
+ PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
+ PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
+ PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
+ PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
+
+Then the linear 2-byte formats. When naming these "Y" is used to
+indicate a luminance (gray) channel. The component order within the pixel
+is always the same - there is no provision for swapping the order of the
+components in the linear format. The components are 16-bit integers in
+the native byte order for your platform, and there is no provision for
+swapping the bytes to a different endian condition.
+
+ PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
+ PNG_FORMAT_LINEAR_Y_ALPHA
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
+ PNG_FORMAT_LINEAR_RGB
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
+ PNG_FORMAT_LINEAR_RGB_ALPHA
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|
+ PNG_FORMAT_FLAG_ALPHA)
+
+Color-mapped formats are obtained by calling png_image_{read,write}_colormap,
+as appropriate after setting png_image::format to the format of the color-map
+to be read or written. Applications may check the value of
+PNG_FORMAT_FLAG_COLORMAP to see if they have called the colormap API. The
+format of the color-map may be extracted using the following macro.
+
+ PNG_FORMAT_OF_COLORMAP(fmt) ((fmt) & ~PNG_FORMAT_FLAG_COLORMAP)
+
+PNG_IMAGE macros
+
+These are convenience macros to derive information from a png_image
+structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
+actual image sample values - either the entries in the color-map or the
+pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
+for the pixels and will always return 1 after a call to
+png_image_{read,write}_colormap. The remaining macros return information
+about the rows in the image and the complete image.
+
+NOTE: All the macros that take a png_image::format parameter are compile time
+constants if the format parameter is, itself, a constant. Therefore these
+macros can be used in array declarations and case labels where required.
+Similarly the macros are also pre-processor constants (sizeof is not used) so
+they can be used in #if tests.
+
+First the information about the samples.
+
+ PNG_IMAGE_SAMPLE_CHANNELS(fmt)
+ Returns the total number of channels in a given format: 1..4
+
+ PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)
+ Returns the size in bytes of a single component of a pixel or color-map
+ entry (as appropriate) in the image.
+
+ PNG_IMAGE_SAMPLE_SIZE(fmt)
+ This is the size of the sample data for one sample. If the image is
+ color-mapped it is the size of one color-map entry (and image pixels are
+ one byte in size), otherwise it is the size of one image pixel.
+
+ PNG_IMAGE_COLORMAP_SIZE(fmt)
+ The size of the color-map required by the format; this is the size of the
+ color-map buffer passed to the png_image_{read,write}_colormap APIs, it is
+ a fixed number determined by the format so can easily be allocated on the
+ stack if necessary.
+
+#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
+ (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
+ /* The maximum size of the color-map required by the format expressed in a
+ * count of components. This can be used to compile-time allocate a
+ * color-map:
+ *
+ * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
+ *
+ * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
+ *
+ * Alternatively, use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
+ * information from one of the png_image_begin_read_ APIs and dynamically
+ * allocate the required memory.
+ */
+
+
+Corresponding information about the pixels
+
+ PNG_IMAGE_PIXEL_(test,fmt)
+
+ PNG_IMAGE_PIXEL_CHANNELS(fmt)
+ The number of separate channels (components) in a pixel; 1 for a
+ color-mapped image.
+
+ PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
+ The size, in bytes, of each component in a pixel; 1 for a color-mapped
+ image.
+
+ PNG_IMAGE_PIXEL_SIZE(fmt)
+ The size, in bytes, of a complete pixel; 1 for a color-mapped image.
+
+Information about the whole row, or whole image
+
+ PNG_IMAGE_ROW_STRIDE(image)
+ Returns the total number of components in a single row of the image; this
+ is the minimum 'row stride', the minimum count of components between each
+ row. For a color-mapped image this is the minimum number of bytes in a
+ row.
+
+ If you need the stride measured in bytes, row_stride_bytes is
+ PNG_IMAGE_ROW_STRIDE(image) * PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)
+ plus any padding bytes that your application might need, for example
+ to start the next row on a 4-byte boundary.
+
+ PNG_IMAGE_BUFFER_SIZE(image, row_stride)
+ Returns the size, in bytes, of an image buffer given a png_image and a row
+ stride - the number of components to leave space for in each row. This
+ macro takes care of multiplying row_stride by PNG_IMAGE_PIXEL_COMONENT_SIZE
+ when the image has 2-byte components.
+
+ PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB == 0x01
+ This indicates the the RGB values of the in-memory bitmap do not
+ correspond to the red, green and blue end-points defined by sRGB.
+
+ PNG_IMAGE_FLAG_COLORMAP == 0x02
+ The PNG is color-mapped. If this flag is set png_image_read_colormap
+ can be used without further loss of image information. If it is not set
+ png_image_read_colormap will cause significant loss if the image has any
+
+READ APIs
+
+ The png_image passed to the read APIs must have been initialized by setting
+ the png_controlp field 'opaque' to NULL (or, better, memset the whole thing.)
+
+ int png_image_begin_read_from_file( png_imagep image,
+ const char *file_name)
+
+ The named file is opened for read and the image header
+ is filled in from the PNG header in the file.
+
+ int png_image_begin_read_from_stdio (png_imagep image,
+ FILE* file)
+
+ The PNG header is read from the stdio FILE object.
+
+ int png_image_begin_read_from_memory(png_imagep image,
+ png_const_voidp memory, png_size_t size)
+
+ The PNG header is read from the given memory buffer.
+
+ int png_image_finish_read(png_imagep image,
+ png_colorp background, void *buffer,
+ png_int_32 row_stride, void *colormap));
+
+ Finish reading the image into the supplied buffer and
+ clean up the png_image structure.
+
+ row_stride is the step, in png_byte or png_uint_16 units
+ as appropriate, between adjacent rows. A positive stride
+ indicates that the top-most row is first in the buffer -
+ the normal top-down arrangement. A negative stride
+ indicates that the bottom-most row is first in the buffer.
+
+ background need only be supplied if an alpha channel must
+ be removed from a png_byte format and the removal is to be
+ done by compositing on a solid color; otherwise it may be
+ NULL and any composition will be done directly onto the
+ buffer. The value is an sRGB color to use for the
+ background, for grayscale output the green channel is used.
+
+ For linear output removing the alpha channel is always done
+ by compositing on black.
+
+ void png_image_free(png_imagep image)
+
+ Free any data allocated by libpng in image->opaque,
+ setting the pointer to NULL. May be called at any time
+ after the structure is initialized.
+
+When the simplified API needs to convert between sRGB and linear colorspaces,
+the actual sRGB transfer curve defined in the sRGB specification (see the
+article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+approximation used elsewhere in libpng.
+
+WRITE APIS
+
+For write you must initialize a png_image structure to describe the image to
+be written:
+
+ version: must be set to PNG_IMAGE_VERSION
+ opaque: must be initialized to NULL
+ width: image width in pixels
+ height: image height in rows
+ format: the format of the data you wish to write
+ flags: set to 0 unless one of the defined flags applies; set
+ PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images
+ where the RGB values do not correspond to the colors in sRGB.
+ colormap_entries: set to the number of entries in the color-map (0 to 256)
+
+ int png_image_write_to_file, (png_imagep image,
+ const char *file, int convert_to_8bit, const void *buffer,
+ png_int_32 row_stride, const void *colormap));
+
+ Write the image to the named file.
+
+ int png_image_write_to_stdio(png_imagep image, FILE *file,
+ int convert_to_8_bit, const void *buffer,
+ png_int_32 row_stride, const void *colormap)
+
+ Write the image to the given (FILE*).
+
+With all write APIs if image is in one of the linear formats with
+(png_uint_16) data then setting convert_to_8_bit will cause the output to be
+a (png_byte) PNG gamma encoded according to the sRGB specification, otherwise
+a 16-bit linear encoded PNG file is written.
+
+With all APIs row_stride is handled as in the read APIs - it is the spacing
+from one row to the next in component sized units (float) and if negative
+indicates a bottom-up row layout in the buffer.
+
+Note that the write API does not support interlacing, sub-8-bit pixels,
+and indexed (paletted) images.
+
+VI. Modifying/Customizing libpng
There are two issues here. The first is changing how libpng does
standard things like memory allocation, input/output, and error handling.
@@ -3450,19 +4088,17 @@ in pngmem.c, pngrio.c, pngwio.c, and pngerror.c, respectively. To change
these functions, call the appropriate png_set_*_fn() function.
Memory allocation is done through the functions png_malloc(), png_calloc(),
-and png_free(). These currently just call the standard C functions.
-png_calloc() calls png_malloc() and then clears the newly
-allocated memory to zero. There is limited support for certain systems
-with segmented memory architectures and the types of pointers declared by
-png.h match this; you will have to use appropriate pointers in your
-application. Since it is
-unlikely that the method of handling memory allocation on a platform
-will change between applications, these functions must be modified in
-the library at compile time. If you prefer to use a different method
-of allocating and freeing data, you can use png_create_read_struct_2() or
-png_create_write_struct_2() to register your own functions as described
-above. These functions also provide a void pointer that can be retrieved
-via
+and png_free(). The png_malloc() and png_free() functions currently just
+call the standard C functions and png_calloc() calls png_malloc() and then
+clears the newly allocated memory to zero; note that png_calloc(png_ptr, size)
+is not the same as the calloc(number, size) function provided by stdlib.h.
+There is limited support for certain systems with segmented memory
+architectures and the types of pointers declared by png.h match this; you
+will have to use appropriate pointers in your application. If you prefer
+to use a different method of allocating and freeing data, you can use
+png_create_read_struct_2() or png_create_write_struct_2() to register your
+own functions as described above. These functions also provide a void
+pointer that can be retrieved via
mem_ptr=png_get_mem_ptr(png_ptr);
@@ -3565,6 +4201,18 @@ compiler documentation for more details. For an alternative approach, you
may wish to use the "cexcept" facility (see http://cexcept.sourceforge.net),
which is illustrated in pngvalid.c and in contrib/visupng.
+Beginning in libpng-1.4.0, the png_set_benign_errors() API became available.
+You can use this to handle certain errors (normally handled as errors)
+as warnings.
+
+ png_set_benign_errors (png_ptr, int allowed);
+
+ allowed: 0: treat png_benign_error() as an error.
+ 1: treat png_benign_error() as a warning.
+
+As of libpng-1.6.0, the default condition is to treat benign errors as
+warnings while reading and as errors while writing.
+
Custom chunks
If you need to read or write custom chunks, you may need to get deeper
@@ -3593,29 +4241,6 @@ the simpler ones to get an idea of how they work. Try to find a similar
transformation to the one you want to add and copy off of it. More details
can be found in the comments inside the code itself.
-Configuring for 16-bit platforms
-
-You will want to look into zconf.h to tell zlib (and thus libpng) that
-it cannot allocate more then 64K at a time. Even if you can, the memory
-won't be accessible. So limit zlib and libpng to 64K by defining MAXSEG_64K.
-
-Configuring for DOS
-
-For DOS users who only have access to the lower 640K, you will
-have to limit zlib's memory usage via a png_set_compression_mem_level()
-call. See zlib.h or zconf.h in the zlib library for more information.
-
-Configuring for Medium Model
-
-Libpng's support for medium model has been tested on most of the popular
-compilers. Make sure MAXSEG_64K gets defined, USE_FAR_KEYWORD gets
-defined, and FAR gets defined to far in pngconf.h, and you should be
-all set. Everything in the library (except for zlib's structure) is
-expecting far data. You must use the typedefs with the p or pp on
-the end for pointers (or at least look at them and be careful). Make
-note that the rows of data are defined as png_bytepp, which is
-an "unsigned char far * far *".
-
Configuring for gui/windowing platforms:
You will need to write new error and warning functions that use the GUI
@@ -3625,18 +4250,6 @@ in order to have them available during the structure initialization.
They can be changed later via png_set_error_fn(). On some compilers,
you may also have to change the memory allocators (png_malloc, etc.).
-Configuring for compiler xxx:
-
-All includes for libpng are in pngconf.h. If you need to add, change
-or delete an include, this is the place to do it.
-The includes that are not needed outside libpng are placed in pngpriv.h,
-which is only used by the routines inside libpng itself.
-The files in libpng proper only include pngpriv.h and png.h, which
-in turn includes pngconf.h and, as of libpng-1.5.0, pnglibconf.h.
-As of libpng-1.5.0, pngpriv.h also includes three other private header
-files, pngstruct.h, pnginfo.h, and pngdebug.h, which contain material
-that previously appeared in the public headers.
-
Configuring zlib:
There are special functions to configure the compression. Perhaps the
@@ -3678,6 +4291,8 @@ zlib.h for more information on what these mean.
png_set_compression_method(png_ptr, method);
+This controls the size of the IDAT chunks (default 8192):
+
png_set_compression_buffer_size(png_ptr, size);
As of libpng version 1.5.4, additional APIs became
@@ -3685,7 +4300,7 @@ available to set these separately for non-IDAT
compressed chunks such as zTXt, iTXt, and iCCP:
#include zlib.h
- #if PNG_LIBPNG_VER <= 10504
+ #if PNG_LIBPNG_VER >= 10504
png_set_text_compression_level(png_ptr, level);
png_set_text_compression_mem_level(png_ptr, level);
@@ -3776,46 +4391,6 @@ Note that the numbers above were invented purely for this example and
are given only to help explain the function usage. Little testing has
been done to find optimum values for either the costs or the weights.
-Removing unwanted object code
-
-There are a bunch of #define's in pngconf.h that control what parts of
-libpng are compiled. All the defines end in _SUPPORTED. If you are
-never going to use a capability, you can change the #define to #undef
-before recompiling libpng and save yourself code and data space, or
-you can turn off individual capabilities with defines that begin with
-PNG_NO_.
-
-In libpng-1.5.0 and later, the #define's are in pnglibconf.h instead.
-
-You can also turn all of the transforms and ancillary chunk capabilities
-off en masse with compiler directives that define
-PNG_NO_READ[or WRITE]_TRANSFORMS, or PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS,
-or all four,
-along with directives to turn on any of the capabilities that you do
-want. The PNG_NO_READ[or WRITE]_TRANSFORMS directives disable the extra
-transformations but still leave the library fully capable of reading
-and writing PNG files with all known public chunks. Use of the
-PNG_NO_READ[or WRITE]_ANCILLARY_CHUNKS directive produces a library
-that is incapable of reading or writing ancillary chunks. If you are
-not using the progressive reading capability, you can turn that off
-with PNG_NO_PROGRESSIVE_READ (don't confuse this with the INTERLACING
-capability, which you'll still have).
-
-All the reading and writing specific code are in separate files, so the
-linker should only grab the files it needs. However, if you want to
-make sure, or if you are building a stand alone library, all the
-reading files start with "pngr" and all the writing files start with "pngw".
-The files that don't match either (like png.c, pngtrans.c, etc.)
-are used for both reading and writing, and always need to be included.
-The progressive reader is in pngpread.c
-
-If you are creating or distributing a dynamically linked library (a .so
-or DLL file), you should not remove or disable any parts of the library,
-as this will cause applications linked with different versions of the
-library to fail if they call functions not available in your library.
-The size of the library itself should not be an issue, because only
-those sections that are actually used will be loaded into memory.
-
Requesting debug printout
The macro definition PNG_DEBUG can be used to request debugging
@@ -3835,7 +4410,7 @@ the message, "message" is the formatted string to be printed,
and p1 and p2 are parameters that are to be embedded in the string
according to printf-style formatting directives. For example,
- png_debug1(2, "foo=%d\n", foo);
+ png_debug1(2, "foo=%d", foo);
is expanded to
@@ -3853,7 +4428,7 @@ When PNG_DEBUG = 1, the macros are defined, but only png_debug statements
having level = 0 will be printed. There aren't any such statements in
this version of libpng, but if you insert some they will be printed.
-VI. MNG support
+VII. MNG support
The MNG specification (available at http://www.libpng.org/pub/mng) allows
certain extensions to PNG for PNG images that are embedded in MNG datastreams.
@@ -3880,7 +4455,7 @@ or any other MNG chunks; your application must provide its own support for
them. You may wish to consider using libmng (available at
http://www.libmng.com) instead.
-VII. Changes to Libpng from version 0.88
+VIII. Changes to Libpng from version 0.88
It should be noted that versions of libpng later than 0.96 are not
distributed by the original libpng author, Guy Schalnat, nor by
@@ -3915,6 +4490,9 @@ png_set_error_fn(), which is essentially the same function, but with a new
name to force compilation errors with applications that try to use the old
method.
+Support for the sCAL, iCCP, iTXt, and sPLT chunks was added at libpng-1.0.6;
+however, iTXt support was not enabled by default.
+
Starting with version 1.0.7, you can find out which version of the library
you are using at run-time:
@@ -3932,7 +4510,7 @@ application:
png_uint_32 application_vn = PNG_LIBPNG_VER;
-VIII. Changes to Libpng from version 1.0.x to 1.2.x
+IX. Changes to Libpng from version 1.0.x to 1.2.x
Support for user memory management was enabled by default. To
accomplish this, the functions png_create_read_struct_2(),
@@ -4029,7 +4607,7 @@ which also expands tRNS to alpha was replaced with
png_set_expand_gray_1_2_4_to_8()
which does not. It has been deprecated since libpng-1.0.18 and 1.2.9.
-IX. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x
+X. Changes to Libpng from version 1.0.x/1.2.x to 1.4.x
Private libpng prototypes and macro definitions were moved from
png.h and pngconf.h into a new pngpriv.h header file.
@@ -4122,14 +4700,16 @@ png_set_strip_error_numbers() was removed from the library by default.
The png_zalloc() and png_zfree() functions are no longer exported.
The png_zalloc() function no longer zeroes out the memory that it
-allocates.
+allocates. Applications that called png_zalloc(png_ptr, number, size)
+can call png_calloc(png_ptr, number*size) instead, and can call
+png_free() instead of png_zfree().
Support for dithering was disabled by default in libpng-1.4.0, because
it has not been well tested and doesn't actually "dither".
The code was not
removed, however, and could be enabled by building libpng with
PNG_READ_DITHER_SUPPORTED defined. In libpng-1.4.2, this support
-was reenabled, but the function was renamed png_set_quantize() to
+was re-enabled, but the function was renamed png_set_quantize() to
reflect more accurately what it actually does. At the same time,
the PNG_DITHER_[RED,GREEN_BLUE]_BITS macros were also renamed to
PNG_QUANTIZE_[RED,GREEN,BLUE]_BITS, and PNG_READ_DITHER_SUPPORTED
@@ -4137,37 +4717,61 @@ was renamed to PNG_READ_QUANTIZE_SUPPORTED.
We removed the trailing '.' from the warning and error messages.
-X. Changes to Libpng from version 1.4.x to 1.5.x
+XI. Changes to Libpng from version 1.4.x to 1.5.x
From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
function) incorrectly returned a value of type png_uint_32.
+The incorrect macro was removed from libpng-1.4.5.
-Checking for invalid palette index on read or write was added at libpng
-1.5.10. When an invalid index is found, libpng issues a benign error.
-This is enabled by default but can be disabled in each png_ptr with
+Checking for invalid palette index on write was added at libpng
+1.5.10. If a pixel contains an invalid (out-of-range) index libpng issues
+a benign error. This is enabled by default because this condition is an
+error according to the PNG specification, Clause 11.3.2, but the error can
+be ignored in each png_ptr with
png_set_check_for_invalid_index(png_ptr, allowed);
allowed - one of
- 0: disable
- 1: enable
+ 0: disable benign error (accept the
+ invalid data without warning).
+ 1: enable benign error (treat the
+ invalid data as an error or a
+ warning).
+
+If the error is ignored, or if png_benign_error() treats it as a warning,
+any invalid pixels are decoded as opaque black by the decoder and written
+as-is by the encoder.
+
+Retrieving the maximum palette index found was added at libpng-1.5.15.
+This statement must appear after png_read_png() or png_read_image() while
+reading, and after png_write_png() or png_write_image() while writing.
+
+ int max_palette = png_get_palette_max(png_ptr, info_ptr);
-A. Changes that affect users of libpng
+This will return the maximum palette index found in the image, or "-1" if
+the palette was not checked, or "0" if no palette was found. Note that this
+does not account for any palette index used by ancillary chunks such as the
+bKGD chunk; you must check those separately to determine the maximum
+palette index actually used.
There are no substantial API changes between the non-deprecated parts of
-the 1.4.5 API and the 1.5.0 API, however the ability to directly access
-the main libpng control structures, png_struct and png_info, deprecated
-in earlier versions of libpng, has been completely removed from
+the 1.4.5 API and the 1.5.0 API; however, the ability to directly access
+members of the main libpng control structures, png_struct and png_info,
+deprecated in earlier versions of libpng, has been completely removed from
libpng 1.5.
-We no longer include zlib.h in png.h. Applications that need access
-to information in zlib.h will need to add the '#include "zlib.h"'
-directive. It does not matter whether it is placed prior to or after
+We no longer include zlib.h in png.h. The include statement has been moved
+to pngstruct.h, where it is not accessible by applications. Applications that
+need access to information in zlib.h will need to add the '#include "zlib.h"'
+directive. It does not matter whether this is placed prior to or after
the '"#include png.h"' directive.
-We moved the png_strcpy(), png_strncpy(), png_strlen(), png_memcpy(),
-png_memcmp(), png_sprintf, and png_memcpy() macros into a private
-header file (pngpriv.h) that is not accessible to applications.
+The png_sprintf(), png_strcpy(), and png_strncpy() macros are no longer used
+and were removed.
+
+We moved the png_strlen(), png_memcpy(), png_memset(), and png_memcmp()
+macros into a private header file (pngpriv.h) that is not accessible to
+applications.
In png_get_iCCP, the type of "profile" was changed from png_charpp
to png_bytepp, and in png_set_iCCP, from png_charp to png_const_bytep.
@@ -4220,7 +4824,10 @@ and the accuracy of PNG fixed point values is insufficient for
representation of these values. Consequently a "string" API
(png_get_sCAL_s and png_set_sCAL_s) is the only reliable way of reading
arbitrary sCAL chunks in the absence of either the floating point API or
-internal floating point calculations.
+internal floating point calculations. Starting with libpng-1.5.0, both
+of these functions are present when PNG_sCAL_SUPPORTED is defined. Prior
+to libpng-1.5.0, their presence also depended upon PNG_FIXED_POINT_SUPPORTED
+being defined and PNG_FLOATING_POINT_SUPPORTED not being defined.
Applications no longer need to include the optional distribution header
file pngusr.h or define the corresponding macros during application
@@ -4240,15 +4847,10 @@ reset by pngusr.h or by explicit settings on the compiler command line.
These settings may produce compiler warnings or errors in 1.5.0 because
of macro redefinition.
-From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
-function) incorrectly returned a value of type png_uint_32. libpng 1.5.0
-is consistent with the implementation in 1.4.5 and 1.2.x (where the macro
-did not exist.)
-
Applications can now choose whether to use these macros or to call the
corresponding function by defining PNG_USE_READ_MACROS or
PNG_NO_USE_READ_MACROS before including png.h. Notice that this is
-only supported from 1.5.0 -defining PNG_NO_USE_READ_MACROS prior to 1.5.0
+only supported from 1.5.0; defining PNG_NO_USE_READ_MACROS prior to 1.5.0
will lead to a link failure.
Prior to libpng-1.5.4, the zlib compressor used the same set of parameters
@@ -4262,7 +4864,10 @@ option was off by default, and slightly inaccurate scaling occurred.
This option can no longer be turned off, and the choice of accurate
or inaccurate 16-to-8 scaling is by using the new png_set_scale_16_to_8()
API for accurate scaling or the old png_set_strip_16_to_8() API for simple
-chopping.
+chopping. In libpng-1.5.4, the PNG_READ_16_TO_8_ACCURATE_SCALE_SUPPORTED
+macro became PNG_READ_SCALE_16_TO_8_SUPPORTED, and the PNG_READ_16_TO_8
+macro became PNG_READ_STRIP_16_TO_8_SUPPORTED, to enable the two
+png_set_*_16_to_8() functions separately.
Prior to libpng-1.5.4, the png_set_user_limits() function could only be
used to reduce the width and height limits from the value of
@@ -4284,25 +4889,8 @@ limits are now
png_user_chunk_cache_max 0 (unlimited) 128
png_user_chunk_malloc_max 0 (unlimited) 8,000,000
-B. Changes to the build and configuration of libpng
-
-Details of internal changes to the library code can be found in the CHANGES
-file and in the GIT repository logs. These will be of no concern to the vast
-majority of library users or builders, however the few who configure libpng
-to a non-default feature set may need to change how this is done.
-
-There should be no need for library builders to alter build scripts if
-these use the distributed build support - configure or the makefiles -
-however users of the makefiles may care to update their build scripts
-to build pnglibconf.h where the corresponding makefile does not do so.
-
-Building libpng with a non-default configuration has changed completely.
-The old method using pngusr.h should still work correctly even though the
-way pngusr.h is used in the build has been changed; however, library
-builders will probably want to examine the changes to take advantage of
-new capabilities and to simplify their build system.
-
-B.1 Specific changes to library configuration capabilities
+The png_set_option() function (and the "options" member of the png struct) was
+added to libpng-1.5.15.
The library now supports a complete fixed point implementation and can
thus be used on systems that have no floating point support or very
@@ -4314,27 +4902,7 @@ independent of the choice of fixed versus floating point APIs and all the
missing fixed point APIs have been implemented.
The exact mechanism used to control attributes of API functions has
-changed. A single set of operating system independent macro definitions
-is used and operating system specific directives are defined in
-pnglibconf.h
-
-As part of this the mechanism used to choose procedure call standards on
-those systems that allow a choice has been changed. At present this only
-affects certain Microsoft (DOS, Windows) and IBM (OS/2) operating systems
-running on Intel processors. As before, PNGAPI is defined where required
-to control the exported API functions; however, two new macros, PNGCBAPI
-and PNGCAPI, are used instead for callback functions (PNGCBAPI) and
-(PNGCAPI) for functions that must match a C library prototype (currently
-only png_longjmp_ptr, which must match the C longjmp function.) The new
-approach is documented in pngconf.h
-
-Despite these changes, libpng 1.5.0 only supports the native C function
-calling standard on those platforms tested so far (__cdecl on Microsoft
-Windows). This is because the support requirements for alternative
-calling conventions seem to no longer exist. Developers who find it
-necessary to set PNG_API_RULE to 1 should advise the mailing list
-(png-mng-implement) of this and library builders who use Openwatcom and
-therefore set PNG_API_RULE to 2 should also contact the mailing list.
+changed, as described in the INSTALL file.
A new test program, pngvalid, is provided in addition to pngtest.
pngvalid validates the arithmetic accuracy of the gamma correction
@@ -4399,7 +4967,7 @@ merely stops the function from being exported.
PNG_FLOATING_ARITHMETIC_SUPPORTED chooses between the internal floating
point implementation or the fixed point one. Typically the fixed point
implementation is larger and slower than the floating point implementation
-on a system that supports floating point, however it may be faster on a
+on a system that supports floating point; however, it may be faster on a
system which lacks floating point hardware and therefore uses a software
emulation.
@@ -4410,47 +4978,138 @@ even though the default is to use the macros - this allows applications
to choose at app buildtime whether or not to use macros (previously
impossible because the functions weren't in the default build.)
-B.2 Changes to the configuration mechanism
-
-Prior to libpng-1.5.0 library builders who needed to configure libpng
-had either to modify the exported pngconf.h header file to add system
-specific configuration or had to write feature selection macros into
-pngusr.h and cause this to be included into pngconf.h by defining
-PNG_USER_CONFIG. The latter mechanism had the disadvantage that an
-application built without PNG_USER_CONFIG defined would see the
-unmodified, default, libpng API and thus would probably fail to link.
-
-These mechanisms still work in the configure build and in any makefile
-build that builds pnglibconf.h, although the feature selection macros
-have changed somewhat as described above. In 1.5.0, however, pngusr.h is
-processed only once, when the exported header file pnglibconf.h is built.
-pngconf.h no longer includes pngusr.h, therefore pngusr.h is ignored after the
-build of pnglibconf.h and it is never included in an application build.
-
-The rarely used alternative of adding a list of feature macros to the
-CFLAGS setting in the build also still works, however the macros will be
-copied to pnglibconf.h and this may produce macro redefinition warnings
-when the individual C files are compiled.
-
-All configuration now only works if pnglibconf.h is built from
-scripts/pnglibconf.dfa. This requires the program awk. Brian Kernighan
-(the original author of awk) maintains C source code of that awk and this
-and all known later implementations (often called by subtly different
-names - nawk and gawk for example) are adequate to build pnglibconf.h.
-The Sun Microsystems (now Oracle) program 'awk' is an earlier version
-and does not work; this may also apply to other systems that have a
-functioning awk called 'nawk'.
-
-Configuration options are now documented in scripts/pnglibconf.dfa. This
-file also includes dependency information that ensures a configuration is
-consistent; that is, if a feature is switched off dependent features are
-also removed. As a recommended alternative to using feature macros in
-pngusr.h a system builder may also define equivalent options in pngusr.dfa
-(or, indeed, any file) and add that to the configuration by setting
-DFA_XTRA to the file name. The makefiles in contrib/pngminim illustrate
-how to do this, and a case where pngusr.h is still required.
-
-XI. Detecting libpng
+XII. Changes to Libpng from version 1.5.x to 1.6.x
+
+A "simplified API" has been added (see documentation in png.h and a simple
+example in contrib/examples/pngtopng.c). The new publicly visible API
+includes the following:
+
+ macros:
+ PNG_FORMAT_*
+ PNG_IMAGE_*
+ structures:
+ png_control
+ png_image
+ read functions
+ png_image_begin_read_from_file()
+ png_image_begin_read_from_stdio()
+ png_image_begin_read_from_memory()
+ png_image_finish_read()
+ png_image_free()
+ write functions
+ png_image_write_to_file()
+ png_image_write_to_stdio()
+
+Starting with libpng-1.6.0, you can configure libpng to prefix all exported
+symbols, using the PNG_PREFIX macro.
+
+We no longer include string.h in png.h. The include statement has been moved
+to pngpriv.h, where it is not accessible by applications. Applications that
+need access to information in string.h must add an '#include <string.h>'
+directive. It does not matter whether this is placed prior to or after
+the '#include "png.h"' directive.
+
+The following API are now DEPRECATED:
+ png_info_init_3()
+ png_convert_to_rfc1123() which has been replaced
+ with png_convert_to_rfc1123_buffer()
+ png_malloc_default()
+ png_free_default()
+ png_reset_zstream()
+
+The following have been removed:
+ png_get_io_chunk_name(), which has been replaced
+ with png_get_io_chunk_type(). The new
+ function returns a 32-bit integer instead of
+ a string.
+ The png_sizeof(), png_strlen(), png_memcpy(), png_memcmp(), and
+ png_memset() macros are no longer used in the libpng sources and
+ have been removed. These had already been made invisible to applications
+ (i.e., defined in the private pngpriv.h header file) since libpng-1.5.0.
+
+The signatures of many exported functions were changed, such that
+ png_structp became png_structrp or png_const_structrp
+ png_infop became png_inforp or png_const_inforp
+where "rp" indicates a "restricted pointer".
+
+The support for FAR/far types has been eliminated and the definition of
+png_alloc_size_t is now controlled by a flag so that 'small size_t' systems
+can select it if necessary.
+
+Error detection in some chunks has improved; in particular the iCCP chunk
+reader now does pretty complete validation of the basic format. Some bad
+profiles that were previously accepted are now accepted with a warning or
+rejected, depending upon the png_set_benign_errors() setting, in particular
+the very old broken Microsoft/HP 3144-byte sRGB profile. Starting with
+libpng-1.6.11, recognizing and checking sRGB profiles can be avoided by
+means of
+
+ #if defined(PNG_SKIP_sRGB_CHECK_PROFILE) && \
+ defined(PNG_SET_OPTION_SUPPORTED)
+ png_set_option(png_ptr, PNG_SKIP_sRGB_CHECK_PROFILE,
+ PNG_OPTION_ON);
+ #endif
+
+It's not a good idea to do this if you are using the "simplified API",
+which needs to be able to recognize sRGB profiles conveyed via the iCCP
+chunk.
+
+The PNG spec requirement that only grayscale profiles may appear in images
+with color type 0 or 4 and that even if the image only contains gray pixels,
+only RGB profiles may appear in images with color type 2, 3, or 6, is now
+enforced. The sRGB chunk is allowed to appear in images with any color type
+and is interpreted by libpng to convey a one-tracer-curve gray profile or a
+three-tracer-curve RGB profile as appropriate.
+
+Prior to libpng-1.6.0 a warning would be issued if the iTXt chunk contained
+an empty language field or an empty translated keyword. Both of these
+are allowed by the PNG specification, so these warnings are no longer issued.
+
+The library now issues an error if the application attempts to set a
+transform after it calls png_read_update_info() or if it attempts to call
+both png_read_update_info() and png_start_read_image() or to call either
+of them more than once.
+
+The default condition for benign_errors is now to treat benign errors as
+warnings while reading and as errors while writing.
+
+The library now issues a warning if both background processing and RGB to
+gray are used when gamma correction happens. As with previous versions of
+the library the results are numerically very incorrect in this case.
+
+There are some minor arithmetic changes in some transforms such as
+png_set_background(), that might be detected by certain regression tests.
+
+Unknown chunk handling has been improved internally, without any API change.
+This adds more correct option control of the unknown handling, corrects
+a pre-existing bug where the per-chunk 'keep' setting is ignored, and makes
+it possible to skip IDAT chunks in the sequential reader.
+
+The machine-generated configure files are no longer included in branches
+libpng16 and later of the GIT repository. They continue to be included
+in the tarball releases, however.
+
+Libpng-1.6.0 through 1.6.2 used the CMF bytes at the beginning of the IDAT
+stream to set the size of the sliding window for reading instead of using the
+default 32-kbyte sliding window size. It was discovered that there are
+hundreds of PNG files in the wild that have incorrect CMF bytes that caused
+zlib to issue the "invalid distance too far back" error and reject the file.
+Libpng-1.6.3 and later calculate their own safe CMF from the image dimensions,
+provide a way to revert to the libpng-1.5.x behavior (ignoring the CMF bytes
+and using a 32-kbyte sliding window), by using
+
+ png_set_option(png_ptr, PNG_MAXIMUM_INFLATE_WINDOW,
+ PNG_OPTION_ON);
+
+and provide a tool (contrib/tools/pngfix) for rewriting a PNG file while
+optimizing the CMF bytes in its IDAT chunk correctly.
+
+Libpng-1.6.0 and libpng-1.6.1 wrote uncompressed iTXt chunks with the wrong
+length, which resulted in PNG files that cannot be read beyond the bad iTXt
+chunk. This error was fixed in libpng-1.6.3, and a tool (called
+contrib/tools/png-fix-itxt) has been added to the libpng distribution.
+
+XIII. Detecting libpng
The png_get_io_ptr() function has been present since libpng-0.88, has never
changed, and is unaffected by conditional compilation macros. It is the
@@ -4459,18 +5118,18 @@ libpng version since 0.88. In an autoconf "configure.in" you could use
AC_CHECK_LIB(png, png_get_io_ptr, ...
-XII. Source code repository
+XV. Source code repository
Since about February 2009, version 1.2.34, libpng has been under "git" source
control. The git repository was built from old libpng-x.y.z.tar.gz files
going back to version 0.70. You can access the git repository (read only)
at
- git://libpng.git.sourceforge.net/gitroot/libpng
+ git://git.code.sf.net/p/libpng/code
-or you can browse it via "gitweb" at
+or you can browse it with a web browser by selecting the "code" button at
- http://libpng.git.sourceforge.net/git/gitweb.cgi?p=libpng
+ https://sourceforge.net/projects/libpng
Patches can be sent to glennrp at users.sourceforge.net or to
png-mng-implement at lists.sourceforge.net or you can upload them to
@@ -4483,9 +5142,10 @@ simple verbal discriptions of bug fixes, reported either to the
SourceForge bug tracker, to the png-mng-implement at lists.sf.net
mailing list, or directly to glennrp.
-XIII. Coding style
+XV. Coding style
-Our coding style is similar to the "Allman" style, with curly
+Our coding style is similar to the "Allman" style
+(See http://en.wikipedia.org/wiki/Indent_style#Allman_style), with curly
braces on separate lines:
if (condition)
@@ -4548,6 +5208,9 @@ exported functions are marked with PNGAPI:
body;
}
+The return type and decorations are placed on a separate line
+ahead of the function name, as illustrated above.
+
The prototypes for all exported functions appear in png.h,
above the comment that says
@@ -4562,17 +5225,29 @@ We mark all non-exported functions with "/* PRIVATE */"":
}
The prototypes for non-exported functions (except for those in
-pngtest) appear in
-pngpriv.h
-above the comment that says
+pngtest) appear in pngpriv.h above the comment that says
- /* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+ /* Maintainer: Put new private prototypes here ^ */
To avoid polluting the global namespace, the names of all exported
functions and variables begin with "png_", and all publicly visible C
preprocessor macros begin with "PNG". We request that applications that
use libpng *not* begin any of their own symbols with either of these strings.
+We put a space after the "sizeof" operator and we omit the
+optional parentheses around its argument when the argument
+is an expression, not a type name, and we always enclose the
+sizeof operator, with its argument, in parentheses:
+
+ (sizeof (png_uint_32))
+ (sizeof array)
+
+Prior to libpng-1.6.0 we used a "png_sizeof()" macro, formatted as
+though it were a function.
+
+Control keywords if, for, while, and switch are always followed by a space
+to distinguish them from function calls, which have no trailing space.
+
We put a space after each comma and after each semicolon
in "for" statements, and we put spaces before and after each
C binary operator and after "for" or "while", and before
@@ -4583,44 +5258,52 @@ left parenthesis that follows it:
for (i = 2; i > 0; --i)
y[i] = a(x) + (int)b;
-We prefer #ifdef and #ifndef to #if defined() and if !defined()
-when there is only one macro being tested.
+We prefer #ifdef and #ifndef to #if defined() and #if !defined()
+when there is only one macro being tested. We always use parentheses
+with "defined".
We prefer to express integers that are used as bit masks in hex format,
with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100).
+We prefer to use underscores in variable names rather than camelCase, except
+for a few type names that we inherit from zlib.h.
+
+We prefer "if (something != 0)" and "if (something == 0)"
+over "if (something)" and if "(!something)", respectively.
+
We do not use the TAB character for indentation in the C sources.
Lines do not exceed 80 characters.
Other rules can be inferred by inspecting the libpng source.
-XIV. Y2K Compliance in libpng
+XVI. Y2K Compliance in libpng
-March 29, 2012
+March 26, 2015
Since the PNG Development group is an ad-hoc body, we can't make
an official declaration.
This is your unofficial assurance that libpng from version 0.71 and
-upward through 1.5.10 are Y2K compliant. It is my belief that earlier
+upward through 1.6.17 are Y2K compliant. It is my belief that earlier
versions were also Y2K compliant.
-Libpng only has three year fields. One is a 2-byte unsigned integer that
-will hold years up to 65535. The other two hold the date in text
-format, and will hold years up to 9999.
+Libpng only has two year fields. One is a 2-byte unsigned integer
+that will hold years up to 65535. The other, which is deprecated,
+holds the date in text format, and will hold years up to 9999.
The integer is
"png_uint_16 year" in png_time_struct.
-The strings are
- "png_charp time_buffer" in png_struct and
- "near_time_buffer", which is a local character string in png.c.
+The string is
+ "char time_buffer[29]" in png_struct. This is no longer used
+in libpng-1.6.x and will be removed from libpng-1.7.0.
There are seven time-related functions:
- png_convert_to_rfc_1123() in png.c
- (formerly png_convert_to_rfc_1152() in error)
+ png_convert_to_rfc_1123_buffer() in png.c
+ (formerly png_convert_to_rfc_1152() in error, and
+ also formerly png_convert_to_rfc_1123())
png_convert_from_struct_tm() in pngwrite.c, called
in pngwrite.c
png_convert_from_time_t() in pngwrite.c
diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c
index cba18ba915..7575ede97b 100644
--- a/src/3rdparty/libpng/png.c
+++ b/src/3rdparty/libpng/png.c
@@ -1,8 +1,8 @@
/* png.c - location for general purpose libpng functions
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,7 +14,7 @@
#include "pngpriv.h"
/* Generate a compiler error if there is an old png.h in the search path. */
-typedef png_libpng_version_1_5_10 Your_png_h_is_not_version_1_5_10;
+typedef png_libpng_version_1_6_17 Your_png_h_is_not_version_1_6_17;
/* Tells libpng that we have already handled the first "num_bytes" bytes
* of the PNG file signature. If the PNG data is embedded into another
@@ -24,7 +24,7 @@ typedef png_libpng_version_1_5_10 Your_png_h_is_not_version_1_5_10;
#ifdef PNG_READ_SUPPORTED
void PNGAPI
-png_set_sig_bytes(png_structp png_ptr, int num_bytes)
+png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
{
png_debug(1, "in png_set_sig_bytes");
@@ -34,7 +34,7 @@ png_set_sig_bytes(png_structp png_ptr, int num_bytes)
if (num_bytes > 8)
png_error(png_ptr, "Too many bytes for PNG signature");
- png_ptr->sig_bytes = (png_byte)(num_bytes < 0 ? 0 : num_bytes);
+ png_ptr->sig_bytes = (png_byte)((num_bytes < 0 ? 0 : num_bytes) & 0xff);
}
/* Checks whether the supplied bytes match the PNG signature. We allow
@@ -62,50 +62,44 @@ png_sig_cmp(png_const_bytep sig, png_size_t start, png_size_t num_to_check)
if (start + num_to_check > 8)
num_to_check = 8 - start;
- return ((int)(png_memcmp(&sig[start], &png_signature[start], num_to_check)));
+ return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* Function to allocate memory for zlib */
PNG_FUNCTION(voidpf /* PRIVATE */,
png_zalloc,(voidpf png_ptr, uInt items, uInt size),PNG_ALLOCATED)
{
- png_voidp ptr;
- png_structp p=(png_structp)png_ptr;
- png_uint_32 save_flags=p->flags;
- png_alloc_size_t num_bytes;
+ png_alloc_size_t num_bytes = size;
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
- if (items > PNG_UINT_32_MAX/size)
+ if (items >= (~(png_alloc_size_t)0)/size)
{
- png_warning (p, "Potential overflow in png_zalloc()");
- return (NULL);
+ png_warning (png_voidcast(png_structrp, png_ptr),
+ "Potential overflow in png_zalloc()");
+ return NULL;
}
- num_bytes = (png_alloc_size_t)items * size;
-
- p->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
- ptr = (png_voidp)png_malloc((png_structp)png_ptr, num_bytes);
- p->flags=save_flags;
- return ((voidpf)ptr);
+ num_bytes *= items;
+ return png_malloc_warn(png_voidcast(png_structrp, png_ptr), num_bytes);
}
/* Function to free memory for zlib */
void /* PRIVATE */
png_zfree(voidpf png_ptr, voidpf ptr)
{
- png_free((png_structp)png_ptr, (png_voidp)ptr);
+ png_free(png_voidcast(png_const_structrp,png_ptr), ptr);
}
/* Reset the CRC variable to 32 bits of 1's. Care must be taken
* in case CRC is > 32 bits to leave the top bits 0.
*/
void /* PRIVATE */
-png_reset_crc(png_structp png_ptr)
+png_reset_crc(png_structrp png_ptr)
{
/* The cast is safe because the crc is a 32 bit value. */
png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0);
@@ -117,11 +111,11 @@ png_reset_crc(png_structp png_ptr)
* trouble of calculating it.
*/
void /* PRIVATE */
-png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
+png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length)
{
int need_crc = 1;
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
@@ -130,33 +124,35 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
else /* critical */
{
- if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
need_crc = 0;
}
- /* 'uLong' is defined as unsigned long, this means that on some systems it is
- * a 64 bit value. crc32, however, returns 32 bits so the following cast is
- * safe. 'uInt' may be no more than 16 bits, so it is necessary to perform a
- * loop here.
+ /* 'uLong' is defined in zlib.h as unsigned long; this means that on some
+ * systems it is a 64 bit value. crc32, however, returns 32 bits so the
+ * following cast is safe. 'uInt' may be no more than 16 bits, so it is
+ * necessary to perform a loop here.
*/
- if (need_crc && length > 0)
+ if (need_crc != 0 && length > 0)
{
uLong crc = png_ptr->crc; /* Should never issue a warning */
do
{
- uInt safeLength = (uInt)length;
- if (safeLength == 0)
- safeLength = (uInt)-1; /* evil, but safe */
+ uInt safe_length = (uInt)length;
+#ifndef __COVERITY__
+ if (safe_length == 0)
+ safe_length = (uInt)-1; /* evil, but safe */
+#endif
- crc = crc32(crc, ptr, safeLength);
+ crc = crc32(crc, ptr, safe_length);
- /* The following should never issue compiler warnings, if they do the
+ /* The following should never issue compiler warnings; if they do the
* target system has characteristics that will probably violate other
* assumptions within the libpng code.
*/
- ptr += safeLength;
- length -= safeLength;
+ ptr += safe_length;
+ length -= safe_length;
}
while (length > 0);
@@ -166,97 +162,205 @@ png_calculate_crc(png_structp png_ptr, png_const_bytep ptr, png_size_t length)
}
/* Check a user supplied version number, called from both read and write
- * functions that create a png_struct
+ * functions that create a png_struct.
*/
int
-png_user_version_check(png_structp png_ptr, png_const_charp user_png_ver)
+png_user_version_check(png_structrp png_ptr, png_const_charp user_png_ver)
{
- if (user_png_ver)
+ /* Libpng versions 1.0.0 and later are binary compatible if the version
+ * string matches through the second '.'; we must recompile any
+ * applications that use any older library version.
+ */
+
+ if (user_png_ver != NULL)
{
- int i = 0;
+ int i = -1;
+ int found_dots = 0;
do
{
- if (user_png_ver[i] != png_libpng_ver[i])
+ i++;
+ if (user_png_ver[i] != PNG_LIBPNG_VER_STRING[i])
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- } while (png_libpng_ver[i++]);
+ if (user_png_ver[i] == '.')
+ found_dots++;
+ } while (found_dots < 2 && user_png_ver[i] != 0 &&
+ PNG_LIBPNG_VER_STRING[i] != 0);
}
else
png_ptr->flags |= PNG_FLAG_LIBRARY_MISMATCH;
- if (png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH)
+ if ((png_ptr->flags & PNG_FLAG_LIBRARY_MISMATCH) != 0)
{
- /* Libpng 0.90 and later are binary incompatible with libpng 0.89, so
- * we must recompile any applications that use any older library version.
- * For versions after libpng 1.0, we will be compatible, so we need
- * only check the first digit.
- */
- if (user_png_ver == NULL || user_png_ver[0] != png_libpng_ver[0] ||
- (user_png_ver[0] == '1' && user_png_ver[2] != png_libpng_ver[2]) ||
- (user_png_ver[0] == '0' && user_png_ver[2] < '9'))
- {
#ifdef PNG_WARNINGS_SUPPORTED
- size_t pos = 0;
- char m[128];
+ size_t pos = 0;
+ char m[128];
- pos = png_safecat(m, sizeof m, pos, "Application built with libpng-");
- pos = png_safecat(m, sizeof m, pos, user_png_ver);
- pos = png_safecat(m, sizeof m, pos, " but running with ");
- pos = png_safecat(m, sizeof m, pos, png_libpng_ver);
+ pos = png_safecat(m, (sizeof m), pos,
+ "Application built with libpng-");
+ pos = png_safecat(m, (sizeof m), pos, user_png_ver);
+ pos = png_safecat(m, (sizeof m), pos, " but running with ");
+ pos = png_safecat(m, (sizeof m), pos, PNG_LIBPNG_VER_STRING);
+ PNG_UNUSED(pos)
- png_warning(png_ptr, m);
+ png_warning(png_ptr, m);
#endif
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- png_ptr->flags = 0;
+ png_ptr->flags = 0;
#endif
- return 0;
- }
+ return 0;
}
/* Success return. */
return 1;
}
-/* Allocate the memory for an info_struct for the application. We don't
- * really need the png_ptr, but it could potentially be useful in the
- * future. This should be used in favour of malloc(png_sizeof(png_info))
- * and png_info_init() so that applications that want to use a shared
- * libpng don't have to be recompiled if png_info changes size.
+/* Generic function to create a png_struct for either read or write - this
+ * contains the common initialization.
*/
+PNG_FUNCTION(png_structp /* PRIVATE */,
+png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
+ png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
+ png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
+{
+ png_struct create_struct;
+# ifdef PNG_SETJMP_SUPPORTED
+ jmp_buf create_jmp_buf;
+# endif
+
+ /* This temporary stack-allocated structure is used to provide a place to
+ * build enough context to allow the user provided memory allocator (if any)
+ * to be called.
+ */
+ memset(&create_struct, 0, (sizeof create_struct));
+
+ /* Added at libpng-1.2.6 */
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ create_struct.user_width_max = PNG_USER_WIDTH_MAX;
+ create_struct.user_height_max = PNG_USER_HEIGHT_MAX;
+
+# ifdef PNG_USER_CHUNK_CACHE_MAX
+ /* Added at libpng-1.2.43 and 1.4.0 */
+ create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
+# endif
+
+# ifdef PNG_USER_CHUNK_MALLOC_MAX
+ /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists
+ * in png_struct regardless.
+ */
+ create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+# endif
+
+ /* The following two API calls simply set fields in png_struct, so it is safe
+ * to do them now even though error handling is not yet set up.
+ */
+# ifdef PNG_USER_MEM_SUPPORTED
+ png_set_mem_fn(&create_struct, mem_ptr, malloc_fn, free_fn);
+# else
+ PNG_UNUSED(mem_ptr)
+ PNG_UNUSED(malloc_fn)
+ PNG_UNUSED(free_fn)
+# endif
+
+ /* (*error_fn) can return control to the caller after the error_ptr is set,
+ * this will result in a memory leak unless the error_fn does something
+ * extremely sophisticated. The design lacks merit but is implicit in the
+ * API.
+ */
+ png_set_error_fn(&create_struct, error_ptr, error_fn, warn_fn);
+
+# ifdef PNG_SETJMP_SUPPORTED
+ if (!setjmp(create_jmp_buf))
+ {
+ /* Temporarily fake out the longjmp information until we have
+ * successfully completed this function. This only works if we have
+ * setjmp() support compiled in, but it is safe - this stuff should
+ * never happen.
+ */
+ create_struct.jmp_buf_ptr = &create_jmp_buf;
+ create_struct.jmp_buf_size = 0; /*stack allocation*/
+ create_struct.longjmp_fn = longjmp;
+# else
+ {
+# endif
+ /* Call the general version checker (shared with read and write code):
+ */
+ if (png_user_version_check(&create_struct, user_png_ver) != 0)
+ {
+ png_structrp png_ptr = png_voidcast(png_structrp,
+ png_malloc_warn(&create_struct, (sizeof *png_ptr)));
+
+ if (png_ptr != NULL)
+ {
+ /* png_ptr->zstream holds a back-pointer to the png_struct, so
+ * this can only be done now:
+ */
+ create_struct.zstream.zalloc = png_zalloc;
+ create_struct.zstream.zfree = png_zfree;
+ create_struct.zstream.opaque = png_ptr;
+
+# ifdef PNG_SETJMP_SUPPORTED
+ /* Eliminate the local error handling: */
+ create_struct.jmp_buf_ptr = NULL;
+ create_struct.jmp_buf_size = 0;
+ create_struct.longjmp_fn = 0;
+# endif
+
+ *png_ptr = create_struct;
+
+ /* This is the successful return point */
+ return png_ptr;
+ }
+ }
+ }
+
+ /* A longjmp because of a bug in the application storage allocator or a
+ * simple failure to allocate the png_struct.
+ */
+ return NULL;
+}
+
+/* Allocate the memory for an info_struct for the application. */
PNG_FUNCTION(png_infop,PNGAPI
-png_create_info_struct,(png_structp png_ptr),PNG_ALLOCATED)
+png_create_info_struct,(png_const_structrp png_ptr),PNG_ALLOCATED)
{
- png_infop info_ptr;
+ png_inforp info_ptr;
png_debug(1, "in png_create_info_struct");
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
+
+ /* Use the internal API that does not (or at least should not) error out, so
+ * that this call always returns ok. The application typically sets up the
+ * error handling *after* creating the info_struct because this is the way it
+ * has always been done in 'example.c'.
+ */
+ info_ptr = png_voidcast(png_inforp, png_malloc_base(png_ptr,
+ (sizeof *info_ptr)));
-#ifdef PNG_USER_MEM_SUPPORTED
- info_ptr = (png_infop)png_create_struct_2(PNG_STRUCT_INFO,
- png_ptr->malloc_fn, png_ptr->mem_ptr);
-#else
- info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
-#endif
if (info_ptr != NULL)
- png_info_init_3(&info_ptr, png_sizeof(png_info));
+ memset(info_ptr, 0, (sizeof *info_ptr));
- return (info_ptr);
+ return info_ptr;
}
/* This function frees the memory associated with a single info struct.
* Normally, one would use either png_destroy_read_struct() or
* png_destroy_write_struct() to free an info struct, but this may be
- * useful for some applications.
+ * useful for some applications. From libpng 1.6.0 this function is also used
+ * internally to implement the png_info release part of the 'struct' destroy
+ * APIs. This ensures that all possible approaches free the same data (all of
+ * it).
*/
void PNGAPI
-png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
+png_destroy_info_struct(png_const_structrp png_ptr, png_infopp info_ptr_ptr)
{
- png_infop info_ptr = NULL;
+ png_inforp info_ptr = NULL;
png_debug(1, "in png_destroy_info_struct");
@@ -268,46 +372,57 @@ png_destroy_info_struct(png_structp png_ptr, png_infopp info_ptr_ptr)
if (info_ptr != NULL)
{
- png_info_destroy(png_ptr, info_ptr);
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, png_ptr->free_fn,
- png_ptr->mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
+ /* Do this first in case of an error below; if the app implements its own
+ * memory management this can lead to png_free calling png_error, which
+ * will abort this routine and return control to the app error handler.
+ * An infinite loop may result if it then tries to free the same info
+ * ptr.
+ */
*info_ptr_ptr = NULL;
+
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
+ memset(info_ptr, 0, (sizeof *info_ptr));
+ png_free(png_ptr, info_ptr);
}
}
/* Initialize the info structure. This is now an internal function (0.89)
* and applications using it are urged to use png_create_info_struct()
- * instead.
+ * instead. Use deprecated in 1.6.0, internal use removed (used internally it
+ * is just a memset).
+ *
+ * NOTE: it is almost inconceivable that this API is used because it bypasses
+ * the user-memory mechanism and the user error handling/warning mechanisms in
+ * those cases where it does anything other than a memset.
*/
-
-void PNGAPI
-png_info_init_3(png_infopp ptr_ptr, png_size_t png_info_struct_size)
+PNG_FUNCTION(void,PNGAPI
+png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size),
+ PNG_DEPRECATED)
{
- png_infop info_ptr = *ptr_ptr;
+ png_inforp info_ptr = *ptr_ptr;
png_debug(1, "in png_info_init_3");
if (info_ptr == NULL)
return;
- if (png_sizeof(png_info) > png_info_struct_size)
+ if ((sizeof (png_info)) > png_info_struct_size)
{
- png_destroy_struct(info_ptr);
- info_ptr = (png_infop)png_create_struct(PNG_STRUCT_INFO);
+ *ptr_ptr = NULL;
+ /* The following line is why this API should not be used: */
+ free(info_ptr);
+ info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL,
+ (sizeof *info_ptr)));
*ptr_ptr = info_ptr;
}
/* Set everything to 0 */
- png_memset(info_ptr, 0, png_sizeof(png_info));
+ memset(info_ptr, 0, (sizeof *info_ptr));
}
+/* The following API is not called internally */
void PNGAPI
-png_data_freer(png_structp png_ptr, png_infop info_ptr,
+png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
int freer, png_uint_32 mask)
{
png_debug(1, "in png_data_freer");
@@ -322,12 +437,11 @@ png_data_freer(png_structp png_ptr, png_infop info_ptr,
info_ptr->free_me &= ~mask;
else
- png_warning(png_ptr,
- "Unknown freer parameter in png_data_freer");
+ png_error(png_ptr, "Unknown freer parameter in png_data_freer");
}
void PNGAPI
-png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
+png_free_data(png_const_structrp png_ptr, png_inforp info_ptr, png_uint_32 mask,
int num)
{
png_debug(1, "in png_free_data");
@@ -337,42 +451,43 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_TEXT_SUPPORTED
/* Free text item num or (if num == -1) all text items */
- if ((mask & PNG_FREE_TEXT) & info_ptr->free_me)
+ if (info_ptr->text != 0 &&
+ ((mask & PNG_FREE_TEXT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->text && info_ptr->text[num].key)
- {
- png_free(png_ptr, info_ptr->text[num].key);
- info_ptr->text[num].key = NULL;
- }
+ png_free(png_ptr, info_ptr->text[num].key);
+ info_ptr->text[num].key = NULL;
}
else
{
int i;
+
for (i = 0; i < info_ptr->num_text; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, i);
+ png_free(png_ptr, info_ptr->text[i].key);
+
png_free(png_ptr, info_ptr->text);
info_ptr->text = NULL;
- info_ptr->num_text=0;
+ info_ptr->num_text = 0;
}
}
#endif
#ifdef PNG_tRNS_SUPPORTED
/* Free any tRNS entry */
- if ((mask & PNG_FREE_TRNS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_TRNS) & info_ptr->free_me) != 0)
{
+ info_ptr->valid &= ~PNG_INFO_tRNS;
png_free(png_ptr, info_ptr->trans_alpha);
info_ptr->trans_alpha = NULL;
- info_ptr->valid &= ~PNG_INFO_tRNS;
+ info_ptr->num_trans = 0;
}
#endif
#ifdef PNG_sCAL_SUPPORTED
/* Free any sCAL entry */
- if ((mask & PNG_FREE_SCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_SCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->scal_s_width);
png_free(png_ptr, info_ptr->scal_s_height);
@@ -384,20 +499,20 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_pCAL_SUPPORTED
/* Free any pCAL entry */
- if ((mask & PNG_FREE_PCAL) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PCAL) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->pcal_purpose);
png_free(png_ptr, info_ptr->pcal_units);
info_ptr->pcal_purpose = NULL;
info_ptr->pcal_units = NULL;
+
if (info_ptr->pcal_params != NULL)
{
int i;
- for (i = 0; i < (int)info_ptr->pcal_nparams; i++)
- {
+
+ for (i = 0; i < info_ptr->pcal_nparams; i++)
png_free(png_ptr, info_ptr->pcal_params[i]);
- info_ptr->pcal_params[i] = NULL;
- }
+
png_free(png_ptr, info_ptr->pcal_params);
info_ptr->pcal_params = NULL;
}
@@ -406,8 +521,8 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
#ifdef PNG_iCCP_SUPPORTED
- /* Free any iCCP entry */
- if ((mask & PNG_FREE_ICCP) & info_ptr->free_me)
+ /* Free any profile entry */
+ if (((mask & PNG_FREE_ICCP) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->iccp_name);
png_free(png_ptr, info_ptr->iccp_profile);
@@ -419,74 +534,62 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_sPLT_SUPPORTED
/* Free a given sPLT entry, or (if num == -1) all sPLT entries */
- if ((mask & PNG_FREE_SPLT) & info_ptr->free_me)
+ if (info_ptr->splt_palettes != 0 &&
+ ((mask & PNG_FREE_SPLT) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->splt_palettes)
- {
- png_free(png_ptr, info_ptr->splt_palettes[num].name);
- png_free(png_ptr, info_ptr->splt_palettes[num].entries);
- info_ptr->splt_palettes[num].name = NULL;
- info_ptr->splt_palettes[num].entries = NULL;
- }
+ png_free(png_ptr, info_ptr->splt_palettes[num].name);
+ png_free(png_ptr, info_ptr->splt_palettes[num].entries);
+ info_ptr->splt_palettes[num].name = NULL;
+ info_ptr->splt_palettes[num].entries = NULL;
}
else
{
- if (info_ptr->splt_palettes_num)
- {
- int i;
- for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_SPLT, i);
+ int i;
- png_free(png_ptr, info_ptr->splt_palettes);
- info_ptr->splt_palettes = NULL;
- info_ptr->splt_palettes_num = 0;
+ for (i = 0; i < info_ptr->splt_palettes_num; i++)
+ {
+ png_free(png_ptr, info_ptr->splt_palettes[i].name);
+ png_free(png_ptr, info_ptr->splt_palettes[i].entries);
}
+
+ png_free(png_ptr, info_ptr->splt_palettes);
+ info_ptr->splt_palettes = NULL;
+ info_ptr->splt_palettes_num = 0;
info_ptr->valid &= ~PNG_INFO_sPLT;
}
}
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
- if (png_ptr->unknown_chunk.data)
- {
- png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- if ((mask & PNG_FREE_UNKN) & info_ptr->free_me)
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ if (info_ptr->unknown_chunks != 0 &&
+ ((mask & PNG_FREE_UNKN) & info_ptr->free_me) != 0)
{
if (num != -1)
{
- if (info_ptr->unknown_chunks)
- {
- png_free(png_ptr, info_ptr->unknown_chunks[num].data);
- info_ptr->unknown_chunks[num].data = NULL;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks[num].data);
+ info_ptr->unknown_chunks[num].data = NULL;
}
else
{
int i;
- if (info_ptr->unknown_chunks_num)
- {
- for (i = 0; i < info_ptr->unknown_chunks_num; i++)
- png_free_data(png_ptr, info_ptr, PNG_FREE_UNKN, i);
+ for (i = 0; i < info_ptr->unknown_chunks_num; i++)
+ png_free(png_ptr, info_ptr->unknown_chunks[i].data);
- png_free(png_ptr, info_ptr->unknown_chunks);
- info_ptr->unknown_chunks = NULL;
- info_ptr->unknown_chunks_num = 0;
- }
+ png_free(png_ptr, info_ptr->unknown_chunks);
+ info_ptr->unknown_chunks = NULL;
+ info_ptr->unknown_chunks_num = 0;
}
}
#endif
#ifdef PNG_hIST_SUPPORTED
/* Free any hIST entry */
- if ((mask & PNG_FREE_HIST) & info_ptr->free_me)
+ if (((mask & PNG_FREE_HIST) & info_ptr->free_me) != 0)
{
png_free(png_ptr, info_ptr->hist);
info_ptr->hist = NULL;
@@ -495,9 +598,9 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#endif
/* Free any PLTE entry that was internally allocated */
- if ((mask & PNG_FREE_PLTE) & info_ptr->free_me)
+ if (((mask & PNG_FREE_PLTE) & info_ptr->free_me) != 0)
{
- png_zfree(png_ptr, info_ptr->palette);
+ png_free(png_ptr, info_ptr->palette);
info_ptr->palette = NULL;
info_ptr->valid &= ~PNG_INFO_PLTE;
info_ptr->num_palette = 0;
@@ -505,16 +608,14 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Free any image bits attached to the info structure */
- if ((mask & PNG_FREE_ROWS) & info_ptr->free_me)
+ if (((mask & PNG_FREE_ROWS) & info_ptr->free_me) != 0)
{
- if (info_ptr->row_pointers)
+ if (info_ptr->row_pointers != 0)
{
- int row;
- for (row = 0; row < (int)info_ptr->height; row++)
- {
+ png_uint_32 row;
+ for (row = 0; row < info_ptr->height; row++)
png_free(png_ptr, info_ptr->row_pointers[row]);
- info_ptr->row_pointers[row] = NULL;
- }
+
png_free(png_ptr, info_ptr->row_pointers);
info_ptr->row_pointers = NULL;
}
@@ -527,37 +628,14 @@ png_free_data(png_structp png_ptr, png_infop info_ptr, png_uint_32 mask,
info_ptr->free_me &= ~mask;
}
-
-/* This is an internal routine to free any memory that the info struct is
- * pointing to before re-using it or freeing the struct itself. Recall
- * that png_free() checks for NULL pointers for us.
- */
-void /* PRIVATE */
-png_info_destroy(png_structp png_ptr, png_infop info_ptr)
-{
- png_debug(1, "in png_info_destroy");
-
- png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_ptr->num_chunk_list)
- {
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->chunk_list = NULL;
- png_ptr->num_chunk_list = 0;
- }
-#endif
-
- png_info_init_3(&info_ptr, png_sizeof(png_info));
-}
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+#endif /* READ || WRITE */
/* This function returns a pointer to the io_ptr associated with the user
* functions. The application should free any memory associated with this
* pointer before png_write_destroy() or png_read_destroy() are called.
*/
png_voidp PNGAPI
-png_get_io_ptr(png_structp png_ptr)
+png_get_io_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
@@ -574,7 +652,7 @@ png_get_io_ptr(png_structp png_ptr)
* function of your own because "FILE *" isn't necessarily available.
*/
void PNGAPI
-png_init_io(png_structp png_ptr, png_FILE_p fp)
+png_init_io(png_structrp png_ptr, png_FILE_p fp)
{
png_debug(1, "in png_init_io");
@@ -585,42 +663,52 @@ png_init_io(png_structp png_ptr, png_FILE_p fp)
}
# endif
+# ifdef PNG_SAVE_INT_32_SUPPORTED
+/* The png_save_int_32 function assumes integers are stored in two's
+ * complement format. If this isn't the case, then this routine needs to
+ * be modified to write data in two's complement format. Note that,
+ * the following works correctly even if png_int_32 has more than 32 bits
+ * (compare the more complex code required on read for sign extension.)
+ */
+void PNGAPI
+png_save_int_32(png_bytep buf, png_int_32 i)
+{
+ buf[0] = (png_byte)((i >> 24) & 0xff);
+ buf[1] = (png_byte)((i >> 16) & 0xff);
+ buf[2] = (png_byte)((i >> 8) & 0xff);
+ buf[3] = (png_byte)(i & 0xff);
+}
+# endif
+
# ifdef PNG_TIME_RFC1123_SUPPORTED
/* Convert the supplied time into an RFC 1123 string suitable for use in
* a "Creation Time" or other text-based time string.
*/
-png_const_charp PNGAPI
-png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime)
+int PNGAPI
+png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
{
static PNG_CONST char short_months[12][4] =
{"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
- if (png_ptr == NULL)
- return (NULL);
+ if (out == NULL)
+ return 0;
if (ptime->year > 9999 /* RFC1123 limitation */ ||
ptime->month == 0 || ptime->month > 12 ||
ptime->day == 0 || ptime->day > 31 ||
ptime->hour > 23 || ptime->minute > 59 ||
ptime->second > 60)
- {
- png_warning(png_ptr, "Ignoring invalid time value");
- return (NULL);
- }
+ return 0;
{
size_t pos = 0;
char number_buf[5]; /* enough for a four-digit year */
-# define APPEND_STRING(string)\
- pos = png_safecat(png_ptr->time_buffer, sizeof png_ptr->time_buffer,\
- pos, (string))
+# define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
# define APPEND_NUMBER(format, value)\
APPEND_STRING(PNG_FORMAT_NUMBER(number_buf, format, (value)))
-# define APPEND(ch)\
- if (pos < (sizeof png_ptr->time_buffer)-1)\
- png_ptr->time_buffer[pos++] = (ch)
+# define APPEND(ch) if (pos < 28) out[pos++] = (ch)
APPEND_NUMBER(PNG_NUMBER_FORMAT_u, (unsigned)ptime->day);
APPEND(' ');
@@ -640,14 +728,37 @@ png_convert_to_rfc1123(png_structp png_ptr, png_const_timep ptime)
# undef APPEND_STRING
}
- return png_ptr->time_buffer;
+ return 1;
+}
+
+# if PNG_LIBPNG_VER < 10700
+/* To do: remove the following from libpng-1.7 */
+/* Original API that uses a private buffer in png_struct.
+ * Deprecated because it causes png_struct to carry a spurious temporary
+ * buffer (png_struct::time_buffer), better to have the caller pass this in.
+ */
+png_const_charp PNGAPI
+png_convert_to_rfc1123(png_structrp png_ptr, png_const_timep ptime)
+{
+ if (png_ptr != NULL)
+ {
+ /* The only failure above if png_ptr != NULL is from an invalid ptime */
+ if (png_convert_to_rfc1123_buffer(png_ptr->time_buffer, ptime) == 0)
+ png_warning(png_ptr, "Ignoring invalid time value");
+
+ else
+ return png_ptr->time_buffer;
+ }
+
+ return NULL;
}
-# endif /* PNG_TIME_RFC1123_SUPPORTED */
+# endif /* LIBPNG_VER < 10700 */
+# endif /* TIME_RFC1123 */
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+#endif /* READ || WRITE */
png_const_charp PNGAPI
-png_get_copyright(png_const_structp png_ptr)
+png_get_copyright(png_const_structrp png_ptr)
{
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
#ifdef PNG_STRING_COPYRIGHT
@@ -655,14 +766,14 @@ png_get_copyright(png_const_structp png_ptr)
#else
# ifdef __STDC__
return PNG_STRING_NEWLINE \
- "libpng version 1.5.10 - March 29, 2012" PNG_STRING_NEWLINE \
- "Copyright (c) 1998-2011 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
+ "libpng version 1.6.17 - March 26, 2015" PNG_STRING_NEWLINE \
+ "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \
"Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
"Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \
PNG_STRING_NEWLINE;
# else
- return "libpng version 1.5.10 - March 29, 2012\
- Copyright (c) 1998-2011 Glenn Randers-Pehrson\
+ return "libpng version 1.6.17 - March 26, 2015\
+ Copyright (c) 1998-2015 Glenn Randers-Pehrson\
Copyright (c) 1996-1997 Andreas Dilger\
Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.";
# endif
@@ -678,14 +789,14 @@ png_get_copyright(png_const_structp png_ptr)
* it is guaranteed that png.c uses the correct version of png.h.
*/
png_const_charp PNGAPI
-png_get_libpng_ver(png_const_structp png_ptr)
+png_get_libpng_ver(png_const_structrp png_ptr)
{
/* Version of *.c files used when building libpng */
return png_get_header_ver(png_ptr);
}
png_const_charp PNGAPI
-png_get_header_ver(png_const_structp png_ptr)
+png_get_header_ver(png_const_structrp png_ptr)
{
/* Version of *.h files used when building libpng */
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
@@ -693,7 +804,7 @@ png_get_header_ver(png_const_structp png_ptr)
}
png_const_charp PNGAPI
-png_get_header_version(png_const_structp png_ptr)
+png_get_header_version(png_const_structrp png_ptr)
{
/* Returns longer string containing both version and date */
PNG_UNUSED(png_ptr) /* Silence compiler warning about unused png_ptr */
@@ -708,55 +819,122 @@ png_get_header_version(png_const_structp png_ptr)
#endif
}
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
+/* NOTE: this routine is not used internally! */
+/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
+ * large of png_color. This lets grayscale images be treated as
+ * paletted. Most useful for gamma correction and simplification
+ * of code. This API is not used internally.
+ */
+void PNGAPI
+png_build_grayscale_palette(int bit_depth, png_colorp palette)
+{
+ int num_palette;
+ int color_inc;
+ int i;
+ int v;
+
+ png_debug(1, "in png_do_build_grayscale_palette");
+
+ if (palette == NULL)
+ return;
+
+ switch (bit_depth)
+ {
+ case 1:
+ num_palette = 2;
+ color_inc = 0xff;
+ break;
+
+ case 2:
+ num_palette = 4;
+ color_inc = 0x55;
+ break;
+
+ case 4:
+ num_palette = 16;
+ color_inc = 0x11;
+ break;
+
+ case 8:
+ num_palette = 256;
+ color_inc = 1;
+ break;
+
+ default:
+ num_palette = 0;
+ color_inc = 0;
+ break;
+ }
+
+ for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
+ {
+ palette[i].red = (png_byte)(v & 0xff);
+ palette[i].green = (png_byte)(v & 0xff);
+ palette[i].blue = (png_byte)(v & 0xff);
+ }
+}
+#endif
+
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
int PNGAPI
-png_handle_as_unknown(png_structp png_ptr, png_const_bytep chunk_name)
+png_handle_as_unknown(png_const_structrp png_ptr, png_const_bytep chunk_name)
{
/* Check chunk_name and return "keep" value if it's on the list, else 0 */
png_const_bytep p, p_end;
- if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list <= 0)
+ if (png_ptr == NULL || chunk_name == NULL || png_ptr->num_chunk_list == 0)
return PNG_HANDLE_CHUNK_AS_DEFAULT;
p_end = png_ptr->chunk_list;
p = p_end + png_ptr->num_chunk_list*5; /* beyond end */
/* The code is the fifth byte after each four byte string. Historically this
- * code was always searched from the end of the list, so it should continue
- * to do so in case there are duplicated entries.
+ * code was always searched from the end of the list, this is no longer
+ * necessary because the 'set' routine handles duplicate entries correcty.
*/
do /* num_chunk_list > 0, so at least one */
{
p -= 5;
- if (!png_memcmp(chunk_name, p, 4))
+
+ if (memcmp(chunk_name, p, 4) == 0)
return p[4];
}
while (p > p_end);
+ /* This means that known chunks should be processed and unknown chunks should
+ * be handled according to the value of png_ptr->unknown_default; this can be
+ * confusing because, as a result, there are two levels of defaulting for
+ * unknown chunks.
+ */
return PNG_HANDLE_CHUNK_AS_DEFAULT;
}
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
int /* PRIVATE */
-png_chunk_unknown_handling(png_structp png_ptr, png_uint_32 chunk_name)
+png_chunk_unknown_handling(png_const_structrp png_ptr, png_uint_32 chunk_name)
{
png_byte chunk_string[5];
PNG_CSTRING_FROM_CHUNK(chunk_string, chunk_name);
return png_handle_as_unknown(png_ptr, chunk_string);
}
-#endif
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
+#endif /* SET_UNKNOWN_CHUNKS */
#ifdef PNG_READ_SUPPORTED
/* This function, added to libpng-1.0.6g, is untested. */
int PNGAPI
-png_reset_zstream(png_structp png_ptr)
+png_reset_zstream(png_structrp png_ptr)
{
if (png_ptr == NULL)
return Z_STREAM_ERROR;
+ /* WARNING: this resets the window bits to the maximum! */
return (inflateReset(&png_ptr->zstream));
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
/* This function was added to libpng-1.0.7 */
png_uint_32 PNGAPI
@@ -766,126 +944,291 @@ png_access_version_number(void)
return((png_uint_32)PNG_LIBPNG_VER);
}
+#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
+/* Ensure that png_ptr->zstream.msg holds some appropriate error message string.
+ * If it doesn't 'ret' is used to set it to something appropriate, even in cases
+ * like Z_OK or Z_STREAM_END where the error code is apparently a success code.
+ */
+void /* PRIVATE */
+png_zstream_error(png_structrp png_ptr, int ret)
+{
+ /* Translate 'ret' into an appropriate error string, priority is given to the
+ * one in zstream if set. This always returns a string, even in cases like
+ * Z_OK or Z_STREAM_END where the error code is a success code.
+ */
+ if (png_ptr->zstream.msg == NULL) switch (ret)
+ {
+ default:
+ case Z_OK:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return code");
+ break;
+
+ case Z_STREAM_END:
+ /* Normal exit */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected end of LZ stream");
+ break;
+ case Z_NEED_DICT:
+ /* This means the deflate stream did not have a dictionary; this
+ * indicates a bogus PNG.
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("missing LZ dictionary");
+ break;
+
+ case Z_ERRNO:
+ /* gz APIs only: should not happen */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zlib IO error");
+ break;
+
+ case Z_STREAM_ERROR:
+ /* internal libpng error */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("bad parameters to zlib");
+ break;
+
+ case Z_DATA_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("damaged LZ stream");
+ break;
+
+ case Z_MEM_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("insufficient memory");
+ break;
+
+ case Z_BUF_ERROR:
+ /* End of input or output; not a problem if the caller is doing
+ * incremental read or write.
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("truncated");
+ break;
+
+ case Z_VERSION_ERROR:
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unsupported zlib version");
+ break;
+
+ case PNG_UNEXPECTED_ZLIB_RETURN:
+ /* Compile errors here mean that zlib now uses the value co-opted in
+ * pngpriv.h for PNG_UNEXPECTED_ZLIB_RETURN; update the switch above
+ * and change pngpriv.h. Note that this message is "... return",
+ * whereas the default/Z_OK one is "... return code".
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("unexpected zlib return");
+ break;
+ }
+}
-#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
/* png_convert_size: a PNGAPI but no longer in png.h, so deleted
* at libpng 1.5.5!
*/
/* Added at libpng version 1.2.34 and 1.4.0 (moved from pngset.c) */
-# ifdef PNG_CHECK_cHRM_SUPPORTED
-
-int /* PRIVATE */
-png_check_cHRM_fixed(png_structp png_ptr,
- png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
- png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
- png_fixed_point blue_x, png_fixed_point blue_y)
+#ifdef PNG_GAMMA_SUPPORTED /* always set if COLORSPACE */
+static int
+png_colorspace_check_gamma(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA, int from)
+ /* This is called to check a new gamma value against an existing one. The
+ * routine returns false if the new gamma value should not be written.
+ *
+ * 'from' says where the new gamma value comes from:
+ *
+ * 0: the new gamma value is the libpng estimate for an ICC profile
+ * 1: the new gamma value comes from a gAMA chunk
+ * 2: the new gamma value comes from an sRGB chunk
+ */
{
- int ret = 1;
- unsigned long xy_hi,xy_lo,yx_hi,yx_lo;
+ png_fixed_point gtest;
- png_debug(1, "in function png_check_cHRM_fixed");
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ (png_muldiv(&gtest, colorspace->gamma, PNG_FP_1, gAMA) == 0 ||
+ png_gamma_significant(gtest) != 0))
+ {
+ /* Either this is an sRGB image, in which case the calculated gamma
+ * approximation should match, or this is an image with a profile and the
+ * value libpng calculates for the gamma of the profile does not match the
+ * value recorded in the file. The former, sRGB, case is an error, the
+ * latter is just a warning.
+ */
+ if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0 || from == 2)
+ {
+ png_chunk_report(png_ptr, "gamma value does not match sRGB",
+ PNG_CHUNK_ERROR);
+ /* Do not overwrite an sRGB value */
+ return from == 2;
+ }
- if (png_ptr == NULL)
- return 0;
+ else /* sRGB tag not involved */
+ {
+ png_chunk_report(png_ptr, "gamma value does not match libpng estimate",
+ PNG_CHUNK_WARNING);
+ return from == 1;
+ }
+ }
+
+ return 1;
+}
- /* (x,y,z) values are first limited to 0..100000 (PNG_FP_1), the white
- * y must also be greater than 0. To test for the upper limit calculate
- * (PNG_FP_1-y) - x must be <= to this for z to be >= 0 (and the expression
- * cannot overflow.) At this point we know x and y are >= 0 and (x+y) is
- * <= PNG_FP_1. The previous test on PNG_MAX_UINT_31 is removed because it
- * pointless (and it produces compiler warnings!)
+void /* PRIVATE */
+png_colorspace_set_gamma(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA)
+{
+ /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
+ * occur. Since the fixed point representation is asymetrical it is
+ * possible for 1/gamma to overflow the limit of 21474 and this means the
+ * gamma value must be at least 5/100000 and hence at most 20000.0. For
+ * safety the limits here are a little narrower. The values are 0.00016 to
+ * 6250.0, which are truly ridiculous gamma values (and will produce
+ * displays that are all black or all white.)
+ *
+ * In 1.6.0 this test replaces the ones in pngrutil.c, in the gAMA chunk
+ * handling code, which only required the value to be >0.
*/
- if (white_x < 0 || white_y <= 0 ||
- red_x < 0 || red_y < 0 ||
- green_x < 0 || green_y < 0 ||
- blue_x < 0 || blue_y < 0)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set negative chromaticity value");
- ret = 0;
- }
- /* And (x+y) must be <= PNG_FP_1 (so z is >= 0) */
- if (white_x > PNG_FP_1 - white_y)
- {
- png_warning(png_ptr, "Invalid cHRM white point");
- ret = 0;
- }
+ png_const_charp errmsg;
- if (red_x > PNG_FP_1 - red_y)
+ if (gAMA < 16 || gAMA > 625000000)
+ errmsg = "gamma value out of range";
+
+# ifdef PNG_READ_gAMA_SUPPORTED
+ /* Allow the application to set the gamma value more than once */
+ else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0)
+ errmsg = "duplicate";
+# endif
+
+ /* Do nothing if the colorspace is already invalid */
+ else if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return;
+
+ else
{
- png_warning(png_ptr, "Invalid cHRM red point");
- ret = 0;
+ if (png_colorspace_check_gamma(png_ptr, colorspace, gAMA,
+ 1/*from gAMA*/) != 0)
+ {
+ /* Store this gamma value. */
+ colorspace->gamma = gAMA;
+ colorspace->flags |=
+ (PNG_COLORSPACE_HAVE_GAMMA | PNG_COLORSPACE_FROM_gAMA);
+ }
+
+ /* At present if the check_gamma test fails the gamma of the colorspace is
+ * not updated however the colorspace is not invalidated. This
+ * corresponds to the case where the existing gamma comes from an sRGB
+ * chunk or profile. An error message has already been output.
+ */
+ return;
}
- if (green_x > PNG_FP_1 - green_y)
+ /* Error exit - errmsg has been set. */
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_chunk_report(png_ptr, errmsg, PNG_CHUNK_WRITE_ERROR);
+}
+
+void /* PRIVATE */
+png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr)
+{
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{
- png_warning(png_ptr, "Invalid cHRM green point");
- ret = 0;
+ /* Everything is invalid */
+ info_ptr->valid &= ~(PNG_INFO_gAMA|PNG_INFO_cHRM|PNG_INFO_sRGB|
+ PNG_INFO_iCCP);
+
+# ifdef PNG_COLORSPACE_SUPPORTED
+ /* Clean up the iCCP profile now if it won't be used. */
+ png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/);
+# else
+ PNG_UNUSED(png_ptr)
+# endif
}
- if (blue_x > PNG_FP_1 - blue_y)
+ else
{
- png_warning(png_ptr, "Invalid cHRM blue point");
- ret = 0;
- }
+# ifdef PNG_COLORSPACE_SUPPORTED
+ /* Leave the INFO_iCCP flag set if the pngset.c code has already set
+ * it; this allows a PNG to contain a profile which matches sRGB and
+ * yet still have that profile retrievable by the application.
+ */
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0)
+ info_ptr->valid |= PNG_INFO_sRGB;
- png_64bit_product(green_x - red_x, blue_y - red_y, &xy_hi, &xy_lo);
- png_64bit_product(green_y - red_y, blue_x - red_x, &yx_hi, &yx_lo);
+ else
+ info_ptr->valid &= ~PNG_INFO_sRGB;
- if (xy_hi == yx_hi && xy_lo == yx_lo)
- {
- png_warning(png_ptr,
- "Ignoring attempt to set cHRM RGB triangle with zero area");
- ret = 0;
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ info_ptr->valid |= PNG_INFO_cHRM;
+
+ else
+ info_ptr->valid &= ~PNG_INFO_cHRM;
+# endif
+
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0)
+ info_ptr->valid |= PNG_INFO_gAMA;
+
+ else
+ info_ptr->valid &= ~PNG_INFO_gAMA;
}
+}
- return ret;
+#ifdef PNG_READ_SUPPORTED
+void /* PRIVATE */
+png_colorspace_sync(png_const_structrp png_ptr, png_inforp info_ptr)
+{
+ if (info_ptr == NULL) /* reduce code size; check here not in the caller */
+ return;
+
+ info_ptr->colorspace = png_ptr->colorspace;
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
-# endif /* PNG_CHECK_cHRM_SUPPORTED */
+#endif
+#endif /* GAMMA */
-#ifdef PNG_cHRM_SUPPORTED
+#ifdef PNG_COLORSPACE_SUPPORTED
/* Added at libpng-1.5.5 to support read and write of true CIEXYZ values for
* cHRM, as opposed to using chromaticities. These internal APIs return
* non-zero on a parameter error. The X, Y and Z values are required to be
* positive and less than 1.0.
*/
-int png_xy_from_XYZ(png_xy *xy, png_XYZ XYZ)
+static int
+png_xy_from_XYZ(png_xy *xy, const png_XYZ *XYZ)
{
png_int_32 d, dwhite, whiteX, whiteY;
- d = XYZ.redX + XYZ.redY + XYZ.redZ;
- if (!png_muldiv(&xy->redx, XYZ.redX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->redy, XYZ.redY, PNG_FP_1, d)) return 1;
+ d = XYZ->red_X + XYZ->red_Y + XYZ->red_Z;
+ if (png_muldiv(&xy->redx, XYZ->red_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->redy, XYZ->red_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite = d;
- whiteX = XYZ.redX;
- whiteY = XYZ.redY;
+ whiteX = XYZ->red_X;
+ whiteY = XYZ->red_Y;
- d = XYZ.greenX + XYZ.greenY + XYZ.greenZ;
- if (!png_muldiv(&xy->greenx, XYZ.greenX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->greeny, XYZ.greenY, PNG_FP_1, d)) return 1;
+ d = XYZ->green_X + XYZ->green_Y + XYZ->green_Z;
+ if (png_muldiv(&xy->greenx, XYZ->green_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->greeny, XYZ->green_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite += d;
- whiteX += XYZ.greenX;
- whiteY += XYZ.greenY;
+ whiteX += XYZ->green_X;
+ whiteY += XYZ->green_Y;
- d = XYZ.blueX + XYZ.blueY + XYZ.blueZ;
- if (!png_muldiv(&xy->bluex, XYZ.blueX, PNG_FP_1, d)) return 1;
- if (!png_muldiv(&xy->bluey, XYZ.blueY, PNG_FP_1, d)) return 1;
+ d = XYZ->blue_X + XYZ->blue_Y + XYZ->blue_Z;
+ if (png_muldiv(&xy->bluex, XYZ->blue_X, PNG_FP_1, d) == 0)
+ return 1;
+ if (png_muldiv(&xy->bluey, XYZ->blue_Y, PNG_FP_1, d) == 0)
+ return 1;
dwhite += d;
- whiteX += XYZ.blueX;
- whiteY += XYZ.blueY;
+ whiteX += XYZ->blue_X;
+ whiteY += XYZ->blue_Y;
- /* The reference white is simply the same of the end-point (X,Y,Z) vectors,
+ /* The reference white is simply the sum of the end-point (X,Y,Z) vectors,
* thus:
*/
- if (!png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite)) return 1;
- if (!png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite)) return 1;
+ if (png_muldiv(&xy->whitex, whiteX, PNG_FP_1, dwhite) == 0)
+ return 1;
+ if (png_muldiv(&xy->whitey, whiteY, PNG_FP_1, dwhite) == 0)
+ return 1;
return 0;
}
-int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
+static int
+png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy)
{
png_fixed_point red_inverse, green_inverse, blue_scale;
png_fixed_point left, right, denominator;
@@ -894,14 +1237,14 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
* have end points with 0 tristimulus values (these are impossible end
* points, but they are used to cover the possible colors.)
*/
- if (xy.redx < 0 || xy.redx > PNG_FP_1) return 1;
- if (xy.redy < 0 || xy.redy > PNG_FP_1-xy.redx) return 1;
- if (xy.greenx < 0 || xy.greenx > PNG_FP_1) return 1;
- if (xy.greeny < 0 || xy.greeny > PNG_FP_1-xy.greenx) return 1;
- if (xy.bluex < 0 || xy.bluex > PNG_FP_1) return 1;
- if (xy.bluey < 0 || xy.bluey > PNG_FP_1-xy.bluex) return 1;
- if (xy.whitex < 0 || xy.whitex > PNG_FP_1) return 1;
- if (xy.whitey < 0 || xy.whitey > PNG_FP_1-xy.whitex) return 1;
+ if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1;
+ if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1;
+ if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1;
+ if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1;
+ if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1;
+ if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1;
+ if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1;
+ if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1;
/* The reverse calculation is more difficult because the original tristimulus
* value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8
@@ -969,14 +1312,14 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
* and it is certain that it becomes unstable where the end points are close
* together.
*
- * So this code uses the perhaps slighly less optimal but more understandable
- * and totally obvious approach of calculating color-scale.
+ * So this code uses the perhaps slightly less optimal but more
+ * understandable and totally obvious approach of calculating color-scale.
*
* This algorithm depends on the precision in white-scale and that is
* (1/white-y), so we can immediately see that as white-y approaches 0 the
* accuracy inherent in the cHRM chunk drops off substantially.
*
- * libpng arithmetic: a simple invertion of the above equations
+ * libpng arithmetic: a simple inversion of the above equations
* ------------------------------------------------------------
*
* white_scale = 1/white-y
@@ -1082,91 +1425,1050 @@ int png_XYZ_from_xy(png_XYZ *XYZ, png_xy xy)
/* By the argument, above overflow should be impossible here. The return
* value of 2 indicates an internal error to the caller.
*/
- if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.redy - xy.bluey, 7)) return 2;
- if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.redx - xy.bluex, 7)) return 2;
+ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->redy - xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->greeny-xy->bluey, xy->redx - xy->bluex, 7) == 0)
+ return 2;
denominator = left - right;
/* Now find the red numerator. */
- if (!png_muldiv(&left, xy.greenx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
- if (!png_muldiv(&right, xy.greeny-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
+ if (png_muldiv(&left, xy->greenx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->greeny-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+ return 2;
/* Overflow is possible here and it indicates an extreme set of PNG cHRM
* chunk values. This calculation actually returns the reciprocal of the
* scale value because this allows us to delay the multiplication of white-y
* into the denominator, which tends to produce a small number.
*/
- if (!png_muldiv(&red_inverse, xy.whitey, denominator, left-right) ||
- red_inverse <= xy.whitey /* r+g+b scales = white scale */)
+ if (png_muldiv(&red_inverse, xy->whitey, denominator, left-right) == 0 ||
+ red_inverse <= xy->whitey /* r+g+b scales = white scale */)
return 1;
/* Similarly for green_inverse: */
- if (!png_muldiv(&left, xy.redy-xy.bluey, xy.whitex-xy.bluex, 7)) return 2;
- if (!png_muldiv(&right, xy.redx-xy.bluex, xy.whitey-xy.bluey, 7)) return 2;
- if (!png_muldiv(&green_inverse, xy.whitey, denominator, left-right) ||
- green_inverse <= xy.whitey)
+ if (png_muldiv(&left, xy->redy-xy->bluey, xy->whitex-xy->bluex, 7) == 0)
+ return 2;
+ if (png_muldiv(&right, xy->redx-xy->bluex, xy->whitey-xy->bluey, 7) == 0)
+ return 2;
+ if (png_muldiv(&green_inverse, xy->whitey, denominator, left-right) == 0 ||
+ green_inverse <= xy->whitey)
return 1;
/* And the blue scale, the checks above guarantee this can't overflow but it
* can still produce 0 for extreme cHRM values.
*/
- blue_scale = png_reciprocal(xy.whitey) - png_reciprocal(red_inverse) -
- png_reciprocal(green_inverse);
- if (blue_scale <= 0) return 1;
+ blue_scale = png_reciprocal(xy->whitey) - png_reciprocal(red_inverse) -
+ png_reciprocal(green_inverse);
+ if (blue_scale <= 0)
+ return 1;
/* And fill in the png_XYZ: */
- if (!png_muldiv(&XYZ->redX, xy.redx, PNG_FP_1, red_inverse)) return 1;
- if (!png_muldiv(&XYZ->redY, xy.redy, PNG_FP_1, red_inverse)) return 1;
- if (!png_muldiv(&XYZ->redZ, PNG_FP_1 - xy.redx - xy.redy, PNG_FP_1,
- red_inverse))
+ if (png_muldiv(&XYZ->red_X, xy->redx, PNG_FP_1, red_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Y, xy->redy, PNG_FP_1, red_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Z, PNG_FP_1 - xy->redx - xy->redy, PNG_FP_1,
+ red_inverse) == 0)
return 1;
- if (!png_muldiv(&XYZ->greenX, xy.greenx, PNG_FP_1, green_inverse)) return 1;
- if (!png_muldiv(&XYZ->greenY, xy.greeny, PNG_FP_1, green_inverse)) return 1;
- if (!png_muldiv(&XYZ->greenZ, PNG_FP_1 - xy.greenx - xy.greeny, PNG_FP_1,
- green_inverse))
+ if (png_muldiv(&XYZ->green_X, xy->greenx, PNG_FP_1, green_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Y, xy->greeny, PNG_FP_1, green_inverse) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Z, PNG_FP_1 - xy->greenx - xy->greeny, PNG_FP_1,
+ green_inverse) == 0)
return 1;
- if (!png_muldiv(&XYZ->blueX, xy.bluex, blue_scale, PNG_FP_1)) return 1;
- if (!png_muldiv(&XYZ->blueY, xy.bluey, blue_scale, PNG_FP_1)) return 1;
- if (!png_muldiv(&XYZ->blueZ, PNG_FP_1 - xy.bluex - xy.bluey, blue_scale,
- PNG_FP_1))
+ if (png_muldiv(&XYZ->blue_X, xy->bluex, blue_scale, PNG_FP_1) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Y, xy->bluey, blue_scale, PNG_FP_1) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Z, PNG_FP_1 - xy->bluex - xy->bluey, blue_scale,
+ PNG_FP_1) == 0)
return 1;
return 0; /*success*/
}
-int png_XYZ_from_xy_checked(png_structp png_ptr, png_XYZ *XYZ, png_xy xy)
+static int
+png_XYZ_normalize(png_XYZ *XYZ)
{
- switch (png_XYZ_from_xy(XYZ, xy))
+ png_int_32 Y;
+
+ if (XYZ->red_Y < 0 || XYZ->green_Y < 0 || XYZ->blue_Y < 0 ||
+ XYZ->red_X < 0 || XYZ->green_X < 0 || XYZ->blue_X < 0 ||
+ XYZ->red_Z < 0 || XYZ->green_Z < 0 || XYZ->blue_Z < 0)
+ return 1;
+
+ /* Normalize by scaling so the sum of the end-point Y values is PNG_FP_1.
+ * IMPLEMENTATION NOTE: ANSI requires signed overflow not to occur, therefore
+ * relying on addition of two positive values producing a negative one is not
+ * safe.
+ */
+ Y = XYZ->red_Y;
+ if (0x7fffffff - Y < XYZ->green_X)
+ return 1;
+ Y += XYZ->green_Y;
+ if (0x7fffffff - Y < XYZ->blue_X)
+ return 1;
+ Y += XYZ->blue_Y;
+
+ if (Y != PNG_FP_1)
{
- case 0: /* success */
+ if (png_muldiv(&XYZ->red_X, XYZ->red_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Y, XYZ->red_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->red_Z, XYZ->red_Z, PNG_FP_1, Y) == 0)
+ return 1;
+
+ if (png_muldiv(&XYZ->green_X, XYZ->green_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Y, XYZ->green_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->green_Z, XYZ->green_Z, PNG_FP_1, Y) == 0)
return 1;
+ if (png_muldiv(&XYZ->blue_X, XYZ->blue_X, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Y, XYZ->blue_Y, PNG_FP_1, Y) == 0)
+ return 1;
+ if (png_muldiv(&XYZ->blue_Z, XYZ->blue_Z, PNG_FP_1, Y) == 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+static int
+png_colorspace_endpoints_match(const png_xy *xy1, const png_xy *xy2, int delta)
+{
+ /* Allow an error of +/-0.01 (absolute value) on each chromaticity */
+ if (PNG_OUT_OF_RANGE(xy1->whitex, xy2->whitex,delta) ||
+ PNG_OUT_OF_RANGE(xy1->whitey, xy2->whitey,delta) ||
+ PNG_OUT_OF_RANGE(xy1->redx, xy2->redx, delta) ||
+ PNG_OUT_OF_RANGE(xy1->redy, xy2->redy, delta) ||
+ PNG_OUT_OF_RANGE(xy1->greenx, xy2->greenx,delta) ||
+ PNG_OUT_OF_RANGE(xy1->greeny, xy2->greeny,delta) ||
+ PNG_OUT_OF_RANGE(xy1->bluex, xy2->bluex, delta) ||
+ PNG_OUT_OF_RANGE(xy1->bluey, xy2->bluey, delta))
+ return 0;
+ return 1;
+}
+
+/* Added in libpng-1.6.0, a different check for the validity of a set of cHRM
+ * chunk chromaticities. Earlier checks used to simply look for the overflow
+ * condition (where the determinant of the matrix to solve for XYZ ends up zero
+ * because the chromaticity values are not all distinct.) Despite this it is
+ * theoretically possible to produce chromaticities that are apparently valid
+ * but that rapidly degrade to invalid, potentially crashing, sets because of
+ * arithmetic inaccuracies when calculations are performed on them. The new
+ * check is to round-trip xy -> XYZ -> xy and then check that the result is
+ * within a small percentage of the original.
+ */
+static int
+png_colorspace_check_xy(png_XYZ *XYZ, const png_xy *xy)
+{
+ int result;
+ png_xy xy_test;
+
+ /* As a side-effect this routine also returns the XYZ endpoints. */
+ result = png_XYZ_from_xy(XYZ, xy);
+ if (result != 0)
+ return result;
+
+ result = png_xy_from_XYZ(&xy_test, XYZ);
+ if (result != 0)
+ return result;
+
+ if (png_colorspace_endpoints_match(xy, &xy_test,
+ 5/*actually, the math is pretty accurate*/) != 0)
+ return 0;
+
+ /* Too much slip */
+ return 1;
+}
+
+/* This is the check going the other way. The XYZ is modified to normalize it
+ * (another side-effect) and the xy chromaticities are returned.
+ */
+static int
+png_colorspace_check_XYZ(png_xy *xy, png_XYZ *XYZ)
+{
+ int result;
+ png_XYZ XYZtemp;
+
+ result = png_XYZ_normalize(XYZ);
+ if (result != 0)
+ return result;
+
+ result = png_xy_from_XYZ(xy, XYZ);
+ if (result != 0)
+ return result;
+
+ XYZtemp = *XYZ;
+ return png_colorspace_check_xy(&XYZtemp, xy);
+}
+
+/* Used to check for an endpoint match against sRGB */
+static const png_xy sRGB_xy = /* From ITU-R BT.709-3 */
+{
+ /* color x y */
+ /* red */ 64000, 33000,
+ /* green */ 30000, 60000,
+ /* blue */ 15000, 6000,
+ /* white */ 31270, 32900
+};
+
+static int
+png_colorspace_set_xy_and_XYZ(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_xy *xy, const png_XYZ *XYZ,
+ int preferred)
+{
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ /* The consistency check is performed on the chromaticities; this factors out
+ * variations because of the normalization (or not) of the end point Y
+ * values.
+ */
+ if (preferred < 2 &&
+ (colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ /* The end points must be reasonably close to any we already have. The
+ * following allows an error of up to +/-.001
+ */
+ if (png_colorspace_endpoints_match(xy, &colorspace->end_points_xy,
+ 100) == 0)
+ {
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "inconsistent chromaticities");
+ return 0; /* failed */
+ }
+
+ /* Only overwrite with preferred values */
+ if (preferred == 0)
+ return 1; /* ok, but no change */
+ }
+
+ colorspace->end_points_xy = *xy;
+ colorspace->end_points_XYZ = *XYZ;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_ENDPOINTS;
+
+ /* The end points are normally quoted to two decimal digits, so allow +/-0.01
+ * on this test.
+ */
+ if (png_colorspace_endpoints_match(xy, &sRGB_xy, 1000) != 0)
+ colorspace->flags |= PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB;
+
+ else
+ colorspace->flags &= PNG_COLORSPACE_CANCEL(
+ PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+
+ return 2; /* ok and changed */
+}
+
+int /* PRIVATE */
+png_colorspace_set_chromaticities(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_xy *xy, int preferred)
+{
+ /* We must check the end points to ensure they are reasonable - in the past
+ * color management systems have crashed as a result of getting bogus
+ * colorant values, while this isn't the fault of libpng it is the
+ * responsibility of libpng because PNG carries the bomb and libpng is in a
+ * position to protect against it.
+ */
+ png_XYZ XYZ;
+
+ switch (png_colorspace_check_xy(&XYZ, xy))
+ {
+ case 0: /* success */
+ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, xy, &XYZ,
+ preferred);
+
case 1:
- /* The chunk may be technically valid, but we got png_fixed_point
- * overflow while trying to get XYZ values out of it. This is
- * entirely benign - the cHRM chunk is pretty extreme.
+ /* We can't invert the chromaticities so we can't produce value XYZ
+ * values. Likely as not a color management system will fail too.
*/
- png_warning(png_ptr,
- "extreme cHRM chunk cannot be converted to tristimulus values");
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "invalid chromaticities");
break;
default:
/* libpng is broken; this should be a warning but if it happens we
* want error reports so for the moment it is an error.
*/
- png_error(png_ptr, "internal error in png_XYZ_from_xy");
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_error(png_ptr, "internal error checking chromaticities");
+ break;
+ }
+
+ return 0; /* failed */
+}
+
+int /* PRIVATE */
+png_colorspace_set_endpoints(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, const png_XYZ *XYZ_in, int preferred)
+{
+ png_XYZ XYZ = *XYZ_in;
+ png_xy xy;
+
+ switch (png_colorspace_check_XYZ(&xy, &XYZ))
+ {
+ case 0:
+ return png_colorspace_set_xy_and_XYZ(png_ptr, colorspace, &xy, &XYZ,
+ preferred);
+
+ case 1:
+ /* End points are invalid. */
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_benign_error(png_ptr, "invalid end points");
+ break;
+
+ default:
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+ png_error(png_ptr, "internal error checking chromaticities");
break;
}
- /* ERROR RETURN */
+ return 0; /* failed */
+}
+
+#if defined(PNG_sRGB_SUPPORTED) || defined(PNG_iCCP_SUPPORTED)
+/* Error message generation */
+static char
+png_icc_tag_char(png_uint_32 byte)
+{
+ byte &= 0xff;
+ if (byte >= 32 && byte <= 126)
+ return (char)byte;
+ else
+ return '?';
+}
+
+static void
+png_icc_tag_name(char *name, png_uint_32 tag)
+{
+ name[0] = '\'';
+ name[1] = png_icc_tag_char(tag >> 24);
+ name[2] = png_icc_tag_char(tag >> 16);
+ name[3] = png_icc_tag_char(tag >> 8);
+ name[4] = png_icc_tag_char(tag );
+ name[5] = '\'';
+}
+
+static int
+is_ICC_signature_char(png_alloc_size_t it)
+{
+ return it == 32 || (it >= 48 && it <= 57) || (it >= 65 && it <= 90) ||
+ (it >= 97 && it <= 122);
+}
+
+static int
+is_ICC_signature(png_alloc_size_t it)
+{
+ return is_ICC_signature_char(it >> 24) /* checks all the top bits */ &&
+ is_ICC_signature_char((it >> 16) & 0xff) &&
+ is_ICC_signature_char((it >> 8) & 0xff) &&
+ is_ICC_signature_char(it & 0xff);
+}
+
+static int
+png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_alloc_size_t value, png_const_charp reason)
+{
+ size_t pos;
+ char message[196]; /* see below for calculation */
+
+ if (colorspace != NULL)
+ colorspace->flags |= PNG_COLORSPACE_INVALID;
+
+ pos = png_safecat(message, (sizeof message), 0, "profile '"); /* 9 chars */
+ pos = png_safecat(message, pos+79, pos, name); /* Truncate to 79 chars */
+ pos = png_safecat(message, (sizeof message), pos, "': "); /* +2 = 90 */
+ if (is_ICC_signature(value) != 0)
+ {
+ /* So 'value' is at most 4 bytes and the following cast is safe */
+ png_icc_tag_name(message+pos, (png_uint_32)value);
+ pos += 6; /* total +8; less than the else clause */
+ message[pos++] = ':';
+ message[pos++] = ' ';
+ }
+# ifdef PNG_WARNINGS_SUPPORTED
+ else
+ {
+ char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114*/
+
+ pos = png_safecat(message, (sizeof message), pos,
+ png_format_number(number, number+(sizeof number),
+ PNG_NUMBER_FORMAT_x, value));
+ pos = png_safecat(message, (sizeof message), pos, "h: "); /*+2 = 116*/
+ }
+# endif
+ /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
+ pos = png_safecat(message, (sizeof message), pos, reason);
+ PNG_UNUSED(pos)
+
+ /* This is recoverable, but make it unconditionally an app_error on write to
+ * avoid writing invalid ICC profiles into PNG files (i.e., we handle them
+ * on read, with a warning, but on write unless the app turns off
+ * application errors the PNG won't be written.)
+ */
+ png_chunk_report(png_ptr, message,
+ (colorspace != NULL) ? PNG_CHUNK_ERROR : PNG_CHUNK_WRITE_ERROR);
+
return 0;
}
+#endif /* sRGB || iCCP */
+
+#ifdef PNG_sRGB_SUPPORTED
+int /* PRIVATE */
+png_colorspace_set_sRGB(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ int intent)
+{
+ /* sRGB sets known gamma, end points and (from the chunk) intent. */
+ /* IMPORTANT: these are not necessarily the values found in an ICC profile
+ * because ICC profiles store values adapted to a D50 environment; it is
+ * expected that the ICC profile mediaWhitePointTag will be D50; see the
+ * checks and code elsewhere to understand this better.
+ *
+ * These XYZ values, which are accurate to 5dp, produce rgb to gray
+ * coefficients of (6968,23435,2366), which are reduced (because they add up
+ * to 32769 not 32768) to (6968,23434,2366). These are the values that
+ * libpng has traditionally used (and are the best values given the 15bit
+ * algorithm used by the rgb to gray code.)
+ */
+ static const png_XYZ sRGB_XYZ = /* D65 XYZ (*not* the D50 adapted values!) */
+ {
+ /* color X Y Z */
+ /* red */ 41239, 21264, 1933,
+ /* green */ 35758, 71517, 11919,
+ /* blue */ 18048, 7219, 95053
+ };
+
+ /* Do nothing if the colorspace is already invalidated. */
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ /* Check the intent, then check for existing settings. It is valid for the
+ * PNG file to have cHRM or gAMA chunks along with sRGB, but the values must
+ * be consistent with the correct values. If, however, this function is
+ * called below because an iCCP chunk matches sRGB then it is quite
+ * conceivable that an older app recorded incorrect gAMA and cHRM because of
+ * an incorrect calculation based on the values in the profile - this does
+ * *not* invalidate the profile (though it still produces an error, which can
+ * be ignored.)
+ */
+ if (intent < 0 || intent >= PNG_sRGB_INTENT_LAST)
+ return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+ (unsigned)intent, "invalid sRGB rendering intent");
+
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_INTENT) != 0 &&
+ colorspace->rendering_intent != intent)
+ return png_icc_profile_error(png_ptr, colorspace, "sRGB",
+ (unsigned)intent, "inconsistent rendering intents");
+
+ if ((colorspace->flags & PNG_COLORSPACE_FROM_sRGB) != 0)
+ {
+ png_benign_error(png_ptr, "duplicate sRGB information ignored");
+ return 0;
+ }
+
+ /* If the standard sRGB cHRM chunk does not match the one from the PNG file
+ * warn but overwrite the value with the correct one.
+ */
+ if ((colorspace->flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0 &&
+ !png_colorspace_endpoints_match(&sRGB_xy, &colorspace->end_points_xy,
+ 100))
+ png_chunk_report(png_ptr, "cHRM chunk does not match sRGB",
+ PNG_CHUNK_ERROR);
+
+ /* This check is just done for the error reporting - the routine always
+ * returns true when the 'from' argument corresponds to sRGB (2).
+ */
+ (void)png_colorspace_check_gamma(png_ptr, colorspace, PNG_GAMMA_sRGB_INVERSE,
+ 2/*from sRGB*/);
+
+ /* intent: bugs in GCC force 'int' to be used as the parameter type. */
+ colorspace->rendering_intent = (png_uint_16)intent;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_INTENT;
+
+ /* endpoints */
+ colorspace->end_points_xy = sRGB_xy;
+ colorspace->end_points_XYZ = sRGB_XYZ;
+ colorspace->flags |=
+ (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB);
+
+ /* gamma */
+ colorspace->gamma = PNG_GAMMA_sRGB_INVERSE;
+ colorspace->flags |= PNG_COLORSPACE_HAVE_GAMMA;
+
+ /* Finally record that we have an sRGB profile */
+ colorspace->flags |=
+ (PNG_COLORSPACE_MATCHES_sRGB|PNG_COLORSPACE_FROM_sRGB);
+
+ return 1; /* set */
+}
+#endif /* sRGB */
+
+#ifdef PNG_iCCP_SUPPORTED
+/* Encoded value of D50 as an ICC XYZNumber. From the ICC 2010 spec the value
+ * is XYZ(0.9642,1.0,0.8249), which scales to:
+ *
+ * (63189.8112, 65536, 54060.6464)
+ */
+static const png_byte D50_nCIEXYZ[12] =
+ { 0x00, 0x00, 0xf6, 0xd6, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0xd3, 0x2d };
+
+int /* PRIVATE */
+png_icc_check_length(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length)
+{
+ if (profile_length < 132)
+ return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+ "too short");
+
+ return 1;
+}
+
+int /* PRIVATE */
+png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length,
+ png_const_bytep profile/* first 132 bytes only */, int color_type)
+{
+ png_uint_32 temp;
+
+ /* Length check; this cannot be ignored in this code because profile_length
+ * is used later to check the tag table, so even if the profile seems over
+ * long profile_length from the caller must be correct. The caller can fix
+ * this up on read or write by just passing in the profile header length.
+ */
+ temp = png_get_uint_32(profile);
+ if (temp != profile_length)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "length does not match profile");
+
+ temp = (png_uint_32) (*(profile+8));
+ if (temp > 3 && (profile_length & 3))
+ return png_icc_profile_error(png_ptr, colorspace, name, profile_length,
+ "invalid length");
+
+ temp = png_get_uint_32(profile+128); /* tag count: 12 bytes/tag */
+ if (temp > 357913930 || /* (2^32-4-132)/12: maximum possible tag count */
+ profile_length < 132+12*temp) /* truncated tag table */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "tag count too large");
+
+ /* The 'intent' must be valid or we can't store it, ICC limits the intent to
+ * 16 bits.
+ */
+ temp = png_get_uint_32(profile+64);
+ if (temp >= 0xffff) /* The ICC limit */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid rendering intent");
+
+ /* This is just a warning because the profile may be valid in future
+ * versions.
+ */
+ if (temp >= PNG_sRGB_INTENT_LAST)
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "intent outside defined range");
+
+ /* At this point the tag table can't be checked because it hasn't necessarily
+ * been loaded; however, various header fields can be checked. These checks
+ * are for values permitted by the PNG spec in an ICC profile; the PNG spec
+ * restricts the profiles that can be passed in an iCCP chunk (they must be
+ * appropriate to processing PNG data!)
+ */
+
+ /* Data checks (could be skipped). These checks must be independent of the
+ * version number; however, the version number doesn't accomodate changes in
+ * the header fields (just the known tags and the interpretation of the
+ * data.)
+ */
+ temp = png_get_uint_32(profile+36); /* signature 'ascp' */
+ if (temp != 0x61637370)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid signature");
+
+ /* Currently the PCS illuminant/adopted white point (the computational
+ * white point) are required to be D50,
+ * however the profile contains a record of the illuminant so perhaps ICC
+ * expects to be able to change this in the future (despite the rationale in
+ * the introduction for using a fixed PCS adopted white.) Consequently the
+ * following is just a warning.
+ */
+ if (memcmp(profile+68, D50_nCIEXYZ, 12) != 0)
+ (void)png_icc_profile_error(png_ptr, NULL, name, 0/*no tag value*/,
+ "PCS illuminant is not D50");
+
+ /* The PNG spec requires this:
+ * "If the iCCP chunk is present, the image samples conform to the colour
+ * space represented by the embedded ICC profile as defined by the
+ * International Color Consortium [ICC]. The colour space of the ICC profile
+ * shall be an RGB colour space for colour images (PNG colour types 2, 3, and
+ * 6), or a greyscale colour space for greyscale images (PNG colour types 0
+ * and 4)."
+ *
+ * This checking code ensures the embedded profile (on either read or write)
+ * conforms to the specification requirements. Notice that an ICC 'gray'
+ * color-space profile contains the information to transform the monochrome
+ * data to XYZ or L*a*b (according to which PCS the profile uses) and this
+ * should be used in preference to the standard libpng K channel replication
+ * into R, G and B channels.
+ *
+ * Previously it was suggested that an RGB profile on grayscale data could be
+ * handled. However it it is clear that using an RGB profile in this context
+ * must be an error - there is no specification of what it means. Thus it is
+ * almost certainly more correct to ignore the profile.
+ */
+ temp = png_get_uint_32(profile+16); /* data colour space field */
+ switch (temp)
+ {
+ case 0x52474220: /* 'RGB ' */
+ if ((color_type & PNG_COLOR_MASK_COLOR) == 0)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "RGB color space not permitted on grayscale PNG");
+ break;
+
+ case 0x47524159: /* 'GRAY' */
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "Gray color space not permitted on RGB PNG");
+ break;
+
+ default:
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid ICC profile color space");
+ }
+
+ /* It is up to the application to check that the profile class matches the
+ * application requirements; the spec provides no guidance, but it's pretty
+ * weird if the profile is not scanner ('scnr'), monitor ('mntr'), printer
+ * ('prtr') or 'spac' (for generic color spaces). Issue a warning in these
+ * cases. Issue an error for device link or abstract profiles - these don't
+ * contain the records necessary to transform the color-space to anything
+ * other than the target device (and not even that for an abstract profile).
+ * Profiles of these classes may not be embedded in images.
+ */
+ temp = png_get_uint_32(profile+12); /* profile/device class */
+ switch (temp)
+ {
+ case 0x73636E72: /* 'scnr' */
+ case 0x6D6E7472: /* 'mntr' */
+ case 0x70727472: /* 'prtr' */
+ case 0x73706163: /* 'spac' */
+ /* All supported */
+ break;
+
+ case 0x61627374: /* 'abst' */
+ /* May not be embedded in an image */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "invalid embedded Abstract ICC profile");
+
+ case 0x6C696E6B: /* 'link' */
+ /* DeviceLink profiles cannot be interpreted in a non-device specific
+ * fashion, if an app uses the AToB0Tag in the profile the results are
+ * undefined unless the result is sent to the intended device,
+ * therefore a DeviceLink profile should not be found embedded in a
+ * PNG.
+ */
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "unexpected DeviceLink ICC profile class");
+
+ case 0x6E6D636C: /* 'nmcl' */
+ /* A NamedColor profile is also device specific, however it doesn't
+ * contain an AToB0 tag that is open to misinterpretation. Almost
+ * certainly it will fail the tests below.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "unexpected NamedColor ICC profile class");
+ break;
+
+ default:
+ /* To allow for future enhancements to the profile accept unrecognized
+ * profile classes with a warning, these then hit the test below on the
+ * tag content to ensure they are backward compatible with one of the
+ * understood profiles.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, temp,
+ "unrecognized ICC profile class");
+ break;
+ }
+
+ /* For any profile other than a device link one the PCS must be encoded
+ * either in XYZ or Lab.
+ */
+ temp = png_get_uint_32(profile+20);
+ switch (temp)
+ {
+ case 0x58595A20: /* 'XYZ ' */
+ case 0x4C616220: /* 'Lab ' */
+ break;
+
+ default:
+ return png_icc_profile_error(png_ptr, colorspace, name, temp,
+ "unexpected ICC PCS encoding");
+ }
+
+ return 1;
+}
+
+int /* PRIVATE */
+png_icc_check_tag_table(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length,
+ png_const_bytep profile /* header plus whole tag table */)
+{
+ png_uint_32 tag_count = png_get_uint_32(profile+128);
+ png_uint_32 itag;
+ png_const_bytep tag = profile+132; /* The first tag */
+
+ /* First scan all the tags in the table and add bits to the icc_info value
+ * (temporarily in 'tags').
+ */
+ for (itag=0; itag < tag_count; ++itag, tag += 12)
+ {
+ png_uint_32 tag_id = png_get_uint_32(tag+0);
+ png_uint_32 tag_start = png_get_uint_32(tag+4); /* must be aligned */
+ png_uint_32 tag_length = png_get_uint_32(tag+8);/* not padded */
+
+ /* The ICC specification does not exclude zero length tags, therefore the
+ * start might actually be anywhere if there is no data, but this would be
+ * a clear abuse of the intent of the standard so the start is checked for
+ * being in range. All defined tag types have an 8 byte header - a 4 byte
+ * type signature then 0.
+ */
+ if ((tag_start & 3) != 0)
+ {
+ /* CNHP730S.icc shipped with Microsoft Windows 64 violates this, it is
+ * only a warning here because libpng does not care about the
+ * alignment.
+ */
+ (void)png_icc_profile_error(png_ptr, NULL, name, tag_id,
+ "ICC profile tag start not a multiple of 4");
+ }
+
+ /* This is a hard error; potentially it can cause read outside the
+ * profile.
+ */
+ if (tag_start > profile_length || tag_length > profile_length - tag_start)
+ return png_icc_profile_error(png_ptr, colorspace, name, tag_id,
+ "ICC profile tag outside profile");
+ }
+
+ return 1; /* success, maybe with warnings */
+}
+
+#ifdef PNG_sRGB_SUPPORTED
+#if PNG_sRGB_PROFILE_CHECKS >= 0
+/* Information about the known ICC sRGB profiles */
+static const struct
+{
+ png_uint_32 adler, crc, length;
+ png_uint_32 md5[4];
+ png_byte have_md5;
+ png_byte is_broken;
+ png_uint_16 intent;
+
+# define PNG_MD5(a,b,c,d) { a, b, c, d }, (a!=0)||(b!=0)||(c!=0)||(d!=0)
+# define PNG_ICC_CHECKSUM(adler, crc, md5, intent, broke, date, length, fname)\
+ { adler, crc, length, md5, broke, intent },
+
+} png_sRGB_checks[] =
+{
+ /* This data comes from contrib/tools/checksum-icc run on downloads of
+ * all four ICC sRGB profiles from www.color.org.
+ */
+ /* adler32, crc32, MD5[4], intent, date, length, file-name */
+ PNG_ICC_CHECKSUM(0x0a3fd9f6, 0x3b8772b9,
+ PNG_MD5(0x29f83dde, 0xaff255ae, 0x7842fae4, 0xca83390d), 0, 0,
+ "2009/03/27 21:36:31", 3048, "sRGB_IEC61966-2-1_black_scaled.icc")
+
+ /* ICC sRGB v2 perceptual no black-compensation: */
+ PNG_ICC_CHECKSUM(0x4909e5e1, 0x427ebb21,
+ PNG_MD5(0xc95bd637, 0xe95d8a3b, 0x0df38f99, 0xc1320389), 1, 0,
+ "2009/03/27 21:37:45", 3052, "sRGB_IEC61966-2-1_no_black_scaling.icc")
+
+ PNG_ICC_CHECKSUM(0xfd2144a1, 0x306fd8ae,
+ PNG_MD5(0xfc663378, 0x37e2886b, 0xfd72e983, 0x8228f1b8), 0, 0,
+ "2009/08/10 17:28:01", 60988, "sRGB_v4_ICC_preference_displayclass.icc")
+
+ /* ICC sRGB v4 perceptual */
+ PNG_ICC_CHECKSUM(0x209c35d2, 0xbbef7812,
+ PNG_MD5(0x34562abf, 0x994ccd06, 0x6d2c5721, 0xd0d68c5d), 0, 0,
+ "2007/07/25 00:05:37", 60960, "sRGB_v4_ICC_preference.icc")
+
+ /* The following profiles have no known MD5 checksum. If there is a match
+ * on the (empty) MD5 the other fields are used to attempt a match and
+ * a warning is produced. The first two of these profiles have a 'cprt' tag
+ * which suggests that they were also made by Hewlett Packard.
+ */
+ PNG_ICC_CHECKSUM(0xa054d762, 0x5d5129ce,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 0,
+ "2004/07/21 18:57:42", 3024, "sRGB_IEC61966-2-1_noBPC.icc")
+
+ /* This is a 'mntr' (display) profile with a mediaWhitePointTag that does not
+ * match the D50 PCS illuminant in the header (it is in fact the D65 values,
+ * so the white point is recorded as the un-adapted value.) The profiles
+ * below only differ in one byte - the intent - and are basically the same as
+ * the previous profile except for the mediaWhitePointTag error and a missing
+ * chromaticAdaptationTag.
+ */
+ PNG_ICC_CHECKSUM(0xf784f3fb, 0x182ea552,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 0, 1/*broken*/,
+ "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 perceptual")
+
+ PNG_ICC_CHECKSUM(0x0398f3fc, 0xf29e526d,
+ PNG_MD5(0x00000000, 0x00000000, 0x00000000, 0x00000000), 1, 1/*broken*/,
+ "1998/02/09 06:49:00", 3144, "HP-Microsoft sRGB v2 media-relative")
+};
+
+static int
+png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr,
+ png_const_bytep profile, uLong adler)
+{
+ /* The quick check is to verify just the MD5 signature and trust the
+ * rest of the data. Because the profile has already been verified for
+ * correctness this is safe. png_colorspace_set_sRGB will check the 'intent'
+ * field too, so if the profile has been edited with an intent not defined
+ * by sRGB (but maybe defined by a later ICC specification) the read of
+ * the profile will fail at that point.
+ */
+
+ png_uint_32 length = 0;
+ png_uint_32 intent = 0x10000; /* invalid */
+#if PNG_sRGB_PROFILE_CHECKS > 1
+ uLong crc = 0; /* the value for 0 length data */
+#endif
+ unsigned int i;
+
+#ifdef PNG_SET_OPTION_SUPPORTED
+ /* First see if PNG_SKIP_sRGB_CHECK_PROFILE has been set to "on" */
+ if (((png_ptr->options >> PNG_SKIP_sRGB_CHECK_PROFILE) & 3) ==
+ PNG_OPTION_ON)
+ return 0;
+#endif
+
+ for (i=0; i < (sizeof png_sRGB_checks) / (sizeof png_sRGB_checks[0]); ++i)
+ {
+ if (png_get_uint_32(profile+84) == png_sRGB_checks[i].md5[0] &&
+ png_get_uint_32(profile+88) == png_sRGB_checks[i].md5[1] &&
+ png_get_uint_32(profile+92) == png_sRGB_checks[i].md5[2] &&
+ png_get_uint_32(profile+96) == png_sRGB_checks[i].md5[3])
+ {
+ /* This may be one of the old HP profiles without an MD5, in that
+ * case we can only use the length and Adler32 (note that these
+ * are not used by default if there is an MD5!)
+ */
+# if PNG_sRGB_PROFILE_CHECKS == 0
+ if (png_sRGB_checks[i].have_md5 != 0)
+ return 1+png_sRGB_checks[i].is_broken;
+# endif
+
+ /* Profile is unsigned or more checks have been configured in. */
+ if (length == 0)
+ {
+ length = png_get_uint_32(profile);
+ intent = png_get_uint_32(profile+64);
+ }
+
+ /* Length *and* intent must match */
+ if (length == png_sRGB_checks[i].length &&
+ intent == png_sRGB_checks[i].intent)
+ {
+ /* Now calculate the adler32 if not done already. */
+ if (adler == 0)
+ {
+ adler = adler32(0, NULL, 0);
+ adler = adler32(adler, profile, length);
+ }
+
+ if (adler == png_sRGB_checks[i].adler)
+ {
+ /* These basic checks suggest that the data has not been
+ * modified, but if the check level is more than 1 perform
+ * our own crc32 checksum on the data.
+ */
+# if PNG_sRGB_PROFILE_CHECKS > 1
+ if (crc == 0)
+ {
+ crc = crc32(0, NULL, 0);
+ crc = crc32(crc, profile, length);
+ }
+
+ /* So this check must pass for the 'return' below to happen.
+ */
+ if (crc == png_sRGB_checks[i].crc)
+# endif
+ {
+ if (png_sRGB_checks[i].is_broken != 0)
+ {
+ /* These profiles are known to have bad data that may cause
+ * problems if they are used, therefore attempt to
+ * discourage their use, skip the 'have_md5' warning below,
+ * which is made irrelevant by this error.
+ */
+ png_chunk_report(png_ptr, "known incorrect sRGB profile",
+ PNG_CHUNK_ERROR);
+ }
+
+ /* Warn that this being done; this isn't even an error since
+ * the profile is perfectly valid, but it would be nice if
+ * people used the up-to-date ones.
+ */
+ else if (png_sRGB_checks[i].have_md5 == 0)
+ {
+ png_chunk_report(png_ptr,
+ "out-of-date sRGB profile with no signature",
+ PNG_CHUNK_WARNING);
+ }
+
+ return 1+png_sRGB_checks[i].is_broken;
+ }
+ }
+
+# if PNG_sRGB_PROFILE_CHECKS > 0
+ /* The signature matched, but the profile had been changed in some
+ * way. This probably indicates a data error or uninformed hacking.
+ * Fall through to "no match".
+ */
+ png_chunk_report(png_ptr,
+ "Not recognizing known sRGB profile that has been edited",
+ PNG_CHUNK_WARNING);
+ break;
+# endif
+ }
+ }
+ }
+
+ return 0; /* no match */
+}
+#endif /* PNG_sRGB_PROFILE_CHECKS >= 0 */
+
+void /* PRIVATE */
+png_icc_set_sRGB(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_bytep profile, uLong adler)
+{
+ /* Is this profile one of the known ICC sRGB profiles? If it is, just set
+ * the sRGB information.
+ */
+#if PNG_sRGB_PROFILE_CHECKS >= 0
+ if (png_compare_ICC_profile_with_sRGB(png_ptr, profile, adler) != 0)
+#endif
+ (void)png_colorspace_set_sRGB(png_ptr, colorspace,
+ (int)/*already checked*/png_get_uint_32(profile+64));
+}
+#endif /* sRGB */
+
+int /* PRIVATE */
+png_colorspace_set_ICC(png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_charp name, png_uint_32 profile_length, png_const_bytep profile,
+ int color_type)
+{
+ if ((colorspace->flags & PNG_COLORSPACE_INVALID) != 0)
+ return 0;
+
+ if (png_icc_check_length(png_ptr, colorspace, name, profile_length) != 0 &&
+ png_icc_check_header(png_ptr, colorspace, name, profile_length, profile,
+ color_type) != 0 &&
+ png_icc_check_tag_table(png_ptr, colorspace, name, profile_length,
+ profile) != 0)
+ {
+# ifdef PNG_sRGB_SUPPORTED
+ /* If no sRGB support, don't try storing sRGB information */
+ png_icc_set_sRGB(png_ptr, colorspace, profile, 0);
+# endif
+ return 1;
+ }
+
+ /* Failure case */
+ return 0;
+}
+#endif /* iCCP */
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+void /* PRIVATE */
+png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
+{
+ /* Set the rgb_to_gray coefficients from the colorspace. */
+ if (png_ptr->rgb_to_gray_coefficients_set == 0 &&
+ (png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ /* png_set_background has not been called, get the coefficients from the Y
+ * values of the colorspace colorants.
+ */
+ png_fixed_point r = png_ptr->colorspace.end_points_XYZ.red_Y;
+ png_fixed_point g = png_ptr->colorspace.end_points_XYZ.green_Y;
+ png_fixed_point b = png_ptr->colorspace.end_points_XYZ.blue_Y;
+ png_fixed_point total = r+g+b;
+
+ if (total > 0 &&
+ r >= 0 && png_muldiv(&r, r, 32768, total) && r >= 0 && r <= 32768 &&
+ g >= 0 && png_muldiv(&g, g, 32768, total) && g >= 0 && g <= 32768 &&
+ b >= 0 && png_muldiv(&b, b, 32768, total) && b >= 0 && b <= 32768 &&
+ r+g+b <= 32769)
+ {
+ /* We allow 0 coefficients here. r+g+b may be 32769 if two or
+ * all of the coefficients were rounded up. Handle this by
+ * reducing the *largest* coefficient by 1; this matches the
+ * approach used for the default coefficients in pngrtran.c
+ */
+ int add = 0;
+
+ if (r+g+b > 32768)
+ add = -1;
+ else if (r+g+b < 32768)
+ add = 1;
+
+ if (add != 0)
+ {
+ if (g >= r && g >= b)
+ g += add;
+ else if (r >= g && r >= b)
+ r += add;
+ else
+ b += add;
+ }
+
+ /* Check for an internal error. */
+ if (r+g+b != 32768)
+ png_error(png_ptr,
+ "internal error handling cHRM coefficients");
+
+ else
+ {
+ png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
+ png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
+ }
+ }
+
+ /* This is a png_error at present even though it could be ignored -
+ * it should never happen, but it is important that if it does, the
+ * bug is fixed.
+ */
+ else
+ png_error(png_ptr, "internal error handling cHRM->XYZ");
+ }
+}
+#endif /* READ_RGB_TO_GRAY */
+
+#endif /* COLORSPACE */
+
+#ifdef __GNUC__
+/* This exists solely to work round a warning from GNU C. */
+static int /* PRIVATE */
+png_gt(size_t a, size_t b)
+{
+ return a > b;
+}
+#else
+# define png_gt(a,b) ((a) > (b))
#endif
void /* PRIVATE */
-png_check_IHDR(png_structp png_ptr,
+png_check_IHDR(png_const_structrp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
@@ -1180,36 +2482,47 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (height == 0)
+ if (width > PNG_UINT_31_MAX)
{
- png_warning(png_ptr, "Image height is zero in IHDR");
+ png_warning(png_ptr, "Invalid image width in IHDR");
error = 1;
}
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (width > png_ptr->user_width_max)
-
-# else
- if (width > PNG_USER_WIDTH_MAX)
-# endif
+ if (png_gt(((width + 7) & (~7)),
+ ((PNG_SIZE_MAX
+ - 48 /* big_row_buf hack */
+ - 1) /* filter byte */
+ / 8) /* 8-byte RGBA pixels */
+ - 1)) /* extra max_pixel_depth pad */
{
- png_warning(png_ptr, "Image width exceeds user limit in IHDR");
+ /* The size of the row must be within the limits of this architecture.
+ * Because the read code can perform arbitrary transformations the
+ * maximum size is checked here. Because the code in png_read_start_row
+ * adds extra space "for safety's sake" in several places a conservative
+ * limit is used here.
+ *
+ * NOTE: it would be far better to check the size that is actually used,
+ * but the effect in the real world is minor and the changes are more
+ * extensive, therefore much more dangerous and much more difficult to
+ * write in a way that avoids compiler warnings.
+ */
+ png_warning(png_ptr, "Image width is too large for this architecture");
error = 1;
}
-# ifdef PNG_SET_USER_LIMITS_SUPPORTED
- if (height > png_ptr->user_height_max)
-# else
- if (height > PNG_USER_HEIGHT_MAX)
-# endif
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (width > png_ptr->user_width_max)
+#else
+ if (width > PNG_USER_WIDTH_MAX)
+#endif
{
- png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ png_warning(png_ptr, "Image width exceeds user limit in IHDR");
error = 1;
}
- if (width > PNG_UINT_31_MAX)
+ if (height == 0)
{
- png_warning(png_ptr, "Invalid image width in IHDR");
+ png_warning(png_ptr, "Image height is zero in IHDR");
error = 1;
}
@@ -1219,13 +2532,15 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (width > (PNG_UINT_32_MAX
- >> 3) /* 8-byte RGBA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- png_warning(png_ptr, "Width is too large for libpng to process pixels");
+#ifdef PNG_SET_USER_LIMITS_SUPPORTED
+ if (height > png_ptr->user_height_max)
+#else
+ if (height > PNG_USER_HEIGHT_MAX)
+#endif
+ {
+ png_warning(png_ptr, "Image height exceeds user limit in IHDR");
+ error = 1;
+ }
/* Check other values */
if (bit_depth != 1 && bit_depth != 2 && bit_depth != 4 &&
@@ -1263,7 +2578,7 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
-# ifdef PNG_MNG_FEATURES_SUPPORTED
+#ifdef PNG_MNG_FEATURES_SUPPORTED
/* Accept filter_method 64 (intrapixel differencing) only if
* 1. Libpng was compiled with PNG_MNG_FEATURES_SUPPORTED and
* 2. Libpng did not read a PNG signature (this filter_method is only
@@ -1273,13 +2588,13 @@ png_check_IHDR(png_structp png_ptr,
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
- if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) &&
- png_ptr->mng_features_permitted)
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 &&
+ png_ptr->mng_features_permitted != 0)
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
if (filter_type != PNG_FILTER_TYPE_BASE)
{
- if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if (!((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(filter_type == PNG_INTRAPIXEL_DIFFERENCING) &&
((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
(color_type == PNG_COLOR_TYPE_RGB ||
@@ -1289,20 +2604,20 @@ png_check_IHDR(png_structp png_ptr,
error = 1;
}
- if (png_ptr->mode & PNG_HAVE_PNG_SIGNATURE)
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0)
{
png_warning(png_ptr, "Invalid filter method in IHDR");
error = 1;
}
}
-# else
+#else
if (filter_type != PNG_FILTER_TYPE_BASE)
{
png_warning(png_ptr, "Unknown filter method in IHDR");
error = 1;
}
-# endif
+#endif
if (error == 1)
png_error(png_ptr, "Invalid IHDR data");
@@ -1349,7 +2664,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
switch ((state & PNG_FP_STATE) + (type & PNG_FP_SAW_ANY))
{
case PNG_FP_INTEGER + PNG_FP_SAW_SIGN:
- if (state & PNG_FP_SAW_ANY)
+ if ((state & PNG_FP_SAW_ANY) != 0)
goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, type);
@@ -1357,10 +2672,10 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
case PNG_FP_INTEGER + PNG_FP_SAW_DOT:
/* Ok as trailer, ok as lead of fraction. */
- if (state & PNG_FP_SAW_DOT) /* two dots */
+ if ((state & PNG_FP_SAW_DOT) != 0) /* two dots */
goto PNG_FP_End;
- else if (state & PNG_FP_SAW_DIGIT) /* trailing dot? */
+ else if ((state & PNG_FP_SAW_DIGIT) != 0) /* trailing dot? */
png_fp_add(state, type);
else
@@ -1369,7 +2684,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
break;
case PNG_FP_INTEGER + PNG_FP_SAW_DIGIT:
- if (state & PNG_FP_SAW_DOT) /* delayed fraction */
+ if ((state & PNG_FP_SAW_DOT) != 0) /* delayed fraction */
png_fp_set(state, PNG_FP_FRACTION | PNG_FP_SAW_DOT);
png_fp_add(state, type | PNG_FP_WAS_VALID);
@@ -1407,7 +2722,7 @@ png_check_fp_number(png_const_charp string, png_size_t size, int *statep,
break;
case PNG_FP_EXPONENT + PNG_FP_SAW_SIGN:
- if (state & PNG_FP_SAW_ANY)
+ if ((state & PNG_FP_SAW_ANY) != 0)
goto PNG_FP_End; /* not a part of the number */
png_fp_add(state, PNG_FP_SAW_SIGN);
@@ -1450,15 +2765,15 @@ png_check_fp_string(png_const_charp string, png_size_t size)
int state=0;
png_size_t char_index=0;
- if (png_check_fp_number(string, size, &state, &char_index) &&
+ if (png_check_fp_number(string, size, &state, &char_index) != 0 &&
(char_index == size || string[char_index] == 0))
return state /* must be non-zero - see above */;
return 0; /* i.e. fail */
}
-#endif /* pCAL or sCAL */
+#endif /* pCAL || sCAL */
-#ifdef PNG_READ_sCAL_SUPPORTED
+#ifdef PNG_sCAL_SUPPORTED
# ifdef PNG_FLOATING_POINT_SUPPORTED
/* Utility used below - a simple accurate power of ten from an integral
* exponent.
@@ -1467,7 +2782,7 @@ static double
png_pow10(int power)
{
int recip = 0;
- double d = 1.0;
+ double d = 1;
/* Handle negative exponent with a reciprocal at the end because
* 10 is exact whereas .1 is inexact in base 2
@@ -1481,7 +2796,7 @@ png_pow10(int power)
if (power > 0)
{
/* Decompose power bitwise. */
- double mult = 10.0;
+ double mult = 10;
do
{
if (power & 1) d *= mult;
@@ -1490,7 +2805,7 @@ png_pow10(int power)
}
while (power > 0);
- if (recip) d = 1/d;
+ if (recip != 0) d = 1/d;
}
/* else power is 0 and d is 1 */
@@ -1501,7 +2816,7 @@ png_pow10(int power)
* precision.
*/
void /* PRIVATE */
-png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
+png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size,
double fp, unsigned int precision)
{
/* We use standard functions from math.h, but not printf because
@@ -1600,8 +2915,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
double d;
- fp *= 10.0;
-
+ fp *= 10;
/* Use modf here, not floor and subtract, so that
* the separation is done in one step. At the end
* of the loop don't break the number into parts so
@@ -1614,7 +2928,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
d = floor(fp + .5);
- if (d > 9.0)
+ if (d > 9)
{
/* Rounding up to 10, handle that here. */
if (czero > 0)
@@ -1622,10 +2936,9 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
--czero, d = 1;
if (cdigits == 0) --clead;
}
-
else
{
- while (cdigits > 0 && d > 9.0)
+ while (cdigits > 0 && d > 9)
{
int ch = *--ascii;
@@ -1650,7 +2963,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
* exponent but take into account the leading
* decimal point.
*/
- if (d > 9.0) /* cdigits == 0 */
+ if (d > 9) /* cdigits == 0 */
{
if (exp_b10 == (-1))
{
@@ -1671,19 +2984,18 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
++exp_b10;
/* In all cases we output a '1' */
- d = 1.0;
+ d = 1;
}
}
}
fp = 0; /* Guarantees termination below. */
}
- if (d == 0.0)
+ if (d == 0)
{
++czero;
if (cdigits == 0) ++clead;
}
-
else
{
/* Included embedded zeros in the digit count. */
@@ -1707,11 +3019,11 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
if (exp_b10 != (-1))
{
- if (exp_b10 == 0) *ascii++ = 46, --size; /* counted
- above */
+ if (exp_b10 == 0)
+ *ascii++ = 46, --size; /* counted above */
+
--exp_b10;
}
-
*ascii++ = (char)(48 + (int)d), ++cdigits;
}
}
@@ -1722,7 +3034,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Check for an exponent, if we don't need one we are
* done and just need to terminate the string. At
* this point exp_b10==(-1) is effectively if flag - it got
- * to '-1' because of the decrement after outputing
+ * to '-1' because of the decrement after outputting
* the decimal point above (the exponent required is
* *not* -1!)
*/
@@ -1730,7 +3042,7 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
{
/* The following only happens if we didn't output the
* leading zeros above for negative exponent, so this
- * doest add to the digit requirement. Note that the
+ * doesn't add to the digit requirement. Note that the
* two zeros here can only be output if the two leading
* zeros were *not* output, so this doesn't increase
* the output count.
@@ -1819,8 +3131,8 @@ png_ascii_from_fp(png_structp png_ptr, png_charp ascii, png_size_t size,
/* Function to format a fixed point value in ASCII.
*/
void /* PRIVATE */
-png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
- png_fixed_point fp)
+png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
+ png_size_t size, png_fixed_point fp)
{
/* Require space for 10 decimal digits, a decimal point, a minus sign and a
* trailing \0, 13 characters:
@@ -1887,24 +3199,33 @@ png_ascii_from_fixed(png_structp png_ptr, png_charp ascii, png_size_t size,
png_error(png_ptr, "ASCII conversion buffer too small");
}
# endif /* FIXED_POINT */
-#endif /* READ_SCAL */
+#endif /* SCAL */
#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
- !defined(PNG_FIXED_POINT_MACRO_SUPPORTED)
+ !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
+ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
+ (defined(PNG_sCAL_SUPPORTED) && \
+ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
png_fixed_point
-png_fixed(png_structp png_ptr, double fp, png_const_charp text)
+png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
{
double r = floor(100000 * fp + .5);
if (r > 2147483647. || r < -2147483648.)
png_fixed_error(png_ptr, text);
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(text)
+# endif
+
return (png_fixed_point)r;
}
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || \
- defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG__READ_pHYs_SUPPORTED)
+#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_COLORSPACE_SUPPORTED) ||\
+ defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
/* muldiv functions */
/* This API takes signed arguments and rounds the result to the nearest
* integer (or, for a fixed point number - the standard argument - to
@@ -2008,11 +3329,12 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
if (s00 >= (D >> 1))
++result;
- if (negative)
+ if (negative != 0)
result = -result;
/* Check for overflow. */
- if ((negative && result <= 0) || (!negative && result >= 0))
+ if ((negative != 0 && result <= 0) ||
+ (negative == 0 && result >= 0))
{
*res = result;
return 1;
@@ -2031,12 +3353,12 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
* result.
*/
png_fixed_point
-png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
+png_muldiv_warn(png_const_structrp png_ptr, png_fixed_point a, png_int_32 times,
png_int_32 divisor)
{
png_fixed_point result;
- if (png_muldiv(&result, a, times, divisor))
+ if (png_muldiv(&result, a, times, divisor) != 0)
return result;
png_warning(png_ptr, "fixed point overflow ignored");
@@ -2044,7 +3366,7 @@ png_muldiv_warn(png_structp png_ptr, png_fixed_point a, png_int_32 times,
}
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED /* more fixed point functions for gammma */
+#ifdef PNG_GAMMA_SUPPORTED /* more fixed point functions for gamma */
/* Calculate a reciprocal, return 0 on div-by-zero or overflow. */
png_fixed_point
png_reciprocal(png_fixed_point a)
@@ -2057,13 +3379,26 @@ png_reciprocal(png_fixed_point a)
#else
png_fixed_point res;
- if (png_muldiv(&res, 100000, 100000, a))
+ if (png_muldiv(&res, 100000, 100000, a) != 0)
return res;
#endif
return 0; /* error/overflow */
}
+/* This is the shared test on whether a gamma value is 'significant' - whether
+ * it is worth doing gamma correction.
+ */
+int /* PRIVATE */
+png_gamma_significant(png_fixed_point gamma_val)
+{
+ return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
+ gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
+}
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+#ifdef PNG_16BIT_SUPPORTED
/* A local convenience routine. */
static png_fixed_point
png_product2(png_fixed_point a, png_fixed_point b)
@@ -2079,12 +3414,13 @@ png_product2(png_fixed_point a, png_fixed_point b)
#else
png_fixed_point res;
- if (png_muldiv(&res, a, b, 100000))
+ if (png_muldiv(&res, a, b, 100000) != 0)
return res;
#endif
return 0; /* overflow */
}
+#endif /* 16BIT */
/* The inverse of the above. */
png_fixed_point
@@ -2092,12 +3428,15 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
{
/* The required result is 1/a * 1/b; the following preserves accuracy. */
#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = 1E15/a;
- r /= b;
- r = floor(r+.5);
+ if (a != 0 && b != 0)
+ {
+ double r = 1E15/a;
+ r /= b;
+ r = floor(r+.5);
- if (r <= 2147483647. && r >= -2147483648.)
- return (png_fixed_point)r;
+ if (r <= 2147483647. && r >= -2147483648.)
+ return (png_fixed_point)r;
+ }
#else
/* This may overflow because the range of png_fixed_point isn't symmetric,
* but this API is only used for the product of file and screen gamma so it
@@ -2114,73 +3453,28 @@ png_reciprocal2(png_fixed_point a, png_fixed_point b)
}
#endif /* READ_GAMMA */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-/* Added at libpng version 1.2.34 (Dec 8, 2008) and 1.4.0 (Jan 2,
- * 2010: moved from pngset.c) */
-/*
- * Multiply two 32-bit numbers, V1 and V2, using 32-bit
- * arithmetic, to produce a 64-bit result in the HI/LO words.
- *
- * A B
- * x C D
- * ------
- * AD || BD
- * AC || CB || 0
- *
- * where A and B are the high and low 16-bit words of V1,
- * C and D are the 16-bit words of V2, AD is the product of
- * A and D, and X || Y is (X << 16) + Y.
-*/
-
-void /* PRIVATE */
-png_64bit_product (long v1, long v2, unsigned long *hi_product,
- unsigned long *lo_product)
-{
- int a, b, c, d;
- long lo, hi, x, y;
-
- a = (v1 >> 16) & 0xffff;
- b = v1 & 0xffff;
- c = (v2 >> 16) & 0xffff;
- d = v2 & 0xffff;
-
- lo = b * d; /* BD */
- x = a * d + c * b; /* AD + CB */
- y = ((lo >> 16) & 0xffff) + x;
-
- lo = (lo & 0xffff) | ((y & 0xffff) << 16);
- hi = (y >> 16) & 0xffff;
-
- hi += a * c; /* AC */
-
- *hi_product = (unsigned long)hi;
- *lo_product = (unsigned long)lo;
-}
-#endif /* CHECK_cHRM */
-
#ifdef PNG_READ_GAMMA_SUPPORTED /* gamma table code */
#ifndef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Fixed point gamma.
*
+ * The code to calculate the tables used below can be found in the shell script
+ * contrib/tools/intgamma.sh
+ *
* To calculate gamma this code implements fast log() and exp() calls using only
* fixed point arithmetic. This code has sufficient precision for either 8-bit
* or 16-bit sample values.
*
* The tables used here were calculated using simple 'bc' programs, but C double
- * precision floating point arithmetic would work fine. The programs are given
- * at the head of each table.
+ * precision floating point arithmetic would work fine.
*
* 8-bit log table
* This is a table of -log(value/255)/log(2) for 'value' in the range 128 to
* 255, so it's the base 2 logarithm of a normalized 8-bit floating point
* mantissa. The numbers are 32-bit fractions.
*/
-static png_uint_32
+static const png_uint_32
png_8bit_l2[128] =
{
-# ifdef PNG_DO_BC
- for (i=128;i<256;++i) { .5 - l(i/255)/l(2)*65536*65536; }
-# else
4270715492U, 4222494797U, 4174646467U, 4127164793U, 4080044201U, 4033279239U,
3986864580U, 3940795015U, 3895065449U, 3849670902U, 3804606499U, 3759867474U,
3715449162U, 3671346997U, 3627556511U, 3584073329U, 3540893168U, 3498011834U,
@@ -2203,7 +3497,6 @@ png_8bit_l2[128] =
324227938U, 298676034U, 273229066U, 247886176U, 222646516U, 197509248U,
172473545U, 147538590U, 122703574U, 97967701U, 73330182U, 48790236U,
24347096U, 0U
-# endif
#if 0
/* The following are the values for 16-bit tables - these work fine for the
@@ -2226,18 +3519,18 @@ png_8bit_l2[128] =
#endif
};
-PNG_STATIC png_int_32
+static png_int_32
png_log8bit(unsigned int x)
{
unsigned int lg2 = 0;
/* Each time 'x' is multiplied by 2, 1 must be subtracted off the final log,
* because the log is actually negate that means adding 1. The final
* returned value thus has the range 0 (for 255 input) to 7.994 (for 1
- * input), return 7.99998 for the overflow (log 0) case - so the result is
+ * input), return -1 for the overflow (log 0) case, - so the result is
* always at most 19 bits.
*/
if ((x &= 0xff) == 0)
- return 0xffffffff;
+ return -1;
if ((x & 0xf0) == 0)
lg2 = 4, x <<= 4;
@@ -2282,14 +3575,15 @@ png_log8bit(unsigned int x)
* Zero (257): 0
* End (258): 23499
*/
-PNG_STATIC png_int_32
+#ifdef PNG_16BIT_SUPPORTED
+static png_int_32
png_log16bit(png_uint_32 x)
{
unsigned int lg2 = 0;
/* As above, but now the input has 16 bits. */
if ((x &= 0xffff) == 0)
- return 0xffffffff;
+ return -1;
if ((x & 0xff00) == 0)
lg2 = 8, x <<= 8;
@@ -2332,13 +3626,14 @@ png_log16bit(png_uint_32 x)
/* Safe, because the result can't have more than 20 bits: */
return (png_int_32)((lg2 + 2048) >> 12);
}
+#endif /* 16BIT */
/* The 'exp()' case must invert the above, taking a 20-bit fixed point
* logarithmic value and returning a 16 or 8-bit number as appropriate. In
* each case only the low 16 bits are relevant - the fraction - since the
* integer bits (the top 4) simply determine a shift.
*
- * The worst case is the 16-bit distinction between 65535 and 65534, this
+ * The worst case is the 16-bit distinction between 65535 and 65534. This
* requires perhaps spurious accuracy in the decoding of the logarithm to
* distinguish log2(65535/65534.5) - 10^-5 or 17 bits. There is little chance
* of getting this accuracy in practice.
@@ -2347,21 +3642,17 @@ png_log16bit(png_uint_32 x)
* frational part of the logarithm by using an accurate 32-bit value from the
* top four fractional bits then multiplying in the remaining bits.
*/
-static png_uint_32
+static const png_uint_32
png_32bit_exp[16] =
{
-# ifdef PNG_DO_BC
- for (i=0;i<16;++i) { .5 + e(-i/16*l(2))*2^32; }
-# else
/* NOTE: the first entry is deliberately set to the maximum 32-bit value. */
4294967295U, 4112874773U, 3938502376U, 3771522796U, 3611622603U, 3458501653U,
3311872529U, 3171459999U, 3037000500U, 2908241642U, 2784941738U, 2666869345U,
2553802834U, 2445529972U, 2341847524U, 2242560872U
-# endif
};
/* Adjustment table; provided to explain the numbers in the code below. */
-#ifdef PNG_DO_BC
+#if 0
for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
11 44937.64284865548751208448
10 45180.98734845585101160448
@@ -2377,7 +3668,7 @@ for (i=11;i>=0;--i){ print i, " ", (1 - e(-(2^i)/65536*l(2))) * 2^(32-i), "\n"}
0 45425.85339951654943850496
#endif
-PNG_STATIC png_uint_32
+static png_uint_32
png_exp(png_fixed_point x)
{
if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */
@@ -2425,21 +3716,22 @@ png_exp(png_fixed_point x)
return 0;
}
-PNG_STATIC png_byte
+static png_byte
png_exp8bit(png_fixed_point lg2)
{
/* Get a 32-bit value: */
png_uint_32 x = png_exp(lg2);
- /* Convert the 32-bit value to 0..255 by multiplying by 256-1, note that the
+ /* Convert the 32-bit value to 0..255 by multiplying by 256-1. Note that the
* second, rounding, step can't overflow because of the first, subtraction,
* step.
*/
x -= x >> 8;
- return (png_byte)((x + 0x7fffffU) >> 24);
+ return (png_byte)(((x + 0x7fffffU) >> 24) & 0xff);
}
-PNG_STATIC png_uint_16
+#ifdef PNG_16BIT_SUPPORTED
+static png_uint_16
png_exp16bit(png_fixed_point lg2)
{
/* Get a 32-bit value: */
@@ -2449,6 +3741,7 @@ png_exp16bit(png_fixed_point lg2)
x -= x >> 16;
return (png_uint_16)((x + 32767U) >> 16);
}
+#endif /* 16BIT */
#endif /* FLOATING_ARITHMETIC */
png_byte
@@ -2457,13 +3750,37 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
if (value > 0 && value < 255)
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = floor(255*pow(value/255.,gamma_val*.00001)+.5);
+ /* 'value' is unsigned, ANSI-C90 requires the compiler to correctly
+ * convert this to a floating point value. This includes values that
+ * would overflow if 'value' were to be converted to 'int'.
+ *
+ * Apparently GCC, however, does an intermediate conversion to (int)
+ * on some (ARM) but not all (x86) platforms, possibly because of
+ * hardware FP limitations. (E.g. if the hardware conversion always
+ * assumes the integer register contains a signed value.) This results
+ * in ANSI-C undefined behavior for large values.
+ *
+ * Other implementations on the same machine might actually be ANSI-C90
+ * conformant and therefore compile spurious extra code for the large
+ * values.
+ *
+ * We can be reasonably sure that an unsigned to float conversion
+ * won't be faster than an int to float one. Therefore this code
+ * assumes responsibility for the undefined behavior, which it knows
+ * can't happen because of the check above.
+ *
+ * Note the argument to this routine is an (unsigned int) because, on
+ * 16-bit platforms, it is assigned a value which might be out of
+ * range for an (int); that would result in undefined behavior in the
+ * caller if the *argument* ('value') were to be declared (int).
+ */
+ double r = floor(255*pow((int)/*SAFE*/value/255.,gamma_val*.00001)+.5);
return (png_byte)r;
# else
png_int_32 lg2 = png_log8bit(value);
png_fixed_point res;
- if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
+ if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
return png_exp8bit(res);
/* Overflow. */
@@ -2471,22 +3788,29 @@ png_gamma_8bit_correct(unsigned int value, png_fixed_point gamma_val)
# endif
}
- return (png_byte)value;
+ return (png_byte)(value & 0xff);
}
+#ifdef PNG_16BIT_SUPPORTED
png_uint_16
png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
{
if (value > 0 && value < 65535)
{
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
- double r = floor(65535*pow(value/65535.,gamma_val*.00001)+.5);
+ /* The same (unsigned int)->(double) constraints apply here as above,
+ * however in this case the (unsigned int) to (int) conversion can
+ * overflow on an ANSI-C90 compliant system so the cast needs to ensure
+ * that this is not possible.
+ */
+ double r = floor(65535*pow((png_int_32)value/65535.,
+ gamma_val*.00001)+.5);
return (png_uint_16)r;
# else
png_int_32 lg2 = png_log16bit(value);
png_fixed_point res;
- if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1))
+ if (png_muldiv(&res, gamma_val, lg2, PNG_FP_1) != 0)
return png_exp16bit(res);
/* Overflow. */
@@ -2496,6 +3820,7 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
return (png_uint_16)value;
}
+#endif /* 16BIT */
/* This does the right thing based on the bit_depth field of the
* png_struct, interpreting values as 8-bit or 16-bit. While the result
@@ -2503,28 +3828,24 @@ png_gamma_16bit_correct(unsigned int value, png_fixed_point gamma_val)
* 8-bit (as are the arguments.)
*/
png_uint_16 /* PRIVATE */
-png_gamma_correct(png_structp png_ptr, unsigned int value,
+png_gamma_correct(png_structrp png_ptr, unsigned int value,
png_fixed_point gamma_val)
{
if (png_ptr->bit_depth == 8)
return png_gamma_8bit_correct(value, gamma_val);
+#ifdef PNG_16BIT_SUPPORTED
else
return png_gamma_16bit_correct(value, gamma_val);
+#else
+ /* should not reach this */
+ return 0;
+#endif /* 16BIT */
}
-/* This is the shared test on whether a gamma value is 'significant' - whether
- * it is worth doing gamma correction.
- */
-int /* PRIVATE */
-png_gamma_significant(png_fixed_point gamma_val)
-{
- return gamma_val < PNG_FP_1 - PNG_GAMMA_THRESHOLD_FIXED ||
- gamma_val > PNG_FP_1 + PNG_GAMMA_THRESHOLD_FIXED;
-}
-
+#ifdef PNG_16BIT_SUPPORTED
/* Internal function to build a single 16-bit table - the table consists of
- * 'num' 256-entry subtables, where 'num' is determined by 'shift' - the amount
+ * 'num' 256 entry subtables, where 'num' is determined by 'shift' - the amount
* to shift the input values right (or 16-number_of_signifiant_bits).
*
* The caller is responsible for ensuring that the table gets cleaned up on
@@ -2532,27 +3853,33 @@ png_gamma_significant(png_fixed_point gamma_val)
* should be somewhere that will be cleaned.
*/
static void
-png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
+png_build_16bit_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
{
/* Various values derived from 'shift': */
PNG_CONST unsigned int num = 1U << (8U - shift);
+#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+ /* CSE the division and work round wacky GCC warnings (see the comments
+ * in png_gamma_8bit_correct for where these come from.)
+ */
+ PNG_CONST double fmax = 1./(((png_int_32)1 << (16U - shift))-1);
+#endif
PNG_CONST unsigned int max = (1U << (16U - shift))-1U;
PNG_CONST unsigned int max_by_2 = 1U << (15U-shift);
unsigned int i;
png_uint_16pp table = *ptable =
- (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+ (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
for (i = 0; i < num; i++)
{
png_uint_16p sub_table = table[i] =
- (png_uint_16p)png_malloc(png_ptr, 256 * png_sizeof(png_uint_16));
+ (png_uint_16p)png_malloc(png_ptr, 256 * (sizeof (png_uint_16)));
/* The 'threshold' test is repeated here because it can arise for one of
* the 16-bit tables even if the others don't hit it.
*/
- if (png_gamma_significant(gamma_val))
+ if (png_gamma_significant(gamma_val) != 0)
{
/* The old code would overflow at the end and this would cause the
* 'pow' function to return a result >1, resulting in an
@@ -2568,10 +3895,13 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
png_uint_32 ig = (j << (8-shift)) + i;
# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
/* Inline the 'max' scaling operation: */
- double d = floor(65535*pow(ig/(double)max, gamma_val*.00001)+.5);
+ /* See png_gamma_8bit_correct for why the cast to (int) is
+ * required here.
+ */
+ double d = floor(65535.*pow(ig*fmax, gamma_val*.00001)+.5);
sub_table[j] = (png_uint_16)d;
# else
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = png_gamma_16bit_correct(ig, gamma_val);
@@ -2587,7 +3917,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
{
png_uint_32 ig = (j << (8-shift)) + i;
- if (shift)
+ if (shift != 0)
ig = (ig * 65535U + max_by_2)/max;
sub_table[j] = (png_uint_16)ig;
@@ -2600,7 +3930,7 @@ png_build_16bit_table(png_structp png_ptr, png_uint_16pp *ptable,
* required.
*/
static void
-png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
+png_build_16to8_table(png_structrp png_ptr, png_uint_16pp *ptable,
PNG_CONST unsigned int shift, PNG_CONST png_fixed_point gamma_val)
{
PNG_CONST unsigned int num = 1U << (8U - shift);
@@ -2609,15 +3939,15 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
png_uint_32 last;
png_uint_16pp table = *ptable =
- (png_uint_16pp)png_calloc(png_ptr, num * png_sizeof(png_uint_16p));
+ (png_uint_16pp)png_calloc(png_ptr, num * (sizeof (png_uint_16p)));
- /* 'num' is the number of tables and also the number of low bits of the
- * input 16-bit value used to select a table. Each table is itself indexed
- * by the high 8 bits of the value.
+ /* 'num' is the number of tables and also the number of low bits of low
+ * bits of the input 16-bit value used to select a table. Each table is
+ * itself indexed by the high 8 bits of the value.
*/
for (i = 0; i < num; i++)
table[i] = (png_uint_16p)png_malloc(png_ptr,
- 256 * png_sizeof(png_uint_16));
+ 256 * (sizeof (png_uint_16)));
/* 'gamma_val' is set to the reciprocal of the value calculated above, so
* pow(out,g) is an *input* value. 'last' is the last input value set.
@@ -2661,34 +3991,38 @@ png_build_16to8_table(png_structp png_ptr, png_uint_16pp *ptable,
last++;
}
}
+#endif /* 16BIT */
/* Build a single 8-bit table: same as the 16-bit case but much simpler (and
* typically much faster). Note that libpng currently does no sBIT processing
* (apparently contrary to the spec) so a 256-entry table is always generated.
*/
static void
-png_build_8bit_table(png_structp png_ptr, png_bytepp ptable,
+png_build_8bit_table(png_structrp png_ptr, png_bytepp ptable,
PNG_CONST png_fixed_point gamma_val)
{
unsigned int i;
png_bytep table = *ptable = (png_bytep)png_malloc(png_ptr, 256);
- if (png_gamma_significant(gamma_val)) for (i=0; i<256; i++)
- table[i] = png_gamma_8bit_correct(i, gamma_val);
+ if (png_gamma_significant(gamma_val) != 0)
+ for (i=0; i<256; i++)
+ table[i] = png_gamma_8bit_correct(i, gamma_val);
- else for (i=0; i<256; ++i)
- table[i] = (png_byte)i;
+ else
+ for (i=0; i<256; ++i)
+ table[i] = (png_byte)(i & 0xff);
}
/* Used from png_read_destroy and below to release the memory used by the gamma
* tables.
*/
void /* PRIVATE */
-png_destroy_gamma_table(png_structp png_ptr)
+png_destroy_gamma_table(png_structrp png_ptr)
{
png_free(png_ptr, png_ptr->gamma_table);
png_ptr->gamma_table = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_table != NULL)
{
int i;
@@ -2700,6 +4034,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_16_table);
png_ptr->gamma_16_table = NULL;
}
+#endif /* 16BIT */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
@@ -2709,6 +4044,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_to_1);
png_ptr->gamma_to_1 = NULL;
+#ifdef PNG_16BIT_SUPPORTED
if (png_ptr->gamma_16_from_1 != NULL)
{
int i;
@@ -2731,6 +4067,7 @@ png_destroy_gamma_table(png_structp png_ptr)
png_free(png_ptr, png_ptr->gamma_16_to_1);
png_ptr->gamma_16_to_1 = NULL;
}
+#endif /* 16BIT */
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
@@ -2740,7 +4077,7 @@ png_destroy_gamma_table(png_structp png_ptr)
* we don't need to allocate > 64K chunks for a full 16-bit table.
*/
void /* PRIVATE */
-png_build_gamma_table(png_structp png_ptr, int bit_depth)
+png_build_gamma_table(png_structrp png_ptr, int bit_depth)
{
png_debug(1, "in png_build_gamma_table");
@@ -2759,28 +4096,29 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
if (bit_depth <= 8)
{
png_build_8bit_table(png_ptr, &png_ptr->gamma_table,
- png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
- if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
+ if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
{
png_build_8bit_table(png_ptr, &png_ptr->gamma_to_1,
- png_reciprocal(png_ptr->gamma));
+ png_reciprocal(png_ptr->colorspace.gamma));
png_build_8bit_table(png_ptr, &png_ptr->gamma_from_1,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
- png_ptr->gamma/* Probably doing rgb_to_gray */);
+ png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
}
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#ifdef PNG_16BIT_SUPPORTED
else
{
png_byte shift, sig_bit;
- if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
sig_bit = png_ptr->sig_bit.red;
@@ -2812,12 +4150,13 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
*
*/
if (sig_bit > 0 && sig_bit < 16U)
- shift = (png_byte)(16U - sig_bit); /* shift == insignificant bits */
+ /* shift == insignificant bits */
+ shift = (png_byte)((16U - sig_bit) & 0xff);
else
shift = 0; /* keep all 16 bits */
- if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
+ if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
{
/* PNG_MAX_GAMMA_8 is the number of bits to keep - effectively
* the significant bits in the *input* when the output will
@@ -2832,32 +4171,28 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
png_ptr->gamma_shift = shift;
-#ifdef PNG_16BIT_SUPPORTED
/* NOTE: prior to 1.5.4 this test used to include PNG_BACKGROUND (now
* PNG_COMPOSE). This effectively smashed the background calculation for
* 16-bit output because the 8-bit table assumes the result will be reduced
* to 8 bits.
*/
- if (png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8))
-#endif
+ if ((png_ptr->transformations & (PNG_16_TO_8 | PNG_SCALE_16_TO_8)) != 0)
png_build_16to8_table(png_ptr, &png_ptr->gamma_16_table, shift,
- png_ptr->screen_gamma > 0 ? png_product2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_product2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
-#ifdef PNG_16BIT_SUPPORTED
else
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_table, shift,
- png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->gamma,
+ png_ptr->screen_gamma > 0 ? png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma) : PNG_FP_1);
-#endif
#if defined(PNG_READ_BACKGROUND_SUPPORTED) || \
defined(PNG_READ_ALPHA_MODE_SUPPORTED) || \
defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)
- if (png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY))
+ if ((png_ptr->transformations & (PNG_COMPOSE | PNG_RGB_TO_GRAY)) != 0)
{
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_to_1, shift,
- png_reciprocal(png_ptr->gamma));
+ png_reciprocal(png_ptr->colorspace.gamma));
/* Notice that the '16 from 1' table should be full precision, however
* the lookup on this table still uses gamma_shift, so it can't be.
@@ -2865,10 +4200,291 @@ png_build_gamma_table(png_structp png_ptr, int bit_depth)
*/
png_build_16bit_table(png_ptr, &png_ptr->gamma_16_from_1, shift,
png_ptr->screen_gamma > 0 ? png_reciprocal(png_ptr->screen_gamma) :
- png_ptr->gamma/* Probably doing rgb_to_gray */);
+ png_ptr->colorspace.gamma/* Probably doing rgb_to_gray */);
}
#endif /* READ_BACKGROUND || READ_ALPHA_MODE || RGB_TO_GRAY */
}
+#endif /* 16BIT */
}
#endif /* READ_GAMMA */
-#endif /* defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED) */
+
+/* HARDWARE OR SOFTWARE OPTION SUPPORT */
+#ifdef PNG_SET_OPTION_SUPPORTED
+int PNGAPI
+png_set_option(png_structrp png_ptr, int option, int onoff)
+{
+ if (png_ptr != NULL && option >= 0 && option < PNG_OPTION_NEXT &&
+ (option & 1) == 0)
+ {
+ int mask = 3 << option;
+ int setting = (2 + (onoff != 0)) << option;
+ int current = png_ptr->options;
+
+ png_ptr->options = (png_byte)(((current & ~mask) | setting) & 0xff);
+
+ return (current & mask) >> option;
+ }
+
+ return PNG_OPTION_INVALID;
+}
+#endif
+
+/* sRGB support */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+/* sRGB conversion tables; these are machine generated with the code in
+ * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the
+ * specification (see the article at http://en.wikipedia.org/wiki/SRGB)
+ * is used, not the gamma=1/2.2 approximation use elsewhere in libpng.
+ * The sRGB to linear table is exact (to the nearest 16 bit linear fraction).
+ * The inverse (linear to sRGB) table has accuracies as follows:
+ *
+ * For all possible (255*65535+1) input values:
+ *
+ * error: -0.515566 - 0.625971, 79441 (0.475369%) of readings inexact
+ *
+ * For the input values corresponding to the 65536 16-bit values:
+ *
+ * error: -0.513727 - 0.607759, 308 (0.469978%) of readings inexact
+ *
+ * In all cases the inexact readings are only off by one.
+ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* The convert-to-sRGB table is only currently required for read. */
+const png_uint_16 png_sRGB_table[256] =
+{
+ 0,20,40,60,80,99,119,139,
+ 159,179,199,219,241,264,288,313,
+ 340,367,396,427,458,491,526,562,
+ 599,637,677,718,761,805,851,898,
+ 947,997,1048,1101,1156,1212,1270,1330,
+ 1391,1453,1517,1583,1651,1720,1790,1863,
+ 1937,2013,2090,2170,2250,2333,2418,2504,
+ 2592,2681,2773,2866,2961,3058,3157,3258,
+ 3360,3464,3570,3678,3788,3900,4014,4129,
+ 4247,4366,4488,4611,4736,4864,4993,5124,
+ 5257,5392,5530,5669,5810,5953,6099,6246,
+ 6395,6547,6700,6856,7014,7174,7335,7500,
+ 7666,7834,8004,8177,8352,8528,8708,8889,
+ 9072,9258,9445,9635,9828,10022,10219,10417,
+ 10619,10822,11028,11235,11446,11658,11873,12090,
+ 12309,12530,12754,12980,13209,13440,13673,13909,
+ 14146,14387,14629,14874,15122,15371,15623,15878,
+ 16135,16394,16656,16920,17187,17456,17727,18001,
+ 18277,18556,18837,19121,19407,19696,19987,20281,
+ 20577,20876,21177,21481,21787,22096,22407,22721,
+ 23038,23357,23678,24002,24329,24658,24990,25325,
+ 25662,26001,26344,26688,27036,27386,27739,28094,
+ 28452,28813,29176,29542,29911,30282,30656,31033,
+ 31412,31794,32179,32567,32957,33350,33745,34143,
+ 34544,34948,35355,35764,36176,36591,37008,37429,
+ 37852,38278,38706,39138,39572,40009,40449,40891,
+ 41337,41785,42236,42690,43147,43606,44069,44534,
+ 45002,45473,45947,46423,46903,47385,47871,48359,
+ 48850,49344,49841,50341,50844,51349,51858,52369,
+ 52884,53401,53921,54445,54971,55500,56032,56567,
+ 57105,57646,58190,58737,59287,59840,60396,60955,
+ 61517,62082,62650,63221,63795,64372,64952,65535
+};
+#endif /* SIMPLIFIED_READ */
+
+/* The base/delta tables are required for both read and write (but currently
+ * only the simplified versions.)
+ */
+const png_uint_16 png_sRGB_base[512] =
+{
+ 128,1782,3383,4644,5675,6564,7357,8074,
+ 8732,9346,9921,10463,10977,11466,11935,12384,
+ 12816,13233,13634,14024,14402,14769,15125,15473,
+ 15812,16142,16466,16781,17090,17393,17690,17981,
+ 18266,18546,18822,19093,19359,19621,19879,20133,
+ 20383,20630,20873,21113,21349,21583,21813,22041,
+ 22265,22487,22707,22923,23138,23350,23559,23767,
+ 23972,24175,24376,24575,24772,24967,25160,25352,
+ 25542,25730,25916,26101,26284,26465,26645,26823,
+ 27000,27176,27350,27523,27695,27865,28034,28201,
+ 28368,28533,28697,28860,29021,29182,29341,29500,
+ 29657,29813,29969,30123,30276,30429,30580,30730,
+ 30880,31028,31176,31323,31469,31614,31758,31902,
+ 32045,32186,32327,32468,32607,32746,32884,33021,
+ 33158,33294,33429,33564,33697,33831,33963,34095,
+ 34226,34357,34486,34616,34744,34873,35000,35127,
+ 35253,35379,35504,35629,35753,35876,35999,36122,
+ 36244,36365,36486,36606,36726,36845,36964,37083,
+ 37201,37318,37435,37551,37668,37783,37898,38013,
+ 38127,38241,38354,38467,38580,38692,38803,38915,
+ 39026,39136,39246,39356,39465,39574,39682,39790,
+ 39898,40005,40112,40219,40325,40431,40537,40642,
+ 40747,40851,40955,41059,41163,41266,41369,41471,
+ 41573,41675,41777,41878,41979,42079,42179,42279,
+ 42379,42478,42577,42676,42775,42873,42971,43068,
+ 43165,43262,43359,43456,43552,43648,43743,43839,
+ 43934,44028,44123,44217,44311,44405,44499,44592,
+ 44685,44778,44870,44962,45054,45146,45238,45329,
+ 45420,45511,45601,45692,45782,45872,45961,46051,
+ 46140,46229,46318,46406,46494,46583,46670,46758,
+ 46846,46933,47020,47107,47193,47280,47366,47452,
+ 47538,47623,47709,47794,47879,47964,48048,48133,
+ 48217,48301,48385,48468,48552,48635,48718,48801,
+ 48884,48966,49048,49131,49213,49294,49376,49458,
+ 49539,49620,49701,49782,49862,49943,50023,50103,
+ 50183,50263,50342,50422,50501,50580,50659,50738,
+ 50816,50895,50973,51051,51129,51207,51285,51362,
+ 51439,51517,51594,51671,51747,51824,51900,51977,
+ 52053,52129,52205,52280,52356,52432,52507,52582,
+ 52657,52732,52807,52881,52956,53030,53104,53178,
+ 53252,53326,53400,53473,53546,53620,53693,53766,
+ 53839,53911,53984,54056,54129,54201,54273,54345,
+ 54417,54489,54560,54632,54703,54774,54845,54916,
+ 54987,55058,55129,55199,55269,55340,55410,55480,
+ 55550,55620,55689,55759,55828,55898,55967,56036,
+ 56105,56174,56243,56311,56380,56448,56517,56585,
+ 56653,56721,56789,56857,56924,56992,57059,57127,
+ 57194,57261,57328,57395,57462,57529,57595,57662,
+ 57728,57795,57861,57927,57993,58059,58125,58191,
+ 58256,58322,58387,58453,58518,58583,58648,58713,
+ 58778,58843,58908,58972,59037,59101,59165,59230,
+ 59294,59358,59422,59486,59549,59613,59677,59740,
+ 59804,59867,59930,59993,60056,60119,60182,60245,
+ 60308,60370,60433,60495,60558,60620,60682,60744,
+ 60806,60868,60930,60992,61054,61115,61177,61238,
+ 61300,61361,61422,61483,61544,61605,61666,61727,
+ 61788,61848,61909,61969,62030,62090,62150,62211,
+ 62271,62331,62391,62450,62510,62570,62630,62689,
+ 62749,62808,62867,62927,62986,63045,63104,63163,
+ 63222,63281,63340,63398,63457,63515,63574,63632,
+ 63691,63749,63807,63865,63923,63981,64039,64097,
+ 64155,64212,64270,64328,64385,64443,64500,64557,
+ 64614,64672,64729,64786,64843,64900,64956,65013,
+ 65070,65126,65183,65239,65296,65352,65409,65465
+};
+
+const png_byte png_sRGB_delta[512] =
+{
+ 207,201,158,129,113,100,90,82,77,72,68,64,61,59,56,54,
+ 52,50,49,47,46,45,43,42,41,40,39,39,38,37,36,36,
+ 35,34,34,33,33,32,32,31,31,30,30,30,29,29,28,28,
+ 28,27,27,27,27,26,26,26,25,25,25,25,24,24,24,24,
+ 23,23,23,23,23,22,22,22,22,22,22,21,21,21,21,21,
+ 21,20,20,20,20,20,20,20,20,19,19,19,19,19,19,19,
+ 19,18,18,18,18,18,18,18,18,18,18,17,17,17,17,17,
+ 17,17,17,17,17,17,16,16,16,16,16,16,16,16,16,16,
+ 16,16,16,16,15,15,15,15,15,15,15,15,15,15,15,15,
+ 15,15,15,15,14,14,14,14,14,14,14,14,14,14,14,14,
+ 14,14,14,14,14,14,14,13,13,13,13,13,13,13,13,13,
+ 13,13,13,13,13,13,13,13,13,13,13,13,13,13,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,12,
+ 12,12,12,12,12,12,12,12,12,12,12,12,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,
+ 11,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,10,
+ 10,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,
+ 9,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
+ 8,8,8,8,8,8,8,8,8,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
+ 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
+};
+#endif /* SIMPLIFIED READ/WRITE sRGB support */
+
+/* SIMPLIFIED READ/WRITE SUPPORT */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+static int
+png_image_free_function(png_voidp argument)
+{
+ png_imagep image = png_voidcast(png_imagep, argument);
+ png_controlp cp = image->opaque;
+ png_control c;
+
+ /* Double check that we have a png_ptr - it should be impossible to get here
+ * without one.
+ */
+ if (cp->png_ptr == NULL)
+ return 0;
+
+ /* First free any data held in the control structure. */
+# ifdef PNG_STDIO_SUPPORTED
+ if (cp->owned_file != 0)
+ {
+ FILE *fp = png_voidcast(FILE*, cp->png_ptr->io_ptr);
+ cp->owned_file = 0;
+
+ /* Ignore errors here. */
+ if (fp != NULL)
+ {
+ cp->png_ptr->io_ptr = NULL;
+ (void)fclose(fp);
+ }
+ }
+# endif
+
+ /* Copy the control structure so that the original, allocated, version can be
+ * safely freed. Notice that a png_error here stops the remainder of the
+ * cleanup, but this is probably fine because that would indicate bad memory
+ * problems anyway.
+ */
+ c = *cp;
+ image->opaque = &c;
+ png_free(c.png_ptr, cp);
+
+ /* Then the structures, calling the correct API. */
+ if (c.for_write != 0)
+ {
+# ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+ png_destroy_write_struct(&c.png_ptr, &c.info_ptr);
+# else
+ png_error(c.png_ptr, "simplified write not supported");
+# endif
+ }
+ else
+ {
+# ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+ png_destroy_read_struct(&c.png_ptr, &c.info_ptr, NULL);
+# else
+ png_error(c.png_ptr, "simplified read not supported");
+# endif
+ }
+
+ /* Success. */
+ return 1;
+}
+
+void PNGAPI
+png_image_free(png_imagep image)
+{
+ /* Safely call the real function, but only if doing so is safe at this point
+ * (if not inside an error handling context). Otherwise assume
+ * png_safe_execute will call this API after the return.
+ */
+ if (image != NULL && image->opaque != NULL &&
+ image->opaque->error_buf == NULL)
+ {
+ /* Ignore errors here: */
+ (void)png_safe_execute(image, png_image_free_function, image);
+ image->opaque = NULL;
+ }
+}
+
+int /* PRIVATE */
+png_image_error(png_imagep image, png_const_charp error_message)
+{
+ /* Utility to log an error. */
+ png_safecat(image->message, (sizeof image->message), 0, error_message);
+ image->warning_or_error |= PNG_IMAGE_ERROR;
+ png_image_free(image);
+ return 0;
+}
+
+#endif /* SIMPLIFIED READ/WRITE */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h
index 4e0dee1793..372599bfb4 100644
--- a/src/3rdparty/libpng/png.h
+++ b/src/3rdparty/libpng/png.h
@@ -1,8 +1,9 @@
/* png.h - header file for PNG reference library
*
- * libpng version 1.5.10 - March 29, 2012
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * libpng version 1.6.17, March 26, 2015
+ *
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,7 +12,7 @@
* Authors and maintainers:
* libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat
* libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger
- * libpng versions 0.97, January 1998, through 1.5.10 - March 29, 2012: Glenn
+ * libpng versions 0.97, January 1998, through 1.6.17, March 26, 2015: Glenn
* See also "Contributing Authors", below.
*
* Note about libpng version numbers:
@@ -166,14 +167,55 @@
* 1.5.7beta01-05 15 10507 15.so.15.7[.0]
* 1.5.7rc01-03 15 10507 15.so.15.7[.0]
* 1.5.7 15 10507 15.so.15.7[.0]
- * 1.5.8beta01 15 10508 15.so.15.8[.0]
- * 1.5.8rc01 15 10508 15.so.15.8[.0]
- * 1.5.8 15 10508 15.so.15.8[.0]
- * 1.5.9beta01-02 15 10509 15.so.15.9[.0]
- * 1.5.9rc01 15 10509 15.so.15.9[.0]
- * 1.5.9 15 10509 15.so.15.9[.0]
- * 1.5.10beta01-05 15 10510 15.so.15.10[.0]
- * 1.5.10 15 10510 15.so.15.10[.0]
+ * 1.6.0beta01-40 16 10600 16.so.16.0[.0]
+ * 1.6.0rc01-08 16 10600 16.so.16.0[.0]
+ * 1.6.0 16 10600 16.so.16.0[.0]
+ * 1.6.1beta01-09 16 10601 16.so.16.1[.0]
+ * 1.6.1rc01 16 10601 16.so.16.1[.0]
+ * 1.6.1 16 10601 16.so.16.1[.0]
+ * 1.6.2beta01 16 10602 16.so.16.2[.0]
+ * 1.6.2rc01-06 16 10602 16.so.16.2[.0]
+ * 1.6.2 16 10602 16.so.16.2[.0]
+ * 1.6.3beta01-11 16 10603 16.so.16.3[.0]
+ * 1.6.3rc01 16 10603 16.so.16.3[.0]
+ * 1.6.3 16 10603 16.so.16.3[.0]
+ * 1.6.4beta01-02 16 10604 16.so.16.4[.0]
+ * 1.6.4rc01 16 10604 16.so.16.4[.0]
+ * 1.6.4 16 10604 16.so.16.4[.0]
+ * 1.6.5 16 10605 16.so.16.5[.0]
+ * 1.6.6 16 10606 16.so.16.6[.0]
+ * 1.6.7beta01-04 16 10607 16.so.16.7[.0]
+ * 1.6.7rc01-03 16 10607 16.so.16.7[.0]
+ * 1.6.7 16 10607 16.so.16.7[.0]
+ * 1.6.8beta01-02 16 10608 16.so.16.8[.0]
+ * 1.6.8rc01-02 16 10608 16.so.16.8[.0]
+ * 1.6.8 16 10608 16.so.16.8[.0]
+ * 1.6.9beta01-04 16 10609 16.so.16.9[.0]
+ * 1.6.9rc01-02 16 10609 16.so.16.9[.0]
+ * 1.6.9 16 10609 16.so.16.9[.0]
+ * 1.6.10beta01-03 16 10610 16.so.16.10[.0]
+ * 1.6.10rc01-03 16 10610 16.so.16.10[.0]
+ * 1.6.10 16 10610 16.so.16.10[.0]
+ * 1.6.11beta01-06 16 10611 16.so.16.11[.0]
+ * 1.6.11rc01-02 16 10611 16.so.16.11[.0]
+ * 1.6.11 16 10611 16.so.16.11[.0]
+ * 1.6.12rc01-03 16 10612 16.so.16.12[.0]
+ * 1.6.12 16 10612 16.so.16.12[.0]
+ * 1.6.13beta01-04 16 10613 16.so.16.13[.0]
+ * 1.6.13rc01-02 16 10613 16.so.16.13[.0]
+ * 1.6.13 16 10613 16.so.16.13[.0]
+ * 1.6.14beta01-07 16 10614 16.so.16.14[.0]
+ * 1.6.14rc01-02 16 10614 16.so.16.14[.0]
+ * 1.6.14 16 10614 16.so.16.14[.0]
+ * 1.6.15beta01-08 16 10615 16.so.16.15[.0]
+ * 1.6.15rc01-03 16 10615 16.so.16.15[.0]
+ * 1.6.15 16 10615 16.so.16.15[.0]
+ * 1.6.16beta01-03 16 10616 16.so.16.16[.0]
+ * 1.6.16rc01-02 16 10616 16.so.16.16[.0]
+ * 1.6.16 16 10616 16.so.16.16[.0]
+ * 1.6.17beta01-06 16 10617 16.so.16.17[.0]
+ * 1.6.17rc01-06 16 10617 16.so.16.17[.0]
+ * 1.6.17 16 10617 16.so.16.17[.0]
*
* Henceforth the source version will match the shared-library major
* and minor numbers; the shared-library major version number will be
@@ -205,8 +247,8 @@
*
* This code is released under the libpng license.
*
- * libpng versions 1.2.6, August 15, 2004, through 1.5.10, March 29, 2012, are
- * Copyright (c) 2004, 2006-2012 Glenn Randers-Pehrson, and are
+ * libpng versions 1.2.6, August 15, 2004, through 1.6.17, March 26, 2015, are
+ * Copyright (c) 2004, 2006-2015 Glenn Randers-Pehrson, and are
* distributed according to the same disclaimer and license as libpng-1.2.5
* with the following individual added to the list of Contributing Authors:
*
@@ -317,28 +359,30 @@
* Y2K compliance in libpng:
* =========================
*
- * March 29, 2012
+ * March 26, 2015
*
* Since the PNG Development group is an ad-hoc body, we can't make
* an official declaration.
*
* This is your unofficial assurance that libpng from version 0.71 and
- * upward through 1.5.10 are Y2K compliant. It is my belief that
+ * upward through 1.6.17 are Y2K compliant. It is my belief that
* earlier versions were also Y2K compliant.
*
* Libpng only has two year fields. One is a 2-byte unsigned integer
- * that will hold years up to 65535. The other holds the date in text
- * format, and will hold years up to 9999.
+ * that will hold years up to 65535. The other, which is deprecated,
+ * holds the date in text format, and will hold years up to 9999.
*
* The integer is
* "png_uint_16 year" in png_time_struct.
*
* The string is
- * "png_char time_buffer" in png_struct
+ * "char time_buffer[29]" in png_struct. This is no longer used
+ * in libpng-1.6.x and will be removed from libpng-1.7.0.
*
* There are seven time-related functions:
- * png.c: png_convert_to_rfc_1123() in png.c
- * (formerly png_convert_to_rfc_1152() in error)
+ * png.c: png_convert_to_rfc_1123_buffer() in png.c
+ * (formerly png_convert_to_rfc_1123() prior to libpng-1.5.x and
+ * png_convert_to_rfc_1152() in error prior to libpng-0.98)
* png_convert_from_struct_tm() in pngwrite.c, called in pngwrite.c
* png_convert_from_time_t() in pngwrite.c
* png_get_tIME() in pngget.c
@@ -349,8 +393,8 @@
* All handle dates properly in a Y2K environment. The
* png_convert_from_time_t() function calls gmtime() to convert from system
* clock time, which returns (year - 1900), which we properly convert to
- * the full 4-digit year. There is a possibility that applications using
- * libpng are not passing 4-digit years into the png_convert_to_rfc_1123()
+ * the full 4-digit year. There is a possibility that libpng applications
+ * are not passing 4-digit years into the png_convert_to_rfc_1123_buffer()
* function, or that they are incorrectly passing only a 2-digit year
* instead of "year - 1900" into the png_convert_from_struct_tm() function,
* but this is not under our control. The libpng documentation has always
@@ -374,24 +418,26 @@
/* This is not the place to learn how to use libpng. The file libpng-manual.txt
* describes how to use libpng, and the file example.c summarizes it
* with some code on which to build. This file is useful for looking
- * at the actual function definitions and structure components.
+ * at the actual function definitions and structure components. If that
+ * file has been stripped from your copy of libpng, you can find it at
+ * <http://www.libpng.org/pub/png/libpng-manual.txt>
*
* If you just need to read a PNG file and don't want to read the documentation
* skip to the end of this file and read the section entitled 'simplified API'.
*/
/* Version information for png.h - this should match the version in png.c */
-#define PNG_LIBPNG_VER_STRING "1.5.10"
+#define PNG_LIBPNG_VER_STRING "1.6.17"
#define PNG_HEADER_VERSION_STRING \
- " libpng version 1.5.10 - March 29, 2012\n"
+ " libpng version 1.6.17 - March 26, 2015\n"
-#define PNG_LIBPNG_VER_SONUM 15
-#define PNG_LIBPNG_VER_DLLNUM 15
+#define PNG_LIBPNG_VER_SONUM 16
+#define PNG_LIBPNG_VER_DLLNUM 16
/* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
#define PNG_LIBPNG_VER_MAJOR 1
-#define PNG_LIBPNG_VER_MINOR 5
-#define PNG_LIBPNG_VER_RELEASE 10
+#define PNG_LIBPNG_VER_MINOR 6
+#define PNG_LIBPNG_VER_RELEASE 17
/* This should match the numeric part of the final component of
* PNG_LIBPNG_VER_STRING, omitting any leading zero:
@@ -422,7 +468,7 @@
* version 1.0.0 was mis-numbered 100 instead of 10000). From
* version 1.0.1 it's xxyyzz, where x=major, y=minor, z=release
*/
-#define PNG_LIBPNG_VER 10510 /* 1.5.10 */
+#define PNG_LIBPNG_VER 10617 /* 1.6.17 */
/* Library configuration: these options cannot be changed after
* the library has been built.
@@ -435,25 +481,7 @@
#endif
#ifndef PNG_VERSION_INFO_ONLY
-# ifndef PNG_BUILDING_SYMBOL_TABLE
- /*
- * Standard header files (not needed for the version info or while
- * building symbol table -- see scripts/pnglibconf.dfa)
- */
-# ifdef PNG_SETJMP_SUPPORTED
-# include <setjmp.h>
-# endif
-
- /* Need the time information for converting tIME chunks, it
- * defines struct tm:
- */
-# ifdef PNG_CONVERT_tIME_SUPPORTED
- /* "time.h" functions are not supported on all operating systems */
-# include <time.h>
-# endif
-# endif
-
-/* Machine specific configuration. */
+ /* Machine specific configuration. */
# include "pngconf.h"
#endif
@@ -502,6 +530,7 @@ extern "C" {
* 2. Type definitions (base types are defined in pngconf.h), structure
* definitions.
* 3. Exported library functions.
+ * 4. Simplified API.
*
* The library source code has additional files (principally pngpriv.h) that
* allow configuration of the library.
@@ -544,7 +573,48 @@ extern "C" {
/* This triggers a compiler error in png.c, if png.c and png.h
* do not agree upon the version number.
*/
-typedef char* png_libpng_version_1_5_10;
+typedef char* png_libpng_version_1_6_17;
+
+/* Basic control structions. Read libpng-manual.txt or libpng.3 for more info.
+ *
+ * png_struct is the cache of information used while reading or writing a single
+ * PNG file. One of these is always required, although the simplified API
+ * (below) hides the creation and destruction of it.
+ */
+typedef struct png_struct_def png_struct;
+typedef const png_struct * png_const_structp;
+typedef png_struct * png_structp;
+typedef png_struct * * png_structpp;
+
+/* png_info contains information read from or to be written to a PNG file. One
+ * or more of these must exist while reading or creating a PNG file. The
+ * information is not used by libpng during read but is used to control what
+ * gets written when a PNG file is created. "png_get_" function calls read
+ * information during read and "png_set_" functions calls write information
+ * when creating a PNG.
+ * been moved into a separate header file that is not accessible to
+ * applications. Read libpng-manual.txt or libpng.3 for more info.
+ */
+typedef struct png_info_def png_info;
+typedef png_info * png_infop;
+typedef const png_info * png_const_infop;
+typedef png_info * * png_infopp;
+
+/* Types with names ending 'p' are pointer types. The corresponding types with
+ * names ending 'rp' are identical pointer types except that the pointer is
+ * marked 'restrict', which means that it is the only pointer to the object
+ * passed to the function. Applications should not use the 'restrict' types;
+ * it is always valid to pass 'p' to a pointer with a function argument of the
+ * corresponding 'rp' type. Different compilers have different rules with
+ * regard to type matching in the presence of 'restrict'. For backward
+ * compatibility libpng callbacks never have 'restrict' in their parameters and,
+ * consequentially, writing portable application code is extremely difficult if
+ * an attempt is made to use 'restrict'.
+ */
+typedef png_struct * PNG_RESTRICT png_structrp;
+typedef const png_struct * PNG_RESTRICT png_const_structrp;
+typedef png_info * PNG_RESTRICT png_inforp;
+typedef const png_info * PNG_RESTRICT png_const_inforp;
/* Three color definitions. The order of the red, green, and blue, (and the
* exact size) is not important, although the size of the fields need to
@@ -556,9 +626,9 @@ typedef struct png_color_struct
png_byte green;
png_byte blue;
} png_color;
-typedef png_color FAR * png_colorp;
-typedef PNG_CONST png_color FAR * png_const_colorp;
-typedef png_color FAR * FAR * png_colorpp;
+typedef png_color * png_colorp;
+typedef const png_color * png_const_colorp;
+typedef png_color * * png_colorpp;
typedef struct png_color_16_struct
{
@@ -568,9 +638,9 @@ typedef struct png_color_16_struct
png_uint_16 blue;
png_uint_16 gray; /* for use in grayscale files */
} png_color_16;
-typedef png_color_16 FAR * png_color_16p;
-typedef PNG_CONST png_color_16 FAR * png_const_color_16p;
-typedef png_color_16 FAR * FAR * png_color_16pp;
+typedef png_color_16 * png_color_16p;
+typedef const png_color_16 * png_const_color_16p;
+typedef png_color_16 * * png_color_16pp;
typedef struct png_color_8_struct
{
@@ -580,9 +650,9 @@ typedef struct png_color_8_struct
png_byte gray; /* for use in grayscale files */
png_byte alpha; /* for alpha channel files */
} png_color_8;
-typedef png_color_8 FAR * png_color_8p;
-typedef PNG_CONST png_color_8 FAR * png_const_color_8p;
-typedef png_color_8 FAR * FAR * png_color_8pp;
+typedef png_color_8 * png_color_8p;
+typedef const png_color_8 * png_const_color_8p;
+typedef png_color_8 * * png_color_8pp;
/*
* The following two structures are used for the in-core representation
@@ -596,9 +666,9 @@ typedef struct png_sPLT_entry_struct
png_uint_16 alpha;
png_uint_16 frequency;
} png_sPLT_entry;
-typedef png_sPLT_entry FAR * png_sPLT_entryp;
-typedef PNG_CONST png_sPLT_entry FAR * png_const_sPLT_entryp;
-typedef png_sPLT_entry FAR * FAR * png_sPLT_entrypp;
+typedef png_sPLT_entry * png_sPLT_entryp;
+typedef const png_sPLT_entry * png_const_sPLT_entryp;
+typedef png_sPLT_entry * * png_sPLT_entrypp;
/* When the depth of the sPLT palette is 8 bits, the color and alpha samples
* occupy the LSB of their respective members, and the MSB of each member
@@ -612,9 +682,9 @@ typedef struct png_sPLT_struct
png_sPLT_entryp entries; /* palette entries */
png_int_32 nentries; /* number of palette entries */
} png_sPLT_t;
-typedef png_sPLT_t FAR * png_sPLT_tp;
-typedef PNG_CONST png_sPLT_t FAR * png_const_sPLT_tp;
-typedef png_sPLT_t FAR * FAR * png_sPLT_tpp;
+typedef png_sPLT_t * png_sPLT_tp;
+typedef const png_sPLT_t * png_const_sPLT_tp;
+typedef png_sPLT_t * * png_sPLT_tpp;
#ifdef PNG_TEXT_SUPPORTED
/* png_text holds the contents of a text/ztxt/itxt chunk in a PNG file,
@@ -651,9 +721,9 @@ typedef struct png_text_struct
png_charp lang_key; /* keyword translated UTF-8 string, 0 or more
chars or a NULL pointer */
} png_text;
-typedef png_text FAR * png_textp;
-typedef PNG_CONST png_text FAR * png_const_textp;
-typedef png_text FAR * FAR * png_textpp;
+typedef png_text * png_textp;
+typedef const png_text * png_const_textp;
+typedef png_text * * png_textpp;
#endif
/* Supported compression types for text in PNG files (tEXt, and zTXt).
@@ -681,49 +751,45 @@ typedef struct png_time_struct
png_byte minute; /* minute of hour, 0 - 59 */
png_byte second; /* second of minute, 0 - 60 (for leap seconds) */
} png_time;
-typedef png_time FAR * png_timep;
-typedef PNG_CONST png_time FAR * png_const_timep;
-typedef png_time FAR * FAR * png_timepp;
+typedef png_time * png_timep;
+typedef const png_time * png_const_timep;
+typedef png_time * * png_timepp;
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
- defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_USER_CHUNKS_SUPPORTED)
/* png_unknown_chunk is a structure to hold queued chunks for which there is
* no specific support. The idea is that we can use this to queue
* up private chunks for output even though the library doesn't actually
* know about their semantics.
+ *
+ * The data in the structure is set by libpng on read and used on write.
*/
typedef struct png_unknown_chunk_t
{
- png_byte name[5];
- png_byte *data;
+ png_byte name[5]; /* Textual chunk name with '\0' terminator */
+ png_byte *data; /* Data, should not be modified on read! */
png_size_t size;
- /* libpng-using applications should NOT directly modify this byte. */
+ /* On write 'location' must be set using the flag values listed below.
+ * Notice that on read it is set by libpng however the values stored have
+ * more bits set than are listed below. Always treat the value as a
+ * bitmask. On write set only one bit - setting multiple bits may cause the
+ * chunk to be written in multiple places.
+ */
png_byte location; /* mode of operation at read time */
}
-
-
png_unknown_chunk;
-typedef png_unknown_chunk FAR * png_unknown_chunkp;
-typedef PNG_CONST png_unknown_chunk FAR * png_const_unknown_chunkp;
-typedef png_unknown_chunk FAR * FAR * png_unknown_chunkpp;
-#endif
-/* Values for the unknown chunk location byte */
+typedef png_unknown_chunk * png_unknown_chunkp;
+typedef const png_unknown_chunk * png_const_unknown_chunkp;
+typedef png_unknown_chunk * * png_unknown_chunkpp;
+#endif
+/* Flag values for the unknown chunk location byte. */
#define PNG_HAVE_IHDR 0x01
#define PNG_HAVE_PLTE 0x02
#define PNG_AFTER_IDAT 0x08
-/* The complete definition of png_info has, as of libpng-1.5.0,
- * been moved into a separate header file that is not accessible to
- * applications. Read libpng-manual.txt or libpng.3 for more info.
- */
-typedef struct png_info_def png_info;
-typedef png_info FAR * png_infop;
-typedef PNG_CONST png_info FAR * png_const_infop;
-typedef png_info FAR * FAR * png_infopp;
-
/* Maximum positive integer used in PNG is (2^31)-1 */
#define PNG_UINT_31_MAX ((png_uint_32)0x7fffffffL)
#define PNG_UINT_32_MAX ((png_uint_32)(-1))
@@ -839,16 +905,8 @@ typedef struct png_row_info_struct
png_byte pixel_depth; /* bits per pixel (depth * channels) */
} png_row_info;
-typedef png_row_info FAR * png_row_infop;
-typedef png_row_info FAR * FAR * png_row_infopp;
-
-/* The complete definition of png_struct has, as of libpng-1.5.0,
- * been moved into a separate header file that is not accessible to
- * applications. Read libpng-manual.txt or libpng.3 for more info.
- */
-typedef struct png_struct_def png_struct;
-typedef PNG_CONST png_struct FAR * png_const_structp;
-typedef png_struct FAR * png_structp;
+typedef png_row_info * png_row_infop;
+typedef png_row_info * * png_row_infopp;
/* These are the function types for the I/O functions and for the functions
* that allow the user to override the default I/O functions with his or her
@@ -895,7 +953,8 @@ typedef PNG_CALLBACK(int, *png_user_chunk_ptr, (png_structp,
png_unknown_chunkp));
#endif
#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
-typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp));
+/* not used anywhere */
+/* typedef PNG_CALLBACK(void, *png_unknown_chunk_ptr, (png_structp)); */
#endif
#ifdef PNG_SETJMP_SUPPORTED
@@ -951,8 +1010,6 @@ typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp,
png_alloc_size_t));
typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp));
-typedef png_struct FAR * FAR * png_structpp;
-
/* Section 3: exported functions
* Here are the function definitions most commonly used. This is not
* the place to find out how to use libpng. See libpng-manual.txt for the
@@ -988,7 +1045,7 @@ PNG_EXPORT(1, png_uint_32, png_access_version_number, (void));
/* Tell lib we have already handled the first <num_bytes> magic bytes.
* Handling more than 8 bytes from the beginning of the file is an error.
*/
-PNG_EXPORT(2, void, png_set_sig_bytes, (png_structp png_ptr, int num_bytes));
+PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
/* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
* PNG file. Returns zero if the supplied bytes match the 8-byte PNG
@@ -1016,9 +1073,9 @@ PNG_EXPORTA(5, png_structp, png_create_write_struct,
PNG_ALLOCATED);
PNG_EXPORT(6, png_size_t, png_get_compression_buffer_size,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
-PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr,
+PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structrp png_ptr,
png_size_t size));
/* Moved from pngconf.h in 1.4.0 and modified to ensure setjmp/longjmp
@@ -1032,10 +1089,10 @@ PNG_EXPORT(7, void, png_set_compression_buffer_size, (png_structp png_ptr,
* allocated by the library - the call will return NULL on a mismatch
* indicating an ABI mismatch.
*/
-PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr,
+PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structrp png_ptr,
png_longjmp_ptr longjmp_fn, size_t jmp_buf_size));
# define png_jmpbuf(png_ptr) \
- (*png_set_longjmp_fn((png_ptr), longjmp, sizeof (jmp_buf)))
+ (*png_set_longjmp_fn((png_ptr), longjmp, (sizeof (jmp_buf))))
#else
# define png_jmpbuf(png_ptr) \
(LIBPNG_WAS_COMPILED_WITH__PNG_NO_SETJMP)
@@ -1045,12 +1102,12 @@ PNG_EXPORT(8, jmp_buf*, png_set_longjmp_fn, (png_structp png_ptr,
* will use it; otherwise it will call PNG_ABORT(). This function was
* added in libpng-1.5.0.
*/
-PNG_EXPORTA(9, void, png_longjmp, (png_structp png_ptr, int val),
+PNG_EXPORTA(9, void, png_longjmp, (png_const_structrp png_ptr, int val),
PNG_NORETURN);
#ifdef PNG_READ_SUPPORTED
/* Reset the compression stream */
-PNG_EXPORT(10, int, png_reset_zstream, (png_structp png_ptr));
+PNG_EXPORTA(10, int, png_reset_zstream, (png_structrp png_ptr), PNG_DEPRECATED);
#endif
/* New functions added in libpng-1.0.2 (not enabled by default until 1.2.0) */
@@ -1068,81 +1125,92 @@ PNG_EXPORTA(12, png_structp, png_create_write_struct_2,
#endif
/* Write the PNG file signature. */
-PNG_EXPORT(13, void, png_write_sig, (png_structp png_ptr));
+PNG_EXPORT(13, void, png_write_sig, (png_structrp png_ptr));
/* Write a PNG chunk - size, type, (optional) data, CRC. */
-PNG_EXPORT(14, void, png_write_chunk, (png_structp png_ptr, png_const_bytep
+PNG_EXPORT(14, void, png_write_chunk, (png_structrp png_ptr, png_const_bytep
chunk_name, png_const_bytep data, png_size_t length));
/* Write the start of a PNG chunk - length and chunk name. */
-PNG_EXPORT(15, void, png_write_chunk_start, (png_structp png_ptr,
+PNG_EXPORT(15, void, png_write_chunk_start, (png_structrp png_ptr,
png_const_bytep chunk_name, png_uint_32 length));
/* Write the data of a PNG chunk started with png_write_chunk_start(). */
-PNG_EXPORT(16, void, png_write_chunk_data, (png_structp png_ptr,
+PNG_EXPORT(16, void, png_write_chunk_data, (png_structrp png_ptr,
png_const_bytep data, png_size_t length));
/* Finish a chunk started with png_write_chunk_start() (includes CRC). */
-PNG_EXPORT(17, void, png_write_chunk_end, (png_structp png_ptr));
+PNG_EXPORT(17, void, png_write_chunk_end, (png_structrp png_ptr));
/* Allocate and initialize the info structure */
-PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_structp png_ptr),
+PNG_EXPORTA(18, png_infop, png_create_info_struct, (png_const_structrp png_ptr),
PNG_ALLOCATED);
-PNG_EXPORT(19, void, png_info_init_3, (png_infopp info_ptr,
- png_size_t png_info_struct_size));
+/* DEPRECATED: this function allowed init structures to be created using the
+ * default allocation method (typically malloc). Use is deprecated in 1.6.0 and
+ * the API will be removed in the future.
+ */
+PNG_EXPORTA(19, void, png_info_init_3, (png_infopp info_ptr,
+ png_size_t png_info_struct_size), PNG_DEPRECATED);
/* Writes all the PNG information before the image. */
PNG_EXPORT(20, void, png_write_info_before_PLTE,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(21, void, png_write_info,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_const_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the information before the actual image data. */
PNG_EXPORT(22, void, png_read_info,
- (png_structp png_ptr, png_infop info_ptr));
+ (png_structrp png_ptr, png_inforp info_ptr));
#endif
#ifdef PNG_TIME_RFC1123_SUPPORTED
-PNG_EXPORT(23, png_const_charp, png_convert_to_rfc1123,
- (png_structp png_ptr,
+ /* Convert to a US string format: there is no localization support in this
+ * routine. The original implementation used a 29 character buffer in
+ * png_struct, this will be removed in future versions.
+ */
+#if PNG_LIBPNG_VER < 10700
+/* To do: remove this from libpng17 (and from libpng17/png.c and pngstruct.h) */
+PNG_EXPORTA(23, png_const_charp, png_convert_to_rfc1123, (png_structrp png_ptr,
+ png_const_timep ptime),PNG_DEPRECATED);
+#endif
+PNG_EXPORT(241, int, png_convert_to_rfc1123_buffer, (char out[29],
png_const_timep ptime));
#endif
#ifdef PNG_CONVERT_tIME_SUPPORTED
/* Convert from a struct tm to png_time */
PNG_EXPORT(24, void, png_convert_from_struct_tm, (png_timep ptime,
- PNG_CONST struct tm FAR * ttime));
+ const struct tm * ttime));
/* Convert from time_t to png_time. Uses gmtime() */
-PNG_EXPORT(25, void, png_convert_from_time_t,
- (png_timep ptime, time_t ttime));
-#endif /* PNG_CONVERT_tIME_SUPPORTED */
+PNG_EXPORT(25, void, png_convert_from_time_t, (png_timep ptime, time_t ttime));
+#endif /* CONVERT_tIME */
#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand data to 24-bit RGB, or 8-bit grayscale, with alpha if available. */
-PNG_EXPORT(26, void, png_set_expand, (png_structp png_ptr));
-PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structp png_ptr));
-PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structp png_ptr));
-PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structp png_ptr));
+PNG_EXPORT(26, void, png_set_expand, (png_structrp png_ptr));
+PNG_EXPORT(27, void, png_set_expand_gray_1_2_4_to_8, (png_structrp png_ptr));
+PNG_EXPORT(28, void, png_set_palette_to_rgb, (png_structrp png_ptr));
+PNG_EXPORT(29, void, png_set_tRNS_to_alpha, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16-bit channels, forces conversion of palette to RGB and expansion
* of a tRNS chunk if present.
*/
-PNG_EXPORT(221, void, png_set_expand_16, (png_structp png_ptr));
+PNG_EXPORT(221, void, png_set_expand_16, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Use blue, green, red order for pixels. */
-PNG_EXPORT(30, void, png_set_bgr, (png_structp png_ptr));
+PNG_EXPORT(30, void, png_set_bgr, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand the grayscale to 24-bit RGB if necessary. */
-PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
+PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
@@ -1152,12 +1220,12 @@ PNG_EXPORT(31, void, png_set_gray_to_rgb, (png_structp png_ptr));
#define PNG_ERROR_ACTION_ERROR 3
#define PNG_RGB_TO_GRAY_DEFAULT (-1)/*for red/green coefficients*/
-PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structp png_ptr,
- int error_action, double red, double green));
-PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structp png_ptr,
- int error_action, png_fixed_point red, png_fixed_point green));
+PNG_FP_EXPORT(32, void, png_set_rgb_to_gray, (png_structrp png_ptr,
+ int error_action, double red, double green))
+PNG_FIXED_EXPORT(33, void, png_set_rgb_to_gray_fixed, (png_structrp png_ptr,
+ int error_action, png_fixed_point red, png_fixed_point green))
-PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structp
+PNG_EXPORT(34, png_byte, png_get_rgb_to_gray_status, (png_const_structrp
png_ptr));
#endif
@@ -1167,9 +1235,9 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
#endif
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-/* How the alpha channel is interpreted - this affects how the color channels of
- * a PNG file are returned when an alpha channel, or tRNS chunk in a palette
- * file, is present.
+/* How the alpha channel is interpreted - this affects how the color channels
+ * of a PNG file are returned to the calling application when an alpha channel,
+ * or a tRNS chunk in a palette file, is present.
*
* This has no effect on the way pixels are written into a PNG output
* datastream. The color samples in a PNG datastream are never premultiplied
@@ -1177,33 +1245,19 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
*
* The default is to return data according to the PNG specification: the alpha
* channel is a linear measure of the contribution of the pixel to the
- * corresponding composited pixel. The gamma encoded color channels must be
- * scaled according to the contribution and to do this it is necessary to undo
+ * corresponding composited pixel, and the color channels are unassociated
+ * (not premultiplied). The gamma encoded color channels must be scaled
+ * according to the contribution and to do this it is necessary to undo
* the encoding, scale the color values, perform the composition and reencode
* the values. This is the 'PNG' mode.
*
* The alternative is to 'associate' the alpha with the color information by
- * storing color channel values that have been scaled by the alpha. The
- * advantage is that the color channels can be resampled (the image can be
- * scaled) in this form. The disadvantage is that normal practice is to store
- * linear, not (gamma) encoded, values and this requires 16-bit channels for
- * still images rather than the 8-bit channels that are just about sufficient if
- * gamma encoding is used. In addition all non-transparent pixel values,
- * including completely opaque ones, must be gamma encoded to produce the final
- * image. This is the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' mode (the
- * latter being the two common names for associated alpha color channels.)
- *
- * Since it is not necessary to perform arithmetic on opaque color values so
- * long as they are not to be resampled and are in the final color space it is
- * possible to optimize the handling of alpha by storing the opaque pixels in
- * the PNG format (adjusted for the output color space) while storing partially
- * opaque pixels in the standard, linear, format. The accuracy required for
- * standard alpha composition is relatively low, because the pixels are
- * isolated, therefore typically the accuracy loss in storing 8-bit linear
- * values is acceptable. (This is not true if the alpha channel is used to
- * simulate transparency over large areas - use 16 bits or the PNG mode in
- * this case!) This is the 'OPTIMIZED' mode. For this mode a pixel is
- * treated as opaque only if the alpha value is equal to the maximum value.
+ * storing color channel values that have been scaled by the alpha.
+ * image. These are the 'STANDARD', 'ASSOCIATED' or 'PREMULTIPLIED' modes
+ * (the latter being the two common names for associated alpha color channels).
+ *
+ * For the 'OPTIMIZED' mode, a pixel is treated as opaque only if the alpha
+ * value is equal to the maximum value.
*
* The final choice is to gamma encode the alpha channel as well. This is
* broken because, in practice, no implementation that uses this choice
@@ -1222,76 +1276,15 @@ PNG_EXPORT(35, void, png_build_grayscale_palette, (int bit_depth,
#define PNG_ALPHA_OPTIMIZED 2 /* 'PNG' for opaque pixels, else 'STANDARD' */
#define PNG_ALPHA_BROKEN 3 /* the alpha channel is gamma encoded */
-PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structp png_ptr, int mode,
- double output_gamma));
-PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
- int mode, png_fixed_point output_gamma));
+PNG_FP_EXPORT(227, void, png_set_alpha_mode, (png_structrp png_ptr, int mode,
+ double output_gamma))
+PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structrp png_ptr,
+ int mode, png_fixed_point output_gamma))
#endif
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_GAMMA_SUPPORTED) || defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* The output_gamma value is a screen gamma in libpng terminology: it expresses
- * how to decode the output values, not how they are encoded. The values used
- * correspond to the normal numbers used to describe the overall gamma of a
- * computer display system; for example 2.2 for an sRGB conformant system. The
- * values are scaled by 100000 in the _fixed version of the API (so 220000 for
- * sRGB.)
- *
- * The inverse of the value is always used to provide a default for the PNG file
- * encoding if it has no gAMA chunk and if png_set_gamma() has not been called
- * to override the PNG gamma information.
- *
- * When the ALPHA_OPTIMIZED mode is selected the output gamma is used to encode
- * opaque pixels however pixels with lower alpha values are not encoded,
- * regardless of the output gamma setting.
- *
- * When the standard Porter Duff handling is requested with mode 1 the output
- * encoding is set to be linear and the output_gamma value is only relevant
- * as a default for input data that has no gamma information. The linear output
- * encoding will be overridden if png_set_gamma() is called - the results may be
- * highly unexpected!
- *
- * The following numbers are derived from the sRGB standard and the research
- * behind it. sRGB is defined to be approximated by a PNG gAMA chunk value of
- * 0.45455 (1/2.2) for PNG. The value implicitly includes any viewing
- * correction required to take account of any differences in the color
- * environment of the original scene and the intended display environment; the
- * value expresses how to *decode* the image for display, not how the original
- * data was *encoded*.
- *
- * sRGB provides a peg for the PNG standard by defining a viewing environment.
- * sRGB itself, and earlier TV standards, actually use a more complex transform
- * (a linear portion then a gamma 2.4 power law) than PNG can express. (PNG is
- * limited to simple power laws.) By saying that an image for direct display on
- * an sRGB conformant system should be stored with a gAMA chunk value of 45455
- * (11.3.3.2 and 11.3.3.5 of the ISO PNG specification) the PNG specification
- * makes it possible to derive values for other display systems and
- * environments.
- *
- * The Mac value is deduced from the sRGB based on an assumption that the actual
- * extra viewing correction used in early Mac display systems was implemented as
- * a power 1.45 lookup table.
- *
- * Any system where a programmable lookup table is used or where the behavior of
- * the final display device characteristics can be changed requires system
- * specific code to obtain the current characteristic. However this can be
- * difficult and most PNG gamma correction only requires an approximate value.
- *
- * By default, if png_set_alpha_mode() is not called, libpng assumes that all
- * values are unencoded, linear, values and that the output device also has a
- * linear characteristic. This is only very rarely correct - it is invariably
- * better to call png_set_alpha_mode() with PNG_DEFAULT_sRGB than rely on the
- * default if you don't know what the right answer is!
- *
- * The special value PNG_GAMMA_MAC_18 indicates an older Mac system (pre Mac OS
- * 10.6) which used a correction table to implement a somewhat lower gamma on an
- * otherwise sRGB system.
- *
- * Both these values are reserved (not simple gamma values) in order to allow
- * more precise correction internally in the future.
- *
- * NOTE: the following values can be passed to either the fixed or floating
- * point APIs, but the floating point API will also accept floating point
- * values.
+ * how to decode the output values, not how they are encoded.
*/
#define PNG_DEFAULT_sRGB -1 /* sRGB gamma and color space */
#define PNG_GAMMA_MAC_18 -2 /* Old Mac '1.8' gamma and color space */
@@ -1376,51 +1369,50 @@ PNG_FIXED_EXPORT(228, void, png_set_alpha_mode_fixed, (png_structp png_ptr,
*/
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
-PNG_EXPORT(36, void, png_set_strip_alpha, (png_structp png_ptr));
+PNG_EXPORT(36, void, png_set_strip_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
-PNG_EXPORT(37, void, png_set_swap_alpha, (png_structp png_ptr));
+PNG_EXPORT(37, void, png_set_swap_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
-PNG_EXPORT(38, void, png_set_invert_alpha, (png_structp png_ptr));
+PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(39, void, png_set_filler, (png_structp png_ptr, png_uint_32 filler,
+PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler,
int flags));
/* The values of the PNG_FILLER_ defines should NOT be changed */
# define PNG_FILLER_BEFORE 0
# define PNG_FILLER_AFTER 1
/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */
-PNG_EXPORT(40, void, png_set_add_alpha,
- (png_structp png_ptr, png_uint_32 filler,
- int flags));
-#endif /* PNG_READ_FILLER_SUPPORTED || PNG_WRITE_FILLER_SUPPORTED */
+PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr,
+ png_uint_32 filler, int flags));
+#endif /* READ_FILLER || WRITE_FILLER */
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Swap bytes in 16-bit depth files. */
-PNG_EXPORT(41, void, png_set_swap, (png_structp png_ptr));
+PNG_EXPORT(41, void, png_set_swap, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Use 1 byte per pixel in 1, 2, or 4-bit depth files. */
-PNG_EXPORT(42, void, png_set_packing, (png_structp png_ptr));
+PNG_EXPORT(42, void, png_set_packing, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Swap packing order of pixels in bytes. */
-PNG_EXPORT(43, void, png_set_packswap, (png_structp png_ptr));
+PNG_EXPORT(43, void, png_set_packswap, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
/* Converts files to legal bit depths. */
-PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p
+PNG_EXPORT(44, void, png_set_shift, (png_structrp png_ptr, png_const_color_8p
true_bits));
#endif
@@ -1432,12 +1424,12 @@ PNG_EXPORT(44, void, png_set_shift, (png_structp png_ptr, png_const_color_8p
* necessary to call png_read_row or png_read_rows png_get_image_height
* times for each pass.
*/
-PNG_EXPORT(45, int, png_set_interlace_handling, (png_structp png_ptr));
+PNG_EXPORT(45, int, png_set_interlace_handling, (png_structrp png_ptr));
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
/* Invert monochrome files */
-PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
+PNG_EXPORT(46, void, png_set_invert_mono, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
@@ -1446,12 +1438,12 @@ PNG_EXPORT(46, void, png_set_invert_mono, (png_structp png_ptr));
* read. Doing so will result in unexpected behavior and possible warnings or
* errors if the PNG file contains a bKGD chunk.
*/
-PNG_FP_EXPORT(47, void, png_set_background, (png_structp png_ptr,
+PNG_FP_EXPORT(47, void, png_set_background, (png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, double background_gamma));
-PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
+ int need_expand, double background_gamma))
+PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
- int need_expand, png_fixed_point background_gamma));
+ int need_expand, png_fixed_point background_gamma))
#endif
#ifdef PNG_READ_BACKGROUND_SUPPORTED
# define PNG_BACKGROUND_GAMMA_UNKNOWN 0
@@ -1462,23 +1454,22 @@ PNG_FIXED_EXPORT(215, void, png_set_background_fixed, (png_structp png_ptr,
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale a 16-bit depth file down to 8-bit, accurately. */
-PNG_EXPORT(229, void, png_set_scale_16, (png_structp png_ptr));
+PNG_EXPORT(229, void, png_set_scale_16, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_16_TO_8 SUPPORTED /* Name prior to 1.5.4 */
/* Strip the second byte of information from a 16-bit depth file. */
-PNG_EXPORT(48, void, png_set_strip_16, (png_structp png_ptr));
+PNG_EXPORT(48, void, png_set_strip_16, (png_structrp png_ptr));
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
/* Turn on quantizing, and reduce the palette to the number of colors
* available.
*/
-PNG_EXPORT(49, void, png_set_quantize,
- (png_structp png_ptr, png_colorp palette,
- int num_palette, int maximum_colors, png_const_uint_16p histogram,
- int full_quantize));
+PNG_EXPORT(49, void, png_set_quantize, (png_structrp png_ptr,
+ png_colorp palette, int num_palette, int maximum_colors,
+ png_const_uint_16p histogram, int full_quantize));
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
@@ -1498,71 +1489,69 @@ PNG_EXPORT(49, void, png_set_quantize,
* API (floating point or fixed.) Notice, however, that the 'file_gamma' value
* is the inverse of a 'screen gamma' value.
*/
-PNG_FP_EXPORT(50, void, png_set_gamma,
- (png_structp png_ptr, double screen_gamma,
- double override_file_gamma));
-PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structp png_ptr,
- png_fixed_point screen_gamma, png_fixed_point override_file_gamma));
+PNG_FP_EXPORT(50, void, png_set_gamma, (png_structrp png_ptr,
+ double screen_gamma, double override_file_gamma))
+PNG_FIXED_EXPORT(208, void, png_set_gamma_fixed, (png_structrp png_ptr,
+ png_fixed_point screen_gamma, png_fixed_point override_file_gamma))
#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
/* Set how many lines between output flushes - 0 for no flushing */
-PNG_EXPORT(51, void, png_set_flush, (png_structp png_ptr, int nrows));
+PNG_EXPORT(51, void, png_set_flush, (png_structrp png_ptr, int nrows));
/* Flush the current PNG output buffer */
-PNG_EXPORT(52, void, png_write_flush, (png_structp png_ptr));
+PNG_EXPORT(52, void, png_write_flush, (png_structrp png_ptr));
#endif
/* Optional update palette with requested transformations */
-PNG_EXPORT(53, void, png_start_read_image, (png_structp png_ptr));
+PNG_EXPORT(53, void, png_start_read_image, (png_structrp png_ptr));
/* Optional call to update the users info structure */
-PNG_EXPORT(54, void, png_read_update_info,
- (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(54, void, png_read_update_info, (png_structrp png_ptr,
+ png_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read one or more rows of image data. */
-PNG_EXPORT(55, void, png_read_rows, (png_structp png_ptr, png_bytepp row,
+PNG_EXPORT(55, void, png_read_rows, (png_structrp png_ptr, png_bytepp row,
png_bytepp display_row, png_uint_32 num_rows));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read a row of data. */
-PNG_EXPORT(56, void, png_read_row, (png_structp png_ptr, png_bytep row,
+PNG_EXPORT(56, void, png_read_row, (png_structrp png_ptr, png_bytep row,
png_bytep display_row));
#endif
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the whole image into memory at once. */
-PNG_EXPORT(57, void, png_read_image, (png_structp png_ptr, png_bytepp image));
+PNG_EXPORT(57, void, png_read_image, (png_structrp png_ptr, png_bytepp image));
#endif
/* Write a row of image data */
-PNG_EXPORT(58, void, png_write_row,
- (png_structp png_ptr, png_const_bytep row));
+PNG_EXPORT(58, void, png_write_row, (png_structrp png_ptr,
+ png_const_bytep row));
/* Write a few rows of image data: (*row) is not written; however, the type
* is declared as writeable to maintain compatibility with previous versions
* of libpng and to allow the 'display_row' array from read_rows to be passed
* unchanged to write_rows.
*/
-PNG_EXPORT(59, void, png_write_rows, (png_structp png_ptr, png_bytepp row,
+PNG_EXPORT(59, void, png_write_rows, (png_structrp png_ptr, png_bytepp row,
png_uint_32 num_rows));
/* Write the image data */
-PNG_EXPORT(60, void, png_write_image,
- (png_structp png_ptr, png_bytepp image));
+PNG_EXPORT(60, void, png_write_image, (png_structrp png_ptr, png_bytepp image));
/* Write the end of the PNG file. */
-PNG_EXPORT(61, void, png_write_end,
- (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(61, void, png_write_end, (png_structrp png_ptr,
+ png_inforp info_ptr));
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the end of the PNG file. */
-PNG_EXPORT(62, void, png_read_end, (png_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(62, void, png_read_end, (png_structrp png_ptr, png_inforp info_ptr));
#endif
/* Free any memory associated with the png_info_struct */
-PNG_EXPORT(63, void, png_destroy_info_struct, (png_structp png_ptr,
+PNG_EXPORT(63, void, png_destroy_info_struct, (png_const_structrp png_ptr,
png_infopp info_ptr_ptr));
/* Free any memory associated with the png_struct and the png_info_structs */
@@ -1574,8 +1563,8 @@ PNG_EXPORT(65, void, png_destroy_write_struct, (png_structpp png_ptr_ptr,
png_infopp info_ptr_ptr));
/* Set the libpng method of handling chunk CRC errors */
-PNG_EXPORT(66, void, png_set_crc_action,
- (png_structp png_ptr, int crit_action, int ancil_action));
+PNG_EXPORT(66, void, png_set_crc_action, (png_structrp png_ptr, int crit_action,
+ int ancil_action));
/* Values for png_set_crc_action() say how to handle CRC errors in
* ancillary and critical chunks, and whether to use the data contained
@@ -1593,6 +1582,7 @@ PNG_EXPORT(66, void, png_set_crc_action,
#define PNG_CRC_QUIET_USE 4 /* quiet/use data quiet/use data */
#define PNG_CRC_NO_CHANGE 5 /* use current value use current value */
+#ifdef PNG_WRITE_SUPPORTED
/* These functions give the user control over the scan-line filtering in
* libpng and the compression methods used by zlib. These functions are
* mainly useful for testing, as the defaults should work with most users.
@@ -1604,8 +1594,9 @@ PNG_EXPORT(66, void, png_set_crc_action,
/* Set the filtering method(s) used by libpng. Currently, the only valid
* value for "method" is 0.
*/
-PNG_EXPORT(67, void, png_set_filter,
- (png_structp png_ptr, int method, int filters));
+PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method,
+ int filters));
+#endif /* WRITE */
/* Flags for png_set_filter() to say which filters to use. The flags
* are chosen so that they don't conflict with real filter types
@@ -1631,6 +1622,7 @@ PNG_EXPORT(67, void, png_set_filter,
#define PNG_FILTER_VALUE_PAETH 4
#define PNG_FILTER_VALUE_LAST 5
+#ifdef PNG_WRITE_SUPPORTED
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */
/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_
* defines, either the default (minimum-sum-of-absolute-differences), or
@@ -1660,14 +1652,14 @@ PNG_EXPORT(67, void, png_set_filter,
* the weights and costs are set to 1.0, this degenerates the WEIGHTED method
* to the UNWEIGHTED method, but with added encoding time/computation.
*/
-PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structp png_ptr,
+PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr,
int heuristic_method, int num_weights, png_const_doublep filter_weights,
- png_const_doublep filter_costs));
+ png_const_doublep filter_costs))
PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
- (png_structp png_ptr,
- int heuristic_method, int num_weights, png_const_fixed_point_p
- filter_weights, png_const_fixed_point_p filter_costs));
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+ (png_structrp png_ptr, int heuristic_method, int num_weights,
+ png_const_fixed_point_p filter_weights,
+ png_const_fixed_point_p filter_costs))
+#endif /* WRITE_WEIGHTED_FILTER */
/* Heuristic used for row filter selection. These defines should NOT be
* changed.
@@ -1677,7 +1669,6 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
#define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */
#define PNG_FILTER_HEURISTIC_LAST 3 /* Not a valid value */
-#ifdef PNG_WRITE_SUPPORTED
/* Set the library compression level. Currently, valid values range from
* 0 - 9, corresponding directly to the zlib compression levels 0 - 9
* (0 - no compression, 9 - "maximal" compression). Note that tests have
@@ -1685,45 +1676,47 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed,
* for PNG images, and do considerably fewer caclulations. In the future,
* these values may not correspond directly to the zlib compression levels.
*/
-PNG_EXPORT(69, void, png_set_compression_level,
- (png_structp png_ptr, int level));
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+PNG_EXPORT(69, void, png_set_compression_level, (png_structrp png_ptr,
+ int level));
-PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structp png_ptr,
+PNG_EXPORT(70, void, png_set_compression_mem_level, (png_structrp png_ptr,
int mem_level));
-PNG_EXPORT(71, void, png_set_compression_strategy, (png_structp png_ptr,
+PNG_EXPORT(71, void, png_set_compression_strategy, (png_structrp png_ptr,
int strategy));
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
* smaller value of window_bits if it can do so safely.
*/
-PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structp png_ptr,
+PNG_EXPORT(72, void, png_set_compression_window_bits, (png_structrp png_ptr,
int window_bits));
-PNG_EXPORT(73, void, png_set_compression_method, (png_structp png_ptr,
+PNG_EXPORT(73, void, png_set_compression_method, (png_structrp png_ptr,
int method));
-#endif
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
/* Also set zlib parameters for compressing non-IDAT chunks */
-PNG_EXPORT(222, void, png_set_text_compression_level,
- (png_structp png_ptr, int level));
+PNG_EXPORT(222, void, png_set_text_compression_level, (png_structrp png_ptr,
+ int level));
-PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structp png_ptr,
+PNG_EXPORT(223, void, png_set_text_compression_mem_level, (png_structrp png_ptr,
int mem_level));
-PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structp png_ptr,
+PNG_EXPORT(224, void, png_set_text_compression_strategy, (png_structrp png_ptr,
int strategy));
/* If PNG_WRITE_OPTIMIZE_CMF_SUPPORTED is defined, libpng will use a
* smaller value of window_bits if it can do so safely.
*/
-PNG_EXPORT(225, void, png_set_text_compression_window_bits, (png_structp
- png_ptr, int window_bits));
+PNG_EXPORT(225, void, png_set_text_compression_window_bits,
+ (png_structrp png_ptr, int window_bits));
-PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr,
+PNG_EXPORT(226, void, png_set_text_compression_method, (png_structrp png_ptr,
int method));
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
+#endif /* WRITE */
/* These next functions are called for input/output, memory, and error
* handling. They are in the file pngrio.c, pngwio.c, and pngerror.c,
@@ -1736,7 +1729,7 @@ PNG_EXPORT(226, void, png_set_text_compression_method, (png_structp png_ptr,
#ifdef PNG_STDIO_SUPPORTED
/* Initialize the input/output for the PNG file to the default functions. */
-PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp));
+PNG_EXPORT(74, void, png_init_io, (png_structrp png_ptr, png_FILE_p fp));
#endif
/* Replace the (error and abort), and warning functions with user
@@ -1747,12 +1740,11 @@ PNG_EXPORT(74, void, png_init_io, (png_structp png_ptr, png_FILE_p fp));
* default function will be used.
*/
-PNG_EXPORT(75, void, png_set_error_fn,
- (png_structp png_ptr, png_voidp error_ptr,
- png_error_ptr error_fn, png_error_ptr warning_fn));
+PNG_EXPORT(75, void, png_set_error_fn, (png_structrp png_ptr,
+ png_voidp error_ptr, png_error_ptr error_fn, png_error_ptr warning_fn));
/* Return the user pointer associated with the error functions */
-PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structrp png_ptr));
/* Replace the default data output functions with a user supplied one(s).
* If buffered output is not used, then output_flush_fn can be set to NULL.
@@ -1764,47 +1756,47 @@ PNG_EXPORT(76, png_voidp, png_get_error_ptr, (png_const_structp png_ptr));
* default flush function, which uses the standard *FILE structure, will
* be used.
*/
-PNG_EXPORT(77, void, png_set_write_fn, (png_structp png_ptr, png_voidp io_ptr,
+PNG_EXPORT(77, void, png_set_write_fn, (png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn));
/* Replace the default data input function with a user supplied one. */
-PNG_EXPORT(78, void, png_set_read_fn, (png_structp png_ptr, png_voidp io_ptr,
+PNG_EXPORT(78, void, png_set_read_fn, (png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn));
/* Return the user pointer associated with the I/O functions */
-PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_structp png_ptr));
+PNG_EXPORT(79, png_voidp, png_get_io_ptr, (png_const_structrp png_ptr));
-PNG_EXPORT(80, void, png_set_read_status_fn, (png_structp png_ptr,
+PNG_EXPORT(80, void, png_set_read_status_fn, (png_structrp png_ptr,
png_read_status_ptr read_row_fn));
-PNG_EXPORT(81, void, png_set_write_status_fn, (png_structp png_ptr,
+PNG_EXPORT(81, void, png_set_write_status_fn, (png_structrp png_ptr,
png_write_status_ptr write_row_fn));
#ifdef PNG_USER_MEM_SUPPORTED
/* Replace the default memory allocation functions with user supplied one(s). */
-PNG_EXPORT(82, void, png_set_mem_fn, (png_structp png_ptr, png_voidp mem_ptr,
+PNG_EXPORT(82, void, png_set_mem_fn, (png_structrp png_ptr, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn));
/* Return the user pointer associated with the memory functions */
-PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(83, png_voidp, png_get_mem_ptr, (png_const_structrp png_ptr));
#endif
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structp png_ptr,
+PNG_EXPORT(84, void, png_set_read_user_transform_fn, (png_structrp png_ptr,
png_user_transform_ptr read_user_transform_fn));
#endif
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
-PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structp png_ptr,
+PNG_EXPORT(85, void, png_set_write_user_transform_fn, (png_structrp png_ptr,
png_user_transform_ptr write_user_transform_fn));
#endif
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
-PNG_EXPORT(86, void, png_set_user_transform_info, (png_structp png_ptr,
+PNG_EXPORT(86, void, png_set_user_transform_info, (png_structrp png_ptr,
png_voidp user_transform_ptr, int user_transform_depth,
int user_transform_channels));
/* Return the user pointer associated with the user transform functions */
PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
@@ -1819,31 +1811,53 @@ PNG_EXPORT(87, png_voidp, png_get_user_transform_ptr,
* find the output pixel (x,y) given an interlaced sub-image pixel
* (row,col,pass). (See below for these macros.)
*/
-PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structp));
-PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structp));
+PNG_EXPORT(217, png_uint_32, png_get_current_row_number, (png_const_structrp));
+PNG_EXPORT(218, png_byte, png_get_current_pass_number, (png_const_structrp));
#endif
-#ifdef PNG_USER_CHUNKS_SUPPORTED
-PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structp png_ptr,
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+/* This callback is called only for *unknown* chunks. If
+ * PNG_HANDLE_AS_UNKNOWN_SUPPORTED is set then it is possible to set known
+ * chunks to be treated as unknown, however in this case the callback must do
+ * any processing required by the chunk (e.g. by calling the appropriate
+ * png_set_ APIs.)
+ *
+ * There is no write support - on write, by default, all the chunks in the
+ * 'unknown' list are written in the specified position.
+ *
+ * The integer return from the callback function is interpreted thus:
+ *
+ * negative: An error occurred; png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be saved. A critical
+ * chunk will cause an error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ *
+ * See "INTERACTION WTIH USER CHUNK CALLBACKS" below for important notes about
+ * how this behavior will change in libpng 1.7
+ */
+PNG_EXPORT(88, void, png_set_read_user_chunk_fn, (png_structrp png_ptr,
png_voidp user_chunk_ptr, png_user_chunk_ptr read_user_chunk_fn));
-PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structp png_ptr));
+#endif
+
+#ifdef PNG_USER_CHUNKS_SUPPORTED
+PNG_EXPORT(89, png_voidp, png_get_user_chunk_ptr, (png_const_structrp png_ptr));
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
/* Sets the function callbacks for the push reader, and a pointer to a
* user-defined structure available to the callback functions.
*/
-PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structp png_ptr,
+PNG_EXPORT(90, void, png_set_progressive_read_fn, (png_structrp png_ptr,
png_voidp progressive_ptr, png_progressive_info_ptr info_fn,
png_progressive_row_ptr row_fn, png_progressive_end_ptr end_fn));
/* Returns the user pointer associated with the push read functions */
-PNG_EXPORT(91, png_voidp, png_get_progressive_ptr, (png_const_structp png_ptr));
+PNG_EXPORT(91, png_voidp, png_get_progressive_ptr,
+ (png_const_structrp png_ptr));
/* Function to be called when data becomes available */
-PNG_EXPORT(92, void, png_process_data,
- (png_structp png_ptr, png_infop info_ptr,
- png_bytep buffer, png_size_t buffer_size));
+PNG_EXPORT(92, void, png_process_data, (png_structrp png_ptr,
+ png_inforp info_ptr, png_bytep buffer, png_size_t buffer_size));
/* A function which may be called *only* within png_process_data to stop the
* processing of any more data. The function returns the number of bytes
@@ -1852,7 +1866,7 @@ PNG_EXPORT(92, void, png_process_data,
* 'save' is set to true the routine will first save all the pending data and
* will always return 0.
*/
-PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save));
+PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structrp, int save));
/* A function which may be called *only* outside (after) a call to
* png_process_data. It returns the number of bytes of data to skip in the
@@ -1860,42 +1874,43 @@ PNG_EXPORT(219, png_size_t, png_process_data_pause, (png_structp, int save));
* application must skip than number of bytes of input data and pass the
* following data to the next call to png_process_data.
*/
-PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structp));
+PNG_EXPORT(220, png_uint_32, png_process_data_skip, (png_structrp));
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Function that combines rows. 'new_row' is a flag that should come from
* the callback and be non-NULL if anything needs to be done; the library
* stores its own version of the new data internally and ignores the passed
* in value.
*/
-PNG_EXPORT(93, void, png_progressive_combine_row, (png_structp png_ptr,
+PNG_EXPORT(93, void, png_progressive_combine_row, (png_const_structrp png_ptr,
png_bytep old_row, png_const_bytep new_row));
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
-PNG_EXPORTA(94, png_voidp, png_malloc,
- (png_structp png_ptr, png_alloc_size_t size),
- PNG_ALLOCATED);
+PNG_EXPORTA(94, png_voidp, png_malloc, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED);
/* Added at libpng version 1.4.0 */
-PNG_EXPORTA(95, png_voidp, png_calloc,
- (png_structp png_ptr, png_alloc_size_t size),
- PNG_ALLOCATED);
+PNG_EXPORTA(95, png_voidp, png_calloc, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED);
/* Added at libpng version 1.2.4 */
-PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_structp png_ptr,
+PNG_EXPORTA(96, png_voidp, png_malloc_warn, (png_const_structrp png_ptr,
png_alloc_size_t size), PNG_ALLOCATED);
/* Frees a pointer allocated by png_malloc() */
-PNG_EXPORT(97, void, png_free, (png_structp png_ptr, png_voidp ptr));
+PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
/* Free data that was allocated internally */
-PNG_EXPORT(98, void, png_free_data,
- (png_structp png_ptr, png_infop info_ptr, png_uint_32 free_me, int num));
+PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 free_me, int num));
/* Reassign responsibility for freeing existing data, whether allocated
- * by libpng or by the application */
-PNG_EXPORT(99, void, png_data_freer,
- (png_structp png_ptr, png_infop info_ptr, int freer, png_uint_32 mask));
+ * by libpng or by the application; this works on the png_info structure passed
+ * in, it does not change the state for other png_info structures.
+ *
+ * It is unlikely that this function works correctly as of 1.6.0 and using it
+ * may result either in memory leaks or double free of allocated data.
+ */
+PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int freer, png_uint_32 mask));
/* Assignments for png_data_freer */
#define PNG_DESTROY_WILL_FREE_DATA 1
@@ -1908,8 +1923,10 @@ PNG_EXPORT(99, void, png_data_freer,
#define PNG_FREE_ROWS 0x0040
#define PNG_FREE_PCAL 0x0080
#define PNG_FREE_SCAL 0x0100
-#define PNG_FREE_UNKN 0x0200
-#define PNG_FREE_LIST 0x0400
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+# define PNG_FREE_UNKN 0x0200
+#endif
+/* PNG_FREE_LIST 0x0400 removed in 1.6.0 because it is ignored */
#define PNG_FREE_PLTE 0x1000
#define PNG_FREE_TRNS 0x2000
#define PNG_FREE_TEXT 0x4000
@@ -1917,50 +1934,55 @@ PNG_EXPORT(99, void, png_data_freer,
#define PNG_FREE_MUL 0x4220 /* PNG_FREE_SPLT|PNG_FREE_TEXT|PNG_FREE_UNKN */
#ifdef PNG_USER_MEM_SUPPORTED
-PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_structp png_ptr,
- png_alloc_size_t size), PNG_ALLOCATED);
-PNG_EXPORT(101, void, png_free_default, (png_structp png_ptr, png_voidp ptr));
+PNG_EXPORTA(100, png_voidp, png_malloc_default, (png_const_structrp png_ptr,
+ png_alloc_size_t size), PNG_ALLOCATED PNG_DEPRECATED);
+PNG_EXPORTA(101, void, png_free_default, (png_const_structrp png_ptr,
+ png_voidp ptr), PNG_DEPRECATED);
#endif
#ifdef PNG_ERROR_TEXT_SUPPORTED
/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(102, void, png_error,
- (png_structp png_ptr, png_const_charp error_message),
- PNG_NORETURN);
+PNG_EXPORTA(102, void, png_error, (png_const_structrp png_ptr,
+ png_const_charp error_message), PNG_NORETURN);
/* The same, but the chunk name is prepended to the error string. */
-PNG_EXPORTA(103, void, png_chunk_error, (png_structp png_ptr,
+PNG_EXPORTA(103, void, png_chunk_error, (png_const_structrp png_ptr,
png_const_charp error_message), PNG_NORETURN);
#else
/* Fatal error in PNG image of libpng - can't continue */
-PNG_EXPORTA(104, void, png_err, (png_structp png_ptr), PNG_NORETURN);
+PNG_EXPORTA(104, void, png_err, (png_const_structrp png_ptr), PNG_NORETURN);
+# define png_error(s1,s2) png_err(s1)
+# define png_chunk_error(s1,s2) png_err(s1)
#endif
#ifdef PNG_WARNINGS_SUPPORTED
/* Non-fatal error in libpng. Can continue, but may have a problem. */
-PNG_EXPORT(105, void, png_warning, (png_structp png_ptr,
+PNG_EXPORT(105, void, png_warning, (png_const_structrp png_ptr,
png_const_charp warning_message));
/* Non-fatal error in libpng, chunk name is prepended to message. */
-PNG_EXPORT(106, void, png_chunk_warning, (png_structp png_ptr,
+PNG_EXPORT(106, void, png_chunk_warning, (png_const_structrp png_ptr,
png_const_charp warning_message));
+#else
+# define png_warning(s1,s2) ((void)(s1))
+# define png_chunk_warning(s1,s2) ((void)(s1))
#endif
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
/* Benign error in libpng. Can continue, but may have a problem.
* User can choose whether to handle as a fatal error or as a warning. */
-# undef png_benign_error
-PNG_EXPORT(107, void, png_benign_error, (png_structp png_ptr,
+PNG_EXPORT(107, void, png_benign_error, (png_const_structrp png_ptr,
png_const_charp warning_message));
-/* Same, chunk name is prepended to message. */
-# undef png_chunk_benign_error
-PNG_EXPORT(108, void, png_chunk_benign_error, (png_structp png_ptr,
+#ifdef PNG_READ_SUPPORTED
+/* Same, chunk name is prepended to message (only during read) */
+PNG_EXPORT(108, void, png_chunk_benign_error, (png_const_structrp png_ptr,
png_const_charp warning_message));
+#endif
PNG_EXPORT(109, void, png_set_benign_errors,
- (png_structp png_ptr, int allowed));
+ (png_structrp png_ptr, int allowed));
#else
# ifdef PNG_ALLOW_BENIGN_ERRORS
# define png_benign_error png_warning
@@ -1984,289 +2006,274 @@ PNG_EXPORT(109, void, png_set_benign_errors,
* png_info_struct.
*/
/* Returns "flag" if chunk data is valid in info_ptr. */
-PNG_EXPORT(110, png_uint_32, png_get_valid,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_32 flag));
+PNG_EXPORT(110, png_uint_32, png_get_valid, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 flag));
/* Returns number of bytes needed to hold a transformed row. */
-PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(111, png_size_t, png_get_rowbytes, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* Returns row_pointers, which is an array of pointers to scanlines that was
* returned from png_read_png().
*/
-PNG_EXPORT(112, png_bytepp, png_get_rows,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(112, png_bytepp, png_get_rows, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
+
/* Set row_pointers, which is an array of pointers to scanlines for use
* by png_write_png().
*/
-PNG_EXPORT(113, void, png_set_rows, (png_structp png_ptr,
- png_infop info_ptr, png_bytepp row_pointers));
+PNG_EXPORT(113, void, png_set_rows, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_bytepp row_pointers));
#endif
/* Returns number of color channels in image. */
-PNG_EXPORT(114, png_byte, png_get_channels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(114, png_byte, png_get_channels, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
#ifdef PNG_EASY_ACCESS_SUPPORTED
/* Returns image width in pixels. */
-PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(115, png_uint_32, png_get_image_width, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image height in pixels. */
-PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(116, png_uint_32, png_get_image_height, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image bit_depth. */
-PNG_EXPORT(117, png_byte, png_get_bit_depth,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+PNG_EXPORT(117, png_byte, png_get_bit_depth, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image color_type. */
-PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(118, png_byte, png_get_color_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image filter_type. */
-PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(119, png_byte, png_get_filter_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image interlace_type. */
-PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(120, png_byte, png_get_interlace_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image compression_type. */
-PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_EXPORT(121, png_byte, png_get_compression_type, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
/* Returns image resolution in pixels per meter, from pHYs chunk data. */
PNG_EXPORT(122, png_uint_32, png_get_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(123, png_uint_32, png_get_x_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(124, png_uint_32, png_get_y_pixels_per_meter,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
/* Returns pixel aspect ratio, computed from pHYs chunk data. */
PNG_FP_EXPORT(125, float, png_get_pixel_aspect_ratio,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
PNG_FIXED_EXPORT(210, png_fixed_point, png_get_pixel_aspect_ratio_fixed,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
/* Returns image x, y offset in pixels or microns, from oFFs chunk data. */
PNG_EXPORT(126, png_int_32, png_get_x_offset_pixels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(127, png_int_32, png_get_y_offset_pixels,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(128, png_int_32, png_get_x_offset_microns,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(129, png_int_32, png_get_y_offset_microns,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
-#endif /* PNG_EASY_ACCESS_SUPPORTED */
+#endif /* EASY_ACCESS */
+#ifdef PNG_READ_SUPPORTED
/* Returns pointer to signature string read from PNG header */
-PNG_EXPORT(130, png_const_bytep, png_get_signature,
- (png_const_structp png_ptr, png_infop info_ptr));
+PNG_EXPORT(130, png_const_bytep, png_get_signature, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr));
+#endif
#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(131, png_uint_32, png_get_bKGD,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_color_16p *background));
+PNG_EXPORT(131, png_uint_32, png_get_bKGD, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_color_16p *background));
#endif
#ifdef PNG_bKGD_SUPPORTED
-PNG_EXPORT(132, void, png_set_bKGD, (png_structp png_ptr, png_infop info_ptr,
- png_const_color_16p background));
+PNG_EXPORT(132, void, png_set_bKGD, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_color_16p background));
#endif
#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structp png_ptr,
- png_const_infop info_ptr, double *white_x, double *white_y, double *red_x,
+PNG_FP_EXPORT(133, png_uint_32, png_get_cHRM, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *white_x, double *white_y, double *red_x,
double *red_y, double *green_x, double *green_y, double *blue_x,
- double *blue_y));
-PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_structp png_ptr,
- png_const_infop info_ptr, double *red_X, double *red_Y, double *red_Z,
+ double *blue_y))
+PNG_FP_EXPORT(230, png_uint_32, png_get_cHRM_XYZ, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *red_X, double *red_Y, double *red_Z,
double *green_X, double *green_Y, double *green_Z, double *blue_X,
- double *blue_Y, double *blue_Z));
-#ifdef PNG_FIXED_POINT_SUPPORTED /* Otherwise not implemented */
+ double *blue_Y, double *blue_Z))
PNG_FIXED_EXPORT(134, png_uint_32, png_get_cHRM_fixed,
- (png_const_structp png_ptr,
- png_const_infop info_ptr, png_fixed_point *int_white_x,
- png_fixed_point *int_white_y, png_fixed_point *int_red_x,
- png_fixed_point *int_red_y, png_fixed_point *int_green_x,
- png_fixed_point *int_green_y, png_fixed_point *int_blue_x,
- png_fixed_point *int_blue_y));
-#endif
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_white_x, png_fixed_point *int_white_y,
+ png_fixed_point *int_red_x, png_fixed_point *int_red_y,
+ png_fixed_point *int_green_x, png_fixed_point *int_green_y,
+ png_fixed_point *int_blue_x, png_fixed_point *int_blue_y))
PNG_FIXED_EXPORT(231, png_uint_32, png_get_cHRM_XYZ_fixed,
- (png_structp png_ptr, png_const_infop info_ptr,
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
- png_fixed_point *int_blue_Z));
+ png_fixed_point *int_blue_Z))
#endif
#ifdef PNG_cHRM_SUPPORTED
-PNG_FP_EXPORT(135, void, png_set_cHRM,
- (png_structp png_ptr, png_infop info_ptr,
+PNG_FP_EXPORT(135, void, png_set_cHRM, (png_const_structrp png_ptr,
+ png_inforp info_ptr,
double white_x, double white_y, double red_x, double red_y, double green_x,
- double green_y, double blue_x, double blue_y));
-PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_structp png_ptr,
- png_infop info_ptr, double red_X, double red_Y, double red_Z,
+ double green_y, double blue_x, double blue_y))
+PNG_FP_EXPORT(232, void, png_set_cHRM_XYZ, (png_const_structrp png_ptr,
+ png_inforp info_ptr, double red_X, double red_Y, double red_Z,
double green_X, double green_Y, double green_Z, double blue_X,
- double blue_Y, double blue_Z));
-PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_white_x,
+ double blue_Y, double blue_Z))
+PNG_FIXED_EXPORT(136, void, png_set_cHRM_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_white_x,
png_fixed_point int_white_y, png_fixed_point int_red_x,
png_fixed_point int_red_y, png_fixed_point int_green_x,
png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
-PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
+ png_fixed_point int_blue_y))
+PNG_FIXED_EXPORT(233, void, png_set_cHRM_XYZ_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_red_X, png_fixed_point int_red_Y,
png_fixed_point int_red_Z, png_fixed_point int_green_X,
png_fixed_point int_green_Y, png_fixed_point int_green_Z,
png_fixed_point int_blue_X, png_fixed_point int_blue_Y,
- png_fixed_point int_blue_Z));
+ png_fixed_point int_blue_Z))
#endif
#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- double *file_gamma));
+PNG_FP_EXPORT(137, png_uint_32, png_get_gAMA, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, double *file_gamma))
PNG_FIXED_EXPORT(138, png_uint_32, png_get_gAMA_fixed,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_fixed_point *int_file_gamma));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_file_gamma))
#endif
#ifdef PNG_gAMA_SUPPORTED
-PNG_FP_EXPORT(139, void, png_set_gAMA, (png_structp png_ptr,
- png_infop info_ptr, double file_gamma));
-PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_structp png_ptr,
- png_infop info_ptr, png_fixed_point int_file_gamma));
+PNG_FP_EXPORT(139, void, png_set_gAMA, (png_const_structrp png_ptr,
+ png_inforp info_ptr, double file_gamma))
+PNG_FIXED_EXPORT(140, void, png_set_gAMA_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_fixed_point int_file_gamma))
#endif
#ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(141, png_uint_32, png_get_hIST,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_16p *hist));
+PNG_EXPORT(141, png_uint_32, png_get_hIST, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_16p *hist));
#endif
#ifdef PNG_hIST_SUPPORTED
-PNG_EXPORT(142, void, png_set_hIST, (png_structp png_ptr,
- png_infop info_ptr, png_const_uint_16p hist));
+PNG_EXPORT(142, void, png_set_hIST, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_uint_16p hist));
#endif
-PNG_EXPORT(143, png_uint_32, png_get_IHDR,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 *width, png_uint_32 *height, int *bit_depth, int *color_type,
- int *interlace_method, int *compression_method, int *filter_method));
+PNG_EXPORT(143, png_uint_32, png_get_IHDR, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *width, png_uint_32 *height,
+ int *bit_depth, int *color_type, int *interlace_method,
+ int *compression_method, int *filter_method));
-PNG_EXPORT(144, void, png_set_IHDR,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
- int interlace_method, int compression_method, int filter_method));
+PNG_EXPORT(144, void, png_set_IHDR, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 width, png_uint_32 height, int bit_depth,
+ int color_type, int interlace_method, int compression_method,
+ int filter_method));
#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(145, png_uint_32, png_get_oFFs,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type));
+PNG_EXPORT(145, png_uint_32, png_get_oFFs, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_int_32 *offset_x, png_int_32 *offset_y,
+ int *unit_type));
#endif
#ifdef PNG_oFFs_SUPPORTED
-PNG_EXPORT(146, void, png_set_oFFs,
- (png_structp png_ptr, png_infop info_ptr,
- png_int_32 offset_x, png_int_32 offset_y, int unit_type));
+PNG_EXPORT(146, void, png_set_oFFs, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_int_32 offset_x, png_int_32 offset_y,
+ int unit_type));
#endif
#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(147, png_uint_32, png_get_pCAL,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type,
- int *nparams,
- png_charp *units, png_charpp *params));
+PNG_EXPORT(147, png_uint_32, png_get_pCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_charp *purpose, png_int_32 *X0,
+ png_int_32 *X1, int *type, int *nparams, png_charp *units,
+ png_charpp *params));
#endif
#ifdef PNG_pCAL_SUPPORTED
-PNG_EXPORT(148, void, png_set_pCAL, (png_structp png_ptr,
- png_infop info_ptr,
- png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
- int nparams, png_const_charp units, png_charpp params));
+PNG_EXPORT(148, void, png_set_pCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_charp purpose, png_int_32 X0, png_int_32 X1,
+ int type, int nparams, png_const_charp units, png_charpp params));
#endif
#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(149, png_uint_32, png_get_pHYs,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type));
+PNG_EXPORT(149, png_uint_32, png_get_pHYs, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
+ int *unit_type));
#endif
#ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(150, void, png_set_pHYs,
- (png_structp png_ptr, png_infop info_ptr,
- png_uint_32 res_x, png_uint_32 res_y, int unit_type));
+PNG_EXPORT(150, void, png_set_pHYs, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 res_x, png_uint_32 res_y, int unit_type));
#endif
-PNG_EXPORT(151, png_uint_32, png_get_PLTE,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_colorp *palette, int *num_palette));
+PNG_EXPORT(151, png_uint_32, png_get_PLTE, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_colorp *palette, int *num_palette));
-PNG_EXPORT(152, void, png_set_PLTE,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_colorp palette, int num_palette));
+PNG_EXPORT(152, void, png_set_PLTE, (png_structrp png_ptr,
+ png_inforp info_ptr, png_const_colorp palette, int num_palette));
#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(153, png_uint_32, png_get_sBIT,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_color_8p *sig_bit));
+PNG_EXPORT(153, png_uint_32, png_get_sBIT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_color_8p *sig_bit));
#endif
#ifdef PNG_sBIT_SUPPORTED
-PNG_EXPORT(154, void, png_set_sBIT,
- (png_structp png_ptr, png_infop info_ptr, png_const_color_8p sig_bit));
+PNG_EXPORT(154, void, png_set_sBIT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_color_8p sig_bit));
#endif
#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structp png_ptr,
- png_const_infop info_ptr, int *file_srgb_intent));
+PNG_EXPORT(155, png_uint_32, png_get_sRGB, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, int *file_srgb_intent));
#endif
#ifdef PNG_sRGB_SUPPORTED
-PNG_EXPORT(156, void, png_set_sRGB,
- (png_structp png_ptr, png_infop info_ptr, int srgb_intent));
-PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_structp png_ptr,
- png_infop info_ptr, int srgb_intent));
+PNG_EXPORT(156, void, png_set_sRGB, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int srgb_intent));
+PNG_EXPORT(157, void, png_set_sRGB_gAMA_and_cHRM, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int srgb_intent));
#endif
#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(158, png_uint_32, png_get_iCCP,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_charpp name, int *compression_type, png_bytepp profile,
- png_uint_32 *proflen));
+PNG_EXPORT(158, png_uint_32, png_get_iCCP, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_charpp name, int *compression_type,
+ png_bytepp profile, png_uint_32 *proflen));
#endif
#ifdef PNG_iCCP_SUPPORTED
-PNG_EXPORT(159, void, png_set_iCCP,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_charp name, int compression_type, png_const_bytep profile,
- png_uint_32 proflen));
+PNG_EXPORT(159, void, png_set_iCCP, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_charp name, int compression_type,
+ png_const_bytep profile, png_uint_32 proflen));
#endif
#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(160, png_uint_32, png_get_sPLT,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_sPLT_tpp entries));
+PNG_EXPORT(160, int, png_get_sPLT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_sPLT_tpp entries));
#endif
#ifdef PNG_sPLT_SUPPORTED
-PNG_EXPORT(161, void, png_set_sPLT,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_sPLT_tp entries, int nentries));
+PNG_EXPORT(161, void, png_set_sPLT, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_sPLT_tp entries, int nentries));
#endif
#ifdef PNG_TEXT_SUPPORTED
/* png_get_text also returns the number of text chunks in *num_text */
-PNG_EXPORT(162, png_uint_32, png_get_text,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- png_textp *text_ptr, int *num_text));
+PNG_EXPORT(162, int, png_get_text, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_textp *text_ptr, int *num_text));
#endif
/* Note while png_set_text() will accept a structure whose text,
@@ -2277,122 +2284,220 @@ PNG_EXPORT(162, png_uint_32, png_get_text,
*/
#ifdef PNG_TEXT_SUPPORTED
-PNG_EXPORT(163, void, png_set_text,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_textp text_ptr, int num_text));
+PNG_EXPORT(163, void, png_set_text, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_textp text_ptr, int num_text));
#endif
#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(164, png_uint_32, png_get_tIME,
- (png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time));
+PNG_EXPORT(164, png_uint_32, png_get_tIME, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_timep *mod_time));
#endif
#ifdef PNG_tIME_SUPPORTED
-PNG_EXPORT(165, void, png_set_tIME,
- (png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time));
+PNG_EXPORT(165, void, png_set_tIME, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_timep mod_time));
#endif
#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(166, png_uint_32, png_get_tRNS,
- (png_const_structp png_ptr, png_infop info_ptr,
- png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color));
+PNG_EXPORT(166, png_uint_32, png_get_tRNS, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_bytep *trans_alpha, int *num_trans,
+ png_color_16p *trans_color));
#endif
#ifdef PNG_tRNS_SUPPORTED
-PNG_EXPORT(167, void, png_set_tRNS,
- (png_structp png_ptr, png_infop info_ptr,
- png_const_bytep trans_alpha, int num_trans,
+PNG_EXPORT(167, void, png_set_tRNS, (png_structrp png_ptr,
+ png_inforp info_ptr, png_const_bytep trans_alpha, int num_trans,
png_const_color_16p trans_color));
#endif
#ifdef PNG_sCAL_SUPPORTED
-PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- int *unit, double *width, double *height));
-#ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+PNG_FP_EXPORT(168, png_uint_32, png_get_sCAL, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, int *unit, double *width, double *height))
+#if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
/* NOTE: this API is currently implemented using floating point arithmetic,
* consequently it can only be used on systems with floating point support.
* In any case the range of values supported by png_fixed_point is small and it
* is highly recommended that png_get_sCAL_s be used instead.
*/
PNG_FIXED_EXPORT(214, png_uint_32, png_get_sCAL_fixed,
- (png_structp png_ptr, png_const_infop info_ptr, int *unit,
- png_fixed_point *width,
- png_fixed_point *height));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
+ png_fixed_point *width, png_fixed_point *height))
#endif
PNG_EXPORT(169, png_uint_32, png_get_sCAL_s,
- (png_const_structp png_ptr, png_const_infop info_ptr,
- int *unit, png_charpp swidth, png_charpp sheight));
-
-PNG_FP_EXPORT(170, void, png_set_sCAL,
- (png_structp png_ptr, png_infop info_ptr,
- int unit, double width, double height));
-PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_structp png_ptr,
- png_infop info_ptr, int unit, png_fixed_point width,
- png_fixed_point height));
-PNG_EXPORT(171, void, png_set_sCAL_s,
- (png_structp png_ptr, png_infop info_ptr,
- int unit, png_const_charp swidth, png_const_charp sheight));
-#endif /* PNG_sCAL_SUPPORTED */
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-/* Provide a list of chunks and how they are to be handled, if the built-in
- handling or default unknown chunk handling is not desired. Any chunks not
- listed will be handled in the default manner. The IHDR and IEND chunks
- must not be listed. Because this turns off the default handling for chunks
- that would otherwise be recognized the behavior of libpng transformations may
- well become incorrect!
- keep = 0: PNG_HANDLE_CHUNK_AS_DEFAULT: follow default behavior
- = 1: PNG_HANDLE_CHUNK_NEVER: do not keep
- = 2: PNG_HANDLE_CHUNK_IF_SAFE: keep only if safe-to-copy
- = 3: PNG_HANDLE_CHUNK_ALWAYS: keep even if unsafe-to-copy
-*/
-PNG_EXPORT(172, void, png_set_keep_unknown_chunks,
- (png_structp png_ptr, int keep,
- png_const_bytep chunk_list, int num_chunks));
-
-/* The handling code is returned; the result is therefore true (non-zero) if
- * special handling is required, false for the default handling.
- */
-PNG_EXPORT(173, int, png_handle_as_unknown, (png_structp png_ptr,
+ (png_const_structrp png_ptr, png_const_inforp info_ptr, int *unit,
+ png_charpp swidth, png_charpp sheight));
+
+PNG_FP_EXPORT(170, void, png_set_sCAL, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit, double width, double height))
+PNG_FIXED_EXPORT(213, void, png_set_sCAL_fixed, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit, png_fixed_point width,
+ png_fixed_point height))
+PNG_EXPORT(171, void, png_set_sCAL_s, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int unit,
+ png_const_charp swidth, png_const_charp sheight));
+#endif /* sCAL */
+
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+/* Provide the default handling for all unknown chunks or, optionally, for
+ * specific unknown chunks.
+ *
+ * NOTE: prior to 1.6.0 the handling specified for particular chunks on read was
+ * ignored and the default was used, the per-chunk setting only had an effect on
+ * write. If you wish to have chunk-specific handling on read in code that must
+ * work on earlier versions you must use a user chunk callback to specify the
+ * desired handling (keep or discard.)
+ *
+ * The 'keep' parameter is a PNG_HANDLE_CHUNK_ value as listed below. The
+ * parameter is interpreted as follows:
+ *
+ * READ:
+ * PNG_HANDLE_CHUNK_AS_DEFAULT:
+ * Known chunks: do normal libpng processing, do not keep the chunk (but
+ * see the comments below about PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+ * Unknown chunks: for a specific chunk use the global default, when used
+ * as the default discard the chunk data.
+ * PNG_HANDLE_CHUNK_NEVER:
+ * Discard the chunk data.
+ * PNG_HANDLE_CHUNK_IF_SAFE:
+ * Keep the chunk data if the chunk is not critical else raise a chunk
+ * error.
+ * PNG_HANDLE_CHUNK_ALWAYS:
+ * Keep the chunk data.
+ *
+ * If the chunk data is saved it can be retrieved using png_get_unknown_chunks,
+ * below. Notice that specifying "AS_DEFAULT" as a global default is equivalent
+ * to specifying "NEVER", however when "AS_DEFAULT" is used for specific chunks
+ * it simply resets the behavior to the libpng default.
+ *
+ * INTERACTION WTIH USER CHUNK CALLBACKS:
+ * The per-chunk handling is always used when there is a png_user_chunk_ptr
+ * callback and the callback returns 0; the chunk is then always stored *unless*
+ * it is critical and the per-chunk setting is other than ALWAYS. Notice that
+ * the global default is *not* used in this case. (In effect the per-chunk
+ * value is incremented to at least IF_SAFE.)
+ *
+ * IMPORTANT NOTE: this behavior will change in libpng 1.7 - the global and
+ * per-chunk defaults will be honored. If you want to preserve the current
+ * behavior when your callback returns 0 you must set PNG_HANDLE_CHUNK_IF_SAFE
+ * as the default - if you don't do this libpng 1.6 will issue a warning.
+ *
+ * If you want unhandled unknown chunks to be discarded in libpng 1.6 and
+ * earlier simply return '1' (handled).
+ *
+ * PNG_HANDLE_AS_UNKNOWN_SUPPORTED:
+ * If this is *not* set known chunks will always be handled by libpng and
+ * will never be stored in the unknown chunk list. Known chunks listed to
+ * png_set_keep_unknown_chunks will have no effect. If it is set then known
+ * chunks listed with a keep other than AS_DEFAULT will *never* be processed
+ * by libpng, in addition critical chunks must either be processed by the
+ * callback or saved.
+ *
+ * The IHDR and IEND chunks must not be listed. Because this turns off the
+ * default handling for chunks that would otherwise be recognized the
+ * behavior of libpng transformations may well become incorrect!
+ *
+ * WRITE:
+ * When writing chunks the options only apply to the chunks specified by
+ * png_set_unknown_chunks (below), libpng will *always* write known chunks
+ * required by png_set_ calls and will always write the core critical chunks
+ * (as required for PLTE).
+ *
+ * Each chunk in the png_set_unknown_chunks list is looked up in the
+ * png_set_keep_unknown_chunks list to find the keep setting, this is then
+ * interpreted as follows:
+ *
+ * PNG_HANDLE_CHUNK_AS_DEFAULT:
+ * Write safe-to-copy chunks and write other chunks if the global
+ * default is set to _ALWAYS, otherwise don't write this chunk.
+ * PNG_HANDLE_CHUNK_NEVER:
+ * Do not write the chunk.
+ * PNG_HANDLE_CHUNK_IF_SAFE:
+ * Write the chunk if it is safe-to-copy, otherwise do not write it.
+ * PNG_HANDLE_CHUNK_ALWAYS:
+ * Write the chunk.
+ *
+ * Note that the default behavior is effectively the opposite of the read case -
+ * in read unknown chunks are not stored by default, in write they are written
+ * by default. Also the behavior of PNG_HANDLE_CHUNK_IF_SAFE is very different
+ * - on write the safe-to-copy bit is checked, on read the critical bit is
+ * checked and on read if the chunk is critical an error will be raised.
+ *
+ * num_chunks:
+ * ===========
+ * If num_chunks is positive, then the "keep" parameter specifies the manner
+ * for handling only those chunks appearing in the chunk_list array,
+ * otherwise the chunk list array is ignored.
+ *
+ * If num_chunks is 0 the "keep" parameter specifies the default behavior for
+ * unknown chunks, as described above.
+ *
+ * If num_chunks is negative, then the "keep" parameter specifies the manner
+ * for handling all unknown chunks plus all chunks recognized by libpng
+ * except for the IHDR, PLTE, tRNS, IDAT, and IEND chunks (which continue to
+ * be processed by libpng.
+ */
+PNG_EXPORT(172, void, png_set_keep_unknown_chunks, (png_structrp png_ptr,
+ int keep, png_const_bytep chunk_list, int num_chunks));
+
+/* The "keep" PNG_HANDLE_CHUNK_ parameter for the specified chunk is returned;
+ * the result is therefore true (non-zero) if special handling is required,
+ * false for the default handling.
+ */
+PNG_EXPORT(173, int, png_handle_as_unknown, (png_const_structrp png_ptr,
png_const_bytep chunk_name));
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
-PNG_EXPORT(174, void, png_set_unknown_chunks, (png_structp png_ptr,
- png_infop info_ptr, png_const_unknown_chunkp unknowns,
+
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+PNG_EXPORT(174, void, png_set_unknown_chunks, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_unknown_chunkp unknowns,
int num_unknowns));
+ /* NOTE: prior to 1.6.0 this routine set the 'location' field of the added
+ * unknowns to the location currently stored in the png_struct. This is
+ * invariably the wrong value on write. To fix this call the following API
+ * for each chunk in the list with the correct location. If you know your
+ * code won't be compiled on earlier versions you can rely on
+ * png_set_unknown_chunks(write-ptr, png_get_unknown_chunks(read-ptr)) doing
+ * the correct thing.
+ */
+
PNG_EXPORT(175, void, png_set_unknown_chunk_location,
- (png_structp png_ptr, png_infop info_ptr, int chunk, int location));
-PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structp png_ptr,
- png_const_infop info_ptr, png_unknown_chunkpp entries));
+ (png_const_structrp png_ptr, png_inforp info_ptr, int chunk, int location));
+
+PNG_EXPORT(176, int, png_get_unknown_chunks, (png_const_structrp png_ptr,
+ png_inforp info_ptr, png_unknown_chunkpp entries));
#endif
/* Png_free_data() will turn off the "valid" flag for anything it frees.
* If you need to turn it off for a chunk that your application has freed,
* you can use png_set_invalid(png_ptr, info_ptr, PNG_INFO_CHNK);
*/
-PNG_EXPORT(177, void, png_set_invalid,
- (png_structp png_ptr, png_infop info_ptr, int mask));
+PNG_EXPORT(177, void, png_set_invalid, (png_const_structrp png_ptr,
+ png_inforp info_ptr, int mask));
#ifdef PNG_INFO_IMAGE_SUPPORTED
/* The "params" pointer is currently not used and is for future expansion. */
-PNG_EXPORT(178, void, png_read_png, (png_structp png_ptr, png_infop info_ptr,
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+PNG_EXPORT(178, void, png_read_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
-PNG_EXPORT(179, void, png_write_png, (png_structp png_ptr, png_infop info_ptr,
+#endif
+#ifdef PNG_WRITE_SUPPORTED
+PNG_EXPORT(179, void, png_write_png, (png_structrp png_ptr, png_inforp info_ptr,
int transforms, png_voidp params));
#endif
+#endif
PNG_EXPORT(180, png_const_charp, png_get_copyright,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(181, png_const_charp, png_get_header_ver,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(182, png_const_charp, png_get_header_version,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(183, png_const_charp, png_get_libpng_ver,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr,
+PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structrp png_ptr,
png_uint_32 mng_features_permitted));
#endif
@@ -2401,75 +2506,77 @@ PNG_EXPORT(184, png_uint_32, png_permit_mng_features, (png_structp png_ptr,
#define PNG_HANDLE_CHUNK_NEVER 1
#define PNG_HANDLE_CHUNK_IF_SAFE 2
#define PNG_HANDLE_CHUNK_ALWAYS 3
+#define PNG_HANDLE_CHUNK_LAST 4
/* Strip the prepended error numbers ("#nnn ") from error and warning
* messages before passing them to the error or warning handler.
*/
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
-PNG_EXPORT(185, void, png_set_strip_error_numbers,
- (png_structp png_ptr,
+PNG_EXPORT(185, void, png_set_strip_error_numbers, (png_structrp png_ptr,
png_uint_32 strip_mode));
#endif
/* Added in libpng-1.2.6 */
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
-PNG_EXPORT(186, void, png_set_user_limits, (png_structp png_ptr,
+PNG_EXPORT(186, void, png_set_user_limits, (png_structrp png_ptr,
png_uint_32 user_width_max, png_uint_32 user_height_max));
PNG_EXPORT(187, png_uint_32, png_get_user_width_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
PNG_EXPORT(188, png_uint_32, png_get_user_height_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* Added in libpng-1.4.0 */
-PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structp png_ptr,
+PNG_EXPORT(189, void, png_set_chunk_cache_max, (png_structrp png_ptr,
png_uint_32 user_chunk_cache_max));
PNG_EXPORT(190, png_uint_32, png_get_chunk_cache_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* Added in libpng-1.4.1 */
-PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structp png_ptr,
+PNG_EXPORT(191, void, png_set_chunk_malloc_max, (png_structrp png_ptr,
png_alloc_size_t user_chunk_cache_max));
PNG_EXPORT(192, png_alloc_size_t, png_get_chunk_malloc_max,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
#endif
#if defined(PNG_INCH_CONVERSIONS_SUPPORTED)
PNG_EXPORT(193, png_uint_32, png_get_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(194, png_uint_32, png_get_x_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_EXPORT(195, png_uint_32, png_get_y_pixels_per_inch,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr));
PNG_FP_EXPORT(196, float, png_get_x_offset_inches,
- (png_const_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(211, png_fixed_point, png_get_x_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#endif
-PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structp png_ptr,
- png_const_infop info_ptr));
+PNG_FP_EXPORT(197, float, png_get_y_offset_inches, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr))
#ifdef PNG_FIXED_POINT_SUPPORTED /* otherwise not implemented. */
PNG_FIXED_EXPORT(212, png_fixed_point, png_get_y_offset_inches_fixed,
- (png_structp png_ptr, png_const_infop info_ptr));
+ (png_const_structrp png_ptr, png_const_inforp info_ptr))
#endif
# ifdef PNG_pHYs_SUPPORTED
-PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structp png_ptr,
- png_const_infop info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
+PNG_EXPORT(198, png_uint_32, png_get_pHYs_dpi, (png_const_structrp png_ptr,
+ png_const_inforp info_ptr, png_uint_32 *res_x, png_uint_32 *res_y,
int *unit_type));
-# endif /* PNG_pHYs_SUPPORTED */
-#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */
+# endif /* pHYs */
+#endif /* INCH_CONVERSIONS */
/* Added in libpng-1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
-PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_structp png_ptr));
+PNG_EXPORT(199, png_uint_32, png_get_io_state, (png_const_structrp png_ptr));
+
+/* Removed from libpng 1.6; use png_get_io_chunk_type. */
+PNG_REMOVED(200, png_const_bytep, png_get_io_chunk_name, (png_structrp png_ptr),
+ PNG_DEPRECATED)
-PNG_EXPORTA(200, png_const_bytep, png_get_io_chunk_name,
- (png_structp png_ptr), PNG_DEPRECATED);
PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
- (png_const_structp png_ptr));
+ (png_const_structrp png_ptr));
/* The flags returned by png_get_io_state() are the following: */
# define PNG_IO_NONE 0x0000 /* no I/O at this moment */
@@ -2481,7 +2588,7 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
# define PNG_IO_CHUNK_CRC 0x0080 /* currently at the chunk crc */
# define PNG_IO_MASK_OP 0x000f /* current operation: reading/writing */
# define PNG_IO_MASK_LOC 0x00f0 /* current location: sig/hdr/data/crc */
-#endif /* ?PNG_IO_STATE_SUPPORTED */
+#endif /* IO_STATE */
/* Interlace support. The following macros are always defined so that if
* libpng interlace handling is turned off the macros may be used to handle
@@ -2525,10 +2632,10 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
* necessary to find the row in the output image given a row in an interlaced
* image, so two more macros:
*/
-#define PNG_ROW_FROM_PASS_ROW(yIn, pass) \
- (((yIn)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
-#define PNG_COL_FROM_PASS_COL(xIn, pass) \
- (((xIn)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
+#define PNG_ROW_FROM_PASS_ROW(y_in, pass) \
+ (((y_in)<<PNG_PASS_ROW_SHIFT(pass))+PNG_PASS_START_ROW(pass))
+#define PNG_COL_FROM_PASS_COL(x_in, pass) \
+ (((x_in)<<PNG_PASS_COL_SHIFT(pass))+PNG_PASS_START_COL(pass))
/* Two macros which return a boolean (0 or 1) saying whether the given row
* or column is in a particular pass. These use a common utility macro that
@@ -2565,27 +2672,29 @@ PNG_EXPORT(216, png_uint_32, png_get_io_chunk_type,
* (png_uint_16)(alpha) \
+ (png_uint_16)(bg)*(png_uint_16)(255 \
- (png_uint_16)(alpha)) + 128); \
- (composite) = (png_byte)((temp + (temp >> 8)) >> 8); }
+ (composite) = (png_byte)(((temp + (temp >> 8)) >> 8) & 0xff); }
# define png_composite_16(composite, fg, alpha, bg) \
{ png_uint_32 temp = (png_uint_32)((png_uint_32)(fg) \
* (png_uint_32)(alpha) \
+ (png_uint_32)(bg)*(65535 \
- (png_uint_32)(alpha)) + 32768); \
- (composite) = (png_uint_16)((temp + (temp >> 16)) >> 16); }
+ (composite) = (png_uint_16)(0xffff & ((temp + (temp >> 16)) >> 16)); }
#else /* Standard method using integer division */
-# define png_composite(composite, fg, alpha, bg) \
- (composite) = (png_byte)(((png_uint_16)(fg) * (png_uint_16)(alpha) + \
- (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
- 127) / 255)
+# define png_composite(composite, fg, alpha, bg) \
+ (composite) = \
+ (png_byte)(0xff & (((png_uint_16)(fg) * (png_uint_16)(alpha) + \
+ (png_uint_16)(bg) * (png_uint_16)(255 - (png_uint_16)(alpha)) + \
+ 127) / 255))
# define png_composite_16(composite, fg, alpha, bg) \
- (composite) = (png_uint_16)(((png_uint_32)(fg) * (png_uint_32)(alpha) + \
- (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \
- 32767) / 65535)
-#endif /* PNG_READ_COMPOSITE_NODIV_SUPPORTED */
+ (composite) = \
+ (png_uint_16)(0xffff & (((png_uint_32)(fg) * (png_uint_32)(alpha) + \
+ (png_uint_32)(bg)*(png_uint_32)(65535 - (png_uint_32)(alpha)) + \
+ 32767) / 65535))
+#endif /* READ_COMPOSITE_NODIV */
#ifdef PNG_READ_INT_FUNCTIONS_SUPPORTED
PNG_EXPORT(201, png_uint_32, png_get_uint_32, (png_const_bytep buf));
@@ -2593,7 +2702,7 @@ PNG_EXPORT(202, png_uint_16, png_get_uint_16, (png_const_bytep buf));
PNG_EXPORT(203, png_int_32, png_get_int_32, (png_const_bytep buf));
#endif
-PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_structp png_ptr,
+PNG_EXPORT(204, png_uint_32, png_get_uint_31, (png_const_structrp png_ptr,
png_const_bytep buf));
/* No png_get_int_16 -- may be added if there's a real need for it. */
@@ -2619,7 +2728,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
* The png_get_int_32() routine assumes we are using two's complement
* format for negative values, which is almost certainly true.
*/
-# define png_get_uint_32(buf) \
+# define PNG_get_uint_32(buf) \
(((png_uint_32)(*(buf)) << 24) + \
((png_uint_32)(*((buf) + 1)) << 16) + \
((png_uint_32)(*((buf) + 2)) << 8) + \
@@ -2628,33 +2737,550 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i));
/* From libpng-1.4.0 until 1.4.4, the png_get_uint_16 macro (but not the
* function) incorrectly returned a value of type png_uint_32.
*/
-# define png_get_uint_16(buf) \
+# define PNG_get_uint_16(buf) \
((png_uint_16) \
(((unsigned int)(*(buf)) << 8) + \
((unsigned int)(*((buf) + 1)))))
-# define png_get_int_32(buf) \
+# define PNG_get_int_32(buf) \
((png_int_32)((*(buf) & 0x80) \
? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \
: (png_int_32)png_get_uint_32(buf)))
+
+ /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h,
+ * but defining a macro name prefixed with PNG_PREFIX.
+ */
+# ifndef PNG_PREFIX
+# define png_get_uint_32(buf) PNG_get_uint_32(buf)
+# define png_get_uint_16(buf) PNG_get_uint_16(buf)
+# define png_get_int_32(buf) PNG_get_int_32(buf)
+# endif
+#else
+# ifdef PNG_PREFIX
+ /* No macros; revert to the (redefined) function */
+# define PNG_get_uint_32 (png_get_uint_32)
+# define PNG_get_uint_16 (png_get_uint_16)
+# define PNG_get_int_32 (png_get_int_32)
+# endif
#endif
-#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
- defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
-PNG_EXPORT(234, void, png_set_check_for_invalid_index, (png_structp png_ptr,
- int allowed));
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+/*******************************************************************************
+ * SIMPLIFIED API
+ *******************************************************************************
+ *
+ * Please read the documentation in libpng-manual.txt (TODO: write said
+ * documentation) if you don't understand what follows.
+ *
+ * The simplified API hides the details of both libpng and the PNG file format
+ * itself. It allows PNG files to be read into a very limited number of
+ * in-memory bitmap formats or to be written from the same formats. If these
+ * formats do not accomodate your needs then you can, and should, use the more
+ * sophisticated APIs above - these support a wide variety of in-memory formats
+ * and a wide variety of sophisticated transformations to those formats as well
+ * as a wide variety of APIs to manipulate ancillary information.
+ *
+ * To read a PNG file using the simplified API:
+ *
+ * 1) Declare a 'png_image' structure (see below) on the stack and set the
+ * version field to PNG_IMAGE_VERSION.
+ * 2) Call the appropriate png_image_begin_read... function.
+ * 3) Set the png_image 'format' member to the required sample format.
+ * 4) Allocate a buffer for the image and, if required, the color-map.
+ * 5) Call png_image_finish_read to read the image and, if required, the
+ * color-map into your buffers.
+ *
+ * There are no restrictions on the format of the PNG input itself; all valid
+ * color types, bit depths, and interlace methods are acceptable, and the
+ * input image is transformed as necessary to the requested in-memory format
+ * during the png_image_finish_read() step. The only caveat is that if you
+ * request a color-mapped image from a PNG that is full-color or makes
+ * complex use of an alpha channel the transformation is extremely lossy and the
+ * result may look terrible.
+ *
+ * To write a PNG file using the simplified API:
+ *
+ * 1) Declare a 'png_image' structure on the stack and memset() it to all zero.
+ * 2) Initialize the members of the structure that describe the image, setting
+ * the 'format' member to the format of the image samples.
+ * 3) Call the appropriate png_image_write... function with a pointer to the
+ * image and, if necessary, the color-map to write the PNG data.
+ *
+ * png_image is a structure that describes the in-memory format of an image
+ * when it is being read or defines the in-memory format of an image that you
+ * need to write:
+ */
+#define PNG_IMAGE_VERSION 1
+
+typedef struct png_control *png_controlp;
+typedef struct
+{
+ png_controlp opaque; /* Initialize to NULL, free with png_image_free */
+ png_uint_32 version; /* Set to PNG_IMAGE_VERSION */
+ png_uint_32 width; /* Image width in pixels (columns) */
+ png_uint_32 height; /* Image height in pixels (rows) */
+ png_uint_32 format; /* Image format as defined below */
+ png_uint_32 flags; /* A bit mask containing informational flags */
+ png_uint_32 colormap_entries;
+ /* Number of entries in the color-map */
+
+ /* In the event of an error or warning the following field will be set to a
+ * non-zero value and the 'message' field will contain a '\0' terminated
+ * string with the libpng error or warning message. If both warnings and
+ * an error were encountered, only the error is recorded. If there
+ * are multiple warnings, only the first one is recorded.
+ *
+ * The upper 30 bits of this value are reserved, the low two bits contain
+ * a value as follows:
+ */
+# define PNG_IMAGE_WARNING 1
+# define PNG_IMAGE_ERROR 2
+ /*
+ * The result is a two-bit code such that a value more than 1 indicates
+ * a failure in the API just called:
+ *
+ * 0 - no warning or error
+ * 1 - warning
+ * 2 - error
+ * 3 - error preceded by warning
+ */
+# define PNG_IMAGE_FAILED(png_cntrl) ((((png_cntrl).warning_or_error)&0x03)>1)
+
+ png_uint_32 warning_or_error;
+
+ char message[64];
+} png_image, *png_imagep;
+
+/* The samples of the image have one to four channels whose components have
+ * original values in the range 0 to 1.0:
+ *
+ * 1: A single gray or luminance channel (G).
+ * 2: A gray/luminance channel and an alpha channel (GA).
+ * 3: Three red, green, blue color channels (RGB).
+ * 4: Three color channels and an alpha channel (RGBA).
+ *
+ * The components are encoded in one of two ways:
+ *
+ * a) As a small integer, value 0..255, contained in a single byte. For the
+ * alpha channel the original value is simply value/255. For the color or
+ * luminance channels the value is encoded according to the sRGB specification
+ * and matches the 8-bit format expected by typical display devices.
+ *
+ * The color/gray channels are not scaled (pre-multiplied) by the alpha
+ * channel and are suitable for passing to color management software.
+ *
+ * b) As a value in the range 0..65535, contained in a 2-byte integer. All
+ * channels can be converted to the original value by dividing by 65535; all
+ * channels are linear. Color channels use the RGB encoding (RGB end-points) of
+ * the sRGB specification. This encoding is identified by the
+ * PNG_FORMAT_FLAG_LINEAR flag below.
+ *
+ * When the simplified API needs to convert between sRGB and linear colorspaces,
+ * the actual sRGB transfer curve defined in the sRGB specification (see the
+ * article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2
+ * approximation used elsewhere in libpng.
+ *
+ * When an alpha channel is present it is expected to denote pixel coverage
+ * of the color or luminance channels and is returned as an associated alpha
+ * channel: the color/gray channels are scaled (pre-multiplied) by the alpha
+ * value.
+ *
+ * The samples are either contained directly in the image data, between 1 and 8
+ * bytes per pixel according to the encoding, or are held in a color-map indexed
+ * by bytes in the image data. In the case of a color-map the color-map entries
+ * are individual samples, encoded as above, and the image data has one byte per
+ * pixel to select the relevant sample from the color-map.
+ */
+
+/* PNG_FORMAT_*
+ *
+ * #defines to be used in png_image::format. Each #define identifies a
+ * particular layout of sample data and, if present, alpha values. There are
+ * separate defines for each of the two component encodings.
+ *
+ * A format is built up using single bit flag values. All combinations are
+ * valid. Formats can be built up from the flag values or you can use one of
+ * the predefined values below. When testing formats always use the FORMAT_FLAG
+ * macros to test for individual features - future versions of the library may
+ * add new flags.
+ *
+ * When reading or writing color-mapped images the format should be set to the
+ * format of the entries in the color-map then png_image_{read,write}_colormap
+ * called to read or write the color-map and set the format correctly for the
+ * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly!
+ *
+ * NOTE: libpng can be built with particular features disabled, if you see
+ * compiler errors because the definition of one of the following flags has been
+ * compiled out it is because libpng does not have the required support. It is
+ * possible, however, for the libpng configuration to enable the format on just
+ * read or just write; in that case you may see an error at run time. You can
+ * guard against this by checking for the definition of the appropriate
+ * "_SUPPORTED" macro, one of:
+ *
+ * PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED
+ */
+#define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */
+#define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */
+#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */
+#define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */
+
+#ifdef PNG_FORMAT_BGR_SUPPORTED
+# define PNG_FORMAT_FLAG_BGR 0x10U /* BGR colors, else order is RGB */
+#endif
+
+#ifdef PNG_FORMAT_AFIRST_SUPPORTED
+# define PNG_FORMAT_FLAG_AFIRST 0x20U /* alpha channel comes first */
+#endif
+
+/* Commonly used formats have predefined macros.
+ *
+ * First the single byte (sRGB) formats:
+ */
+#define PNG_FORMAT_GRAY 0
+#define PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA
+#define PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST)
+#define PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR
+#define PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR)
+#define PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST)
+#define PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST)
+
+/* Then the linear 2-byte formats. When naming these "Y" is used to
+ * indicate a luminance (gray) channel.
+ */
+#define PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR
+#define PNG_FORMAT_LINEAR_Y_ALPHA (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA)
+#define PNG_FORMAT_LINEAR_RGB (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR)
+#define PNG_FORMAT_LINEAR_RGB_ALPHA \
+ (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA)
+
+/* With color-mapped formats the image data is one byte for each pixel, the byte
+ * is an index into the color-map which is formatted as above. To obtain a
+ * color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP
+ * to one of the above definitions, or you can use one of the definitions below.
+ */
+#define PNG_FORMAT_RGB_COLORMAP (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_BGR_COLORMAP (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_RGBA_COLORMAP (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_ARGB_COLORMAP (PNG_FORMAT_ARGB|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_BGRA_COLORMAP (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_COLORMAP)
+#define PNG_FORMAT_ABGR_COLORMAP (PNG_FORMAT_ABGR|PNG_FORMAT_FLAG_COLORMAP)
+
+/* PNG_IMAGE macros
+ *
+ * These are convenience macros to derive information from a png_image
+ * structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the
+ * actual image sample values - either the entries in the color-map or the
+ * pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values
+ * for the pixels and will always return 1 for color-mapped formats. The
+ * remaining macros return information about the rows in the image and the
+ * complete image.
+ *
+ * NOTE: All the macros that take a png_image::format parameter are compile time
+ * constants if the format parameter is, itself, a constant. Therefore these
+ * macros can be used in array declarations and case labels where required.
+ * Similarly the macros are also pre-processor constants (sizeof is not used) so
+ * they can be used in #if tests.
+ *
+ * First the information about the samples.
+ */
+#define PNG_IMAGE_SAMPLE_CHANNELS(fmt)\
+ (((fmt)&(PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_ALPHA))+1)
+ /* Return the total number of channels in a given format: 1..4 */
+
+#define PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt)\
+ ((((fmt) & PNG_FORMAT_FLAG_LINEAR) >> 2)+1)
+ /* Return the size in bytes of a single component of a pixel or color-map
+ * entry (as appropriate) in the image: 1 or 2.
+ */
+
+#define PNG_IMAGE_SAMPLE_SIZE(fmt)\
+ (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt))
+ /* This is the size of the sample data for one sample. If the image is
+ * color-mapped it is the size of one color-map entry (and image pixels are
+ * one byte in size), otherwise it is the size of one image pixel.
+ */
+
+#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\
+ (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256)
+ /* The maximum size of the color-map required by the format expressed in a
+ * count of components. This can be used to compile-time allocate a
+ * color-map:
+ *
+ * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)];
+ *
+ * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)];
+ *
+ * Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the
+ * information from one of the png_image_begin_read_ APIs and dynamically
+ * allocate the required memory.
+ */
+
+/* Corresponding information about the pixels */
+#define PNG_IMAGE_PIXEL_(test,fmt)\
+ (((fmt)&PNG_FORMAT_FLAG_COLORMAP)?1:test(fmt))
+
+#define PNG_IMAGE_PIXEL_CHANNELS(fmt)\
+ PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_CHANNELS,fmt)
+ /* The number of separate channels (components) in a pixel; 1 for a
+ * color-mapped image.
+ */
+
+#define PNG_IMAGE_PIXEL_COMPONENT_SIZE(fmt)\
+ PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_COMPONENT_SIZE,fmt)
+ /* The size, in bytes, of each component in a pixel; 1 for a color-mapped
+ * image.
+ */
+
+#define PNG_IMAGE_PIXEL_SIZE(fmt) PNG_IMAGE_PIXEL_(PNG_IMAGE_SAMPLE_SIZE,fmt)
+ /* The size, in bytes, of a complete pixel; 1 for a color-mapped image. */
+
+/* Information about the whole row, or whole image */
+#define PNG_IMAGE_ROW_STRIDE(image)\
+ (PNG_IMAGE_PIXEL_CHANNELS((image).format) * (image).width)
+ /* Return the total number of components in a single row of the image; this
+ * is the minimum 'row stride', the minimum count of components between each
+ * row. For a color-mapped image this is the minimum number of bytes in a
+ * row.
+ */
+
+#define PNG_IMAGE_BUFFER_SIZE(image, row_stride)\
+ (PNG_IMAGE_PIXEL_COMPONENT_SIZE((image).format)*(image).height*(row_stride))
+ /* Return the size, in bytes, of an image buffer given a png_image and a row
+ * stride - the number of components to leave space for in each row.
+ */
+
+#define PNG_IMAGE_SIZE(image)\
+ PNG_IMAGE_BUFFER_SIZE(image, PNG_IMAGE_ROW_STRIDE(image))
+ /* Return the size, in bytes, of the image in memory given just a png_image;
+ * the row stride is the minimum stride required for the image.
+ */
+
+#define PNG_IMAGE_COLORMAP_SIZE(image)\
+ (PNG_IMAGE_SAMPLE_SIZE((image).format) * (image).colormap_entries)
+ /* Return the size, in bytes, of the color-map of this image. If the image
+ * format is not a color-map format this will return a size sufficient for
+ * 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if
+ * you don't want to allocate a color-map in this case.
+ */
+
+/* PNG_IMAGE_FLAG_*
+ *
+ * Flags containing additional information about the image are held in the
+ * 'flags' field of png_image.
+ */
+#define PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB 0x01
+ /* This indicates the the RGB values of the in-memory bitmap do not
+ * correspond to the red, green and blue end-points defined by sRGB.
+ */
+
+#define PNG_IMAGE_FLAG_FAST 0x02
+ /* On write emphasise speed over compression; the resultant PNG file will be
+ * larger but will be produced significantly faster, particular for large
+ * images. Do not use this option for images which will be distributed, only
+ * used it when producing intermediate files that will be read back in
+ * repeatedly. For a typical 24-bit image the option will double the read
+ * speed at the cost of increasing the image size by 25%, however for many
+ * more compressible images the PNG file can be 10 times larger with only a
+ * slight speed gain.
+ */
+
+#define PNG_IMAGE_FLAG_16BIT_sRGB 0x04
+ /* On read if the image is a 16-bit per component image and there is no gAMA
+ * or sRGB chunk assume that the components are sRGB encoded. Notice that
+ * images output by the simplified API always have gamma information; setting
+ * this flag only affects the interpretation of 16-bit images from an
+ * external source. It is recommended that the application expose this flag
+ * to the user; the user can normally easily recognize the difference between
+ * linear and sRGB encoding. This flag has no effect on write - the data
+ * passed to the write APIs must have the correct encoding (as defined
+ * above.)
+ *
+ * If the flag is not set (the default) input 16-bit per component data is
+ * assumed to be linear.
+ *
+ * NOTE: the flag can only be set after the png_image_begin_read_ call,
+ * because that call initializes the 'flags' field.
+ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* READ APIs
+ * ---------
+ *
+ * The png_image passed to the read APIs must have been initialized by setting
+ * the png_controlp field 'opaque' to NULL (or, safer, memset the whole thing.)
+ */
+#ifdef PNG_STDIO_SUPPORTED
+PNG_EXPORT(234, int, png_image_begin_read_from_file, (png_imagep image,
+ const char *file_name));
+ /* The named file is opened for read and the image header is filled in
+ * from the PNG header in the file.
+ */
+
+PNG_EXPORT(235, int, png_image_begin_read_from_stdio, (png_imagep image,
+ FILE* file));
+ /* The PNG header is read from the stdio FILE object. */
+#endif /* STDIO */
+
+PNG_EXPORT(236, int, png_image_begin_read_from_memory, (png_imagep image,
+ png_const_voidp memory, png_size_t size));
+ /* The PNG header is read from the given memory buffer. */
+
+PNG_EXPORT(237, int, png_image_finish_read, (png_imagep image,
+ png_const_colorp background, void *buffer, png_int_32 row_stride,
+ void *colormap));
+ /* Finish reading the image into the supplied buffer and clean up the
+ * png_image structure.
+ *
+ * row_stride is the step, in byte or 2-byte units as appropriate,
+ * between adjacent rows. A positive stride indicates that the top-most row
+ * is first in the buffer - the normal top-down arrangement. A negative
+ * stride indicates that the bottom-most row is first in the buffer.
+ *
+ * background need only be supplied if an alpha channel must be removed from
+ * a png_byte format and the removal is to be done by compositing on a solid
+ * color; otherwise it may be NULL and any composition will be done directly
+ * onto the buffer. The value is an sRGB color to use for the background,
+ * for grayscale output the green channel is used.
+ *
+ * background must be supplied when an alpha channel must be removed from a
+ * single byte color-mapped output format, in other words if:
+ *
+ * 1) The original format from png_image_begin_read_from_* had
+ * PNG_FORMAT_FLAG_ALPHA set.
+ * 2) The format set by the application does not.
+ * 3) The format set by the application has PNG_FORMAT_FLAG_COLORMAP set and
+ * PNG_FORMAT_FLAG_LINEAR *not* set.
+ *
+ * For linear output removing the alpha channel is always done by compositing
+ * on black and background is ignored.
+ *
+ * colormap must be supplied when PNG_FORMAT_FLAG_COLORMAP is set. It must
+ * be at least the size (in bytes) returned by PNG_IMAGE_COLORMAP_SIZE.
+ * image->colormap_entries will be updated to the actual number of entries
+ * written to the colormap; this may be less than the original value.
+ */
+
+PNG_EXPORT(238, void, png_image_free, (png_imagep image));
+ /* Free any data allocated by libpng in image->opaque, setting the pointer to
+ * NULL. May be called at any time after the structure is initialized.
+ */
+#endif /* SIMPLIFIED_READ */
+
+#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED
+/* WRITE APIS
+ * ----------
+ * For write you must initialize a png_image structure to describe the image to
+ * be written. To do this use memset to set the whole structure to 0 then
+ * initialize fields describing your image.
+ *
+ * version: must be set to PNG_IMAGE_VERSION
+ * opaque: must be initialized to NULL
+ * width: image width in pixels
+ * height: image height in rows
+ * format: the format of the data (image and color-map) you wish to write
+ * flags: set to 0 unless one of the defined flags applies; set
+ * PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB for color format images where the RGB
+ * values do not correspond to the colors in sRGB.
+ * colormap_entries: set to the number of entries in the color-map (0 to 256)
+ */
+PNG_EXPORT(239, int, png_image_write_to_file, (png_imagep image,
+ const char *file, int convert_to_8bit, const void *buffer,
+ png_int_32 row_stride, const void *colormap));
+ /* Write the image to the named file. */
+
+PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file,
+ int convert_to_8_bit, const void *buffer, png_int_32 row_stride,
+ const void *colormap));
+ /* Write the image to the given (FILE*). */
+
+/* With both write APIs if image is in one of the linear formats with 16-bit
+ * data then setting convert_to_8_bit will cause the output to be an 8-bit PNG
+ * gamma encoded according to the sRGB specification, otherwise a 16-bit linear
+ * encoded PNG file is written.
+ *
+ * With color-mapped data formats the colormap parameter point to a color-map
+ * with at least image->colormap_entries encoded in the specified format. If
+ * the format is linear the written PNG color-map will be converted to sRGB
+ * regardless of the convert_to_8_bit flag.
+ *
+ * With all APIs row_stride is handled as in the read APIs - it is the spacing
+ * from one row to the next in component sized units (1 or 2 bytes) and if
+ * negative indicates a bottom-up row layout in the buffer.
+ *
+ * Note that the write API does not support interlacing or sub-8-bit pixels.
+ */
+#endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE */
+/*******************************************************************************
+ * END OF SIMPLIFIED API
+ ******************************************************************************/
+#endif /* SIMPLIFIED_{READ|WRITE} */
+
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+PNG_EXPORT(242, void, png_set_check_for_invalid_index,
+ (png_structrp png_ptr, int allowed));
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr,
+ png_const_infop info_ptr));
+# endif
+#endif /* CHECK_FOR_INVALID_INDEX */
+
+/*******************************************************************************
+ * IMPLEMENTATION OPTIONS
+ *******************************************************************************
+ *
+ * Support for arbitrary implementation-specific optimizations. The API allows
+ * particular options to be turned on or off. 'Option' is the number of the
+ * option and 'onoff' is 0 (off) or non-0 (on). The value returned is given
+ * by the PNG_OPTION_ defines below.
+ *
+ * HARDWARE: normally hardware capabilites, such as the Intel SSE instructions,
+ * are detected at run time, however sometimes it may be impossible
+ * to do this in user mode, in which case it is necessary to discover
+ * the capabilities in an OS specific way. Such capabilities are
+ * listed here when libpng has support for them and must be turned
+ * ON by the application if present.
+ *
+ * SOFTWARE: sometimes software optimizations actually result in performance
+ * decrease on some architectures or systems, or with some sets of
+ * PNG images. 'Software' options allow such optimizations to be
+ * selected at run time.
+ */
+#ifdef PNG_SET_OPTION_SUPPORTED
+#ifdef PNG_ARM_NEON_API_SUPPORTED
+# define PNG_ARM_NEON 0 /* HARDWARE: ARM Neon SIMD instructions supported */
#endif
+#define PNG_MAXIMUM_INFLATE_WINDOW 2 /* SOFTWARE: force maximum window */
+#define PNG_SKIP_sRGB_CHECK_PROFILE 4 /* SOFTWARE: Check ICC profile for sRGB */
+#define PNG_OPTION_NEXT 6 /* Next option - numbers must be even */
+
+/* Return values: NOTE: there are four values and 'off' is *not* zero */
+#define PNG_OPTION_UNSET 0 /* Unset - defaults to off */
+#define PNG_OPTION_INVALID 1 /* Option number out of range */
+#define PNG_OPTION_OFF 2
+#define PNG_OPTION_ON 3
+
+PNG_EXPORT(244, int, png_set_option, (png_structrp png_ptr, int option,
+ int onoff));
+#endif /* SET_OPTION */
+
+/*******************************************************************************
+ * END OF HARDWARE AND SOFTWARE OPTIONS
+ ******************************************************************************/
-/* Maintainer: Put new public prototypes here ^, in libpng.3, and project
- * defs
+/* Maintainer: Put new public prototypes here ^, in libpng.3, in project
+ * defs, and in scripts/symbols.def.
*/
/* The last ordinal number (this is the *last* one already used; the next
- * one to use is one more than this.) Maintainer, remember to add an entry to
- * scripts/symbols.def as well.
+ * one to use is one more than this.)
*/
#ifdef PNG_EXPORT_LAST_ORDINAL
- PNG_EXPORT_LAST_ORDINAL(234);
+ PNG_EXPORT_LAST_ORDINAL(244);
#endif
#ifdef __cplusplus
diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h
index 89add405b6..3f9493e438 100644
--- a/src/3rdparty/libpng/pngconf.h
+++ b/src/3rdparty/libpng/pngconf.h
@@ -1,9 +1,9 @@
/* pngconf.h - machine configurable file for libpng
*
- * libpng version 1.5.10 - March 29, 2012
+ * libpng version 1.6.17, March 26, 2015
*
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -11,9 +11,7 @@
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*
- */
-
-/* Any machine specific code is near the front of this file, so if you
+ * Any machine specific code is near the front of this file, so if you
* are configuring libpng for a machine, you may want to read the section
* starting here down to where it starts to typedef png_color, png_text,
* and png_info.
@@ -22,33 +20,49 @@
#ifndef PNGCONF_H
#define PNGCONF_H
-#ifndef PNG_BUILDING_SYMBOL_TABLE
-/* PNG_NO_LIMITS_H may be used to turn off the use of the standard C
- * definition file for machine specific limits, this may impact the
- * correctness of the definitons below (see uses of INT_MAX).
- */
-# ifndef PNG_NO_LIMITS_H
-# include <limits.h>
-# endif
+#ifndef PNG_BUILDING_SYMBOL_TABLE /* else includes may cause problems */
-/* For the memory copy APIs (i.e. the standard definitions of these),
- * because this file defines png_memcpy and so on the base APIs must
- * be defined here.
+/* From libpng 1.6.0 libpng requires an ANSI X3.159-1989 ("ISOC90") compliant C
+ * compiler for correct compilation. The following header files are required by
+ * the standard. If your compiler doesn't provide these header files, or they
+ * do not match the standard, you will need to provide/improve them.
*/
-# if defined(BSD) && !defined(VXWORKS)
-# include <strings.h>
-# else
-# include <string.h>
-# endif
-
-/* For png_FILE_p - this provides the standard definition of a
- * FILE
+#include <limits.h>
+#include <stddef.h>
+
+/* Library header files. These header files are all defined by ISOC90; libpng
+ * expects conformant implementations, however, an ISOC90 conformant system need
+ * not provide these header files if the functionality cannot be implemented.
+ * In this case it will be necessary to disable the relevant parts of libpng in
+ * the build of pnglibconf.h.
+ *
+ * Prior to 1.6.0 string.h was included here; the API changes in 1.6.0 to not
+ * include this unnecessary header file.
*/
-# ifdef PNG_STDIO_SUPPORTED
-# include <stdio.h>
-# endif
+
+#ifdef PNG_STDIO_SUPPORTED
+ /* Required for the definition of FILE: */
+# include <stdio.h>
+#endif
+
+#ifdef PNG_SETJMP_SUPPORTED
+ /* Required for the definition of jmp_buf and the declaration of longjmp: */
+# include <setjmp.h>
#endif
+#ifdef PNG_CONVERT_tIME_SUPPORTED
+ /* Required for struct tm: */
+# include <time.h>
+#endif
+
+#endif /* PNG_BUILDING_SYMBOL_TABLE */
+
+/* Prior to 1.6.0 it was possible to turn off 'const' in declarations using
+ * PNG_NO_CONST; this is no longer supported except for data declarations which
+ * apparently still cause problems in 2011 on some compilers.
+ */
+#define PNG_CONST const /* backward compatibility only */
+
/* This controls optimization of the reading of 16 and 32 bit values
* from PNG files. It can be set on a per-app-file basis - it
* just changes whether a macro is used when the function is called.
@@ -72,28 +86,13 @@
* may be changed on a per-file basis when compiling against libpng.
*/
-/* The PNGARG macro protects us against machines that don't have function
- * prototypes (ie K&R style headers). If your compiler does not handle
- * function prototypes, define this macro and use the included ansi2knr.
- * I've always been able to use _NO_PROTO as the indicator, but you may
- * need to drag the empty declaration out in front of here, or change the
- * ifdef to suit your own needs.
+/* The PNGARG macro was used in versions of libpng prior to 1.6.0 to protect
+ * against legacy (pre ISOC90) compilers that did not understand function
+ * prototypes. It is not required for modern C compilers.
*/
#ifndef PNGARG
-
-# ifdef OF /* zlib prototype munger */
-# define PNGARG(arglist) OF(arglist)
-# else
-
-# ifdef _NO_PROTO
-# define PNGARG(arglist) ()
-# else
-# define PNGARG(arglist) arglist
-# endif /* _NO_PROTO */
-
-# endif /* OF */
-
-#endif /* PNGARG */
+# define PNGARG(arglist) arglist
+#endif
/* Function calling conventions.
* =============================
@@ -177,18 +176,16 @@
* ==========================
* This code is used at build time to find PNG_IMPEXP, the API settings
* and PNG_EXPORT_TYPE(), it may also set a macro to indicate the DLL
- * import processing is possible. On Windows/x86 systems it also sets
+ * import processing is possible. On Windows systems it also sets
* compiler-specific macros to the values required to change the calling
* conventions of the various functions.
*/
-#if ( defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
- defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__) ) &&\
- ( defined(_X86_) || defined(_X64_) || defined(_M_IX86) ||\
- defined(_M_X64) || defined(_M_IA64) )
- /* Windows system (DOS doesn't support DLLs) running on x86/x64. Includes
- * builds under Cygwin or MinGW. Also includes Watcom builds but these need
- * special treatment because they are not compatible with GCC or Visual C
- * because of different calling conventions.
+#if defined(_Windows) || defined(_WINDOWS) || defined(WIN32) ||\
+ defined(_WIN32) || defined(__WIN32__) || defined(__CYGWIN__)
+ /* Windows system (DOS doesn't support DLLs). Includes builds under Cygwin or
+ * MinGW on any architecture currently supported by Windows. Also includes
+ * Watcom builds but these need special treatment because they are not
+ * compatible with GCC or Visual C because of different calling conventions.
*/
# if PNG_API_RULE == 2
/* If this line results in an error, either because __watcall is not
@@ -199,9 +196,12 @@
# define PNGCAPI __watcall
# endif
-# if defined(__GNUC__) || (defined (_MSC_VER) && (_MSC_VER >= 800))
+# if defined(__GNUC__) || (defined(_MSC_VER) && (_MSC_VER >= 800))
# define PNGCAPI __cdecl
# if PNG_API_RULE == 1
+ /* If this line results in an error __stdcall is not understood and
+ * PNG_API_RULE should not have been set to '1'.
+ */
# define PNGAPI __stdcall
# endif
# else
@@ -216,10 +216,11 @@
# define PNGAPI _stdcall
# endif
# endif /* compiler/api */
+
/* NOTE: PNGCBAPI always defaults to PNGCAPI. */
# if defined(PNGAPI) && !defined(PNG_USER_PRIVATEBUILD)
- ERROR: PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed
+# error "PNG_USER_PRIVATEBUILD must be defined if PNGAPI is changed"
# endif
# if (defined(_MSC_VER) && _MSC_VER < 800) ||\
@@ -239,7 +240,7 @@
# endif
# endif /* compiler */
-#else /* !Windows/x86 */
+#else /* !Windows */
# if (defined(__IBMC__) || defined(__IBMCPP__)) && defined(__OS2__)
# define PNGAPI _System
# else /* !Windows/x86 && !OS/2 */
@@ -333,40 +334,73 @@
#ifdef PNG_PEDANTIC_WARNINGS_SUPPORTED
/* Support for compiler specific function attributes. These are used
- * so that where compiler support is available incorrect use of API
+ * so that where compiler support is available, incorrect use of API
* functions in png.h will generate compiler warnings. Added at libpng
- * version 1.2.41.
+ * version 1.2.41. Disabling these removes the warnings but may also produce
+ * less efficient code.
*/
-# if defined(__GNUC__)
-# ifndef PNG_USE_RESULT
+# if defined(__clang__) && defined(__has_attribute)
+ /* Clang defines both __clang__ and __GNUC__. Check __clang__ first. */
+# if !defined(PNG_USE_RESULT) && __has_attribute(__warn_unused_result__)
# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
# endif
-# ifndef PNG_NORETURN
-# define PNG_NORETURN __attribute__((__noreturn__))
+# if !defined(PNG_NORETURN) && __has_attribute(__noreturn__)
+# define PNG_NORETURN __attribute__((__noreturn__))
# endif
-# ifndef PNG_ALLOCATED
-# define PNG_ALLOCATED __attribute__((__malloc__))
+# if !defined(PNG_ALLOCATED) && __has_attribute(__malloc__)
+# define PNG_ALLOCATED __attribute__((__malloc__))
# endif
-# ifndef PNG_DEPRECATED
+# if !defined(PNG_DEPRECATED) && __has_attribute(__deprecated__)
# define PNG_DEPRECATED __attribute__((__deprecated__))
# endif
-# ifndef PNG_PRIVATE
-# if 0 /* Doesn't work so we use deprecated instead*/
-# define PNG_PRIVATE \
- __attribute__((warning("This function is not exported by libpng.")))
-# else
-# define PNG_PRIVATE \
- __attribute__((__deprecated__))
+# if !defined(PNG_PRIVATE)
+# ifdef __has_extension
+# if __has_extension(attribute_unavailable_with_message)
+# define PNG_PRIVATE __attribute__((__unavailable__(\
+ "This function is not exported by libpng.")))
+# endif
# endif
# endif
-# endif /* __GNUC__ */
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
-# if defined(_MSC_VER) && (_MSC_VER >= 1300)
+# elif defined(__GNUC__)
+# ifndef PNG_USE_RESULT
+# define PNG_USE_RESULT __attribute__((__warn_unused_result__))
+# endif
+# ifndef PNG_NORETURN
+# define PNG_NORETURN __attribute__((__noreturn__))
+# endif
+# if __GNUC__ >= 3
+# ifndef PNG_ALLOCATED
+# define PNG_ALLOCATED __attribute__((__malloc__))
+# endif
+# ifndef PNG_DEPRECATED
+# define PNG_DEPRECATED __attribute__((__deprecated__))
+# endif
+# ifndef PNG_PRIVATE
+# if 0 /* Doesn't work so we use deprecated instead*/
+# define PNG_PRIVATE \
+ __attribute__((warning("This function is not exported by libpng.")))
+# else
+# define PNG_PRIVATE \
+ __attribute__((__deprecated__))
+# endif
+# endif
+# if ((__GNUC__ > 3) || !defined(__GNUC_MINOR__) || (__GNUC_MINOR__ >= 1))
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
+# endif /* __GNUC__.__GNUC_MINOR__ > 3.0 */
+# endif /* __GNUC__ >= 3 */
+
+# elif defined(_MSC_VER) && (_MSC_VER >= 1300)
# ifndef PNG_USE_RESULT
# define PNG_USE_RESULT /* not supported */
# endif
# ifndef PNG_NORETURN
-# define PNG_NORETURN __declspec(noreturn)
+# define PNG_NORETURN __declspec(noreturn)
# endif
# ifndef PNG_ALLOCATED
# if (_MSC_VER >= 1400)
@@ -379,7 +413,17 @@
# ifndef PNG_PRIVATE
# define PNG_PRIVATE __declspec(deprecated)
# endif
-# endif /* _MSC_VER */
+# ifndef PNG_RESTRICT
+# if (_MSC_VER >= 1400)
+# define PNG_RESTRICT __restrict
+# endif
+# endif
+
+# elif defined(__WATCOMC__)
+# ifndef PNG_RESTRICT
+# define PNG_RESTRICT __restrict
+# endif
+# endif
#endif /* PNG_PEDANTIC_WARNINGS */
#ifndef PNG_DEPRECATED
@@ -397,10 +441,14 @@
#ifndef PNG_PRIVATE
# define PNG_PRIVATE /* This is a private libpng function */
#endif
+#ifndef PNG_RESTRICT
+# define PNG_RESTRICT /* The C99 "restrict" feature */
+#endif
+
#ifndef PNG_FP_EXPORT /* A floating point API. */
# ifdef PNG_FLOATING_POINT_SUPPORTED
# define PNG_FP_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No floating point APIs */
# define PNG_FP_EXPORT(ordinal, type, name, args)
# endif
@@ -408,189 +456,167 @@
#ifndef PNG_FIXED_EXPORT /* A fixed point API. */
# ifdef PNG_FIXED_POINT_SUPPORTED
# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
- PNG_EXPORT(ordinal, type, name, args)
+ PNG_EXPORT(ordinal, type, name, args);
# else /* No fixed point APIs */
# define PNG_FIXED_EXPORT(ordinal, type, name, args)
# endif
#endif
-/* The following uses const char * instead of char * for error
- * and warning message functions, so some compilers won't complain.
- * If you do not want to use const, define PNG_NO_CONST here.
+#ifndef PNG_BUILDING_SYMBOL_TABLE
+/* Some typedefs to get us started. These should be safe on most of the common
+ * platforms.
+ *
+ * png_uint_32 and png_int_32 may, currently, be larger than required to hold a
+ * 32-bit value however this is not normally advisable.
+ *
+ * png_uint_16 and png_int_16 should always be two bytes in size - this is
+ * verified at library build time.
+ *
+ * png_byte must always be one byte in size.
*
- * This should not change how the APIs are called, so it can be done
- * on a per-file basis in the application.
+ * The checks below use constants from limits.h, as defined by the ISOC90
+ * standard.
*/
-#ifndef PNG_CONST
-# ifndef PNG_NO_CONST
-# define PNG_CONST const
-# else
-# define PNG_CONST
-# endif
+#if CHAR_BIT == 8 && UCHAR_MAX == 255
+ typedef unsigned char png_byte;
+#else
+# error "libpng requires 8 bit bytes"
#endif
-/* Some typedefs to get us started. These should be safe on most of the
- * common platforms. The typedefs should be at least as large as the
- * numbers suggest (a png_uint_32 must be at least 32 bits long), but they
- * don't have to be exactly that size. Some compilers dislike passing
- * unsigned shorts as function parameters, so you may be better off using
- * unsigned int for png_uint_16.
- */
+#if INT_MIN == -32768 && INT_MAX == 32767
+ typedef int png_int_16;
+#elif SHRT_MIN == -32768 && SHRT_MAX == 32767
+ typedef short png_int_16;
+#else
+# error "libpng requires a signed 16 bit type"
+#endif
-#if defined(INT_MAX) && (INT_MAX > 0x7ffffffeL)
-typedef unsigned int png_uint_32;
-typedef int png_int_32;
+#if UINT_MAX == 65535
+ typedef unsigned int png_uint_16;
+#elif USHRT_MAX == 65535
+ typedef unsigned short png_uint_16;
#else
-typedef unsigned long png_uint_32;
-typedef long png_int_32;
+# error "libpng requires an unsigned 16 bit type"
#endif
-typedef unsigned short png_uint_16;
-typedef short png_int_16;
-typedef unsigned char png_byte;
-#ifdef PNG_NO_SIZE_T
-typedef unsigned int png_size_t;
+#if INT_MIN < -2147483646 && INT_MAX > 2147483646
+ typedef int png_int_32;
+#elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646
+ typedef long int png_int_32;
#else
-typedef size_t png_size_t;
+# error "libpng requires a signed 32 bit (or more) type"
#endif
-#define png_sizeof(x) (sizeof (x))
-/* The following is needed for medium model support. It cannot be in the
- * pngpriv.h header. Needs modification for other compilers besides
- * MSC. Model independent support declares all arrays and pointers to be
- * large using the far keyword. The zlib version used must also support
- * model independent data. As of version zlib 1.0.4, the necessary changes
- * have been made in zlib. The USE_FAR_KEYWORD define triggers other
- * changes that are needed. (Tim Wegner)
- */
+#if UINT_MAX > 4294967294
+ typedef unsigned int png_uint_32;
+#elif ULONG_MAX > 4294967294
+ typedef unsigned long int png_uint_32;
+#else
+# error "libpng requires an unsigned 32 bit (or more) type"
+#endif
-/* Separate compiler dependencies (problem here is that zlib.h always
- * defines FAR. (SJT)
- */
-#ifdef __BORLANDC__
-# if defined(__LARGE__) || defined(__HUGE__) || defined(__COMPACT__)
-# define LDATA 1
-# else
-# define LDATA 0
-# endif
- /* GRR: why is Cygwin in here? Cygwin is not Borland C... */
-# if !defined(__WIN32__) && !defined(__FLAT__) && !defined(__CYGWIN__)
-# define PNG_MAX_MALLOC_64K /* only used in build */
-# if (LDATA != 1)
-# ifndef FAR
-# define FAR __far
-# endif
-# define USE_FAR_KEYWORD
-# endif /* LDATA != 1 */
- /* Possibly useful for moving data out of default segment.
- * Uncomment it if you want. Could also define FARDATA as
- * const if your compiler supports it. (SJT)
-# define FARDATA FAR
- */
-# endif /* __WIN32__, __FLAT__, __CYGWIN__ */
-#endif /* __BORLANDC__ */
-
-
-/* Suggest testing for specific compiler first before testing for
- * FAR. The Watcom compiler defines both __MEDIUM__ and M_I86MM,
- * making reliance oncertain keywords suspect. (SJT)
+/* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however,
+ * requires an ISOC90 compiler and relies on consistent behavior of sizeof.
*/
+typedef size_t png_size_t;
+typedef ptrdiff_t png_ptrdiff_t;
-/* MSC Medium model */
-#ifdef FAR
-# ifdef M_I86MM
-# define USE_FAR_KEYWORD
-# define FARDATA FAR
-# include <dos.h>
+/* libpng needs to know the maximum value of 'size_t' and this controls the
+ * definition of png_alloc_size_t, below. This maximum value of size_t limits
+ * but does not control the maximum allocations the library makes - there is
+ * direct application control of this through png_set_user_limits().
+ */
+#ifndef PNG_SMALL_SIZE_T
+ /* Compiler specific tests for systems where size_t is known to be less than
+ * 32 bits (some of these systems may no longer work because of the lack of
+ * 'far' support; see above.)
+ */
+# if (defined(__TURBOC__) && !defined(__FLAT__)) ||\
+ (defined(_MSC_VER) && defined(MAXSEG_64K))
+# define PNG_SMALL_SIZE_T
# endif
#endif
-/* SJT: default case */
-#ifndef FAR
-# define FAR
+/* png_alloc_size_t is guaranteed to be no smaller than png_size_t, and no
+ * smaller than png_uint_32. Casts from png_size_t or png_uint_32 to
+ * png_alloc_size_t are not necessary; in fact, it is recommended not to use
+ * them at all so that the compiler can complain when something turns out to be
+ * problematic.
+ *
+ * Casts in the other direction (from png_alloc_size_t to png_size_t or
+ * png_uint_32) should be explicitly applied; however, we do not expect to
+ * encounter practical situations that require such conversions.
+ *
+ * PNG_SMALL_SIZE_T must be defined if the maximum value of size_t is less than
+ * 4294967295 - i.e. less than the maximum value of png_uint_32.
+ */
+#ifdef PNG_SMALL_SIZE_T
+ typedef png_uint_32 png_alloc_size_t;
+#else
+ typedef png_size_t png_alloc_size_t;
#endif
-/* At this point FAR is always defined */
-#ifndef FARDATA
-# define FARDATA
-#endif
+/* Prior to 1.6.0 libpng offered limited support for Microsoft C compiler
+ * implementations of Intel CPU specific support of user-mode segmented address
+ * spaces, where 16-bit pointers address more than 65536 bytes of memory using
+ * separate 'segment' registers. The implementation requires two different
+ * types of pointer (only one of which includes the segment value.)
+ *
+ * If required this support is available in version 1.2 of libpng and may be
+ * available in versions through 1.5, although the correctness of the code has
+ * not been verified recently.
+ */
-/* Typedef for floating-point numbers that are converted
- * to fixed-point with a multiple of 100,000, e.g., gamma
+/* Typedef for floating-point numbers that are converted to fixed-point with a
+ * multiple of 100,000, e.g., gamma
*/
typedef png_int_32 png_fixed_point;
/* Add typedefs for pointers */
-typedef void FAR * png_voidp;
-typedef PNG_CONST void FAR * png_const_voidp;
-typedef png_byte FAR * png_bytep;
-typedef PNG_CONST png_byte FAR * png_const_bytep;
-typedef png_uint_32 FAR * png_uint_32p;
-typedef PNG_CONST png_uint_32 FAR * png_const_uint_32p;
-typedef png_int_32 FAR * png_int_32p;
-typedef PNG_CONST png_int_32 FAR * png_const_int_32p;
-typedef png_uint_16 FAR * png_uint_16p;
-typedef PNG_CONST png_uint_16 FAR * png_const_uint_16p;
-typedef png_int_16 FAR * png_int_16p;
-typedef PNG_CONST png_int_16 FAR * png_const_int_16p;
-typedef char FAR * png_charp;
-typedef PNG_CONST char FAR * png_const_charp;
-typedef png_fixed_point FAR * png_fixed_point_p;
-typedef PNG_CONST png_fixed_point FAR * png_const_fixed_point_p;
-typedef png_size_t FAR * png_size_tp;
-typedef PNG_CONST png_size_t FAR * png_const_size_tp;
+typedef void * png_voidp;
+typedef const void * png_const_voidp;
+typedef png_byte * png_bytep;
+typedef const png_byte * png_const_bytep;
+typedef png_uint_32 * png_uint_32p;
+typedef const png_uint_32 * png_const_uint_32p;
+typedef png_int_32 * png_int_32p;
+typedef const png_int_32 * png_const_int_32p;
+typedef png_uint_16 * png_uint_16p;
+typedef const png_uint_16 * png_const_uint_16p;
+typedef png_int_16 * png_int_16p;
+typedef const png_int_16 * png_const_int_16p;
+typedef char * png_charp;
+typedef const char * png_const_charp;
+typedef png_fixed_point * png_fixed_point_p;
+typedef const png_fixed_point * png_const_fixed_point_p;
+typedef png_size_t * png_size_tp;
+typedef const png_size_t * png_const_size_tp;
#ifdef PNG_STDIO_SUPPORTED
typedef FILE * png_FILE_p;
#endif
#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double FAR * png_doublep;
-typedef PNG_CONST double FAR * png_const_doublep;
+typedef double * png_doublep;
+typedef const double * png_const_doublep;
#endif
/* Pointers to pointers; i.e. arrays */
-typedef png_byte FAR * FAR * png_bytepp;
-typedef png_uint_32 FAR * FAR * png_uint_32pp;
-typedef png_int_32 FAR * FAR * png_int_32pp;
-typedef png_uint_16 FAR * FAR * png_uint_16pp;
-typedef png_int_16 FAR * FAR * png_int_16pp;
-typedef PNG_CONST char FAR * FAR * png_const_charpp;
-typedef char FAR * FAR * png_charpp;
-typedef png_fixed_point FAR * FAR * png_fixed_point_pp;
+typedef png_byte * * png_bytepp;
+typedef png_uint_32 * * png_uint_32pp;
+typedef png_int_32 * * png_int_32pp;
+typedef png_uint_16 * * png_uint_16pp;
+typedef png_int_16 * * png_int_16pp;
+typedef const char * * png_const_charpp;
+typedef char * * png_charpp;
+typedef png_fixed_point * * png_fixed_point_pp;
#ifdef PNG_FLOATING_POINT_SUPPORTED
-typedef double FAR * FAR * png_doublepp;
+typedef double * * png_doublepp;
#endif
/* Pointers to pointers to pointers; i.e., pointer to array */
-typedef char FAR * FAR * FAR * png_charppp;
+typedef char * * * png_charppp;
-/* png_alloc_size_t is guaranteed to be no smaller than png_size_t,
- * and no smaller than png_uint_32. Casts from png_size_t or png_uint_32
- * to png_alloc_size_t are not necessary; in fact, it is recommended
- * not to use them at all so that the compiler can complain when something
- * turns out to be problematic.
- * Casts in the other direction (from png_alloc_size_t to png_size_t or
- * png_uint_32) should be explicitly applied; however, we do not expect
- * to encounter practical situations that require such conversions.
- */
-#if defined(__TURBOC__) && !defined(__FLAT__)
- typedef unsigned long png_alloc_size_t;
-#else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- typedef unsigned long png_alloc_size_t;
-# else
- /* This is an attempt to detect an old Windows system where (int) is
- * actually 16 bits, in that case png_malloc must have an argument with a
- * bigger size to accomodate the requirements of the library.
- */
-# if (defined(_Windows) || defined(_WINDOWS) || defined(_WINDOWS_)) && \
- (!defined(INT_MAX) || INT_MAX <= 0x7ffffffeL)
- typedef DWORD png_alloc_size_t;
-# else
- typedef png_size_t png_alloc_size_t;
-# endif
-# endif
-#endif
+#endif /* PNG_BUILDING_SYMBOL_TABLE */
#endif /* PNGCONF_H */
diff --git a/src/3rdparty/libpng/pngdebug.h b/src/3rdparty/libpng/pngdebug.h
index 4547b7d808..6a01b106ed 100644
--- a/src/3rdparty/libpng/pngdebug.h
+++ b/src/3rdparty/libpng/pngdebug.h
@@ -1,12 +1,11 @@
/* pngdebug.h - Debugging macros for libpng, also used in pngtest.c
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.8 [December 19, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -25,7 +24,7 @@
* (actually ((void)0)).
*
* level: level of detail of message, starting at 0. A level 'n'
- * message is preceded by 'n' tab characters (not implemented
+ * message is preceded by 'n' 3-space indentations (not implemented
* on Microsoft compilers unless PNG_DEBUG_FILE is also
* defined, to allow debug DLL compilation with no standard IO).
* message: a printf(3) style text string. A trailing '\n' is added
@@ -77,32 +76,29 @@
# endif /* PNG_DEBUG_FILE */
# if (PNG_DEBUG > 1)
-/* Note: ["%s"m PNG_STRING_NEWLINE] probably does not work on
- * non-ISO compilers
- */
# ifdef __STDC__
# ifndef png_debug
# define png_debug(l,m) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":"")))); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : "")))); \
} while (0)
# endif
# ifndef png_debug1
# define png_debug1(l,m,p1) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1); \
} while (0)
# endif
# ifndef png_debug2
# define png_debug2(l,m,p1,p2) \
do { \
int num_tabs=l; \
- fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? "\t" : \
- (num_tabs==2 ? "\t\t":(num_tabs>2 ? "\t\t\t":""))),p1,p2); \
+ fprintf(PNG_DEBUG_FILE,"%s" m PNG_STRING_NEWLINE,(num_tabs==1 ? " " : \
+ (num_tabs==2 ? " " : (num_tabs>2 ? " " : ""))),p1,p2);\
} while (0)
# endif
# else /* __STDC __ */
diff --git a/src/3rdparty/libpng/pngerror.c b/src/3rdparty/libpng/pngerror.c
index 95002f84f7..0781866a89 100644
--- a/src/3rdparty/libpng/pngerror.c
+++ b/src/3rdparty/libpng/pngerror.c
@@ -1,8 +1,8 @@
/* pngerror.c - stub functions for i/o and memory allocation
*
- * Last changed in libpng 1.5.8 [February 1, 2011]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -20,14 +20,14 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-static PNG_FUNCTION(void, png_default_error,PNGARG((png_structp png_ptr,
+static PNG_FUNCTION(void, png_default_error,PNGARG((png_const_structrp png_ptr,
png_const_charp error_message)),PNG_NORETURN);
#ifdef PNG_WARNINGS_SUPPORTED
static void /* PRIVATE */
-png_default_warning PNGARG((png_structp png_ptr,
+png_default_warning PNGARG((png_const_structrp png_ptr,
png_const_charp warning_message));
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
/* This function is called whenever there is a fatal error. This function
* should not be changed. If there is a need to handle errors differently,
@@ -36,14 +36,15 @@ png_default_warning PNGARG((png_structp png_ptr,
*/
#ifdef PNG_ERROR_TEXT_SUPPORTED
PNG_FUNCTION(void,PNGAPI
-png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
+png_error,(png_const_structrp png_ptr, png_const_charp error_message),
+ PNG_NORETURN)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
char msg[16];
if (png_ptr != NULL)
{
- if (png_ptr->flags&
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+ if ((png_ptr->flags &
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0
{
if (*error_message == PNG_LITERAL_SHARP)
{
@@ -53,7 +54,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
if (error_message[offset] == ' ')
break;
- if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
int i;
for (i = 0; i < offset - 1; i++)
@@ -68,7 +69,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
else
{
- if (png_ptr->flags&PNG_FLAG_STRIP_ERROR_TEXT)
+ if ((png_ptr->flags & PNG_FLAG_STRIP_ERROR_TEXT) != 0)
{
msg[0] = '0';
msg[1] = '\0';
@@ -79,7 +80,8 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
}
#endif
if (png_ptr != NULL && png_ptr->error_fn != NULL)
- (*(png_ptr->error_fn))(png_ptr, error_message);
+ (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr),
+ error_message);
/* If the custom handler doesn't exist, or if it returns,
use the default handler, which will not return. */
@@ -87,7 +89,7 @@ png_error,(png_structp png_ptr, png_const_charp error_message),PNG_NORETURN)
}
#else
PNG_FUNCTION(void,PNGAPI
-png_err,(png_structp png_ptr),PNG_NORETURN)
+png_err,(png_const_structrp png_ptr),PNG_NORETURN)
{
/* Prior to 1.5.2 the error_fn received a NULL pointer, expressed
* erroneously as '\0', instead of the empty string "". This was
@@ -95,13 +97,13 @@ png_err,(png_structp png_ptr),PNG_NORETURN)
* will crash in this case.
*/
if (png_ptr != NULL && png_ptr->error_fn != NULL)
- (*(png_ptr->error_fn))(png_ptr, "");
+ (*(png_ptr->error_fn))(png_constcast(png_structrp,png_ptr), "");
/* If the custom handler doesn't exist, or if it returns,
use the default handler, which will not return. */
png_default_error(png_ptr, "");
}
-#endif /* PNG_ERROR_TEXT_SUPPORTED */
+#endif /* ERROR_TEXT */
/* Utility to safely appends strings to a buffer. This never errors out so
* error checking is not required in the caller.
@@ -150,7 +152,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_fixed:
/* Needs five digits (the fraction) */
mincount = 5;
- if (output || number % 10 != 0)
+ if (output != 0 || number % 10 != 0)
{
*--end = digits[number % 10];
output = 1;
@@ -161,7 +163,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02u:
/* Expects at least 2 digits. */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_u:
*--end = digits[number % 10];
@@ -171,7 +173,7 @@ png_format_number(png_const_charp start, png_charp end, int format,
case PNG_NUMBER_FORMAT_02x:
/* This format expects at least two digits */
mincount = 2;
- /* fall through */
+ /* FALL THROUGH */
case PNG_NUMBER_FORMAT_x:
*--end = digits[number & 0xf];
@@ -187,13 +189,13 @@ png_format_number(png_const_charp start, png_charp end, int format,
++count;
/* Float a fixed number here: */
- if (format == PNG_NUMBER_FORMAT_fixed) if (count == 5) if (end > start)
+ if ((format == PNG_NUMBER_FORMAT_fixed) && (count == 5) && (end > start))
{
/* End of the fraction, but maybe nothing was output? In that case
* drop the decimal point. If the number is a true zero handle that
* here.
*/
- if (output)
+ if (output != 0)
*--end = '.';
else if (number == 0) /* and !output */
*--end = '0';
@@ -211,14 +213,14 @@ png_format_number(png_const_charp start, png_charp end, int format,
* png_set_error_fn() to replace the warning function at run-time.
*/
void PNGAPI
-png_warning(png_structp png_ptr, png_const_charp warning_message)
+png_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
int offset = 0;
if (png_ptr != NULL)
{
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
- if (png_ptr->flags&
- (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT))
+ if ((png_ptr->flags &
+ (PNG_FLAG_STRIP_ERROR_NUMBERS|PNG_FLAG_STRIP_ERROR_TEXT)) != 0)
#endif
{
if (*warning_message == PNG_LITERAL_SHARP)
@@ -230,7 +232,8 @@ png_warning(png_structp png_ptr, png_const_charp warning_message)
}
}
if (png_ptr != NULL && png_ptr->warning_fn != NULL)
- (*(png_ptr->warning_fn))(png_ptr, warning_message + offset);
+ (*(png_ptr->warning_fn))(png_constcast(png_structrp,png_ptr),
+ warning_message + offset);
else
png_default_warning(png_ptr, warning_message + offset);
}
@@ -278,7 +281,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
}
void
-png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
+png_formatted_warning(png_const_structrp png_ptr, png_warning_parameters p,
png_const_charp message)
{
/* The internal buffer is just 192 bytes - enough for all our messages,
@@ -346,29 +349,79 @@ png_formatted_warning(png_structp png_ptr, png_warning_parameters p,
/* i is always less than (sizeof msg), so: */
msg[i] = '\0';
- /* And this is the formatted message, it may be larger than
- * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these are
- * not (currently) formatted.
+ /* And this is the formatted message. It may be larger than
+ * PNG_MAX_ERROR_TEXT, but that is only used for 'chunk' errors and these
+ * are not (currently) formatted.
*/
png_warning(png_ptr, msg);
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_benign_error(png_structp png_ptr, png_const_charp error_message)
+png_benign_error(png_const_structrp png_ptr, png_const_charp error_message)
{
- if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
+ {
+# ifdef PNG_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ png_ptr->chunk_name != 0)
+ png_chunk_warning(png_ptr, error_message);
+ else
+# endif
+ png_warning(png_ptr, error_message);
+ }
+
+ else
+ {
+# ifdef PNG_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ png_ptr->chunk_name != 0)
+ png_chunk_error(png_ptr, error_message);
+ else
+# endif
+ png_error(png_ptr, error_message);
+ }
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
+}
+
+void /* PRIVATE */
+png_app_warning(png_const_structrp png_ptr, png_const_charp error_message)
+{
+ if ((png_ptr->flags & PNG_FLAG_APP_WARNINGS_WARN) != 0)
png_warning(png_ptr, error_message);
else
png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
-#endif
+void /* PRIVATE */
+png_app_error(png_const_structrp png_ptr, png_const_charp error_message)
+{
+ if ((png_ptr->flags & PNG_FLAG_APP_ERRORS_WARN) != 0)
+ png_warning(png_ptr, error_message);
+ else
+ png_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
+}
+#endif /* BENIGN_ERRORS */
+
+#define PNG_MAX_ERROR_TEXT 196 /* Currently limited by profile_error in png.c */
+#if defined(PNG_WARNINGS_SUPPORTED) || \
+ (defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED))
/* These utilities are used internally to build an error message that relates
* to the current chunk. The chunk name comes from png_ptr->chunk_name,
- * this is used to prefix the message. The message is limited in length
- * to 63 bytes, the name characters are output as hex digits wrapped in []
+ * which is used to prefix the message. The message is limited in length
+ * to 63 bytes. The name characters are output as hex digits wrapped in []
* if the character is invalid.
*/
#define isnonalpha(c) ((c) < 65 || (c) > 122 || ((c) > 90 && (c) < 97))
@@ -377,10 +430,8 @@ static PNG_CONST char png_digit[16] = {
'A', 'B', 'C', 'D', 'E', 'F'
};
-#define PNG_MAX_ERROR_TEXT 64
-#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
static void /* PRIVATE */
-png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
+png_format_buffer(png_const_structrp png_ptr, png_charp buffer, png_const_charp
error_message)
{
png_uint_32 chunk_name = png_ptr->chunk_name;
@@ -391,7 +442,7 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
int c = (int)(chunk_name >> ishift) & 0xff;
ishift -= 8;
- if (isnonalpha(c))
+ if (isnonalpha(c) != 0)
{
buffer[iout++] = PNG_LITERAL_LEFT_SQUARE_BRACKET;
buffer[iout++] = png_digit[(c & 0xf0) >> 4];
@@ -422,11 +473,11 @@ png_format_buffer(png_structp png_ptr, png_charp buffer, png_const_charp
buffer[iout] = '\0';
}
}
-#endif /* PNG_WARNINGS_SUPPORTED || PNG_ERROR_TEXT_SUPPORTED */
+#endif /* WARNINGS || ERROR_TEXT */
#if defined(PNG_READ_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
PNG_FUNCTION(void,PNGAPI
-png_chunk_error,(png_structp png_ptr, png_const_charp error_message),
+png_chunk_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
char msg[18+PNG_MAX_ERROR_TEXT];
@@ -439,11 +490,11 @@ png_chunk_error,(png_structp png_ptr, png_const_charp error_message),
png_error(png_ptr, msg);
}
}
-#endif /* PNG_READ_SUPPORTED && PNG_ERROR_TEXT_SUPPORTED */
+#endif /* READ && ERROR_TEXT */
#ifdef PNG_WARNINGS_SUPPORTED
void PNGAPI
-png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
+png_chunk_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
char msg[18+PNG_MAX_ERROR_TEXT];
if (png_ptr == NULL)
@@ -455,38 +506,83 @@ png_chunk_warning(png_structp png_ptr, png_const_charp warning_message)
png_warning(png_ptr, msg);
}
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
#ifdef PNG_READ_SUPPORTED
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_chunk_benign_error(png_structp png_ptr, png_const_charp error_message)
+png_chunk_benign_error(png_const_structrp png_ptr, png_const_charp
+ error_message)
{
- if (png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN)
+ if ((png_ptr->flags & PNG_FLAG_BENIGN_ERRORS_WARN) != 0)
png_chunk_warning(png_ptr, error_message);
else
png_chunk_error(png_ptr, error_message);
+
+# ifndef PNG_ERROR_TEXT_SUPPORTED
+ PNG_UNUSED(error_message)
+# endif
}
#endif
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
+
+void /* PRIVATE */
+png_chunk_report(png_const_structrp png_ptr, png_const_charp message, int error)
+{
+# ifndef PNG_WARNINGS_SUPPORTED
+ PNG_UNUSED(message)
+# endif
+
+ /* This is always supported, but for just read or just write it
+ * unconditionally does the right thing.
+ */
+# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+# endif
+
+# ifdef PNG_READ_SUPPORTED
+ {
+ if (error < PNG_CHUNK_ERROR)
+ png_chunk_warning(png_ptr, message);
+
+ else
+ png_chunk_benign_error(png_ptr, message);
+ }
+# endif
+
+# if defined(PNG_READ_SUPPORTED) && defined(PNG_WRITE_SUPPORTED)
+ else if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+# endif
+
+# ifdef PNG_WRITE_SUPPORTED
+ {
+ if (error < PNG_CHUNK_WRITE_ERROR)
+ png_app_warning(png_ptr, message);
+
+ else
+ png_app_error(png_ptr, message);
+ }
+# endif
+}
#ifdef PNG_ERROR_TEXT_SUPPORTED
#ifdef PNG_FLOATING_POINT_SUPPORTED
PNG_FUNCTION(void,
-png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN)
+png_fixed_error,(png_const_structrp png_ptr, png_const_charp name),PNG_NORETURN)
{
# define fixed_message "fixed point overflow in "
# define fixed_message_ln ((sizeof fixed_message)-1)
int iin;
char msg[fixed_message_ln+PNG_MAX_ERROR_TEXT];
- png_memcpy(msg, fixed_message, fixed_message_ln);
+ memcpy(msg, fixed_message, fixed_message_ln);
iin = 0;
- if (name != NULL) while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
- {
- msg[fixed_message_ln + iin] = name[iin];
- ++iin;
- }
+ if (name != NULL)
+ while (iin < (PNG_MAX_ERROR_TEXT-1) && name[iin] != 0)
+ {
+ msg[fixed_message_ln + iin] = name[iin];
+ ++iin;
+ }
msg[fixed_message_ln + iin] = 0;
png_error(png_ptr, msg);
}
@@ -498,14 +594,111 @@ png_fixed_error,(png_structp png_ptr, png_const_charp name),PNG_NORETURN)
* otherwise it is necessary for png_default_error to be overridden.
*/
jmp_buf* PNGAPI
-png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
+png_set_longjmp_fn(png_structrp png_ptr, png_longjmp_ptr longjmp_fn,
size_t jmp_buf_size)
{
- if (png_ptr == NULL || jmp_buf_size != png_sizeof(jmp_buf))
+ /* From libpng 1.6.0 the app gets one chance to set a 'jmpbuf_size' value
+ * and it must not change after that. Libpng doesn't care how big the
+ * buffer is, just that it doesn't change.
+ *
+ * If the buffer size is no *larger* than the size of jmp_buf when libpng is
+ * compiled a built in jmp_buf is returned; this preserves the pre-1.6.0
+ * semantics that this call will not fail. If the size is larger, however,
+ * the buffer is allocated and this may fail, causing the function to return
+ * NULL.
+ */
+ if (png_ptr == NULL)
return NULL;
+ if (png_ptr->jmp_buf_ptr == NULL)
+ {
+ png_ptr->jmp_buf_size = 0; /* not allocated */
+
+ if (jmp_buf_size <= (sizeof png_ptr->jmp_buf_local))
+ png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local;
+
+ else
+ {
+ png_ptr->jmp_buf_ptr = png_voidcast(jmp_buf *,
+ png_malloc_warn(png_ptr, jmp_buf_size));
+
+ if (png_ptr->jmp_buf_ptr == NULL)
+ return NULL; /* new NULL return on OOM */
+
+ png_ptr->jmp_buf_size = jmp_buf_size;
+ }
+ }
+
+ else /* Already allocated: check the size */
+ {
+ size_t size = png_ptr->jmp_buf_size;
+
+ if (size == 0)
+ {
+ size = (sizeof png_ptr->jmp_buf_local);
+ if (png_ptr->jmp_buf_ptr != &png_ptr->jmp_buf_local)
+ {
+ /* This is an internal error in libpng: somehow we have been left
+ * with a stack allocated jmp_buf when the application regained
+ * control. It's always possible to fix this up, but for the moment
+ * this is a png_error because that makes it easy to detect.
+ */
+ png_error(png_ptr, "Libpng jmp_buf still allocated");
+ /* png_ptr->jmp_buf_ptr = &png_ptr->jmp_buf_local; */
+ }
+ }
+
+ if (size != jmp_buf_size)
+ {
+ png_warning(png_ptr, "Application jmp_buf size changed");
+ return NULL; /* caller will probably crash: no choice here */
+ }
+ }
+
+ /* Finally fill in the function, now we have a satisfactory buffer. It is
+ * valid to change the function on every call.
+ */
png_ptr->longjmp_fn = longjmp_fn;
- return &png_ptr->longjmp_buffer;
+ return png_ptr->jmp_buf_ptr;
+}
+
+void /* PRIVATE */
+png_free_jmpbuf(png_structrp png_ptr)
+{
+ if (png_ptr != NULL)
+ {
+ jmp_buf *jb = png_ptr->jmp_buf_ptr;
+
+ /* A size of 0 is used to indicate a local, stack, allocation of the
+ * pointer; used here and in png.c
+ */
+ if (jb != NULL && png_ptr->jmp_buf_size > 0)
+ {
+
+ /* This stuff is so that a failure to free the error control structure
+ * does not leave libpng in a state with no valid error handling: the
+ * free always succeeds, if there is an error it gets ignored.
+ */
+ if (jb != &png_ptr->jmp_buf_local)
+ {
+ /* Make an internal, libpng, jmp_buf to return here */
+ jmp_buf free_jmp_buf;
+
+ if (!setjmp(free_jmp_buf))
+ {
+ png_ptr->jmp_buf_ptr = &free_jmp_buf; /* come back here */
+ png_ptr->jmp_buf_size = 0; /* stack allocation */
+ png_ptr->longjmp_fn = longjmp;
+ png_free(png_ptr, jb); /* Return to setjmp on error */
+ }
+ }
+ }
+
+ /* *Always* cancel everything out: */
+ png_ptr->jmp_buf_size = 0;
+ png_ptr->jmp_buf_ptr = NULL;
+ png_ptr->longjmp_fn = 0;
+ }
}
#endif
@@ -515,7 +708,7 @@ png_set_longjmp_fn(png_structp png_ptr, png_longjmp_ptr longjmp_fn,
* error function pointer in png_set_error_fn().
*/
static PNG_FUNCTION(void /* PRIVATE */,
-png_default_error,(png_structp png_ptr, png_const_charp error_message),
+png_default_error,(png_const_structrp png_ptr, png_const_charp error_message),
PNG_NORETURN)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
@@ -562,24 +755,23 @@ png_default_error,(png_structp png_ptr, png_const_charp error_message),
}
PNG_FUNCTION(void,PNGAPI
-png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
+png_longjmp,(png_const_structrp png_ptr, int val),PNG_NORETURN)
{
#ifdef PNG_SETJMP_SUPPORTED
- if (png_ptr && png_ptr->longjmp_fn)
- {
-# ifdef USE_FAR_KEYWORD
- {
- jmp_buf tmp_jmpbuf;
- png_memcpy(tmp_jmpbuf, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
- png_ptr->longjmp_fn(tmp_jmpbuf, val);
- }
-
-# else
- png_ptr->longjmp_fn(png_ptr->longjmp_buffer, val);
-# endif
- }
+ if (png_ptr != NULL && png_ptr->longjmp_fn != NULL &&
+ png_ptr->jmp_buf_ptr != NULL)
+ png_ptr->longjmp_fn(*png_ptr->jmp_buf_ptr, val);
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(val)
#endif
- /* Here if not setjmp support or if png_ptr is null. */
+
+ /* If control reaches this point, png_longjmp() must not return. The only
+ * choice is to terminate the whole process (or maybe the thread); to do
+ * this the ANSI-C abort() function is used unless a different method is
+ * implemented by overriding the default configuration setting for
+ * PNG_ABORT().
+ */
PNG_ABORT();
}
@@ -590,7 +782,7 @@ png_longjmp,(png_structp png_ptr, int val),PNG_NORETURN)
* not used, but it is passed in case it may be useful.
*/
static void /* PRIVATE */
-png_default_warning(png_structp png_ptr, png_const_charp warning_message)
+png_default_warning(png_const_structrp png_ptr, png_const_charp warning_message)
{
#ifdef PNG_CONSOLE_IO_SUPPORTED
# ifdef PNG_ERROR_NUMBERS_SUPPORTED
@@ -632,15 +824,15 @@ png_default_warning(png_structp png_ptr, png_const_charp warning_message)
#endif
PNG_UNUSED(png_ptr) /* Make compiler happy */
}
-#endif /* PNG_WARNINGS_SUPPORTED */
+#endif /* WARNINGS */
/* This function is called when the application wants to use another method
* of handling errors and warnings. Note that the error function MUST NOT
* return to the calling routine or serious problems will occur. The return
- * method used in the default routine calls longjmp(png_ptr->longjmp_buffer, 1)
+ * method used in the default routine calls longjmp(png_ptr->jmp_buf_ptr, 1)
*/
void PNGAPI
-png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
+png_set_error_fn(png_structrp png_ptr, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warning_fn)
{
if (png_ptr == NULL)
@@ -661,7 +853,7 @@ png_set_error_fn(png_structp png_ptr, png_voidp error_ptr,
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
-png_get_error_ptr(png_const_structp png_ptr)
+png_get_error_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return NULL;
@@ -672,7 +864,7 @@ png_get_error_ptr(png_const_structp png_ptr)
#ifdef PNG_ERROR_NUMBERS_SUPPORTED
void PNGAPI
-png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
+png_set_strip_error_numbers(png_structrp png_ptr, png_uint_32 strip_mode)
{
if (png_ptr != NULL)
{
@@ -682,4 +874,90 @@ png_set_strip_error_numbers(png_structp png_ptr, png_uint_32 strip_mode)
}
}
#endif
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+ /* Currently the above both depend on SETJMP_SUPPORTED, however it would be
+ * possible to implement without setjmp support just so long as there is some
+ * way to handle the error return here:
+ */
+PNG_FUNCTION(void /* PRIVATE */, (PNGCBAPI
+png_safe_error),(png_structp png_nonconst_ptr, png_const_charp error_message),
+ PNG_NORETURN)
+{
+ const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
+
+ /* An error is always logged here, overwriting anything (typically a warning)
+ * that is already there:
+ */
+ if (image != NULL)
+ {
+ png_safecat(image->message, (sizeof image->message), 0, error_message);
+ image->warning_or_error |= PNG_IMAGE_ERROR;
+
+ /* Retrieve the jmp_buf from within the png_control, making this work for
+ * C++ compilation too is pretty tricky: C++ wants a pointer to the first
+ * element of a jmp_buf, but C doesn't tell us the type of that.
+ */
+ if (image->opaque != NULL && image->opaque->error_buf != NULL)
+ longjmp(png_control_jmp_buf(image->opaque), 1);
+
+ /* Missing longjmp buffer, the following is to help debugging: */
+ {
+ size_t pos = png_safecat(image->message, (sizeof image->message), 0,
+ "bad longjmp: ");
+ png_safecat(image->message, (sizeof image->message), pos,
+ error_message);
+ }
+ }
+
+ /* Here on an internal programming error. */
+ abort();
+}
+
+#ifdef PNG_WARNINGS_SUPPORTED
+void /* PRIVATE */ PNGCBAPI
+png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
+{
+ const png_const_structrp png_ptr = png_nonconst_ptr;
+ png_imagep image = png_voidcast(png_imagep, png_ptr->error_ptr);
+
+ /* A warning is only logged if there is no prior warning or error. */
+ if (image->warning_or_error == 0)
+ {
+ png_safecat(image->message, (sizeof image->message), 0, warning_message);
+ image->warning_or_error |= PNG_IMAGE_WARNING;
+ }
+}
+#endif
+
+int /* PRIVATE */
+png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
+{
+ volatile png_imagep image = image_in;
+ volatile int result;
+ volatile png_voidp saved_error_buf;
+ jmp_buf safe_jmpbuf;
+
+ /* Safely execute function(arg) with png_error returning to this function. */
+ saved_error_buf = image->opaque->error_buf;
+ result = setjmp(safe_jmpbuf) == 0;
+
+ if (result != 0)
+ {
+
+ image->opaque->error_buf = safe_jmpbuf;
+ result = function(arg);
+ }
+
+ image->opaque->error_buf = saved_error_buf;
+
+ /* And do the cleanup prior to any failure return. */
+ if (result == 0)
+ png_image_free(image);
+
+ return result;
+}
+#endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/pngget.c b/src/3rdparty/libpng/pngget.c
index 43400cda7e..743a6a9bbc 100644
--- a/src/3rdparty/libpng/pngget.c
+++ b/src/3rdparty/libpng/pngget.c
@@ -1,8 +1,8 @@
/* pngget.c - retrieval of values from info struct
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -17,7 +17,7 @@
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
png_uint_32 PNGAPI
-png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 flag)
{
if (png_ptr != NULL && info_ptr != NULL)
@@ -27,7 +27,7 @@ png_get_valid(png_const_structp png_ptr, png_const_infop info_ptr,
}
png_size_t PNGAPI
-png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->rowbytes);
@@ -37,7 +37,7 @@ png_get_rowbytes(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_INFO_IMAGE_SUPPORTED
png_bytepp PNGAPI
-png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->row_pointers);
@@ -49,7 +49,7 @@ png_get_rows(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_EASY_ACCESS_SUPPORTED
/* Easy access to info, added in libpng-0.99 */
png_uint_32 PNGAPI
-png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->width;
@@ -58,7 +58,7 @@ png_get_image_width(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_uint_32 PNGAPI
-png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->height;
@@ -67,7 +67,7 @@ png_get_image_height(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->bit_depth;
@@ -76,7 +76,7 @@ png_get_bit_depth(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->color_type;
@@ -85,7 +85,7 @@ png_get_color_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->filter_type;
@@ -94,7 +94,7 @@ png_get_filter_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->interlace_type;
@@ -103,7 +103,7 @@ png_get_interlace_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_byte PNGAPI
-png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return info_ptr->compression_type;
@@ -112,10 +112,12 @@ png_get_compression_type(png_const_structp png_ptr, png_const_infop info_ptr)
}
png_uint_32 PNGAPI
-png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function",
"png_get_x_pixels_per_meter");
@@ -123,16 +125,21 @@ png_get_x_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_uint_32 PNGAPI
-png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function",
"png_get_y_pixels_per_meter");
@@ -140,16 +147,20 @@ png_get_y_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
return (info_ptr->y_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_uint_32 PNGAPI
-png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
@@ -157,6 +168,9 @@ png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
return (info_ptr->x_pixels_per_unit);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -164,10 +178,12 @@ png_get_pixels_per_meter(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
+ info_ptr)
{
#ifdef PNG_READ_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
@@ -175,6 +191,9 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
return ((float)((float)info_ptr->y_pixels_per_unit
/(float)info_ptr->x_pixels_per_unit));
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return ((float)0.0);
@@ -183,14 +202,15 @@ png_get_pixel_aspect_ratio(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FIXED_POINT_SUPPORTED
png_fixed_point PNGAPI
-png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
- png_const_infop info_ptr)
+png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
#ifdef PNG_READ_pHYs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs)
- && info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0
- && info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX
- && info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
+ info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
+ info_ptr->x_pixels_per_unit <= PNG_UINT_31_MAX &&
+ info_ptr->y_pixels_per_unit <= PNG_UINT_31_MAX)
{
png_fixed_point res;
@@ -200,9 +220,12 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
* range of 0..2^31-1; otherwise the cast might overflow.
*/
if (png_muldiv(&res, (png_int_32)info_ptr->y_pixels_per_unit, PNG_FP_1,
- (png_int_32)info_ptr->x_pixels_per_unit))
+ (png_int_32)info_ptr->x_pixels_per_unit) != 0)
return res;
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return 0;
@@ -210,64 +233,80 @@ png_get_pixel_aspect_ratio_fixed(png_const_structp png_ptr,
#endif
png_int_32 PNGAPI
-png_get_x_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_y_offset_microns(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_x_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->x_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
}
png_int_32 PNGAPI
-png_get_y_offset_pixels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
#ifdef PNG_oFFs_SUPPORTED
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
return (info_ptr->y_offset);
}
+#else
+ PNG_UNUSED(png_ptr)
+ PNG_UNUSED(info_ptr)
#endif
return (0);
@@ -298,7 +337,7 @@ ppi_from_ppm(png_uint_32 ppm)
*/
png_fixed_point result;
if (ppm <= PNG_UINT_31_MAX && png_muldiv(&result, (png_int_32)ppm, 127,
- 5000))
+ 5000) != 0)
return result;
/* Overflow. */
@@ -307,26 +346,26 @@ ppi_from_ppm(png_uint_32 ppm)
}
png_uint_32 PNGAPI
-png_get_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_pixels_per_meter(png_ptr, info_ptr));
}
png_uint_32 PNGAPI
-png_get_x_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_x_pixels_per_meter(png_ptr, info_ptr));
}
png_uint_32 PNGAPI
-png_get_y_pixels_per_inch(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_pixels_per_inch(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
return ppi_from_ppm(png_get_y_pixels_per_meter(png_ptr, info_ptr));
}
#ifdef PNG_FIXED_POINT_SUPPORTED
static png_fixed_point
-png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns)
+png_fixed_inches_from_microns(png_const_structrp png_ptr, png_int_32 microns)
{
/* Convert from metres * 1,000,000 to inches * 100,000, meters to
* inches is simply *(100/2.54), so we want *(10/2.54) == 500/127.
@@ -337,8 +376,8 @@ png_fixed_inches_from_microns(png_structp png_ptr, png_int_32 microns)
}
png_fixed_point PNGAPI
-png_get_x_offset_inches_fixed(png_structp png_ptr,
- png_const_infop info_ptr)
+png_get_x_offset_inches_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
return png_fixed_inches_from_microns(png_ptr,
png_get_x_offset_microns(png_ptr, info_ptr));
@@ -347,8 +386,8 @@ png_get_x_offset_inches_fixed(png_structp png_ptr,
#ifdef PNG_FIXED_POINT_SUPPORTED
png_fixed_point PNGAPI
-png_get_y_offset_inches_fixed(png_structp png_ptr,
- png_const_infop info_ptr)
+png_get_y_offset_inches_fixed(png_const_structrp png_ptr,
+ png_const_inforp info_ptr)
{
return png_fixed_inches_from_microns(png_ptr,
png_get_y_offset_microns(png_ptr, info_ptr));
@@ -357,7 +396,7 @@ png_get_y_offset_inches_fixed(png_structp png_ptr,
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_x_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
/* To avoid the overflow do the conversion directly in floating
* point.
@@ -368,7 +407,7 @@ png_get_x_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_FLOATING_POINT_SUPPORTED
float PNGAPI
-png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_y_offset_inches(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
/* To avoid the overflow do the conversion directly in floating
* point.
@@ -379,12 +418,13 @@ png_get_y_offset_inches(png_const_structp png_ptr, png_const_infop info_ptr)
#ifdef PNG_pHYs_SUPPORTED
png_uint_32 PNGAPI
-png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
{
png_uint_32 retval = 0;
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
png_debug1(1, "in %s retrieval function", "pHYs");
@@ -415,15 +455,16 @@ png_get_pHYs_dpi(png_const_structp png_ptr, png_const_infop info_ptr,
return (retval);
}
-#endif /* PNG_pHYs_SUPPORTED */
-#endif /* PNG_INCH_CONVERSIONS_SUPPORTED */
+#endif /* pHYs */
+#endif /* INCH_CONVERSIONS */
/* png_get_channels really belongs in here, too, but it's been around longer */
-#endif /* PNG_EASY_ACCESS_SUPPORTED */
+#endif /* EASY_ACCESS */
+
png_byte PNGAPI
-png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr)
+png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->channels);
@@ -431,22 +472,25 @@ png_get_channels(png_const_structp png_ptr, png_const_infop info_ptr)
return (0);
}
+#ifdef PNG_READ_SUPPORTED
png_const_bytep PNGAPI
-png_get_signature(png_const_structp png_ptr, png_infop info_ptr)
+png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
{
if (png_ptr != NULL && info_ptr != NULL)
return(info_ptr->signature);
return (NULL);
}
+#endif
#ifdef PNG_bKGD_SUPPORTED
png_uint_32 PNGAPI
-png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr,
+png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
png_color_16p *background)
{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD)
- && background != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
+ background != NULL)
{
png_debug1(1, "in %s retrieval function", "bKGD");
@@ -463,87 +507,47 @@ png_get_bKGD(png_const_structp png_ptr, png_infop info_ptr,
* same time to correct the rgb grayscale coefficient defaults obtained from the
* cHRM chunk in 1.5.4
*/
-png_uint_32 PNGFAPI
-png_get_cHRM_XYZ_fixed(png_structp png_ptr, png_const_infop info_ptr,
- png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
- png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
- png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
- png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
- png_fixed_point *int_blue_Z)
-{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
- {
- png_xy xy;
- png_XYZ XYZ;
-
- png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
-
- xy.whitex = info_ptr->x_white;
- xy.whitey = info_ptr->y_white;
- xy.redx = info_ptr->x_red;
- xy.redy = info_ptr->y_red;
- xy.greenx = info_ptr->x_green;
- xy.greeny = info_ptr->y_green;
- xy.bluex = info_ptr->x_blue;
- xy.bluey = info_ptr->y_blue;
-
- /* The *_checked function handles error reporting, so just return 0 if
- * there is a failure here.
- */
- if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy))
- {
- if (int_red_X != NULL)
- *int_red_X = XYZ.redX;
- if (int_red_Y != NULL)
- *int_red_Y = XYZ.redY;
- if (int_red_Z != NULL)
- *int_red_Z = XYZ.redZ;
- if (int_green_X != NULL)
- *int_green_X = XYZ.greenX;
- if (int_green_Y != NULL)
- *int_green_Y = XYZ.greenY;
- if (int_green_Z != NULL)
- *int_green_Z = XYZ.greenZ;
- if (int_blue_X != NULL)
- *int_blue_X = XYZ.blueX;
- if (int_blue_Y != NULL)
- *int_blue_Y = XYZ.blueY;
- if (int_blue_Z != NULL)
- *int_blue_Z = XYZ.blueZ;
-
- return (PNG_INFO_cHRM);
- }
- }
-
- return (0);
-}
-
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *white_x, double *white_y, double *red_x, double *red_y,
double *green_x, double *green_y, double *blue_x, double *blue_y)
{
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ /* Quiet API change: this code used to only return the end points if a cHRM
+ * chunk was present, but the end points can also come from iCCP or sRGB
+ * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
+ * the png_set_ APIs merely check that set end points are mutually
+ * consistent.
+ */
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
png_debug1(1, "in %s retrieval function", "cHRM");
if (white_x != NULL)
- *white_x = png_float(png_ptr, info_ptr->x_white, "cHRM white X");
+ *white_x = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
if (white_y != NULL)
- *white_y = png_float(png_ptr, info_ptr->y_white, "cHRM white Y");
+ *white_y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.whitey, "cHRM white Y");
if (red_x != NULL)
- *red_x = png_float(png_ptr, info_ptr->x_red, "cHRM red X");
+ *red_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redx,
+ "cHRM red X");
if (red_y != NULL)
- *red_y = png_float(png_ptr, info_ptr->y_red, "cHRM red Y");
+ *red_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.redy,
+ "cHRM red Y");
if (green_x != NULL)
- *green_x = png_float(png_ptr, info_ptr->x_green, "cHRM green X");
+ *green_x = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.greenx, "cHRM green X");
if (green_y != NULL)
- *green_y = png_float(png_ptr, info_ptr->y_green, "cHRM green Y");
+ *green_y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_xy.greeny, "cHRM green Y");
if (blue_x != NULL)
- *blue_x = png_float(png_ptr, info_ptr->x_blue, "cHRM blue X");
+ *blue_x = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluex,
+ "cHRM blue X");
if (blue_y != NULL)
- *blue_y = png_float(png_ptr, info_ptr->y_blue, "cHRM blue Y");
+ *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
+ "cHRM blue Y");
return (PNG_INFO_cHRM);
}
@@ -551,35 +555,43 @@ png_get_cHRM(png_const_structp png_ptr, png_const_infop info_ptr,
}
png_uint_32 PNGAPI
-png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *red_X, double *red_Y, double *red_Z, double *green_X,
double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
double *blue_Z)
{
- png_XYZ XYZ;
-
- if (png_get_cHRM_XYZ_fixed(png_ptr, info_ptr,
- &XYZ.redX, &XYZ.redY, &XYZ.redZ, &XYZ.greenX, &XYZ.greenY, &XYZ.greenZ,
- &XYZ.blueX, &XYZ.blueY, &XYZ.blueZ) & PNG_INFO_cHRM)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
+ png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
+
if (red_X != NULL)
- *red_X = png_float(png_ptr, XYZ.redX, "cHRM red X");
+ *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
+ "cHRM red X");
if (red_Y != NULL)
- *red_Y = png_float(png_ptr, XYZ.redY, "cHRM red Y");
+ *red_Y = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Y,
+ "cHRM red Y");
if (red_Z != NULL)
- *red_Z = png_float(png_ptr, XYZ.redZ, "cHRM red Z");
+ *red_Z = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_Z,
+ "cHRM red Z");
if (green_X != NULL)
- *green_X = png_float(png_ptr, XYZ.greenX, "cHRM green X");
+ *green_X = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_X, "cHRM green X");
if (green_Y != NULL)
- *green_Y = png_float(png_ptr, XYZ.greenY, "cHRM green Y");
+ *green_Y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_Y, "cHRM green Y");
if (green_Z != NULL)
- *green_Z = png_float(png_ptr, XYZ.greenZ, "cHRM green Z");
+ *green_Z = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.green_Z, "cHRM green Z");
if (blue_X != NULL)
- *blue_X = png_float(png_ptr, XYZ.blueX, "cHRM blue X");
+ *blue_X = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_X, "cHRM blue X");
if (blue_Y != NULL)
- *blue_Y = png_float(png_ptr, XYZ.blueY, "cHRM blue Y");
+ *blue_Y = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_Y, "cHRM blue Y");
if (blue_Z != NULL)
- *blue_Z = png_float(png_ptr, XYZ.blueZ, "cHRM blue Z");
+ *blue_Z = png_float(png_ptr,
+ info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
return (PNG_INFO_cHRM);
}
@@ -589,31 +601,69 @@ png_get_cHRM_XYZ(png_structp png_ptr, png_const_infop info_ptr,
# ifdef PNG_FIXED_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
+ png_fixed_point *int_red_X, png_fixed_point *int_red_Y,
+ png_fixed_point *int_red_Z, png_fixed_point *int_green_X,
+ png_fixed_point *int_green_Y, png_fixed_point *int_green_Z,
+ png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
+ png_fixed_point *int_blue_Z)
+{
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
+ {
+ png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
+
+ if (int_red_X != NULL)
+ *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
+ if (int_red_Y != NULL)
+ *int_red_Y = info_ptr->colorspace.end_points_XYZ.red_Y;
+ if (int_red_Z != NULL)
+ *int_red_Z = info_ptr->colorspace.end_points_XYZ.red_Z;
+ if (int_green_X != NULL)
+ *int_green_X = info_ptr->colorspace.end_points_XYZ.green_X;
+ if (int_green_Y != NULL)
+ *int_green_Y = info_ptr->colorspace.end_points_XYZ.green_Y;
+ if (int_green_Z != NULL)
+ *int_green_Z = info_ptr->colorspace.end_points_XYZ.green_Z;
+ if (int_blue_X != NULL)
+ *int_blue_X = info_ptr->colorspace.end_points_XYZ.blue_X;
+ if (int_blue_Y != NULL)
+ *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
+ if (int_blue_Z != NULL)
+ *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
+ return (PNG_INFO_cHRM);
+ }
+
+ return (0);
+}
+
+png_uint_32 PNGAPI
+png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *white_x, png_fixed_point *white_y, png_fixed_point *red_x,
png_fixed_point *red_y, png_fixed_point *green_x, png_fixed_point *green_y,
png_fixed_point *blue_x, png_fixed_point *blue_y)
{
png_debug1(1, "in %s retrieval function", "cHRM");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
{
if (white_x != NULL)
- *white_x = info_ptr->x_white;
+ *white_x = info_ptr->colorspace.end_points_xy.whitex;
if (white_y != NULL)
- *white_y = info_ptr->y_white;
+ *white_y = info_ptr->colorspace.end_points_xy.whitey;
if (red_x != NULL)
- *red_x = info_ptr->x_red;
+ *red_x = info_ptr->colorspace.end_points_xy.redx;
if (red_y != NULL)
- *red_y = info_ptr->y_red;
+ *red_y = info_ptr->colorspace.end_points_xy.redy;
if (green_x != NULL)
- *green_x = info_ptr->x_green;
+ *green_x = info_ptr->colorspace.end_points_xy.greenx;
if (green_y != NULL)
- *green_y = info_ptr->y_green;
+ *green_y = info_ptr->colorspace.end_points_xy.greeny;
if (blue_x != NULL)
- *blue_x = info_ptr->x_blue;
+ *blue_x = info_ptr->colorspace.end_points_xy.bluex;
if (blue_y != NULL)
- *blue_y = info_ptr->y_blue;
+ *blue_y = info_ptr->colorspace.end_points_xy.bluey;
return (PNG_INFO_cHRM);
}
@@ -623,49 +673,57 @@ png_get_cHRM_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
#ifdef PNG_gAMA_SUPPORTED
-png_uint_32 PNGFAPI
-png_get_gAMA_fixed(png_const_structp png_ptr, png_const_infop info_ptr,
+# ifdef PNG_FIXED_POINT_SUPPORTED
+png_uint_32 PNGAPI
+png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_fixed_point *file_gamma)
{
png_debug1(1, "in %s retrieval function", "gAMA");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
- && file_gamma != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ file_gamma != NULL)
{
- *file_gamma = info_ptr->gamma;
+ *file_gamma = info_ptr->colorspace.gamma;
return (PNG_INFO_gAMA);
}
return (0);
}
+# endif
+
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_gAMA(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
double *file_gamma)
{
- png_fixed_point igamma;
- png_uint_32 ok = png_get_gAMA_fixed(png_ptr, info_ptr, &igamma);
+ png_debug1(1, "in %s retrieval function", "gAMA(float)");
- if (ok)
- *file_gamma = png_float(png_ptr, igamma, "png_get_gAMA");
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0 &&
+ file_gamma != NULL)
+ {
+ *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
+ "png_get_gAMA");
+ return (PNG_INFO_gAMA);
+ }
- return ok;
+ return (0);
}
-
# endif
#endif
#ifdef PNG_sRGB_SUPPORTED
png_uint_32 PNGAPI
-png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *file_srgb_intent)
{
png_debug1(1, "in %s retrieval function", "sRGB");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB)
- && file_srgb_intent != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
{
- *file_srgb_intent = (int)info_ptr->srgb_intent;
+ *file_srgb_intent = info_ptr->colorspace.rendering_intent;
return (PNG_INFO_sRGB);
}
@@ -675,23 +733,24 @@ png_get_sRGB(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_iCCP_SUPPORTED
png_uint_32 PNGAPI
-png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
png_charpp name, int *compression_type,
png_bytepp profile, png_uint_32 *proflen)
{
png_debug1(1, "in %s retrieval function", "iCCP");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_iCCP)
- && name != NULL && compression_type != NULL && profile != NULL &&
- proflen != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_iCCP) != 0 &&
+ name != NULL && compression_type != NULL && profile != NULL &&
+ proflen != NULL)
{
*name = info_ptr->iccp_name;
*profile = info_ptr->iccp_profile;
- /* Compression_type is a dummy so the API won't have to change
- * if we introduce multiple compression types later.
+ *proflen = png_get_uint_32(info_ptr->iccp_profile);
+ /* This is somewhat irrelevant since the profile data returned has
+ * actually been uncompressed.
*/
- *proflen = info_ptr->iccp_proflen;
- *compression_type = info_ptr->iccp_compression;
+ *compression_type = PNG_COMPRESSION_TYPE_BASE;
return (PNG_INFO_iCCP);
}
@@ -700,14 +759,14 @@ png_get_iCCP(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
#ifdef PNG_sPLT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr,
+int PNGAPI
+png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
png_sPLT_tpp spalettes)
{
if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
{
*spalettes = info_ptr->splt_palettes;
- return ((png_uint_32)info_ptr->splt_palettes_num);
+ return info_ptr->splt_palettes_num;
}
return (0);
@@ -716,13 +775,13 @@ png_get_sPLT(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_hIST_SUPPORTED
png_uint_32 PNGAPI
-png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_16p *hist)
{
png_debug1(1, "in %s retrieval function", "hIST");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST)
- && hist != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
{
*hist = info_ptr->hist;
return (PNG_INFO_hIST);
@@ -733,22 +792,27 @@ png_get_hIST(png_const_structp png_ptr, png_const_infop info_ptr,
#endif
png_uint_32 PNGAPI
-png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
+png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *width, png_uint_32 *height, int *bit_depth,
int *color_type, int *interlace_type, int *compression_type,
int *filter_type)
-
{
png_debug1(1, "in %s retrieval function", "IHDR");
- if (png_ptr == NULL || info_ptr == NULL || width == NULL ||
- height == NULL || bit_depth == NULL || color_type == NULL)
+ if (png_ptr == NULL || info_ptr == NULL)
return (0);
- *width = info_ptr->width;
- *height = info_ptr->height;
- *bit_depth = info_ptr->bit_depth;
- *color_type = info_ptr->color_type;
+ if (width != NULL)
+ *width = info_ptr->width;
+
+ if (height != NULL)
+ *height = info_ptr->height;
+
+ if (bit_depth != NULL)
+ *bit_depth = info_ptr->bit_depth;
+
+ if (color_type != NULL)
+ *color_type = info_ptr->color_type;
if (compression_type != NULL)
*compression_type = info_ptr->compression_type;
@@ -764,7 +828,7 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
* application has ignored our advice not to mess with the members
* of info_ptr directly.
*/
- png_check_IHDR (png_ptr, info_ptr->width, info_ptr->height,
+ png_check_IHDR(png_ptr, info_ptr->width, info_ptr->height,
info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
info_ptr->compression_type, info_ptr->filter_type);
@@ -773,13 +837,14 @@ png_get_IHDR(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_oFFs_SUPPORTED
png_uint_32 PNGAPI
-png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_int_32 *offset_x, png_int_32 *offset_y, int *unit_type)
{
png_debug1(1, "in %s retrieval function", "oFFs");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs)
- && offset_x != NULL && offset_y != NULL && unit_type != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_oFFs) != 0 &&
+ offset_x != NULL && offset_y != NULL && unit_type != NULL)
{
*offset_x = info_ptr->x_offset;
*offset_y = info_ptr->y_offset;
@@ -793,14 +858,15 @@ png_get_oFFs(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_pCAL_SUPPORTED
png_uint_32 PNGAPI
-png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_charp *purpose, png_int_32 *X0, png_int_32 *X1, int *type, int *nparams,
png_charp *units, png_charpp *params)
{
png_debug1(1, "in %s retrieval function", "pCAL");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL)
- && purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_pCAL) != 0 &&
+ purpose != NULL && X0 != NULL && X1 != NULL && type != NULL &&
nparams != NULL && units != NULL && params != NULL)
{
*purpose = info_ptr->pcal_purpose;
@@ -819,16 +885,20 @@ png_get_pCAL(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_sCAL_SUPPORTED
# ifdef PNG_FIXED_POINT_SUPPORTED
-# ifdef PNG_FLOATING_ARITHMETIC_SUPPORTED
+# if defined(PNG_FLOATING_ARITHMETIC_SUPPORTED) || \
+ defined(PNG_FLOATING_POINT_SUPPORTED)
png_uint_32 PNGAPI
-png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, png_fixed_point *width, png_fixed_point *height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
- /*TODO: make this work without FP support */
+ /*TODO: make this work without FP support; the API is currently eliminated
+ * if neither floating point APIs nor internal floating point arithmetic
+ * are enabled.
+ */
*width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
*height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
"sCAL height");
@@ -841,11 +911,11 @@ png_get_sCAL_fixed(png_structp png_ptr, png_const_infop info_ptr,
# endif /* FIXED_POINT */
# ifdef PNG_FLOATING_POINT_SUPPORTED
png_uint_32 PNGAPI
-png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, double *width, double *height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
*width = atof(info_ptr->scal_s_width);
@@ -857,11 +927,11 @@ png_get_sCAL(png_const_structp png_ptr, png_const_infop info_ptr,
}
# endif /* FLOATING POINT */
png_uint_32 PNGAPI
-png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
int *unit, png_charpp width, png_charpp height)
{
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_sCAL))
+ (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
*unit = info_ptr->scal_unit;
*width = info_ptr->scal_s_width;
@@ -875,7 +945,7 @@ png_get_sCAL_s(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_pHYs_SUPPORTED
png_uint_32 PNGAPI
-png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
png_uint_32 *res_x, png_uint_32 *res_y, int *unit_type)
{
png_uint_32 retval = 0;
@@ -883,7 +953,7 @@ png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
png_debug1(1, "in %s retrieval function", "pHYs");
if (png_ptr != NULL && info_ptr != NULL &&
- (info_ptr->valid & PNG_INFO_pHYs))
+ (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
if (res_x != NULL)
{
@@ -909,13 +979,13 @@ png_get_pHYs(png_const_structp png_ptr, png_const_infop info_ptr,
#endif /* pHYs */
png_uint_32 PNGAPI
-png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
png_colorp *palette, int *num_palette)
{
png_debug1(1, "in %s retrieval function", "PLTE");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_PLTE)
- && palette != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_PLTE) != 0 && palette != NULL)
{
*palette = info_ptr->palette;
*num_palette = info_ptr->num_palette;
@@ -928,13 +998,13 @@ png_get_PLTE(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_sBIT_SUPPORTED
png_uint_32 PNGAPI
-png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr,
+png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
png_color_8p *sig_bit)
{
png_debug1(1, "in %s retrieval function", "sBIT");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT)
- && sig_bit != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
{
*sig_bit = &(info_ptr->sig_bit);
return (PNG_INFO_sBIT);
@@ -945,8 +1015,8 @@ png_get_sBIT(png_const_structp png_ptr, png_infop info_ptr,
#endif
#ifdef PNG_TEXT_SUPPORTED
-png_uint_32 PNGAPI
-png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
+int PNGAPI
+png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
png_textp *text_ptr, int *num_text)
{
if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
@@ -960,7 +1030,7 @@ png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
if (num_text != NULL)
*num_text = info_ptr->num_text;
- return ((png_uint_32)info_ptr->num_text);
+ return info_ptr->num_text;
}
if (num_text != NULL)
@@ -972,12 +1042,13 @@ png_get_text(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_tIME_SUPPORTED
png_uint_32 PNGAPI
-png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
+png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_timep *mod_time)
{
png_debug1(1, "in %s retrieval function", "tIME");
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME)
- && mod_time != NULL)
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
{
*mod_time = &(info_ptr->mod_time);
return (PNG_INFO_tIME);
@@ -989,11 +1060,12 @@ png_get_tIME(png_const_structp png_ptr, png_infop info_ptr, png_timep *mod_time)
#ifdef PNG_tRNS_SUPPORTED
png_uint_32 PNGAPI
-png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr,
+png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
{
png_uint_32 retval = 0;
- if (png_ptr != NULL && info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ if (png_ptr != NULL && info_ptr != NULL &&
+ (info_ptr->valid & PNG_INFO_tRNS) != 0)
{
png_debug1(1, "in %s retrieval function", "tRNS");
@@ -1032,9 +1104,9 @@ png_get_tRNS(png_const_structp png_ptr, png_infop info_ptr,
}
#endif
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
int PNGAPI
-png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr,
+png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
png_unknown_chunkpp unknowns)
{
if (png_ptr != NULL && info_ptr != NULL && unknowns != NULL)
@@ -1049,7 +1121,7 @@ png_get_unknown_chunks(png_const_structp png_ptr, png_const_infop info_ptr,
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
png_byte PNGAPI
-png_get_rgb_to_gray_status (png_const_structp png_ptr)
+png_get_rgb_to_gray_status (png_const_structrp png_ptr)
{
return (png_byte)(png_ptr ? png_ptr->rgb_to_gray_status : 0);
}
@@ -1057,68 +1129,91 @@ png_get_rgb_to_gray_status (png_const_structp png_ptr)
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp PNGAPI
-png_get_user_chunk_ptr(png_const_structp png_ptr)
+png_get_user_chunk_ptr(png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_ptr : NULL);
}
#endif
png_size_t PNGAPI
-png_get_compression_buffer_size(png_const_structp png_ptr)
+png_get_compression_buffer_size(png_const_structrp png_ptr)
{
- return (png_ptr ? png_ptr->zbuf_size : 0);
+ if (png_ptr == NULL)
+ return 0;
+
+#ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+#endif
+ {
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ return png_ptr->IDAT_read_size;
+#else
+ return PNG_IDAT_READ_SIZE;
+#endif
+ }
+
+#ifdef PNG_WRITE_SUPPORTED
+ else
+ return png_ptr->zbuffer_size;
+#endif
}
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* These functions were added to libpng 1.2.6 and were enabled
* by default in libpng-1.4.0 */
png_uint_32 PNGAPI
-png_get_user_width_max (png_const_structp png_ptr)
+png_get_user_width_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_width_max : 0);
}
png_uint_32 PNGAPI
-png_get_user_height_max (png_const_structp png_ptr)
+png_get_user_height_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_height_max : 0);
}
/* This function was added to libpng 1.4.0 */
png_uint_32 PNGAPI
-png_get_chunk_cache_max (png_const_structp png_ptr)
+png_get_chunk_cache_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_cache_max : 0);
}
/* This function was added to libpng 1.4.1 */
png_alloc_size_t PNGAPI
-png_get_chunk_malloc_max (png_const_structp png_ptr)
+png_get_chunk_malloc_max (png_const_structrp png_ptr)
{
return (png_ptr ? png_ptr->user_chunk_malloc_max : 0);
}
-#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+#endif /* SET_USER_LIMITS */
/* These functions were added to libpng 1.4.0 */
#ifdef PNG_IO_STATE_SUPPORTED
png_uint_32 PNGAPI
-png_get_io_state (png_structp png_ptr)
+png_get_io_state (png_const_structrp png_ptr)
{
return png_ptr->io_state;
}
png_uint_32 PNGAPI
-png_get_io_chunk_type (png_const_structp png_ptr)
+png_get_io_chunk_type (png_const_structrp png_ptr)
{
return png_ptr->chunk_name;
}
+#endif /* IO_STATE */
-png_const_bytep PNGAPI
-png_get_io_chunk_name (png_structp png_ptr)
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+# ifdef PNG_GET_PALETTE_MAX_SUPPORTED
+int PNGAPI
+png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
{
- PNG_CSTRING_FROM_CHUNK(png_ptr->io_chunk_string, png_ptr->chunk_name);
- return png_ptr->io_chunk_string;
+ if (png_ptr != NULL && info_ptr != NULL)
+ return png_ptr->num_palette_max;
+
+ return (-1);
}
-#endif /* ?PNG_IO_STATE_SUPPORTED */
+# endif
+#endif
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/pnginfo.h b/src/3rdparty/libpng/pnginfo.h
index a33bfab06d..c8c874dd1e 100644
--- a/src/3rdparty/libpng/pnginfo.h
+++ b/src/3rdparty/libpng/pnginfo.h
@@ -1,12 +1,11 @@
/* pnginfo.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.1 [March 28, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -55,7 +54,7 @@
struct png_info_def
{
- /* the following are necessary for every PNG file */
+ /* The following are necessary for every PNG file */
png_uint_32 width; /* width of image in pixels (from IHDR) */
png_uint_32 height; /* height of image in pixels (from IHDR) */
png_uint_32 valid; /* valid chunk data (see PNG_INFO_ below) */
@@ -70,11 +69,17 @@ struct png_info_def
png_byte filter_type; /* must be PNG_FILTER_TYPE_BASE (from IHDR) */
png_byte interlace_type; /* One of PNG_INTERLACE_NONE, PNG_INTERLACE_ADAM7 */
- /* The following is informational only on read, and not used on writes. */
+ /* The following are set by png_set_IHDR, called from the application on
+ * write, but the are never actually used by the write code.
+ */
png_byte channels; /* number of data channels per pixel (1, 2, 3, 4) */
png_byte pixel_depth; /* number of bits per pixel */
png_byte spare_byte; /* to align the data, and for future use */
+
+#ifdef PNG_READ_SUPPORTED
+ /* This is never set during write */
png_byte signature[8]; /* magic bytes read by libpng from start of file */
+#endif
/* The rest of the data is optional. If you are reading, check the
* valid field to see if the information in these are valid. If you
@@ -82,18 +87,25 @@ struct png_info_def
* and initialize the appropriate fields below.
*/
-#if defined(PNG_gAMA_SUPPORTED)
- /* The gAMA chunk describes the gamma characteristics of the system
- * on which the image was created, normally in the range [1.0, 2.5].
- * Data is valid if (valid & PNG_INFO_gAMA) is non-zero.
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+ /* png_colorspace only contains 'flags' if neither GAMMA or COLORSPACE are
+ * defined. When COLORSPACE is switched on all the colorspace-defining
+ * chunks should be enabled, when GAMMA is switched on all the gamma-defining
+ * chunks should be enabled. If this is not done it becomes possible to read
+ * inconsistent PNG files and assign a probably incorrect interpretation to
+ * the information. (In other words, by carefully choosing which chunks to
+ * recognize the system configuration can select an interpretation for PNG
+ * files containing ambiguous data and this will result in inconsistent
+ * behavior between different libpng builds!)
*/
- png_fixed_point gamma;
+ png_colorspace colorspace;
#endif
-#ifdef PNG_sRGB_SUPPORTED
- /* GR-P, 0.96a */
- /* Data valid if (valid & PNG_INFO_sRGB) non-zero. */
- png_byte srgb_intent; /* sRGB rendering intent [0, 1, 2, or 3] */
+#ifdef PNG_iCCP_SUPPORTED
+ /* iCCP chunk data. */
+ png_charp iccp_name; /* profile name */
+ png_bytep iccp_profile; /* International Color Consortium profile data */
+ png_uint_32 iccp_proflen; /* ICC profile data length */
#endif
#ifdef PNG_TEXT_SUPPORTED
@@ -108,7 +120,7 @@ struct png_info_def
int num_text; /* number of comments read or comments to write */
int max_text; /* current size of text array */
png_textp text; /* array of comments read or comments to write */
-#endif /* PNG_TEXT_SUPPORTED */
+#endif /* TEXT */
#ifdef PNG_tIME_SUPPORTED
/* The tIME chunk holds the last time the displayed image data was
@@ -183,23 +195,6 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
png_uint_16p hist;
#endif
-#ifdef PNG_cHRM_SUPPORTED
- /* The cHRM chunk describes the CIE color characteristics of the monitor
- * on which the PNG was created. This data allows the viewer to do gamut
- * mapping of the input image to ensure that the viewer sees the same
- * colors in the image as the creator. Values are in the range
- * [0.0, 0.8]. Data valid if (valid & PNG_INFO_cHRM) non-zero.
- */
- png_fixed_point x_white;
- png_fixed_point y_white;
- png_fixed_point x_red;
- png_fixed_point y_red;
- png_fixed_point x_green;
- png_fixed_point y_green;
- png_fixed_point x_blue;
- png_fixed_point y_blue;
-#endif
-
#ifdef PNG_pCAL_SUPPORTED
/* The pCAL chunk describes a transformation between the stored pixel
* values and original physical data values used to create the image.
@@ -224,25 +219,20 @@ defined(PNG_READ_BACKGROUND_SUPPORTED)
/* New members added in libpng-1.0.6 */
png_uint_32 free_me; /* flags items libpng is responsible for freeing */
-#if defined(PNG_UNKNOWN_CHUNKS_SUPPORTED) || \
- defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
/* Storage for unknown chunks that the library doesn't recognize. */
png_unknown_chunkp unknown_chunks;
- int unknown_chunks_num;
-#endif
-#ifdef PNG_iCCP_SUPPORTED
- /* iCCP chunk data. */
- png_charp iccp_name; /* profile name */
- png_bytep iccp_profile; /* International Color Consortium profile data */
- png_uint_32 iccp_proflen; /* ICC profile data length */
- png_byte iccp_compression; /* Always zero */
+ /* The type of this field is limited by the type of
+ * png_struct::user_chunk_cache_max, else overflow can occur.
+ */
+ int unknown_chunks_num;
#endif
#ifdef PNG_sPLT_SUPPORTED
/* Data on sPLT chunks (there may be more than one). */
png_sPLT_tp splt_palettes;
- png_uint_32 splt_palettes_num;
+ int splt_palettes_num; /* Match type returned by png_get API */
#endif
#ifdef PNG_sCAL_SUPPORTED
diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h
index aa82b574a8..f0fdcf8068 100644
--- a/src/3rdparty/libpng/pnglibconf.h
+++ b/src/3rdparty/libpng/pnglibconf.h
@@ -1,48 +1,31 @@
-
-/* libpng STANDARD API DEFINITION */
+/* libpng 1.6.17 STANDARD API DEFINITION */
/* pnglibconf.h - library build configuration */
-/* Libpng 1.5.10 - March 29, 2012 */
+/* Libpng version 1.6.17 - March 26, 2015 */
-/* Copyright (c) 1998-2012 Glenn Randers-Pehrson */
+/* Copyright (c) 1998-2014 Glenn Randers-Pehrson */
/* This code is released under the libpng license. */
/* For conditions of distribution and use, see the disclaimer */
/* and license in png.h */
/* pnglibconf.h */
+/* Machine generated file: DO NOT EDIT */
/* Derived from: scripts/pnglibconf.dfa */
-/* If you edit this file by hand you must obey the rules expressed in */
-/* pnglibconf.dfa with respect to the dependencies between the following */
-/* symbols. It is much better to generate a new file using */
-/* scripts/libpngconf.mak */
-
#ifndef PNGLCONF_H
#define PNGLCONF_H
-/* settings */
-#define PNG_API_RULE 0
-#define PNG_CALLOC_SUPPORTED
-#define PNG_COST_SHIFT 3
-#define PNG_DEFAULT_READ_MACROS 1
-#define PNG_GAMMA_THRESHOLD_FIXED 5000
-#define PNG_MAX_GAMMA_8 11
-#define PNG_QUANTIZE_BLUE_BITS 5
-#define PNG_QUANTIZE_GREEN_BITS 5
-#define PNG_QUANTIZE_RED_BITS 5
-#define PNG_sCAL_PRECISION 5
-#define PNG_WEIGHT_SHIFT 8
-#define PNG_ZBUF_SIZE 8192
-/* end of settings */
/* options */
#define PNG_16BIT_SUPPORTED
-#define PNG_ALIGN_MEMORY_SUPPORTED
+#define PNG_ALIGNED_MEMORY_SUPPORTED
+/*#undef PNG_ARM_NEON_API_SUPPORTED*/
+/*#undef PNG_ARM_NEON_CHECK_SUPPORTED*/
#define PNG_BENIGN_ERRORS_SUPPORTED
-#define PNG_bKGD_SUPPORTED
+#define PNG_BENIGN_READ_ERRORS_SUPPORTED
+/*#undef PNG_BENIGN_WRITE_ERRORS_SUPPORTED*/
#define PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-#define PNG_CHECK_cHRM_SUPPORTED
#define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_cHRM_SUPPORTED
+#define PNG_COLORSPACE_SUPPORTED
#define PNG_CONSOLE_IO_SUPPORTED
#ifndef _WIN32_WCE
#define PNG_CONVERT_tIME_SUPPORTED
@@ -53,18 +36,15 @@
#define PNG_FIXED_POINT_SUPPORTED
#define PNG_FLOATING_ARITHMETIC_SUPPORTED
#define PNG_FLOATING_POINT_SUPPORTED
-#define PNG_gAMA_SUPPORTED
+#define PNG_FORMAT_AFIRST_SUPPORTED
+#define PNG_FORMAT_BGR_SUPPORTED
+#define PNG_GAMMA_SUPPORTED
+#define PNG_GET_PALETTE_MAX_SUPPORTED
#define PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-#define PNG_hIST_SUPPORTED
-#define PNG_iCCP_SUPPORTED
#define PNG_INCH_CONVERSIONS_SUPPORTED
#define PNG_INFO_IMAGE_SUPPORTED
#define PNG_IO_STATE_SUPPORTED
-#define PNG_iTXt_SUPPORTED
#define PNG_MNG_FEATURES_SUPPORTED
-#define PNG_oFFs_SUPPORTED
-#define PNG_pCAL_SUPPORTED
-#define PNG_pHYs_SUPPORTED
#define PNG_POINTER_INDEXING_SUPPORTED
#define PNG_PROGRESSIVE_READ_SUPPORTED
#define PNG_READ_16BIT_SUPPORTED
@@ -72,68 +52,74 @@
#define PNG_READ_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_READ_BACKGROUND_SUPPORTED
#define PNG_READ_BGR_SUPPORTED
-#define PNG_READ_bKGD_SUPPORTED
#define PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_READ_cHRM_SUPPORTED
#define PNG_READ_COMPOSITE_NODIV_SUPPORTED
#define PNG_READ_COMPRESSED_TEXT_SUPPORTED
#define PNG_READ_EXPAND_16_SUPPORTED
#define PNG_READ_EXPAND_SUPPORTED
#define PNG_READ_FILLER_SUPPORTED
-#define PNG_READ_gAMA_SUPPORTED
#define PNG_READ_GAMMA_SUPPORTED
+#define PNG_READ_GET_PALETTE_MAX_SUPPORTED
#define PNG_READ_GRAY_TO_RGB_SUPPORTED
-#define PNG_READ_hIST_SUPPORTED
-#define PNG_READ_iCCP_SUPPORTED
#define PNG_READ_INTERLACING_SUPPORTED
#define PNG_READ_INT_FUNCTIONS_SUPPORTED
#define PNG_READ_INVERT_ALPHA_SUPPORTED
#define PNG_READ_INVERT_SUPPORTED
-#define PNG_READ_iTXt_SUPPORTED
-#define PNG_READ_oFFs_SUPPORTED
#define PNG_READ_OPT_PLTE_SUPPORTED
-#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_PACKSWAP_SUPPORTED
-#define PNG_READ_pCAL_SUPPORTED
-#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_PACK_SUPPORTED
#define PNG_READ_QUANTIZE_SUPPORTED
#define PNG_READ_RGB_TO_GRAY_SUPPORTED
-#define PNG_READ_sBIT_SUPPORTED
#define PNG_READ_SCALE_16_TO_8_SUPPORTED
-#define PNG_READ_sCAL_SUPPORTED
#define PNG_READ_SHIFT_SUPPORTED
-#define PNG_READ_sPLT_SUPPORTED
-#define PNG_READ_sRGB_SUPPORTED
#define PNG_READ_STRIP_16_TO_8_SUPPORTED
#define PNG_READ_STRIP_ALPHA_SUPPORTED
#define PNG_READ_SUPPORTED
#define PNG_READ_SWAP_ALPHA_SUPPORTED
#define PNG_READ_SWAP_SUPPORTED
-#define PNG_READ_tEXt_SUPPORTED
#define PNG_READ_TEXT_SUPPORTED
-#define PNG_READ_tIME_SUPPORTED
#define PNG_READ_TRANSFORMS_SUPPORTED
-#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_READ_USER_CHUNKS_SUPPORTED
#define PNG_READ_USER_TRANSFORM_SUPPORTED
+#define PNG_READ_bKGD_SUPPORTED
+#define PNG_READ_cHRM_SUPPORTED
+#define PNG_READ_gAMA_SUPPORTED
+#define PNG_READ_hIST_SUPPORTED
+#define PNG_READ_iCCP_SUPPORTED
+#define PNG_READ_iTXt_SUPPORTED
+#define PNG_READ_oFFs_SUPPORTED
+#define PNG_READ_pCAL_SUPPORTED
+#define PNG_READ_pHYs_SUPPORTED
+#define PNG_READ_sBIT_SUPPORTED
+#define PNG_READ_sCAL_SUPPORTED
+#define PNG_READ_sPLT_SUPPORTED
+#define PNG_READ_sRGB_SUPPORTED
+#define PNG_READ_tEXt_SUPPORTED
+#define PNG_READ_tIME_SUPPORTED
+#define PNG_READ_tRNS_SUPPORTED
#define PNG_READ_zTXt_SUPPORTED
#define PNG_SAVE_INT_32_SUPPORTED
-#define PNG_sBIT_SUPPORTED
-#define PNG_sCAL_SUPPORTED
+#define PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SEQUENTIAL_READ_SUPPORTED
+#define PNG_SETJMP_SUPPORTED
#define PNG_SET_CHUNK_CACHE_LIMIT_SUPPORTED
#define PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
-#define PNG_SETJMP_SUPPORTED
+#define PNG_SET_OPTION_SUPPORTED
+#define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_SET_USER_LIMITS_SUPPORTED
-#define PNG_sPLT_SUPPORTED
-#define PNG_sRGB_SUPPORTED
+#ifndef _WIN32_WCE
+#define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+#define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_READ_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+#define PNG_SIMPLIFIED_WRITE_SUPPORTED
+#endif
#define PNG_STDIO_SUPPORTED
-#define PNG_tEXt_SUPPORTED
+#define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_TEXT_SUPPORTED
#define PNG_TIME_RFC1123_SUPPORTED
-#define PNG_tIME_SUPPORTED
-#define PNG_tRNS_SUPPORTED
#define PNG_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_USER_CHUNKS_SUPPORTED
#define PNG_USER_LIMITS_SUPPORTED
@@ -144,46 +130,89 @@
#define PNG_WRITE_16BIT_SUPPORTED
#define PNG_WRITE_ANCILLARY_CHUNKS_SUPPORTED
#define PNG_WRITE_BGR_SUPPORTED
-#define PNG_WRITE_bKGD_SUPPORTED
#define PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
-#define PNG_WRITE_cHRM_SUPPORTED
#define PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+#define PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
#define PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
#define PNG_WRITE_FILLER_SUPPORTED
#define PNG_WRITE_FILTER_SUPPORTED
#define PNG_WRITE_FLUSH_SUPPORTED
-#define PNG_WRITE_gAMA_SUPPORTED
-#define PNG_WRITE_hIST_SUPPORTED
-#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_GET_PALETTE_MAX_SUPPORTED
#define PNG_WRITE_INTERLACING_SUPPORTED
#define PNG_WRITE_INT_FUNCTIONS_SUPPORTED
#define PNG_WRITE_INVERT_ALPHA_SUPPORTED
#define PNG_WRITE_INVERT_SUPPORTED
-#define PNG_WRITE_iTXt_SUPPORTED
-#define PNG_WRITE_oFFs_SUPPORTED
#define PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
-#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_PACKSWAP_SUPPORTED
-#define PNG_WRITE_pCAL_SUPPORTED
-#define PNG_WRITE_pHYs_SUPPORTED
-#define PNG_WRITE_sBIT_SUPPORTED
-#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_PACK_SUPPORTED
#define PNG_WRITE_SHIFT_SUPPORTED
-#define PNG_WRITE_sPLT_SUPPORTED
-#define PNG_WRITE_sRGB_SUPPORTED
#define PNG_WRITE_SUPPORTED
#define PNG_WRITE_SWAP_ALPHA_SUPPORTED
#define PNG_WRITE_SWAP_SUPPORTED
-#define PNG_WRITE_tEXt_SUPPORTED
#define PNG_WRITE_TEXT_SUPPORTED
-#define PNG_WRITE_tIME_SUPPORTED
#define PNG_WRITE_TRANSFORMS_SUPPORTED
-#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
#define PNG_WRITE_USER_TRANSFORM_SUPPORTED
#define PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+#define PNG_WRITE_bKGD_SUPPORTED
+#define PNG_WRITE_cHRM_SUPPORTED
+#define PNG_WRITE_gAMA_SUPPORTED
+#define PNG_WRITE_hIST_SUPPORTED
+#define PNG_WRITE_iCCP_SUPPORTED
+#define PNG_WRITE_iTXt_SUPPORTED
+#define PNG_WRITE_oFFs_SUPPORTED
+#define PNG_WRITE_pCAL_SUPPORTED
+#define PNG_WRITE_pHYs_SUPPORTED
+#define PNG_WRITE_sBIT_SUPPORTED
+#define PNG_WRITE_sCAL_SUPPORTED
+#define PNG_WRITE_sPLT_SUPPORTED
+#define PNG_WRITE_sRGB_SUPPORTED
+#define PNG_WRITE_tEXt_SUPPORTED
+#define PNG_WRITE_tIME_SUPPORTED
+#define PNG_WRITE_tRNS_SUPPORTED
#define PNG_WRITE_zTXt_SUPPORTED
+#define PNG_bKGD_SUPPORTED
+#define PNG_cHRM_SUPPORTED
+#define PNG_gAMA_SUPPORTED
+#define PNG_hIST_SUPPORTED
+#define PNG_iCCP_SUPPORTED
+#define PNG_iTXt_SUPPORTED
+#define PNG_oFFs_SUPPORTED
+#define PNG_pCAL_SUPPORTED
+#define PNG_pHYs_SUPPORTED
+#define PNG_sBIT_SUPPORTED
+#define PNG_sCAL_SUPPORTED
+#define PNG_sPLT_SUPPORTED
+#define PNG_sRGB_SUPPORTED
+#define PNG_tEXt_SUPPORTED
+#define PNG_tIME_SUPPORTED
+#define PNG_tRNS_SUPPORTED
#define PNG_zTXt_SUPPORTED
/* end of options */
-#define PNG_SAFE_LIMITS_SUPPORTED
+/* settings */
+#define PNG_API_RULE 0
+#define PNG_COST_SHIFT 3
+#define PNG_DEFAULT_READ_MACROS 1
+#define PNG_GAMMA_THRESHOLD_FIXED 5000
+#define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE
+#define PNG_INFLATE_BUF_SIZE 1024
+#define PNG_MAX_GAMMA_8 11
+#define PNG_QUANTIZE_BLUE_BITS 5
+#define PNG_QUANTIZE_GREEN_BITS 5
+#define PNG_QUANTIZE_RED_BITS 5
+#define PNG_TEXT_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_TEXT_Z_DEFAULT_STRATEGY 0
+#define PNG_USER_CHUNK_CACHE_MAX 1000
+#define PNG_USER_CHUNK_MALLOC_MAX 8000000
+#define PNG_USER_HEIGHT_MAX 1000000
+#define PNG_USER_WIDTH_MAX 1000000
+#define PNG_WEIGHT_SHIFT 8
+#define PNG_ZBUF_SIZE 8192
+#define PNG_ZLIB_VERNUM 0 /* unknown */
+#define PNG_Z_DEFAULT_COMPRESSION (-1)
+#define PNG_Z_DEFAULT_NOFILTER_STRATEGY 0
+#define PNG_Z_DEFAULT_STRATEGY 1
+#define PNG_sCAL_PRECISION 5
+#define PNG_sRGB_PROFILE_CHECKS 2
+/* end of settings */
#endif /* PNGLCONF_H */
diff --git a/src/3rdparty/libpng/pngmem.c b/src/3rdparty/libpng/pngmem.c
index bf5ff037da..8b157e54d2 100644
--- a/src/3rdparty/libpng/pngmem.c
+++ b/src/3rdparty/libpng/pngmem.c
@@ -1,8 +1,8 @@
/* pngmem.c - stub functions for memory allocation
*
- * Last changed in libpng 1.5.7 [December 15, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -20,627 +20,241 @@
#include "pngpriv.h"
#if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
-
-/* Borland DOS special memory handler */
-#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
-/* If you change this, be sure to change the one in png.h also */
-
-/* Allocate memory for a png_struct. The malloc and memset can be replaced
- by a single call to calloc() if this is thought to improve performance. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct,(int type),PNG_ALLOCATED)
-{
-# ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_struct_2(type, NULL, NULL));
-}
-
-/* Alternate version of png_create_struct, for use with user-defined malloc. */
-PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
- PNG_ALLOCATED)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
- png_size_t size;
- png_voidp struct_ptr;
-
- if (type == PNG_STRUCT_INFO)
- size = png_sizeof(png_info);
-
- else if (type == PNG_STRUCT_PNG)
- size = png_sizeof(png_struct);
-
- else
- return (png_get_copyright(NULL));
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (malloc_fn != NULL)
- {
- png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
- dummy_struct.mem_ptr=mem_ptr;
- struct_ptr = (*(malloc_fn))(&dummy_struct, (png_alloc_size_t)size);
- }
-
- else
-# endif /* PNG_USER_MEM_SUPPORTED */
- struct_ptr = (png_voidp)farmalloc(size);
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
-}
-
-/* Free memory allocated by a png_create_struct() call */
+/* Free a png_struct */
void /* PRIVATE */
-png_destroy_struct(png_voidp struct_ptr)
+png_destroy_png_struct(png_structrp png_ptr)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2(struct_ptr, NULL, NULL);
-}
-
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
- png_voidp mem_ptr)
-{
-# endif
- if (struct_ptr != NULL)
+ if (png_ptr != NULL)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- if (free_fn != NULL)
- {
- png_struct dummy_struct;
- memset(&dummy_struct, 0, sizeof dummy_struct);
- dummy_struct.mem_ptr=mem_ptr;
- (*(free_fn))(&dummy_struct, struct_ptr);
- return;
- }
-
-# endif /* PNG_USER_MEM_SUPPORTED */
- farfree (struct_ptr);
+ /* png_free might call png_error and may certainly call
+ * png_get_mem_ptr, so fake a temporary png_struct to support this.
+ */
+ png_struct dummy_struct = *png_ptr;
+ memset(png_ptr, 0, (sizeof *png_ptr));
+ png_free(&dummy_struct, png_ptr);
+
+# ifdef PNG_SETJMP_SUPPORTED
+ /* We may have a jmp_buf left to deallocate. */
+ png_free_jmpbuf(&dummy_struct);
+# endif
}
}
/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
- * it not to. See zconf.h and png.h for more information. zlib does
+ * 64K. However, zlib may allocate more than 64K if you don't tell
+ * it not to. See zconf.h and png.h for more information. zlib does
* need to allocate exactly 64K, so whatever you call here must
* have the ability to do that.
- *
- * Borland seems to have a problem in DOS mode for exactly 64K.
- * It gives you a segment with an offset of 8 (perhaps to store its
- * memory stuff). zlib doesn't like this at all, so we have to
- * detect and deal with it. This code should not be needed in
- * Windows or OS/2 modes, and only in 16 bit mode. This code has
- * been updated by Alexander Lehmann for version 0.89 to waste less
- * memory.
- *
- * Note that we can't use png_size_t for the "size" declaration,
- * since on some systems a png_size_t is a 16-bit quantity, and as a
- * result, we would be truncating potentially larger memory requests
- * (which should cause a fatal error) and introducing major problems.
*/
PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_calloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
- ret = (png_malloc(png_ptr, size));
+ ret = png_malloc(png_ptr, size);
if (ret != NULL)
- png_memset(ret,0,(png_size_t)size);
-
- return (ret);
-}
-
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
- png_voidp ret;
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr->malloc_fn != NULL)
- ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, size));
-
- else
- ret = (png_malloc_default(png_ptr, size));
-
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of memory");
+ memset(ret, 0, size);
- return (ret);
+ return ret;
}
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+/* png_malloc_base, an internal function added at libpng 1.6.0, does the work of
+ * allocating memory, taking into account limits and PNG_USER_MEM_SUPPORTED.
+ * Checking and error handling must happen outside this routine; it returns NULL
+ * if the allocation cannot be done (for any reason.)
+ */
+PNG_FUNCTION(png_voidp /* PRIVATE */,
+png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED)
{
- png_voidp ret;
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_MAX_MALLOC_64K
- if (size > (png_uint_32)65536L)
- {
- png_warning(png_ptr, "Cannot Allocate > 64K");
- ret = NULL;
- }
-
- else
-# endif
-
- if (size != (size_t)size)
- ret = NULL;
-
- else if (size == (png_uint_32)65536L)
+ /* Moved to png_malloc_base from png_malloc_default in 1.6.0; the DOS
+ * allocators have also been removed in 1.6.0, so any 16-bit system now has
+ * to implement a user memory handler. This checks to be sure it isn't
+ * called with big numbers.
+ */
+#ifndef PNG_USER_MEM_SUPPORTED
+ PNG_UNUSED(png_ptr)
+#endif
+
+ if (size > 0 && size <= PNG_SIZE_MAX
+# ifdef PNG_MAX_MALLOC_64K
+ && size <= 65536U
+# endif
+ )
{
- if (png_ptr->offset_table == NULL)
- {
- /* Try to see if we need to do any of this fancy stuff */
- ret = farmalloc(size);
- if (ret == NULL || ((png_size_t)ret & 0xffff))
- {
- int num_blocks;
- png_uint_32 total_size;
- png_bytep table;
- int i, mem_level, window_bits;
- png_byte huge * hptr;
- int window_bits
-
- if (ret != NULL)
- {
- farfree(ret);
- ret = NULL;
- }
-
- window_bits =
- png_ptr->zlib_window_bits >= png_ptr->zlib_text_window_bits ?
- png_ptr->zlib_window_bits : png_ptr->zlib_text_window_bits;
-
- if (window_bits > 14)
- num_blocks = (int)(1 << (window_bits - 14));
-
- else
- num_blocks = 1;
-
- mem_level =
- png_ptr->zlib_mem_level >= png_ptr->zlib_text_mem_level ?
- png_ptr->zlib_mem_level : png_ptr->zlib_text_mem_level;
-
- if (mem_level >= 7)
- num_blocks += (int)(1 << (mem_level - 7));
-
- else
- num_blocks++;
-
- total_size = ((png_uint_32)65536L) * (png_uint_32)num_blocks+16;
-
- table = farmalloc(total_size);
-
- if (table == NULL)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out Of Memory"); /* Note "O", "M" */
-
- else
- png_warning(png_ptr, "Out Of Memory");
-# endif
- return (NULL);
- }
-
- if ((png_size_t)table & 0xfff0)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr,
- "Farmalloc didn't return normalized pointer");
-
- else
- png_warning(png_ptr,
- "Farmalloc didn't return normalized pointer");
-# endif
- return (NULL);
- }
-
- png_ptr->offset_table = table;
- png_ptr->offset_table_ptr = farmalloc(num_blocks *
- png_sizeof(png_bytep));
-
- if (png_ptr->offset_table_ptr == NULL)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out Of memory"); /* Note "O", "m" */
-
- else
- png_warning(png_ptr, "Out Of memory");
-# endif
- return (NULL);
- }
-
- hptr = (png_byte huge *)table;
- if ((png_size_t)hptr & 0xf)
- {
- hptr = (png_byte huge *)((long)(hptr) & 0xfffffff0L);
- hptr = hptr + 16L; /* "hptr += 16L" fails on Turbo C++ 3.0 */
- }
-
- for (i = 0; i < num_blocks; i++)
- {
- png_ptr->offset_table_ptr[i] = (png_bytep)hptr;
- hptr = hptr + (png_uint_32)65536L; /* "+=" fails on TC++3.0 */
- }
-
- png_ptr->offset_table_number = num_blocks;
- png_ptr->offset_table_count = 0;
- png_ptr->offset_table_count_free = 0;
- }
- }
-
- if (png_ptr->offset_table_count >= png_ptr->offset_table_number)
- {
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory"); /* Note "O" and "M" */
-
- else
- png_warning(png_ptr, "Out of Memory");
-# endif
- return (NULL);
- }
-
- ret = png_ptr->offset_table_ptr[png_ptr->offset_table_count++];
- }
-
- else
- ret = farmalloc(size);
-
-# ifndef PNG_USER_MEM_SUPPORTED
- if (ret == NULL)
- {
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of memory"); /* Note "o" and "m" */
+#ifdef PNG_USER_MEM_SUPPORTED
+ if (png_ptr != NULL && png_ptr->malloc_fn != NULL)
+ return png_ptr->malloc_fn(png_constcast(png_structrp,png_ptr), size);
else
- png_warning(png_ptr, "Out of memory"); /* Note "o" and "m" */
+#endif
+ return malloc((size_t)size); /* checked for truncation above */
}
-# endif
- return (ret);
+ else
+ return NULL;
}
-/* Free a pointer allocated by png_malloc(). In the default
- * configuration, png_ptr is not used, but is passed in case it
- * is needed. If ptr is NULL, return without taking any action.
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
+/* This is really here only to work round a spurious warning in GCC 4.6 and 4.7
+ * that arises because of the checks in png_realloc_array that are repeated in
+ * png_malloc_array.
*/
-void PNGAPI
-png_free(png_structp png_ptr, png_voidp ptr)
+static png_voidp
+png_malloc_array_checked(png_const_structrp png_ptr, int nelements,
+ size_t element_size)
{
- if (png_ptr == NULL || ptr == NULL)
- return;
+ png_alloc_size_t req = nelements; /* known to be > 0 */
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr->free_fn != NULL)
- {
- (*(png_ptr->free_fn))(png_ptr, ptr);
- return;
- }
+ if (req <= PNG_SIZE_MAX/element_size)
+ return png_malloc_base(png_ptr, req * element_size);
- else
- png_free_default(png_ptr, ptr);
+ /* The failure case when the request is too large */
+ return NULL;
}
-void PNGAPI
-png_free_default(png_structp png_ptr, png_voidp ptr)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || ptr == NULL)
- return;
-
- if (png_ptr->offset_table != NULL)
- {
- int i;
-
- for (i = 0; i < png_ptr->offset_table_count; i++)
- {
- if (ptr == png_ptr->offset_table_ptr[i])
- {
- ptr = NULL;
- png_ptr->offset_table_count_free++;
- break;
- }
- }
- if (png_ptr->offset_table_count_free == png_ptr->offset_table_count)
- {
- farfree(png_ptr->offset_table);
- farfree(png_ptr->offset_table_ptr);
- png_ptr->offset_table = NULL;
- png_ptr->offset_table_ptr = NULL;
- }
- }
-
- if (ptr != NULL)
- farfree(ptr);
-}
-
-#else /* Not the Borland DOS special memory handler */
-
-/* Allocate memory for a png_struct or a png_info. The malloc and
- memset can be replaced by a single call to calloc() if this is thought
- to improve performance noticably. */
PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct,(int type),PNG_ALLOCATED)
+png_malloc_array,(png_const_structrp png_ptr, int nelements,
+ size_t element_size),PNG_ALLOCATED)
{
-# ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_struct_2(type, NULL, NULL));
+ if (nelements <= 0 || element_size == 0)
+ png_error(png_ptr, "internal error: array alloc");
+
+ return png_malloc_array_checked(png_ptr, nelements, element_size);
}
-/* Allocate memory for a png_struct or a png_info. The malloc and
- memset can be replaced by a single call to calloc() if this is thought
- to improve performance noticably. */
PNG_FUNCTION(png_voidp /* PRIVATE */,
-png_create_struct_2,(int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr),
- PNG_ALLOCATED)
+png_realloc_array,(png_const_structrp png_ptr, png_const_voidp old_array,
+ int old_elements, int add_elements, size_t element_size),PNG_ALLOCATED)
{
-# endif /* PNG_USER_MEM_SUPPORTED */
- png_size_t size;
- png_voidp struct_ptr;
-
- if (type == PNG_STRUCT_INFO)
- size = png_sizeof(png_info);
-
- else if (type == PNG_STRUCT_PNG)
- size = png_sizeof(png_struct);
-
- else
- return (NULL);
-
-# ifdef PNG_USER_MEM_SUPPORTED
- if (malloc_fn != NULL)
+ /* These are internal errors: */
+ if (add_elements <= 0 || element_size == 0 || old_elements < 0 ||
+ (old_array == NULL && old_elements > 0))
+ png_error(png_ptr, "internal error: array realloc");
+
+ /* Check for overflow on the elements count (so the caller does not have to
+ * check.)
+ */
+ if (add_elements <= INT_MAX - old_elements)
{
- png_struct dummy_struct;
- png_structp png_ptr = &dummy_struct;
- png_ptr->mem_ptr=mem_ptr;
- struct_ptr = (*(malloc_fn))(png_ptr, size);
-
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
- }
-# endif /* PNG_USER_MEM_SUPPORTED */
-
-# if defined(__TURBOC__) && !defined(__FLAT__)
- struct_ptr = (png_voidp)farmalloc(size);
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- struct_ptr = (png_voidp)halloc(size, 1);
-# else
- struct_ptr = (png_voidp)malloc(size);
-# endif
-# endif
-
- if (struct_ptr != NULL)
- png_memset(struct_ptr, 0, size);
-
- return (struct_ptr);
-}
-
+ png_voidp new_array = png_malloc_array_checked(png_ptr,
+ old_elements+add_elements, element_size);
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct(png_voidp struct_ptr)
-{
-# ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2(struct_ptr, NULL, NULL);
-}
-
-/* Free memory allocated by a png_create_struct() call */
-void /* PRIVATE */
-png_destroy_struct_2(png_voidp struct_ptr, png_free_ptr free_fn,
- png_voidp mem_ptr)
-{
-# endif /* PNG_USER_MEM_SUPPORTED */
- if (struct_ptr != NULL)
- {
-# ifdef PNG_USER_MEM_SUPPORTED
- if (free_fn != NULL)
+ if (new_array != NULL)
{
- png_struct dummy_struct;
- png_structp png_ptr = &dummy_struct;
- png_ptr->mem_ptr=mem_ptr;
- (*(free_fn))(png_ptr, struct_ptr);
- return;
- }
-# endif /* PNG_USER_MEM_SUPPORTED */
-# if defined(__TURBOC__) && !defined(__FLAT__)
- farfree(struct_ptr);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- hfree(struct_ptr);
+ /* Because png_malloc_array worked the size calculations below cannot
+ * overflow.
+ */
+ if (old_elements > 0)
+ memcpy(new_array, old_array, element_size*(unsigned)old_elements);
-# else
- free(struct_ptr);
+ memset((char*)new_array + element_size*(unsigned)old_elements, 0,
+ element_size*(unsigned)add_elements);
-# endif
-# endif
+ return new_array;
+ }
}
+
+ return NULL; /* error */
}
+#endif /* TEXT || sPLT || STORE_UNKNOWN_CHUNKS */
-/* Allocate memory. For reasonable files, size should never exceed
- * 64K. However, zlib may allocate more then 64K if you don't tell
- * it not to. See zconf.h and png.h for more information. zlib does
- * need to allocate exactly 64K, so whatever you call here must
- * have the ability to do that.
+/* Various functions that have different error handling are derived from this.
+ * png_malloc always exists, but if PNG_USER_MEM_SUPPORTED is defined a separate
+ * function png_malloc_default is also provided.
*/
-
PNG_FUNCTION(png_voidp,PNGAPI
-png_calloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc,(png_const_structrp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
{
png_voidp ret;
- ret = (png_malloc(png_ptr, size));
+ if (png_ptr == NULL)
+ return NULL;
- if (ret != NULL)
- png_memset(ret,0,(png_size_t)size);
+ ret = png_malloc_base(png_ptr, size);
- return (ret);
+ if (ret == NULL)
+ png_error(png_ptr, "Out of memory"); /* 'm' means png_malloc */
+
+ return ret;
}
+#ifdef PNG_USER_MEM_SUPPORTED
PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc_default,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED PNG_DEPRECATED)
{
png_voidp ret;
-# ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
- if (png_ptr->malloc_fn != NULL)
- ret = ((png_voidp)(*(png_ptr->malloc_fn))(png_ptr, (png_size_t)size));
+ if (png_ptr == NULL)
+ return NULL;
- else
- ret = (png_malloc_default(png_ptr, size));
+ /* Passing 'NULL' here bypasses the application provided memory handler. */
+ ret = png_malloc_base(NULL/*use malloc*/, size);
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory");
+ if (ret == NULL)
+ png_error(png_ptr, "Out of Memory"); /* 'M' means png_malloc_default */
- return (ret);
+ return ret;
}
+#endif /* USER_MEM */
+/* This function was added at libpng version 1.2.3. The png_malloc_warn()
+ * function will issue a png_warning and return NULL instead of issuing a
+ * png_error, if it fails to allocate the requested memory.
+ */
PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_default,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
+png_malloc_warn,(png_const_structrp png_ptr, png_alloc_size_t size),
+ PNG_ALLOCATED)
{
- png_voidp ret;
-# endif /* PNG_USER_MEM_SUPPORTED */
-
- if (png_ptr == NULL || size == 0)
- return (NULL);
-
-# ifdef PNG_MAX_MALLOC_64K
- if (size > (png_uint_32)65536L)
+ if (png_ptr != NULL)
{
-# ifndef PNG_USER_MEM_SUPPORTED
- if ((png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Cannot Allocate > 64K");
-
- else
-# endif
- return NULL;
- }
-# endif
-
- /* Check for overflow */
-# if defined(__TURBOC__) && !defined(__FLAT__)
-
- if (size != (unsigned long)size)
- ret = NULL;
-
- else
- ret = farmalloc(size);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- if (size != (unsigned long)size)
- ret = NULL;
-
- else
- ret = halloc(size, 1);
+ png_voidp ret = png_malloc_base(png_ptr, size);
-# else
- if (size != (size_t)size)
- ret = NULL;
+ if (ret != NULL)
+ return ret;
- else
- ret = malloc((size_t)size);
-# endif
-# endif
-
-# ifndef PNG_USER_MEM_SUPPORTED
- if (ret == NULL && (png_ptr->flags&PNG_FLAG_MALLOC_NULL_MEM_OK) == 0)
- png_error(png_ptr, "Out of Memory");
-# endif
+ png_warning(png_ptr, "Out of memory");
+ }
- return (ret);
+ return NULL;
}
/* Free a pointer allocated by png_malloc(). If ptr is NULL, return
* without taking any action.
*/
void PNGAPI
-png_free(png_structp png_ptr, png_voidp ptr)
+png_free(png_const_structrp png_ptr, png_voidp ptr)
{
if (png_ptr == NULL || ptr == NULL)
return;
-# ifdef PNG_USER_MEM_SUPPORTED
+#ifdef PNG_USER_MEM_SUPPORTED
if (png_ptr->free_fn != NULL)
- {
- (*(png_ptr->free_fn))(png_ptr, ptr);
- return;
- }
+ png_ptr->free_fn(png_constcast(png_structrp,png_ptr), ptr);
else
png_free_default(png_ptr, ptr);
}
-void PNGAPI
-png_free_default(png_structp png_ptr, png_voidp ptr)
+PNG_FUNCTION(void,PNGAPI
+png_free_default,(png_const_structrp png_ptr, png_voidp ptr),PNG_DEPRECATED)
{
if (png_ptr == NULL || ptr == NULL)
return;
+#endif /* USER_MEM */
-# endif /* PNG_USER_MEM_SUPPORTED */
-
-# if defined(__TURBOC__) && !defined(__FLAT__)
- farfree(ptr);
-
-# else
-# if defined(_MSC_VER) && defined(MAXSEG_64K)
- hfree(ptr);
-
-# else
free(ptr);
-
-# endif
-# endif
-}
-#endif /* Not Borland DOS special memory handler */
-
-/* This function was added at libpng version 1.2.3. The png_malloc_warn()
- * function will set up png_malloc() to issue a png_warning and return NULL
- * instead of issuing a png_error, if it fails to allocate the requested
- * memory.
- */
-PNG_FUNCTION(png_voidp,PNGAPI
-png_malloc_warn,(png_structp png_ptr, png_alloc_size_t size),PNG_ALLOCATED)
-{
- png_voidp ptr;
- png_uint_32 save_flags;
- if (png_ptr == NULL)
- return (NULL);
-
- save_flags = png_ptr->flags;
- png_ptr->flags|=PNG_FLAG_MALLOC_NULL_MEM_OK;
- ptr = (png_voidp)png_malloc((png_structp)png_ptr, size);
- png_ptr->flags=save_flags;
- return(ptr);
}
-
#ifdef PNG_USER_MEM_SUPPORTED
/* This function is called when the application wants to use another method
* of allocating and freeing memory.
*/
void PNGAPI
-png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
+png_set_mem_fn(png_structrp png_ptr, png_voidp mem_ptr, png_malloc_ptr
malloc_fn, png_free_ptr free_fn)
{
if (png_ptr != NULL)
@@ -656,12 +270,12 @@ png_set_mem_fn(png_structp png_ptr, png_voidp mem_ptr, png_malloc_ptr
* pointer before png_write_destroy and png_read_destroy are called.
*/
png_voidp PNGAPI
-png_get_mem_ptr(png_const_structp png_ptr)
+png_get_mem_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
- return (NULL);
+ return NULL;
- return ((png_voidp)png_ptr->mem_ptr);
+ return png_ptr->mem_ptr;
}
-#endif /* PNG_USER_MEM_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* USER_MEM */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/pngpread.c b/src/3rdparty/libpng/pngpread.c
index 8a5aa29ec8..823dcad8c0 100644
--- a/src/3rdparty/libpng/pngpread.c
+++ b/src/3rdparty/libpng/pngpread.c
@@ -1,8 +1,8 @@
/* pngpread.c - read a png file in push mode
*
- * Last changed in libpng 1.5.9 [February 18, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -26,8 +26,15 @@
#define PNG_READ_iTXt_MODE 7
#define PNG_ERROR_MODE 8
+#define PNG_PUSH_SAVE_BUFFER_IF_FULL \
+if (png_ptr->push_length + 4 > png_ptr->buffer_size) \
+ { png_push_save_buffer(png_ptr); return; }
+#define PNG_PUSH_SAVE_BUFFER_IF_LT(N) \
+if (png_ptr->buffer_size < N) \
+ { png_push_save_buffer(png_ptr); return; }
+
void PNGAPI
-png_process_data(png_structp png_ptr, png_infop info_ptr,
+png_process_data(png_structrp png_ptr, png_inforp info_ptr,
png_bytep buffer, png_size_t buffer_size)
{
if (png_ptr == NULL || info_ptr == NULL)
@@ -42,14 +49,14 @@ png_process_data(png_structp png_ptr, png_infop info_ptr,
}
png_size_t PNGAPI
-png_process_data_pause(png_structp png_ptr, int save)
+png_process_data_pause(png_structrp png_ptr, int save)
{
if (png_ptr != NULL)
{
- /* It's easiest for the caller if we do the save, then the caller doesn't
+ /* It's easiest for the caller if we do the save; then the caller doesn't
* have to supply the same data again:
*/
- if (save)
+ if (save != 0)
png_push_save_buffer(png_ptr);
else
{
@@ -69,7 +76,7 @@ png_process_data_pause(png_structp png_ptr, int save)
}
png_uint_32 PNGAPI
-png_process_data_skip(png_structp png_ptr)
+png_process_data_skip(png_structrp png_ptr)
{
png_uint_32 remaining = 0;
@@ -103,7 +110,7 @@ png_process_data_skip(png_structp png_ptr)
* doing before we ran out of data...
*/
void /* PRIVATE */
-png_process_some_data(png_structp png_ptr, png_infop info_ptr)
+png_process_some_data(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr == NULL)
return;
@@ -149,10 +156,10 @@ png_process_some_data(png_structp png_ptr, png_infop info_ptr)
* routine.
*/
void /* PRIVATE */
-png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
+png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
- png_size_t num_checked = png_ptr->sig_bytes,
- num_to_check = 8 - num_checked;
+ png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */
+ num_to_check = 8 - num_checked;
if (png_ptr->buffer_size < num_to_check)
{
@@ -172,7 +179,6 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
else
png_error(png_ptr, "PNG file corrupted by ASCII conversion");
}
-
else
{
if (png_ptr->sig_bytes >= 8)
@@ -183,27 +189,25 @@ png_push_read_sig(png_structp png_ptr, png_infop info_ptr)
}
void /* PRIVATE */
-png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
+png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
{
png_uint_32 chunk_name;
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep; /* unknown handling method */
+#endif
- /* First we make sure we have enough data for the 4 byte chunk name
- * and the 4 byte chunk length before proceeding with decoding the
+ /* First we make sure we have enough data for the 4-byte chunk name
+ * and the 4-byte chunk length before proceeding with decoding the
* chunk data. To fully decode each of these chunks, we also make
- * sure we have enough data in the buffer for the 4 byte CRC at the
+ * sure we have enough data in the buffer for the 4-byte CRC at the
* end of every chunk (except IDAT, which is handled separately).
*/
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
{
png_byte chunk_length[4];
png_byte chunk_tag[4];
- if (png_ptr->buffer_size < 8)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(8)
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -217,14 +221,29 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
if (chunk_name == png_IDAT)
{
- /* This is here above the if/else case statement below because if the
- * unknown handling marks 'IDAT' as unknown then the IDAT handling case is
- * completely skipped.
- *
- * TODO: there must be a better way of doing this.
- */
- if (png_ptr->mode & PNG_AFTER_IDAT)
+ if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+
+ /* If we reach an IDAT chunk, this means we have read all of the
+ * header chunks, and we can start reading the image (or if this
+ * is called after the image has been read - we have an error).
+ */
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
+ png_error(png_ptr, "Missing PLTE before IDAT");
+
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ png_ptr->process_mode = PNG_READ_IDAT_MODE;
+
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) == 0)
+ if (png_ptr->push_length == 0)
+ return;
+
+ if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
+ png_benign_error(png_ptr, "Too many IDATs found");
}
if (chunk_name == png_IHDR)
@@ -232,23 +251,13 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
if (png_ptr->push_length != 13)
png_error(png_ptr, "Invalid IHDR length");
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IHDR(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IEND)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_IEND(png_ptr, info_ptr, png_ptr->push_length);
png_ptr->process_mode = PNG_READ_DONE_MODE;
@@ -256,70 +265,25 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
}
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name))
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
- if (chunk_name == png_IDAT)
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
-
- else if (chunk_name == png_IDAT)
- {
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
- }
}
-
#endif
+
else if (chunk_name == png_PLTE)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_PLTE(png_ptr, info_ptr, png_ptr->push_length);
}
else if (chunk_name == png_IDAT)
{
- /* If we reach an IDAT chunk, this means we have read all of the
- * header chunks, and we can start reading the image (or if this
- * is called after the image has been read - we have an error).
- */
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
- if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
- if (png_ptr->push_length == 0)
- return;
-
- if (png_ptr->mode & PNG_AFTER_IDAT)
- png_benign_error(png_ptr, "Too many IDATs found");
- }
-
png_ptr->idat_size = png_ptr->push_length;
- png_ptr->mode |= PNG_HAVE_IDAT;
png_ptr->process_mode = PNG_READ_IDAT_MODE;
png_push_have_info(png_ptr, info_ptr);
png_ptr->zstream.avail_out =
@@ -332,12 +296,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_gAMA_SUPPORTED
else if (png_ptr->chunk_name == png_gAMA)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_gAMA(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -345,12 +304,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sBIT_SUPPORTED
else if (png_ptr->chunk_name == png_sBIT)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sBIT(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -358,12 +312,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_cHRM_SUPPORTED
else if (png_ptr->chunk_name == png_cHRM)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -371,12 +320,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sRGB_SUPPORTED
else if (chunk_name == png_sRGB)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sRGB(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -384,12 +328,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_iCCP_SUPPORTED
else if (png_ptr->chunk_name == png_iCCP)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_iCCP(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -397,12 +336,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sPLT_SUPPORTED
else if (chunk_name == png_sPLT)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sPLT(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -410,12 +344,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tRNS_SUPPORTED
else if (chunk_name == png_tRNS)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tRNS(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -423,12 +352,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_bKGD_SUPPORTED
else if (chunk_name == png_bKGD)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_bKGD(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -436,12 +360,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_hIST_SUPPORTED
else if (chunk_name == png_hIST)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_hIST(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -449,12 +368,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_pHYs_SUPPORTED
else if (chunk_name == png_pHYs)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pHYs(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -462,12 +376,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_oFFs_SUPPORTED
else if (chunk_name == png_oFFs)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_oFFs(png_ptr, info_ptr, png_ptr->push_length);
}
#endif
@@ -475,12 +384,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_pCAL_SUPPORTED
else if (chunk_name == png_pCAL)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_pCAL(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -488,12 +392,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_sCAL_SUPPORTED
else if (chunk_name == png_sCAL)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_sCAL(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -501,12 +400,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tIME_SUPPORTED
else if (chunk_name == png_tIME)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tIME(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -514,12 +408,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_tEXt_SUPPORTED
else if (chunk_name == png_tEXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_tEXt(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -527,12 +416,7 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_zTXt_SUPPORTED
else if (chunk_name == png_zTXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_zTXt(png_ptr, info_ptr, png_ptr->push_length);
}
@@ -540,40 +424,32 @@ png_push_read_chunk(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_READ_iTXt_SUPPORTED
else if (chunk_name == png_iTXt)
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
png_handle_iTXt(png_ptr, info_ptr, png_ptr->push_length);
}
-
#endif
+
else
{
- if (png_ptr->push_length + 4 > png_ptr->buffer_size)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
- png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length);
+ PNG_PUSH_SAVE_BUFFER_IF_FULL
+ png_handle_unknown(png_ptr, info_ptr, png_ptr->push_length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
}
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
}
void /* PRIVATE */
-png_push_crc_skip(png_structp png_ptr, png_uint_32 skip)
+png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip)
{
png_ptr->process_mode = PNG_SKIP_MODE;
png_ptr->skip_length = skip;
}
void /* PRIVATE */
-png_push_crc_finish(png_structp png_ptr)
+png_push_crc_finish(png_structrp png_ptr)
{
- if (png_ptr->skip_length && png_ptr->save_buffer_size)
+ if (png_ptr->skip_length != 0 && png_ptr->save_buffer_size != 0)
{
png_size_t save_size = png_ptr->save_buffer_size;
png_uint_32 skip_length = png_ptr->skip_length;
@@ -597,8 +473,7 @@ png_push_crc_finish(png_structp png_ptr)
png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += save_size;
}
-
- if (png_ptr->skip_length && png_ptr->current_buffer_size)
+ if (png_ptr->skip_length != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size = png_ptr->current_buffer_size;
png_uint_32 skip_length = png_ptr->skip_length;
@@ -619,15 +494,9 @@ png_push_crc_finish(png_structp png_ptr)
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
}
-
- if (!png_ptr->skip_length)
+ if (png_ptr->skip_length == 0)
{
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(4)
png_crc_finish(png_ptr, 0);
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
}
@@ -642,8 +511,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
return;
ptr = buffer;
-
- if (png_ptr->save_buffer_size)
+ if (png_ptr->save_buffer_size != 0)
{
png_size_t save_size;
@@ -653,15 +521,14 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
else
save_size = png_ptr->save_buffer_size;
- png_memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
+ memcpy(ptr, png_ptr->save_buffer_ptr, save_size);
length -= save_size;
ptr += save_size;
png_ptr->buffer_size -= save_size;
png_ptr->save_buffer_size -= save_size;
png_ptr->save_buffer_ptr += save_size;
}
-
- if (length && png_ptr->current_buffer_size)
+ if (length != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size;
@@ -671,7 +538,7 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
else
save_size = png_ptr->current_buffer_size;
- png_memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
+ memcpy(ptr, png_ptr->current_buffer_ptr, save_size);
png_ptr->buffer_size -= save_size;
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
@@ -679,9 +546,9 @@ png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length)
}
void /* PRIVATE */
-png_push_save_buffer(png_structp png_ptr)
+png_push_save_buffer(png_structrp png_ptr)
{
- if (png_ptr->save_buffer_size)
+ if (png_ptr->save_buffer_size != 0)
{
if (png_ptr->save_buffer_ptr != png_ptr->save_buffer)
{
@@ -690,7 +557,6 @@ png_push_save_buffer(png_structp png_ptr)
png_bytep dp;
istop = png_ptr->save_buffer_size;
-
for (i = 0, sp = png_ptr->save_buffer_ptr, dp = png_ptr->save_buffer;
i < istop; i++, sp++, dp++)
{
@@ -698,7 +564,6 @@ png_push_save_buffer(png_structp png_ptr)
}
}
}
-
if (png_ptr->save_buffer_size + png_ptr->current_buffer_size >
png_ptr->save_buffer_max)
{
@@ -713,33 +578,34 @@ png_push_save_buffer(png_structp png_ptr)
new_max = png_ptr->save_buffer_size + png_ptr->current_buffer_size + 256;
old_buffer = png_ptr->save_buffer;
- png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr, new_max);
+ png_ptr->save_buffer = (png_bytep)png_malloc_warn(png_ptr,
+ (png_size_t)new_max);
if (png_ptr->save_buffer == NULL)
{
png_free(png_ptr, old_buffer);
+ old_buffer = NULL;
png_error(png_ptr, "Insufficient memory for save_buffer");
}
- png_memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
+ memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size);
png_free(png_ptr, old_buffer);
+ old_buffer = NULL;
png_ptr->save_buffer_max = new_max;
}
-
if (png_ptr->current_buffer_size)
{
- png_memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
+ memcpy(png_ptr->save_buffer + png_ptr->save_buffer_size,
png_ptr->current_buffer_ptr, png_ptr->current_buffer_size);
png_ptr->save_buffer_size += png_ptr->current_buffer_size;
png_ptr->current_buffer_size = 0;
}
-
png_ptr->save_buffer_ptr = png_ptr->save_buffer;
png_ptr->buffer_size = 0;
}
void /* PRIVATE */
-png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
+png_push_restore_buffer(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
{
png_ptr->current_buffer = buffer;
@@ -749,20 +615,15 @@ png_push_restore_buffer(png_structp png_ptr, png_bytep buffer,
}
void /* PRIVATE */
-png_push_read_IDAT(png_structp png_ptr)
+png_push_read_IDAT(png_structrp png_ptr)
{
- if (!(png_ptr->mode & PNG_HAVE_CHUNK_HEADER))
+ if ((png_ptr->mode & PNG_HAVE_CHUNK_HEADER) == 0)
{
png_byte chunk_length[4];
png_byte chunk_tag[4];
/* TODO: this code can be commoned up with the same code in push_read */
- if (png_ptr->buffer_size < 8)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(8)
png_push_fill_buffer(png_ptr, chunk_length, 4);
png_ptr->push_length = png_get_uint_31(png_ptr, chunk_length);
png_reset_crc(png_ptr);
@@ -774,7 +635,7 @@ png_push_read_IDAT(png_structp png_ptr)
{
png_ptr->process_mode = PNG_READ_CHUNK_MODE;
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
png_error(png_ptr, "Not enough compressed data");
return;
@@ -783,7 +644,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->idat_size = png_ptr->push_length;
}
- if (png_ptr->idat_size && png_ptr->save_buffer_size)
+ if (png_ptr->idat_size != 0 && png_ptr->save_buffer_size != 0)
{
png_size_t save_size = png_ptr->save_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
@@ -810,7 +671,7 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->save_buffer_ptr += save_size;
}
- if (png_ptr->idat_size && png_ptr->current_buffer_size)
+ if (png_ptr->idat_size != 0 && png_ptr->current_buffer_size != 0)
{
png_size_t save_size = png_ptr->current_buffer_size;
png_uint_32 idat_size = png_ptr->idat_size;
@@ -835,23 +696,18 @@ png_push_read_IDAT(png_structp png_ptr)
png_ptr->current_buffer_size -= save_size;
png_ptr->current_buffer_ptr += save_size;
}
-
- if (!png_ptr->idat_size)
+ if (png_ptr->idat_size == 0)
{
- if (png_ptr->buffer_size < 4)
- {
- png_push_save_buffer(png_ptr);
- return;
- }
-
+ PNG_PUSH_SAVE_BUFFER_IF_LT(4)
png_crc_finish(png_ptr, 0);
png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER;
png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->zowner = 0;
}
}
void /* PRIVATE */
-png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
+png_process_IDAT_data(png_structrp png_ptr, png_bytep buffer,
png_size_t buffer_length)
{
/* The caller checks for a non-zero buffer length. */
@@ -863,13 +719,14 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
* handle the uncompressed results.
*/
png_ptr->zstream.next_in = buffer;
+ /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
png_ptr->zstream.avail_in = (uInt)buffer_length;
/* Keep going until the decompressed data is all processed
* or the stream marked as finished.
*/
while (png_ptr->zstream.avail_in > 0 &&
- !(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
+ (png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
{
int ret;
@@ -880,9 +737,9 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
*/
if (!(png_ptr->zstream.avail_out > 0))
{
- png_ptr->zstream.avail_out =
- (uInt) PNG_ROWBYTES(png_ptr->pixel_depth,
- png_ptr->iwidth) + 1;
+ /* TODO: WARNING: TRUNCATION ERROR: DANGER WILL ROBINSON: */
+ png_ptr->zstream.avail_out = (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
+ png_ptr->iwidth) + 1);
png_ptr->zstream.next_out = png_ptr->row_buf;
}
@@ -900,7 +757,8 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
if (ret != Z_OK && ret != Z_STREAM_END)
{
/* Terminate the decompression. */
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ png_ptr->zowner = 0;
/* This may be a truncated stream (missing or
* damaged end code). Treat that as a warning.
@@ -928,7 +786,8 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
{
/* Extra data. */
png_warning(png_ptr, "Extra compressed data in IDAT");
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ png_ptr->zowner = 0;
/* Do no more processing; skip the unprocessed
* input check below.
@@ -943,7 +802,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
/* And check for the end of the stream. */
if (ret == Z_STREAM_END)
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
}
/* All the data should have been processed, if anything
@@ -955,7 +814,7 @@ png_process_IDAT_data(png_structp png_ptr, png_bytep buffer,
}
void /* PRIVATE */
-png_push_process_row(png_structp png_ptr)
+png_push_process_row(png_structrp png_ptr)
{
/* 1.5.6: row_info moved out of png_struct to a local here. */
png_row_info row_info;
@@ -981,10 +840,10 @@ png_push_process_row(png_structp png_ptr)
* it may not be in the future, so this was changed just to copy the
* interlaced row count:
*/
- png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
+ memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
- if (png_ptr->transformations)
+ if (png_ptr->transformations != 0)
png_do_read_transformations(png_ptr, &row_info);
#endif
@@ -1001,15 +860,16 @@ png_push_process_row(png_structp png_ptr)
#ifdef PNG_READ_INTERLACING_SUPPORTED
- /* Blow up interlaced rows to full size */
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ /* Expand interlaced rows to full size */
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
png_ptr->transformations);
- switch (png_ptr->pass)
- {
+ switch (png_ptr->pass)
+ {
case 0:
{
int i;
@@ -1184,26 +1044,26 @@ png_push_process_row(png_structp png_ptr)
}
void /* PRIVATE */
-png_read_push_finish_row(png_structp png_ptr)
+png_read_push_finish_row(png_structrp png_ptr)
{
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
- static PNG_CONST png_byte FARDATA png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
+ static PNG_CONST png_byte png_pass_start[] = {0, 4, 0, 2, 0, 1, 0};
/* Offset to next interlace block */
- static PNG_CONST png_byte FARDATA png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
+ static PNG_CONST png_byte png_pass_inc[] = {8, 8, 4, 4, 2, 2, 1};
/* Start of interlace block in the y direction */
- static PNG_CONST png_byte FARDATA png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
+ static PNG_CONST png_byte png_pass_ystart[] = {0, 0, 4, 0, 2, 0, 1};
/* Offset to next interlace block in the y direction */
- static PNG_CONST png_byte FARDATA png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
+ static PNG_CONST png_byte png_pass_yinc[] = {8, 8, 8, 4, 4, 2, 2};
/* Height of interlace block. This is not currently used - if you need
* it, uncomment it here and in png.h
- static PNG_CONST png_byte FARDATA png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
+ static PNG_CONST png_byte png_pass_height[] = {8, 8, 4, 4, 2, 2, 1};
*/
#endif
@@ -1212,10 +1072,10 @@ png_read_push_finish_row(png_structp png_ptr)
return;
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do
{
@@ -1236,7 +1096,7 @@ png_read_push_finish_row(png_structp png_ptr)
png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass];
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
break;
png_ptr->num_rows = (png_ptr->height +
@@ -1246,25 +1106,25 @@ png_read_push_finish_row(png_structp png_ptr)
} while (png_ptr->iwidth == 0 || png_ptr->num_rows == 0);
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
}
void /* PRIVATE */
-png_push_have_info(png_structp png_ptr, png_infop info_ptr)
+png_push_have_info(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr->info_fn != NULL)
(*(png_ptr->info_fn))(png_ptr, info_ptr);
}
void /* PRIVATE */
-png_push_have_end(png_structp png_ptr, png_infop info_ptr)
+png_push_have_end(png_structrp png_ptr, png_inforp info_ptr)
{
if (png_ptr->end_fn != NULL)
(*(png_ptr->end_fn))(png_ptr, info_ptr);
}
void /* PRIVATE */
-png_push_have_row(png_structp png_ptr, png_bytep row)
+png_push_have_row(png_structrp png_ptr, png_bytep row)
{
if (png_ptr->row_fn != NULL)
(*(png_ptr->row_fn))(png_ptr, row, png_ptr->row_number,
@@ -1273,7 +1133,7 @@ png_push_have_row(png_structp png_ptr, png_bytep row)
#ifdef PNG_READ_INTERLACING_SUPPORTED
void PNGAPI
-png_progressive_combine_row (png_structp png_ptr, png_bytep old_row,
+png_progressive_combine_row(png_const_structrp png_ptr, png_bytep old_row,
png_const_bytep new_row)
{
if (png_ptr == NULL)
@@ -1284,12 +1144,12 @@ png_progressive_combine_row (png_structp png_ptr, png_bytep old_row,
* it must be png_ptr->row_buf+1
*/
if (new_row != NULL)
- png_combine_row(png_ptr, old_row, 1/*display*/);
+ png_combine_row(png_ptr, old_row, 1/*blocky display*/);
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
void PNGAPI
-png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
+png_set_progressive_read_fn(png_structrp png_ptr, png_voidp progressive_ptr,
png_progressive_info_ptr info_fn, png_progressive_row_ptr row_fn,
png_progressive_end_ptr end_fn)
{
@@ -1304,11 +1164,11 @@ png_set_progressive_read_fn(png_structp png_ptr, png_voidp progressive_ptr,
}
png_voidp PNGAPI
-png_get_progressive_ptr(png_const_structp png_ptr)
+png_get_progressive_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
return png_ptr->io_ptr;
}
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h
index f01e56f612..7185444f2c 100644
--- a/src/3rdparty/libpng/pngpriv.h
+++ b/src/3rdparty/libpng/pngpriv.h
@@ -1,20 +1,18 @@
/* pngpriv.h - private declarations for use inside libpng
*
- * For conditions of distribution and use, see copyright notice in png.h
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.10 [March 29, 2012]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
*/
/* The symbols declared in this file (including the functions declared
- * as PNG_EXTERN) are PRIVATE. They are not part of the libpng public
+ * as extern) are PRIVATE. They are not part of the libpng public
* interface, and are not recommended for use by regular applications.
* Some of them may become public in the future; others may stay private,
* change in an incompatible way, or even disappear.
@@ -45,15 +43,43 @@
*/
#define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
-/* This is required for the definition of abort(), used as a last ditch
- * error handler when all else fails.
+#ifndef PNG_VERSION_INFO_ONLY
+/* Standard library headers not required by png.h: */
+# include <stdlib.h>
+# include <string.h>
+#endif
+
+#define PNGLIB_BUILD /*libpng is being built, not used*/
+
+/* If HAVE_CONFIG_H is defined during the build then the build system must
+ * provide an appropriate "config.h" file on the include path. The header file
+ * must provide definitions as required below (search for "HAVE_CONFIG_H");
+ * see configure.ac for more details of the requirements. The macro
+ * "PNG_NO_CONFIG_H" is provided for maintainers to test for dependencies on
+ * 'configure'; define this macro to prevent the configure build including the
+ * configure generated config.h. Libpng is expected to compile without *any*
+ * special build system support on a reasonably ANSI-C compliant system.
*/
-#include <stdlib.h>
+#if defined(HAVE_CONFIG_H) && !defined(PNG_NO_CONFIG_H)
+# include <config.h>
-/* This is used to find 'offsetof', used below for alignment tests. */
-#include <stddef.h>
+ /* Pick up the definition of 'restrict' from config.h if it was read: */
+# define PNG_RESTRICT restrict
+#endif
-#define PNGLIB_BUILD /*libpng is being built, not used*/
+/* To support symbol prefixing it is necessary to know *before* including png.h
+ * whether the fixed point (and maybe other) APIs are exported, because if they
+ * are not internal definitions may be required. This is handled below just
+ * before png.h is included, but load the configuration now if it is available.
+ */
+#ifndef PNGLCONF_H
+# include "pnglibconf.h"
+#endif
+
+/* Local renames may change non-exported API functions from png.h */
+#if defined(PNG_PREFIX) && !defined(PNGPREFIX_H)
+# include "pngprefix.h"
+#endif
#ifdef PNG_USER_CONFIG
# include "pngusr.h"
@@ -66,6 +92,98 @@
# endif
#endif
+/* Compile time options.
+ * =====================
+ * In a multi-arch build the compiler may compile the code several times for the
+ * same object module, producing different binaries for different architectures.
+ * When this happens configure-time setting of the target host options cannot be
+ * done and this interferes with the handling of the ARM NEON optimizations, and
+ * possibly other similar optimizations. Put additional tests here; in general
+ * this is needed when the same option can be changed at both compile time and
+ * run time depending on the target OS (i.e. iOS vs Android.)
+ *
+ * NOTE: symbol prefixing does not pass $(CFLAGS) to the preprocessor, because
+ * this is not possible with certain compilers (Oracle SUN OS CC), as a result
+ * it is necessary to ensure that all extern functions that *might* be used
+ * regardless of $(CFLAGS) get declared in this file. The test on __ARM_NEON__
+ * below is one example of this behavior because it is controlled by the
+ * presence or not of -mfpu=neon on the GCC command line, it is possible to do
+ * this in $(CC), e.g. "CC=gcc -mfpu=neon", but people who build libpng rarely
+ * do this.
+ */
+#ifndef PNG_ARM_NEON_OPT
+ /* ARM NEON optimizations are being controlled by the compiler settings,
+ * typically the target FPU. If the FPU has been set to NEON (-mfpu=neon
+ * with GCC) then the compiler will define __ARM_NEON__ and we can rely
+ * unconditionally on NEON instructions not crashing, otherwise we must
+ * disable use of NEON instructions.
+ *
+ * NOTE: at present these optimizations depend on 'ALIGNED_MEMORY', so they
+ * can only be turned on automatically if that is supported too. If
+ * PNG_ARM_NEON_OPT is set in CPPFLAGS (to >0) then arm/arm_init.c will fail
+ * to compile with an appropriate #error if ALIGNED_MEMORY has been turned
+ * off.
+ *
+ * Note that gcc-4.9 defines __ARM_NEON instead of __ARM_NEON__, so we
+ * check both variants.
+ */
+# if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \
+ defined(PNG_ALIGNED_MEMORY_SUPPORTED)
+# define PNG_ARM_NEON_OPT 2
+# else
+# define PNG_ARM_NEON_OPT 0
+# endif
+#endif
+
+#if PNG_ARM_NEON_OPT > 0
+ /* NEON optimizations are to be at least considered by libpng, so enable the
+ * callbacks to do this.
+ */
+# define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_neon
+
+ /* By default the 'intrinsics' code in arm/filter_neon_intrinsics.c is used
+ * if possible - if __ARM_NEON__ is set and the compiler version is not known
+ * to be broken. This is controlled by PNG_ARM_NEON_IMPLEMENTATION which can
+ * be:
+ *
+ * 1 The intrinsics code (the default with __ARM_NEON__)
+ * 2 The hand coded assembler (the default without __ARM_NEON__)
+ *
+ * It is possible to set PNG_ARM_NEON_IMPLEMENTATION in CPPFLAGS, however
+ * this is *NOT* supported and may cease to work even after a minor revision
+ * to libpng. It *is* valid to do this for testing purposes, e.g. speed
+ * testing or a new compiler, but the results should be communicated to the
+ * libpng implementation list for incorporation in the next minor release.
+ */
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+# if defined(__ARM_NEON__) || defined(__ARM_NEON)
+# if defined(__clang__)
+ /* At present it is unknown by the libpng developers which versions
+ * of clang support the intrinsics, however some or perhaps all
+ * versions do not work with the assembler so this may be
+ * irrelevant, so just use the default (do nothing here.)
+ */
+# elif defined(__GNUC__)
+ /* GCC 4.5.4 NEON support is known to be broken. 4.6.3 is known to
+ * work, so if this *is* GCC, or G++, look for a version >4.5
+ */
+# if __GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 6)
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* no GNUC support */
+# endif /* __GNUC__ */
+# else /* !defined __ARM_NEON__ */
+ /* The 'intrinsics' code simply won't compile without this -mfpu=neon:
+ */
+# define PNG_ARM_NEON_IMPLEMENTATION 2
+# endif /* __ARM_NEON__ */
+# endif /* !PNG_ARM_NEON_IMPLEMENTATION */
+
+# ifndef PNG_ARM_NEON_IMPLEMENTATION
+ /* Use the intrinsics code by default. */
+# define PNG_ARM_NEON_IMPLEMENTATION 1
+# endif
+#endif /* PNG_ARM_NEON_OPT > 0 */
+
/* Is this a build of a DLL where compilation of the object modules requires
* different preprocessor settings to those required for a simple library? If
* so PNG_BUILD_DLL must be set.
@@ -135,76 +253,65 @@
# define PNG_PRIVATE
#endif
-#include "png.h"
-#include "pnginfo.h"
-#include "pngstruct.h"
+/* Symbol preprocessing support.
+ *
+ * To enable listing global, but internal, symbols the following macros should
+ * always be used to declare an extern data or function object in this file.
+ */
+#ifndef PNG_INTERNAL_DATA
+# define PNG_INTERNAL_DATA(type, name, array) extern type name array
+#endif
-/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
-#ifndef PNG_DLL_EXPORT
-# define PNG_DLL_EXPORT
+#ifndef PNG_INTERNAL_FUNCTION
+# define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\
+ extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes)
#endif
-/* SECURITY and SAFETY:
+#ifndef PNG_INTERNAL_CALLBACK
+# define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\
+ extern PNG_FUNCTION(type, (PNGCBAPI name), args, PNG_EMPTY attributes)
+#endif
+
+/* If floating or fixed point APIs are disabled they may still be compiled
+ * internally. To handle this make sure they are declared as the appropriate
+ * internal extern function (otherwise the symbol prefixing stuff won't work and
+ * the functions will be used without definitions.)
*
- * By default libpng is built without any internal limits on image size,
- * individual heap (png_malloc) allocations or the total amount of memory used.
- * If PNG_SAFE_LIMITS_SUPPORTED is defined, however, the limits below are used
- * (unless individually overridden). These limits are believed to be fairly
- * safe, but builders of secure systems should verify the values against the
- * real system capabilities.
- */
-
-#ifdef PNG_SAFE_LIMITS_SUPPORTED
- /* 'safe' limits */
-# ifndef PNG_USER_WIDTH_MAX
-# define PNG_USER_WIDTH_MAX 1000000
-# endif
-# ifndef PNG_USER_HEIGHT_MAX
-# define PNG_USER_HEIGHT_MAX 1000000
-# endif
-# ifndef PNG_USER_CHUNK_CACHE_MAX
-# define PNG_USER_CHUNK_CACHE_MAX 128
-# endif
-# ifndef PNG_USER_CHUNK_MALLOC_MAX
-# define PNG_USER_CHUNK_MALLOC_MAX 8000000
-# endif
-#else
- /* values for no limits */
-# ifndef PNG_USER_WIDTH_MAX
-# define PNG_USER_WIDTH_MAX 0x7fffffff
-# endif
-# ifndef PNG_USER_HEIGHT_MAX
-# define PNG_USER_HEIGHT_MAX 0x7fffffff
-# endif
-# ifndef PNG_USER_CHUNK_CACHE_MAX
-# define PNG_USER_CHUNK_CACHE_MAX 0
+ * NOTE: although all the API functions are declared here they are not all
+ * actually built! Because the declarations are still made it is necessary to
+ * fake out types that they depend on.
+ */
+#ifndef PNG_FP_EXPORT
+# ifndef PNG_FLOATING_POINT_SUPPORTED
+# define PNG_FP_EXPORT(ordinal, type, name, args)\
+ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
+# ifndef PNG_VERSION_INFO_ONLY
+ typedef struct png_incomplete png_double;
+ typedef png_double* png_doublep;
+ typedef const png_double* png_const_doublep;
+ typedef png_double** png_doublepp;
+# endif
# endif
-# ifndef PNG_USER_CHUNK_MALLOC_MAX
-# define PNG_USER_CHUNK_MALLOC_MAX 0
+#endif
+#ifndef PNG_FIXED_EXPORT
+# ifndef PNG_FIXED_POINT_SUPPORTED
+# define PNG_FIXED_EXPORT(ordinal, type, name, args)\
+ PNG_INTERNAL_FUNCTION(type, name, args, PNG_EMPTY);
# endif
#endif
-/* This is used for 16 bit gamma tables - only the top level pointers are const,
- * this could be changed:
- */
-typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
-
-/* Added at libpng-1.2.9 */
-/* Moved to pngpriv.h at libpng-1.5.0 */
+#include "png.h"
-/* config.h is created by and PNG_CONFIGURE_LIBPNG is set by the "configure"
- * script. We may need it here to get the correct configuration on things
- * like limits.
- */
-#ifdef PNG_CONFIGURE_LIBPNG
-# ifdef HAVE_CONFIG_H
-# include "config.h"
-# endif
+/* pngconf.h does not set PNG_DLL_EXPORT unless it is required, so: */
+#ifndef PNG_DLL_EXPORT
+# define PNG_DLL_EXPORT
#endif
-/* Moved to pngpriv.h at libpng-1.5.0 */
-/* NOTE: some of these may have been used in external applications as
- * these definitions were exposed in pngconf.h prior to 1.5.
+/* SECURITY and SAFETY:
+ *
+ * libpng is built with support for internal limits on image dimensions and
+ * memory usage. These are documented in scripts/pnglibconf.dfa of the
+ * source and recorded in the machine generated header file pnglibconf.h.
*/
/* If you are running on a machine where you cannot allocate more
@@ -240,30 +347,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_ZBUF_SIZE 65536L
#endif
-/* PNG_STATIC is used to mark internal file scope functions if they need to be
- * accessed for implementation tests (see the code in tests/?*).
- */
-#ifndef PNG_STATIC
-# define PNG_STATIC static
-#endif
-
-/* C99 restrict is used where possible, to do this 'restrict' is defined as
- * empty if we can't be sure it is supported. configure builds have already
- * done this work.
- */
-#ifdef PNG_CONFIGURE_LIBPNG
-# define PNG_RESTRICT restrict
-#else
- /* Modern compilers support restrict, but assume not for anything not
- * recognized here:
- */
-# if defined __GNUC__ || defined _MSC_VER || defined __WATCOMC__
-# define PNG_RESTRICT restrict
-# else
-# define PNG_RESTRICT
-# endif
-#endif
-
/* If warnings or errors are turned off the code is disabled or redirected here.
* From 1.5.4 functions have been added to allow very limited formatting of
* error and warning messages - this code will also be disabled here.
@@ -271,8 +354,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#ifdef PNG_WARNINGS_SUPPORTED
# define PNG_WARNING_PARAMETERS(p) png_warning_parameters p;
#else
-# define png_warning(s1,s2) ((void)(s1))
-# define png_chunk_warning(s1,s2) ((void)(s1))
# define png_warning_parameter(p,number,string) ((void)0)
# define png_warning_parameter_unsigned(p,number,format,value) ((void)0)
# define png_warning_parameter_signed(p,number,format,value) ((void)0)
@@ -280,8 +361,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNG_WARNING_PARAMETERS(p)
#endif
#ifndef PNG_ERROR_TEXT_SUPPORTED
-# define png_error(s1,s2) png_err(s1)
-# define png_chunk_error(s1,s2) png_err(s1)
# define png_fixed_error(s1,s2) png_err(s1)
#endif
@@ -292,23 +371,18 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
*/
#ifdef __cplusplus
# define png_voidcast(type, value) static_cast<type>(value)
+# define png_constcast(type, value) const_cast<type>(value)
+# define png_aligncast(type, value) \
+ static_cast<type>(static_cast<void*>(value))
+# define png_aligncastconst(type, value) \
+ static_cast<type>(static_cast<const void*>(value))
#else
# define png_voidcast(type, value) (value)
+# define png_constcast(type, value) ((type)(value))
+# define png_aligncast(type, value) ((void*)(value))
+# define png_aligncastconst(type, value) ((const void*)(value))
#endif /* __cplusplus */
-#ifndef PNG_EXTERN
-/* The functions exported by PNG_EXTERN are internal functions, which
- * aren't usually used outside the library (as far as I know), so it is
- * debatable if they should be exported at all. In the future, when it
- * is possible to have run-time registry of chunk-handling functions,
- * some of these might be made available again.
- *
- * 1.5.7: turned the use of 'extern' back on, since it is localized to pngpriv.h
- * it should be safe now (it is unclear why it was turned off.)
- */
-# define PNG_EXTERN extern
-#endif
-
/* Some fixed point APIs are still required even if not exported because
* they get used by the corresponding floating point APIs. This magic
* deals with this:
@@ -319,6 +393,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define PNGFAPI /* PRIVATE */
#endif
+#ifndef PNG_VERSION_INFO_ONLY
/* Other defines specific to compilers can go here. Try to keep
* them inside an appropriate ifdef/endif pair for portability.
*/
@@ -366,6 +441,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# define _WINRT_ /* Define a macro for Windows Runtime builds */
# endif
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
/* Moved here around 1.5.0beta36 from pngconf.h */
/* Users may want to use these so they are not private. Any library
@@ -381,34 +457,6 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
# endif
#endif
-#ifdef USE_FAR_KEYWORD
-/* Use this to make far-to-near assignments */
-# define CHECK 1
-# define NOCHECK 0
-# define CVT_PTR(ptr) (png_far_to_near(png_ptr,ptr,CHECK))
-# define CVT_PTR_NOCHECK(ptr) (png_far_to_near(png_ptr,ptr,NOCHECK))
-# define png_strlen _fstrlen
-# define png_memcmp _fmemcmp /* SJT: added */
-# define png_memcpy _fmemcpy
-# define png_memset _fmemset
-#else
-# if defined(_WINDOWS_) && !defined(_WINRT_) /* Favor Windows over C runtime fns */
-# define CVT_PTR(ptr) (ptr)
-# define CVT_PTR_NOCHECK(ptr) (ptr)
-# define png_strlen lstrlenA
-# define png_memcmp memcmp
-# define png_memcpy CopyMemory
-# define png_memset memset
-# else
-# define CVT_PTR(ptr) (ptr)
-# define CVT_PTR_NOCHECK(ptr) (ptr)
-# define png_strlen strlen
-# define png_memcmp memcmp /* SJT: added */
-# define png_memcpy memcpy
-# define png_memset memset
-# endif
-#endif
-
/* These macros may need to be architecture dependent. */
#define PNG_ALIGN_NONE 0 /* do not use data alignment */
#define PNG_ALIGN_ALWAYS 1 /* assume unaligned accesses are OK */
@@ -430,7 +478,7 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#if PNG_ALIGN_TYPE == PNG_ALIGN_SIZE
/* This is used because in some compiler implementations non-aligned
* structure members are supported, so the offsetof approach below fails.
- * Set PNG_ALIGN_TO_SIZE=0 for compiler combinations where unaligned access
+ * Set PNG_ALIGN_SIZE=0 for compiler combinations where unaligned access
* is good for performance. Do not do this unless you have tested the result
* and understand it.
*/
@@ -471,16 +519,17 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_HAVE_IDAT 0x04
/* #define PNG_AFTER_IDAT 0x08 (defined in png.h) */
#define PNG_HAVE_IEND 0x10
-#define PNG_HAVE_gAMA 0x20
-#define PNG_HAVE_cHRM 0x40
-#define PNG_HAVE_sRGB 0x80
+ /* 0x20 (unused) */
+ /* 0x40 (unused) */
+ /* 0x80 (unused) */
#define PNG_HAVE_CHUNK_HEADER 0x100
#define PNG_WROTE_tIME 0x200
#define PNG_WROTE_INFO_BEFORE_PLTE 0x400
#define PNG_BACKGROUND_IS_GRAY 0x800
#define PNG_HAVE_PNG_SIGNATURE 0x1000
#define PNG_HAVE_CHUNK_AFTER_IDAT 0x2000 /* Have another chunk after IDAT */
-#define PNG_HAVE_iCCP 0x4000
+ /* 0x4000 (unused) */
+#define PNG_IS_READ_STRUCT 0x8000 /* Else is a write struct */
/* Flags for the transformations the PNG library does on the image data */
#define PNG_BGR 0x0001
@@ -508,13 +557,13 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_RGB_TO_GRAY_WARN 0x400000
#define PNG_RGB_TO_GRAY 0x600000 /* two bits, RGB_TO_GRAY_ERR|WARN */
#define PNG_ENCODE_ALPHA 0x800000 /* Added to libpng-1.5.4 */
-#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */
-#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */
-#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */
- /* 0x8000000 unused */
- /* 0x10000000 unused */
- /* 0x20000000 unused */
- /* 0x40000000 unused */
+#define PNG_ADD_ALPHA 0x1000000 /* Added to libpng-1.2.7 */
+#define PNG_EXPAND_tRNS 0x2000000 /* Added to libpng-1.2.9 */
+#define PNG_SCALE_16_TO_8 0x4000000 /* Added to libpng-1.5.4 */
+ /* 0x8000000 unused */
+ /* 0x10000000 unused */
+ /* 0x20000000 unused */
+ /* 0x40000000 unused */
/* Flags for png_create_struct */
#define PNG_STRUCT_PNG 0x0001
#define PNG_STRUCT_INFO 0x0002
@@ -525,36 +574,36 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
/* Flags for the png_ptr->flags rather than declaring a byte for each one */
#define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001
-#define PNG_FLAG_ZLIB_CUSTOM_LEVEL 0x0002
-#define PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL 0x0004
-#define PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS 0x0008
-#define PNG_FLAG_ZLIB_CUSTOM_METHOD 0x0010
-#define PNG_FLAG_ZLIB_FINISHED 0x0020
+#define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */
+ /* 0x0004 unused */
+#define PNG_FLAG_ZSTREAM_ENDED 0x0008 /* Added to libpng-1.6.0 */
+ /* 0x0010 unused */
+ /* 0x0020 unused */
#define PNG_FLAG_ROW_INIT 0x0040
#define PNG_FLAG_FILLER_AFTER 0x0080
#define PNG_FLAG_CRC_ANCILLARY_USE 0x0100
#define PNG_FLAG_CRC_ANCILLARY_NOWARN 0x0200
#define PNG_FLAG_CRC_CRITICAL_USE 0x0400
#define PNG_FLAG_CRC_CRITICAL_IGNORE 0x0800
-#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */
-#define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000
-#define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000
-#define PNG_FLAG_LIBRARY_MISMATCH 0x20000
-#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000
-#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000
-#define PNG_FLAG_MALLOC_NULL_MEM_OK 0x100000
- /* 0x200000 unused */
- /* 0x400000 unused */
-#define PNG_FLAG_BENIGN_ERRORS_WARN 0x800000 /* Added to libpng-1.4.0 */
-#define PNG_FLAG_ZTXT_CUSTOM_STRATEGY 0x1000000 /* 5 lines added */
-#define PNG_FLAG_ZTXT_CUSTOM_LEVEL 0x2000000 /* to libpng-1.5.4 */
-#define PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL 0x4000000
-#define PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS 0x8000000
-#define PNG_FLAG_ZTXT_CUSTOM_METHOD 0x10000000
- /* 0x20000000 unused */
- /* 0x40000000 unused */
+#define PNG_FLAG_ASSUME_sRGB 0x1000 /* Added to libpng-1.5.4 */
+#define PNG_FLAG_OPTIMIZE_ALPHA 0x2000 /* Added to libpng-1.5.4 */
+#define PNG_FLAG_DETECT_UNINITIALIZED 0x4000 /* Added to libpng-1.5.4 */
+/* #define PNG_FLAG_KEEP_UNKNOWN_CHUNKS 0x8000 */
+/* #define PNG_FLAG_KEEP_UNSAFE_CHUNKS 0x10000 */
+#define PNG_FLAG_LIBRARY_MISMATCH 0x20000
+#define PNG_FLAG_STRIP_ERROR_NUMBERS 0x40000
+#define PNG_FLAG_STRIP_ERROR_TEXT 0x80000
+#define PNG_FLAG_BENIGN_ERRORS_WARN 0x100000 /* Added to libpng-1.4.0 */
+#define PNG_FLAG_APP_WARNINGS_WARN 0x200000 /* Added to libpng-1.6.0 */
+#define PNG_FLAG_APP_ERRORS_WARN 0x400000 /* Added to libpng-1.6.0 */
+ /* 0x800000 unused */
+ /* 0x1000000 unused */
+ /* 0x2000000 unused */
+ /* 0x4000000 unused */
+ /* 0x8000000 unused */
+ /* 0x10000000 unused */
+ /* 0x20000000 unused */
+ /* 0x40000000 unused */
#define PNG_FLAG_CRC_ANCILLARY_MASK (PNG_FLAG_CRC_ANCILLARY_USE | \
PNG_FLAG_CRC_ANCILLARY_NOWARN)
@@ -565,24 +614,23 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#define PNG_FLAG_CRC_MASK (PNG_FLAG_CRC_ANCILLARY_MASK | \
PNG_FLAG_CRC_CRITICAL_MASK)
-/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
- * can handle at once. This type need be no larger than 16 bits (so maximum of
- * 65535), this define allows us to discover how big it is, but limited by the
- * maximuum for png_size_t. The value can be overriden in a library build
- * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
- * lower value (e.g. 255 works). A lower value may help memory usage (slightly)
- * and may even improve performance on some systems (and degrade it on others.)
- */
-#ifndef ZLIB_IO_MAX
-# define ZLIB_IO_MAX ((uInt)-1)
-#endif
-
/* Save typing and make code easier to understand */
#define PNG_COLOR_DIST(c1, c2) (abs((int)((c1).red) - (int)((c2).red)) + \
abs((int)((c1).green) - (int)((c2).green)) + \
abs((int)((c1).blue) - (int)((c2).blue)))
+/* Added to libpng-1.6.0: scale a 16-bit value in the range 0..65535 to 0..255
+ * by dividing by 257 *with rounding*. This macro is exact for the given range.
+ * See the discourse in pngrtran.c png_do_scale_16_to_8. The values in the
+ * macro were established by experiment (modifying the added value). The macro
+ * has a second variant that takes a value already scaled by 255 and divides by
+ * 65535 - this has a maximum error of .502. Over the range 0..65535*65535 it
+ * only gives off-by-one errors and only for 0.5% (1 in 200) of the values.
+ */
+#define PNG_DIV65535(v24) (((v24) + 32895) >> 16)
+#define PNG_DIV257(v16) PNG_DIV65535((png_uint_32)(v16) * 255)
+
/* Added to libpng-1.2.6 JB */
#define PNG_ROWBYTES(pixel_bits, width) \
((pixel_bits) >= 8 ? \
@@ -630,10 +678,10 @@ typedef PNG_CONST png_uint_16p FAR * png_const_uint_16pp;
#ifdef PNG_FIXED_POINT_MACRO_SUPPORTED
#define png_fixed(png_ptr, fp, s) ((fp) <= 21474 && (fp) >= -21474 ?\
((png_fixed_point)(100000 * (fp))) : (png_fixed_error(png_ptr, s),0))
-#else
-PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
- png_const_charp text));
#endif
+/* else the corresponding function is defined below, inside the scope of the
+ * cplusplus test.
+ */
#endif
/* Constants for known chunk types. If you need to add a chunk, define the name
@@ -650,53 +698,82 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
* architectures where (int) is only 16 bits.
*/
#define PNG_32b(b,s) ((png_uint_32)(b) << (s))
-#define PNG_CHUNK(b1,b2,b3,b4) \
+#define PNG_U32(b1,b2,b3,b4) \
(PNG_32b(b1,24) | PNG_32b(b2,16) | PNG_32b(b3,8) | PNG_32b(b4,0))
-#define png_IHDR PNG_CHUNK( 73, 72, 68, 82)
-#define png_IDAT PNG_CHUNK( 73, 68, 65, 84)
-#define png_IEND PNG_CHUNK( 73, 69, 78, 68)
-#define png_PLTE PNG_CHUNK( 80, 76, 84, 69)
-#define png_bKGD PNG_CHUNK( 98, 75, 71, 68)
-#define png_cHRM PNG_CHUNK( 99, 72, 82, 77)
-#define png_gAMA PNG_CHUNK(103, 65, 77, 65)
-#define png_hIST PNG_CHUNK(104, 73, 83, 84)
-#define png_iCCP PNG_CHUNK(105, 67, 67, 80)
-#define png_iTXt PNG_CHUNK(105, 84, 88, 116)
-#define png_oFFs PNG_CHUNK(111, 70, 70, 115)
-#define png_pCAL PNG_CHUNK(112, 67, 65, 76)
-#define png_sCAL PNG_CHUNK(115, 67, 65, 76)
-#define png_pHYs PNG_CHUNK(112, 72, 89, 115)
-#define png_sBIT PNG_CHUNK(115, 66, 73, 84)
-#define png_sPLT PNG_CHUNK(115, 80, 76, 84)
-#define png_sRGB PNG_CHUNK(115, 82, 71, 66)
-#define png_sTER PNG_CHUNK(115, 84, 69, 82)
-#define png_tEXt PNG_CHUNK(116, 69, 88, 116)
-#define png_tIME PNG_CHUNK(116, 73, 77, 69)
-#define png_tRNS PNG_CHUNK(116, 82, 78, 83)
-#define png_zTXt PNG_CHUNK(122, 84, 88, 116)
+/* Constants for known chunk types.
+ *
+ * MAINTAINERS: If you need to add a chunk, define the name here.
+ * For historical reasons these constants have the form png_<name>; i.e.
+ * the prefix is lower case. Please use decimal values as the parameters to
+ * match the ISO PNG specification and to avoid relying on the C locale
+ * interpretation of character values. Please keep the list sorted.
+ *
+ * Notice that PNG_U32 is used to define a 32-bit value for the 4 byte chunk
+ * type. In fact the specification does not express chunk types this way,
+ * however using a 32-bit value means that the chunk type can be read from the
+ * stream using exactly the same code as used for a 32-bit unsigned value and
+ * can be examined far more efficiently (using one arithmetic compare).
+ *
+ * Prior to 1.5.6 the chunk type constants were expressed as C strings. The
+ * libpng API still uses strings for 'unknown' chunks and a macro,
+ * PNG_STRING_FROM_CHUNK, allows a string to be generated if required. Notice
+ * that for portable code numeric values must still be used; the string "IHDR"
+ * is not portable and neither is PNG_U32('I', 'H', 'D', 'R').
+ *
+ * In 1.7.0 the definitions will be made public in png.h to avoid having to
+ * duplicate the same definitions in application code.
+ */
+#define png_IDAT PNG_U32( 73, 68, 65, 84)
+#define png_IEND PNG_U32( 73, 69, 78, 68)
+#define png_IHDR PNG_U32( 73, 72, 68, 82)
+#define png_PLTE PNG_U32( 80, 76, 84, 69)
+#define png_bKGD PNG_U32( 98, 75, 71, 68)
+#define png_cHRM PNG_U32( 99, 72, 82, 77)
+#define png_fRAc PNG_U32(102, 82, 65, 99) /* registered, not defined */
+#define png_gAMA PNG_U32(103, 65, 77, 65)
+#define png_gIFg PNG_U32(103, 73, 70, 103)
+#define png_gIFt PNG_U32(103, 73, 70, 116) /* deprecated */
+#define png_gIFx PNG_U32(103, 73, 70, 120)
+#define png_hIST PNG_U32(104, 73, 83, 84)
+#define png_iCCP PNG_U32(105, 67, 67, 80)
+#define png_iTXt PNG_U32(105, 84, 88, 116)
+#define png_oFFs PNG_U32(111, 70, 70, 115)
+#define png_pCAL PNG_U32(112, 67, 65, 76)
+#define png_pHYs PNG_U32(112, 72, 89, 115)
+#define png_sBIT PNG_U32(115, 66, 73, 84)
+#define png_sCAL PNG_U32(115, 67, 65, 76)
+#define png_sPLT PNG_U32(115, 80, 76, 84)
+#define png_sRGB PNG_U32(115, 82, 71, 66)
+#define png_sTER PNG_U32(115, 84, 69, 82)
+#define png_tEXt PNG_U32(116, 69, 88, 116)
+#define png_tIME PNG_U32(116, 73, 77, 69)
+#define png_tRNS PNG_U32(116, 82, 78, 83)
+#define png_zTXt PNG_U32(122, 84, 88, 116)
/* The following will work on (signed char*) strings, whereas the get_uint_32
* macro will fail on top-bit-set values because of the sign extension.
*/
#define PNG_CHUNK_FROM_STRING(s)\
- PNG_CHUNK(0xff&(s)[0], 0xff&(s)[1], 0xff&(s)[2], 0xff&(s)[3])
+ PNG_U32(0xff & (s)[0], 0xff & (s)[1], 0xff & (s)[2], 0xff & (s)[3])
/* This uses (char), not (png_byte) to avoid warnings on systems where (char) is
* signed and the argument is a (char[]) This macro will fail miserably on
* systems where (char) is more than 8 bits.
*/
#define PNG_STRING_FROM_CHUNK(s,c)\
- (void)(((char*)(s))[0]=(char)((c)>>24), ((char*)(s))[1]=(char)((c)>>16),\
- ((char*)(s))[2]=(char)((c)>>8), ((char*)(s))[3]=(char)((c)))
+ (void)(((char*)(s))[0]=(char)(((c)>>24) & 0xff), \
+ ((char*)(s))[1]=(char)(((c)>>16) & 0xff),\
+ ((char*)(s))[2]=(char)(((c)>>8) & 0xff), \
+ ((char*)(s))[3]=(char)((c & 0xff)))
/* Do the same but terminate with a null character. */
#define PNG_CSTRING_FROM_CHUNK(s,c)\
(void)(PNG_STRING_FROM_CHUNK(s,c), ((char*)(s))[4] = 0)
/* Test on flag values as defined in the spec (section 5.4): */
-#define PNG_CHUNK_ANCILLIARY(c) (1 & ((c) >> 29))
-#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLIARY(c))
+#define PNG_CHUNK_ANCILLARY(c) (1 & ((c) >> 29))
+#define PNG_CHUNK_CRITICAL(c) (!PNG_CHUNK_ANCILLARY(c))
#define PNG_CHUNK_PRIVATE(c) (1 & ((c) >> 21))
#define PNG_CHUNK_RESERVED(c) (1 & ((c) >> 13))
#define PNG_CHUNK_SAFE_TO_COPY(c) (1 & ((c) >> 5))
@@ -706,113 +783,212 @@ PNG_EXTERN png_fixed_point png_fixed PNGARG((png_structp png_ptr, double fp,
#define PNG_GAMMA_MAC_INVERSE 65909
#define PNG_GAMMA_sRGB_INVERSE 45455
+/* Almost everything below is C specific; the #defines above can be used in
+ * non-C code (so long as it is C-preprocessed) the rest of this stuff cannot.
+ */
+#ifndef PNG_VERSION_INFO_ONLY
+
+#include "pngstruct.h"
+#include "pnginfo.h"
+
+/* Validate the include paths - the include path used to generate pnglibconf.h
+ * must match that used in the build, or we must be using pnglibconf.h.prebuilt:
+ */
+#if PNG_ZLIB_VERNUM != 0 && PNG_ZLIB_VERNUM != ZLIB_VERNUM
+# error ZLIB_VERNUM != PNG_ZLIB_VERNUM \
+ "-I (include path) error: see the notes in pngpriv.h"
+ /* This means that when pnglibconf.h was built the copy of zlib.h that it
+ * used is not the same as the one being used here. Because the build of
+ * libpng makes decisions to use inflateInit2 and inflateReset2 based on the
+ * zlib version number and because this affects handling of certain broken
+ * PNG files the -I directives must match.
+ *
+ * The most likely explanation is that you passed a -I in CFLAGS. This will
+ * not work; all the preprocessor directories and in particular all the -I
+ * directives must be in CPPFLAGS.
+ */
+#endif
+
+/* This is used for 16 bit gamma tables -- only the top level pointers are
+ * const; this could be changed:
+ */
+typedef const png_uint_16p * png_const_uint_16pp;
+
+/* Added to libpng-1.5.7: sRGB conversion tables */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_table, [256]);
+ /* Convert from an sRGB encoded value 0..255 to a 16-bit linear value,
+ * 0..65535. This table gives the closest 16-bit answers (no errors).
+ */
+#endif
+
+PNG_INTERNAL_DATA(const png_uint_16, png_sRGB_base, [512]);
+PNG_INTERNAL_DATA(const png_byte, png_sRGB_delta, [512]);
+
+#define PNG_sRGB_FROM_LINEAR(linear) \
+ ((png_byte)(0xff & ((png_sRGB_base[(linear)>>15] \
+ + ((((linear) & 0x7fff)*png_sRGB_delta[(linear)>>15])>>12)) >> 8)))
+ /* Given a value 'linear' in the range 0..255*65535 calculate the 8-bit sRGB
+ * encoded value with maximum error 0.646365. Note that the input is not a
+ * 16-bit value; it has been multiplied by 255! */
+#endif /* SIMPLIFIED_READ/WRITE */
+
/* Inhibit C++ name-mangling for libpng functions but not for system calls. */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
-/* These functions are used internally in the code. They generally
- * shouldn't be used unless you are writing code to add or replace some
- * functionality in libpng. More information about most functions can
- * be found in the files where the functions are located.
+/* Internal functions; these are not exported from a DLL however because they
+ * are used within several of the C source files they have to be C extern.
+ *
+ * All of these functions must be declared with PNG_INTERNAL_FUNCTION.
*/
+/* Zlib support */
+#define PNG_UNEXPECTED_ZLIB_RETURN (-7)
+PNG_INTERNAL_FUNCTION(void, png_zstream_error,(png_structrp png_ptr, int ret),
+ PNG_EMPTY);
+ /* Used by the zlib handling functions to ensure that z_stream::msg is always
+ * set before they return.
+ */
+
+#ifdef PNG_WRITE_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_free_buffer_list,(png_structrp png_ptr,
+ png_compression_bufferp *list),PNG_EMPTY);
+ /* Free the buffer list used by the compressed write code. */
+#endif
+
+#if defined(PNG_FLOATING_POINT_SUPPORTED) && \
+ !defined(PNG_FIXED_POINT_MACRO_SUPPORTED) && \
+ (defined(PNG_gAMA_SUPPORTED) || defined(PNG_cHRM_SUPPORTED) || \
+ defined(PNG_sCAL_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED) || \
+ defined(PNG_READ_RGB_TO_GRAY_SUPPORTED)) || \
+ (defined(PNG_sCAL_SUPPORTED) && \
+ defined(PNG_FLOATING_ARITHMETIC_SUPPORTED))
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_fixed,(png_const_structrp png_ptr,
+ double fp, png_const_charp text),PNG_EMPTY);
+#endif
+
/* Check the user version string for compatibility, returns false if the version
* numbers aren't compatible.
*/
-PNG_EXTERN int png_user_version_check(png_structp png_ptr,
- png_const_charp user_png_ver);
+PNG_INTERNAL_FUNCTION(int,png_user_version_check,(png_structrp png_ptr,
+ png_const_charp user_png_ver),PNG_EMPTY);
-/* Allocate memory for an internal libpng struct */
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct,PNGARG((int type)),
- PNG_ALLOCATED);
+/* Internal base allocator - no messages, NULL on failure to allocate. This
+ * does, however, call the application provided allocator and that could call
+ * png_error (although that would be a bug in the application implementation.)
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_base,(png_const_structrp png_ptr,
+ png_alloc_size_t size),PNG_ALLOCATED);
-/* Free memory from internal libpng struct */
-PNG_EXTERN void png_destroy_struct PNGARG((png_voidp struct_ptr));
+#if defined(PNG_TEXT_SUPPORTED) || defined(PNG_sPLT_SUPPORTED) ||\
+ defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED)
+/* Internal array allocator, outputs no error or warning messages on failure,
+ * just returns NULL.
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_malloc_array,(png_const_structrp png_ptr,
+ int nelements, size_t element_size),PNG_ALLOCATED);
-PNG_EXTERN PNG_FUNCTION(png_voidp,png_create_struct_2,
- PNGARG((int type, png_malloc_ptr malloc_fn, png_voidp mem_ptr)),
- PNG_ALLOCATED);
-PNG_EXTERN void png_destroy_struct_2 PNGARG((png_voidp struct_ptr,
- png_free_ptr free_fn, png_voidp mem_ptr));
+/* The same but an existing array is extended by add_elements. This function
+ * also memsets the new elements to 0 and copies the old elements. The old
+ * array is not freed or altered.
+ */
+PNG_INTERNAL_FUNCTION(png_voidp,png_realloc_array,(png_const_structrp png_ptr,
+ png_const_voidp array, int old_elements, int add_elements,
+ size_t element_size),PNG_ALLOCATED);
+#endif /* text, sPLT or unknown chunks */
+
+/* Magic to create a struct when there is no struct to call the user supplied
+ * memory allocators. Because error handling has not been set up the memory
+ * handlers can't safely call png_error, but this is an obscure and undocumented
+ * restriction so libpng has to assume that the 'free' handler, at least, might
+ * call png_error.
+ */
+PNG_INTERNAL_FUNCTION(png_structp,png_create_png_struct,
+ (png_const_charp user_png_ver, png_voidp error_ptr, png_error_ptr error_fn,
+ png_error_ptr warn_fn, png_voidp mem_ptr, png_malloc_ptr malloc_fn,
+ png_free_ptr free_fn),PNG_ALLOCATED);
+
+/* Free memory from internal libpng struct */
+PNG_INTERNAL_FUNCTION(void,png_destroy_png_struct,(png_structrp png_ptr),
+ PNG_EMPTY);
-/* Free any memory that info_ptr points to and reset struct. */
-PNG_EXTERN void png_info_destroy PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+/* Free an allocated jmp_buf (always succeeds) */
+PNG_INTERNAL_FUNCTION(void,png_free_jmpbuf,(png_structrp png_ptr),PNG_EMPTY);
/* Function to allocate memory for zlib. PNGAPI is disallowed. */
-PNG_EXTERN PNG_FUNCTION(voidpf,png_zalloc,PNGARG((voidpf png_ptr, uInt items,
- uInt size)),PNG_ALLOCATED);
+PNG_INTERNAL_FUNCTION(voidpf,png_zalloc,(voidpf png_ptr, uInt items, uInt size),
+ PNG_ALLOCATED);
/* Function to free memory for zlib. PNGAPI is disallowed. */
-PNG_EXTERN void png_zfree PNGARG((voidpf png_ptr, voidpf ptr));
+PNG_INTERNAL_FUNCTION(void,png_zfree,(voidpf png_ptr, voidpf ptr),PNG_EMPTY);
/* Next four functions are used internally as callbacks. PNGCBAPI is required
* but not PNG_EXPORT. PNGAPI added at libpng version 1.2.3, changed to
* PNGCBAPI at 1.5.0
*/
-PNG_EXTERN void PNGCBAPI png_default_read_data PNGARG((png_structp png_ptr,
- png_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_read_data,(png_structp png_ptr,
+ png_bytep data, png_size_t length),PNG_EMPTY);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXTERN void PNGCBAPI png_push_fill_buffer PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_push_fill_buffer,(png_structp png_ptr,
+ png_bytep buffer, png_size_t length),PNG_EMPTY);
#endif
-PNG_EXTERN void PNGCBAPI png_default_write_data PNGARG((png_structp png_ptr,
- png_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_write_data,(png_structp png_ptr,
+ png_bytep data, png_size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
# ifdef PNG_STDIO_SUPPORTED
-PNG_EXTERN void PNGCBAPI png_default_flush PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void PNGCBAPI,png_default_flush,(png_structp png_ptr),
+ PNG_EMPTY);
# endif
#endif
/* Reset the CRC variable */
-PNG_EXTERN void png_reset_crc PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_reset_crc,(png_structrp png_ptr),PNG_EMPTY);
/* Write the "data" buffer to whatever output you are using */
-PNG_EXTERN void png_write_data PNGARG((png_structp png_ptr,
- png_const_bytep data, png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_write_data,(png_structrp png_ptr,
+ png_const_bytep data, png_size_t length),PNG_EMPTY);
/* Read and check the PNG file signature */
-PNG_EXTERN void png_read_sig PNGARG((png_structp png_ptr, png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_sig,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
/* Read the chunk header (length + type name) */
-PNG_EXTERN png_uint_32 png_read_chunk_header PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(png_uint_32,png_read_chunk_header,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Read data from whatever input you are using into the "data" buffer */
-PNG_EXTERN void png_read_data PNGARG((png_structp png_ptr, png_bytep data,
- png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_read_data,(png_structrp png_ptr, png_bytep data,
+ png_size_t length),PNG_EMPTY);
/* Read bytes into buf, and update png_ptr->crc */
-PNG_EXTERN void png_crc_read PNGARG((png_structp png_ptr, png_bytep buf,
- png_size_t length));
-
-/* Decompress data in a chunk that uses compression */
-#if defined(PNG_READ_COMPRESSED_TEXT_SUPPORTED)
-PNG_EXTERN void png_decompress_chunk PNGARG((png_structp png_ptr,
- int comp_type, png_size_t chunklength, png_size_t prefix_length,
- png_size_t *data_length));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_crc_read,(png_structrp png_ptr, png_bytep buf,
+ png_uint_32 length),PNG_EMPTY);
/* Read "skip" bytes, read the file crc, and (optionally) verify png_ptr->crc */
-PNG_EXTERN int png_crc_finish PNGARG((png_structp png_ptr, png_uint_32 skip));
+PNG_INTERNAL_FUNCTION(int,png_crc_finish,(png_structrp png_ptr,
+ png_uint_32 skip),PNG_EMPTY);
/* Read the CRC from the file and compare it to the libpng calculated CRC */
-PNG_EXTERN int png_crc_error PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(int,png_crc_error,(png_structrp png_ptr),PNG_EMPTY);
/* Calculate the CRC over a section of data. Note that we are only
* passing a maximum of 64K on systems that have this as a memory limit,
* since this is the maximum buffer size we can specify.
*/
-PNG_EXTERN void png_calculate_crc PNGARG((png_structp png_ptr,
- png_const_bytep ptr, png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_calculate_crc,(png_structrp png_ptr,
+ png_const_bytep ptr, png_size_t length),PNG_EMPTY);
#ifdef PNG_WRITE_FLUSH_SUPPORTED
-PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_flush,(png_structrp png_ptr),PNG_EMPTY);
#endif
/* Write various chunks */
@@ -820,145 +996,130 @@ PNG_EXTERN void png_flush PNGARG((png_structp png_ptr));
/* Write the IHDR chunk, and update the png_struct with the necessary
* information.
*/
-PNG_EXTERN void png_write_IHDR PNGARG((png_structp png_ptr, png_uint_32 width,
- png_uint_32 height,
- int bit_depth, int color_type, int compression_method, int filter_method,
- int interlace_method));
+PNG_INTERNAL_FUNCTION(void,png_write_IHDR,(png_structrp png_ptr,
+ png_uint_32 width, png_uint_32 height, int bit_depth, int color_type,
+ int compression_method, int filter_method, int interlace_method),PNG_EMPTY);
-PNG_EXTERN void png_write_PLTE PNGARG((png_structp png_ptr,
- png_const_colorp palette, png_uint_32 num_pal));
+PNG_INTERNAL_FUNCTION(void,png_write_PLTE,(png_structrp png_ptr,
+ png_const_colorp palette, png_uint_32 num_pal),PNG_EMPTY);
-PNG_EXTERN void png_write_IDAT PNGARG((png_structp png_ptr, png_bytep data,
- png_size_t length));
+PNG_INTERNAL_FUNCTION(void,png_compress_IDAT,(png_structrp png_ptr,
+ png_const_bytep row_data, png_alloc_size_t row_data_length, int flush),
+ PNG_EMPTY);
-PNG_EXTERN void png_write_IEND PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_IEND,(png_structrp png_ptr),PNG_EMPTY);
#ifdef PNG_WRITE_gAMA_SUPPORTED
-# ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA PNGARG((png_structp png_ptr, double file_gamma));
-# endif
-# ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_write_gAMA_fixed PNGARG((png_structp png_ptr,
- png_fixed_point file_gamma));
-# endif
+PNG_INTERNAL_FUNCTION(void,png_write_gAMA_fixed,(png_structrp png_ptr,
+ png_fixed_point file_gamma),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
-PNG_EXTERN void png_write_sBIT PNGARG((png_structp png_ptr,
- png_const_color_8p sbit, int color_type));
+PNG_INTERNAL_FUNCTION(void,png_write_sBIT,(png_structrp png_ptr,
+ png_const_color_8p sbit, int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_cHRM_SUPPORTED
-# ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_write_cHRM PNGARG((png_structp png_ptr,
- double white_x, double white_y,
- double red_x, double red_y, double green_x, double green_y,
- double blue_x, double blue_y));
-# endif
-PNG_EXTERN void png_write_cHRM_fixed PNGARG((png_structp png_ptr,
- png_fixed_point int_white_x, png_fixed_point int_white_y,
- png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
- int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
+PNG_INTERNAL_FUNCTION(void,png_write_cHRM_fixed,(png_structrp png_ptr,
+ const png_xy *xy), PNG_EMPTY);
+ /* The xy value must have been previously validated */
#endif
#ifdef PNG_WRITE_sRGB_SUPPORTED
-PNG_EXTERN void png_write_sRGB PNGARG((png_structp png_ptr,
- int intent));
+PNG_INTERNAL_FUNCTION(void,png_write_sRGB,(png_structrp png_ptr,
+ int intent),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_iCCP_SUPPORTED
-PNG_EXTERN void png_write_iCCP PNGARG((png_structp png_ptr,
- png_const_charp name, int compression_type,
- png_const_charp profile, int proflen));
- /* Note to maintainer: profile should be png_bytep */
+PNG_INTERNAL_FUNCTION(void,png_write_iCCP,(png_structrp png_ptr,
+ png_const_charp name, png_const_bytep profile), PNG_EMPTY);
+ /* The profile must have been previously validated for correctness, the
+ * length comes from the first four bytes. Only the base, deflate,
+ * compression is supported.
+ */
#endif
#ifdef PNG_WRITE_sPLT_SUPPORTED
-PNG_EXTERN void png_write_sPLT PNGARG((png_structp png_ptr,
- png_const_sPLT_tp palette));
+PNG_INTERNAL_FUNCTION(void,png_write_sPLT,(png_structrp png_ptr,
+ png_const_sPLT_tp palette),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_tRNS_SUPPORTED
-PNG_EXTERN void png_write_tRNS PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_tRNS,(png_structrp png_ptr,
png_const_bytep trans, png_const_color_16p values, int number,
- int color_type));
+ int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
-PNG_EXTERN void png_write_bKGD PNGARG((png_structp png_ptr,
- png_const_color_16p values, int color_type));
+PNG_INTERNAL_FUNCTION(void,png_write_bKGD,(png_structrp png_ptr,
+ png_const_color_16p values, int color_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
-PNG_EXTERN void png_write_hIST PNGARG((png_structp png_ptr,
- png_const_uint_16p hist, int num_hist));
+PNG_INTERNAL_FUNCTION(void,png_write_hIST,(png_structrp png_ptr,
+ png_const_uint_16p hist, int num_hist),PNG_EMPTY);
#endif
/* Chunks that have keywords */
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-PNG_EXTERN png_size_t png_check_keyword PNGARG((png_structp png_ptr,
- png_const_charp key, png_charpp new_key));
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
-PNG_EXTERN void png_write_tEXt PNGARG((png_structp png_ptr, png_const_charp key,
- png_const_charp text, png_size_t text_len));
+PNG_INTERNAL_FUNCTION(void,png_write_tEXt,(png_structrp png_ptr,
+ png_const_charp key, png_const_charp text, png_size_t text_len),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_zTXt_SUPPORTED
-PNG_EXTERN void png_write_zTXt PNGARG((png_structp png_ptr, png_const_charp key,
- png_const_charp text, png_size_t text_len, int compression));
+PNG_INTERNAL_FUNCTION(void,png_write_zTXt,(png_structrp png_ptr, png_const_charp
+ key, png_const_charp text, int compression),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_iTXt_SUPPORTED
-PNG_EXTERN void png_write_iTXt PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_iTXt,(png_structrp png_ptr,
int compression, png_const_charp key, png_const_charp lang,
- png_const_charp lang_key, png_const_charp text));
+ png_const_charp lang_key, png_const_charp text),PNG_EMPTY);
#endif
#ifdef PNG_TEXT_SUPPORTED /* Added at version 1.0.14 and 1.2.4 */
-PNG_EXTERN int png_set_text_2 PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_const_textp text_ptr, int num_text));
+PNG_INTERNAL_FUNCTION(int,png_set_text_2,(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_textp text_ptr, int num_text),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
-PNG_EXTERN void png_write_oFFs PNGARG((png_structp png_ptr,
- png_int_32 x_offset, png_int_32 y_offset, int unit_type));
+PNG_INTERNAL_FUNCTION(void,png_write_oFFs,(png_structrp png_ptr,
+ png_int_32 x_offset, png_int_32 y_offset, int unit_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
-PNG_EXTERN void png_write_pCAL PNGARG((png_structp png_ptr, png_charp purpose,
- png_int_32 X0, png_int_32 X1, int type, int nparams,
- png_const_charp units, png_charpp params));
+PNG_INTERNAL_FUNCTION(void,png_write_pCAL,(png_structrp png_ptr,
+ png_charp purpose, png_int_32 X0, png_int_32 X1, int type, int nparams,
+ png_const_charp units, png_charpp params),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_pHYs_SUPPORTED
-PNG_EXTERN void png_write_pHYs PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_write_pHYs,(png_structrp png_ptr,
png_uint_32 x_pixels_per_unit, png_uint_32 y_pixels_per_unit,
- int unit_type));
+ int unit_type),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
-PNG_EXTERN void png_write_tIME PNGARG((png_structp png_ptr,
- png_const_timep mod_time));
+PNG_INTERNAL_FUNCTION(void,png_write_tIME,(png_structrp png_ptr,
+ png_const_timep mod_time),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
-PNG_EXTERN void png_write_sCAL_s PNGARG((png_structp png_ptr,
- int unit, png_const_charp width, png_const_charp height));
+PNG_INTERNAL_FUNCTION(void,png_write_sCAL_s,(png_structrp png_ptr,
+ int unit, png_const_charp width, png_const_charp height),PNG_EMPTY);
#endif
/* Called when finished processing a row of data */
-PNG_EXTERN void png_write_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Internal use only. Called before first row of data */
-PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_write_start_row,(png_structrp png_ptr),
+ PNG_EMPTY);
/* Combine a row of data, dealing with alpha, etc. if requested. 'row' is an
* array of png_ptr->width pixels. If the image is not interlaced or this
- * is the final pass this just does a png_memcpy, otherwise the "display" flag
+ * is the final pass this just does a memcpy, otherwise the "display" flag
* is used to determine whether to copy pixels that are not in the current pass.
*
* Because 'png_do_read_interlace' (below) replicates pixels this allows this
@@ -982,8 +1143,8 @@ PNG_EXTERN void png_write_start_row PNGARG((png_structp png_ptr));
#ifndef PNG_USE_COMPILE_TIME_MASKS
# define PNG_USE_COMPILE_TIME_MASKS 1
#endif
-PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
- int display));
+PNG_INTERNAL_FUNCTION(void,png_combine_row,(png_const_structrp png_ptr,
+ png_bytep row, int display),PNG_EMPTY);
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Expand an interlaced row: the 'row_info' describes the pass data that has
@@ -992,188 +1153,99 @@ PNG_EXTERN void png_combine_row PNGARG((png_structp png_ptr, png_bytep row,
* the pixels are *replicated* to the intervening space. This is essential for
* the correct operation of png_combine_row, above.
*/
-PNG_EXTERN void png_do_read_interlace PNGARG((png_row_infop row_info,
- png_bytep row, int pass, png_uint_32 transformations));
+PNG_INTERNAL_FUNCTION(void,png_do_read_interlace,(png_row_infop row_info,
+ png_bytep row, int pass, png_uint_32 transformations),PNG_EMPTY);
#endif
/* GRR TO DO (2.0 or whenever): simplify other internal calling interfaces */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Grab pixels out of a row for an interlaced pass */
-PNG_EXTERN void png_do_write_interlace PNGARG((png_row_infop row_info,
- png_bytep row, int pass));
+PNG_INTERNAL_FUNCTION(void,png_do_write_interlace,(png_row_infop row_info,
+ png_bytep row, int pass),PNG_EMPTY);
#endif
/* Unfilter a row: check the filter value before calling this, there is no point
* calling it for PNG_FILTER_VALUE_NONE.
*/
-PNG_EXTERN void png_read_filter_row PNGARG((png_structp pp, png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row, int filter));
-
-PNG_EXTERN void png_read_filter_row_up_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_sub3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_sub4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_avg3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_avg4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_paeth3_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
-PNG_EXTERN void png_read_filter_row_paeth4_neon PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep prev_row));
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row,(png_structrp pp, png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row, int filter),PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_neon,(png_row_infop row_info,
+ png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
+ row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
/* Choose the best filter to use and filter the row data */
-PNG_EXTERN void png_write_find_filter PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
+
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_read_IDAT_data,(png_structrp png_ptr,
+ png_bytep output, png_alloc_size_t avail_out),PNG_EMPTY);
+ /* Read 'avail_out' bytes of data from the IDAT stream. If the output buffer
+ * is NULL the function checks, instead, for the end of the stream. In this
+ * case a benign error will be issued if the stream end is not found or if
+ * extra data has to be consumed.
+ */
+PNG_INTERNAL_FUNCTION(void,png_read_finish_IDAT,(png_structrp png_ptr),
+ PNG_EMPTY);
+ /* This cleans up when the IDAT LZ stream does not end when the last image
+ * byte is read; there is still some pending input.
+ */
-/* Finish a row while reading, dealing with interlacing passes, etc. */
-PNG_EXTERN void png_read_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
+ /* Finish a row while reading, dealing with interlacing passes, etc. */
+#endif /* SEQUENTIAL_READ */
/* Initialize the row buffers, etc. */
-PNG_EXTERN void png_read_start_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_read_start_row,(png_structrp png_ptr),PNG_EMPTY);
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
/* Optional call to update the users info structure */
-PNG_EXTERN void png_read_transform_info PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-#endif
-
-/* These are the functions that do the transformations */
-#ifdef PNG_READ_FILLER_SUPPORTED
-PNG_EXTERN void png_do_read_filler PNGARG((png_row_infop row_info,
- png_bytep row, png_uint_32 filler, png_uint_32 flags));
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_read_swap_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_write_swap_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_read_invert_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-PNG_EXTERN void png_do_write_invert_alpha PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_read_transform_info,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
#endif
+/* Shared transform functions, defined in pngtran.c */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
-PNG_EXTERN void png_do_strip_channel PNGARG((png_row_infop row_info,
- png_bytep row, int at_start));
+PNG_INTERNAL_FUNCTION(void,png_do_strip_channel,(png_row_infop row_info,
+ png_bytep row, int at_start),PNG_EMPTY);
#endif
#ifdef PNG_16BIT_SUPPORTED
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
-PNG_EXTERN void png_do_swap PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_do_swap,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#endif
#if defined(PNG_READ_PACKSWAP_SUPPORTED) || \
defined(PNG_WRITE_PACKSWAP_SUPPORTED)
-PNG_EXTERN void png_do_packswap PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
-PNG_EXTERN int png_do_rgb_to_gray PNGARG((png_structp png_ptr,
- png_row_infop row_info, png_bytep row));
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
-PNG_EXTERN void png_do_gray_to_rgb PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
-PNG_EXTERN void png_do_unpack PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
-PNG_EXTERN void png_do_unshift PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_8p sig_bits));
+PNG_INTERNAL_FUNCTION(void,png_do_packswap,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
-PNG_EXTERN void png_do_invert PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
-PNG_EXTERN void png_do_scale_16_to_8 PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-PNG_EXTERN void png_do_chop PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
-PNG_EXTERN void png_do_quantize PNGARG((png_row_infop row_info,
- png_bytep row, png_const_bytep palette_lookup,
- png_const_bytep quantize_lookup));
-
-# ifdef PNG_CORRECT_PALETTE_SUPPORTED
-PNG_EXTERN void png_correct_palette PNGARG((png_structp png_ptr,
- png_colorp palette, int num_palette));
-# endif
+PNG_INTERNAL_FUNCTION(void,png_do_invert,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
-PNG_EXTERN void png_do_bgr PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
-PNG_EXTERN void png_do_pack PNGARG((png_row_infop row_info,
- png_bytep row, png_uint_32 bit_depth));
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
-PNG_EXTERN void png_do_shift PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_8p bit_depth));
-#endif
-
-#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
- defined(PNG_READ_ALPHA_MODE_SUPPORTED)
-PNG_EXTERN void png_do_compose PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
-PNG_EXTERN void png_do_gamma PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
-PNG_EXTERN void png_do_encode_alpha PNGARG((png_row_infop row_info,
- png_bytep row, png_structp png_ptr));
-#endif
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
-PNG_EXTERN void png_do_expand_palette PNGARG((png_row_infop row_info,
- png_bytep row, png_const_colorp palette, png_const_bytep trans,
- int num_trans));
-PNG_EXTERN void png_do_expand PNGARG((png_row_infop row_info,
- png_bytep row, png_const_color_16p trans_color));
-#endif
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
-PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info,
- png_bytep row));
+PNG_INTERNAL_FUNCTION(void,png_do_bgr,(png_row_infop row_info,
+ png_bytep row),PNG_EMPTY);
#endif
/* The following decodes the appropriate chunks, and does error correction,
@@ -1181,256 +1253,283 @@ PNG_EXTERN void png_do_expand_16 PNGARG((png_row_infop row_info,
*/
/* Decode the IHDR chunk */
-PNG_EXTERN void png_handle_IHDR PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_handle_PLTE PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_handle_IEND PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_IHDR,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_PLTE,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_handle_IEND,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#ifdef PNG_READ_bKGD_SUPPORTED
-PNG_EXTERN void png_handle_bKGD PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_bKGD,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_cHRM_SUPPORTED
-PNG_EXTERN void png_handle_cHRM PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_cHRM,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_gAMA_SUPPORTED
-PNG_EXTERN void png_handle_gAMA PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_gAMA,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_hIST_SUPPORTED
-PNG_EXTERN void png_handle_hIST PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_hIST,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_iCCP_SUPPORTED
-PNG_EXTERN void png_handle_iCCP PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-#endif /* PNG_READ_iCCP_SUPPORTED */
+PNG_INTERNAL_FUNCTION(void,png_handle_iCCP,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+#endif /* READ_iCCP */
#ifdef PNG_READ_iTXt_SUPPORTED
-PNG_EXTERN void png_handle_iTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_oFFs_SUPPORTED
-PNG_EXTERN void png_handle_oFFs PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_oFFs,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_pCAL_SUPPORTED
-PNG_EXTERN void png_handle_pCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_pCAL,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_pHYs_SUPPORTED
-PNG_EXTERN void png_handle_pHYs PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_pHYs,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
-PNG_EXTERN void png_handle_sBIT PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sBIT,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sCAL_SUPPORTED
-PNG_EXTERN void png_handle_sCAL PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sCAL,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_sPLT_SUPPORTED
-PNG_EXTERN void png_handle_sPLT PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
-#endif /* PNG_READ_sPLT_SUPPORTED */
+PNG_INTERNAL_FUNCTION(void,png_handle_sPLT,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+#endif /* READ_sPLT */
#ifdef PNG_READ_sRGB_SUPPORTED
-PNG_EXTERN void png_handle_sRGB PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_sRGB,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tEXt_SUPPORTED
-PNG_EXTERN void png_handle_tEXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tIME_SUPPORTED
-PNG_EXTERN void png_handle_tIME PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tIME,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_tRNS_SUPPORTED
-PNG_EXTERN void png_handle_tRNS PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_tRNS,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
#ifdef PNG_READ_zTXt_SUPPORTED
-PNG_EXTERN void png_handle_zTXt PNGARG((png_structp png_ptr, png_infop info_ptr,
- png_uint_32 length));
+PNG_INTERNAL_FUNCTION(void,png_handle_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
#endif
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-PNG_EXTERN void png_handle_unknown PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_check_chunk_name,(png_structrp png_ptr,
+ png_uint_32 chunk_name),PNG_EMPTY);
-PNG_EXTERN void png_check_chunk_name PNGARG((png_structp png_ptr,
- png_uint_32 chunk_name));
+PNG_INTERNAL_FUNCTION(void,png_handle_unknown,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length, int keep),PNG_EMPTY);
+ /* This is the function that gets called for unknown chunks. The 'keep'
+ * argument is either non-zero for a known chunk that has been set to be
+ * handled as unknown or zero for an unknown chunk. By default the function
+ * just skips the chunk or errors out if it is critical.
+ */
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
-/* Exactly as png_handle_as_unknown() except that the argument is a 32-bit chunk
- * name, not a string.
- */
-PNG_EXTERN int png_chunk_unknown_handling PNGARG((png_structp png_ptr,
- png_uint_32 chunk_name));
-#endif
+#if defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) ||\
+ defined(PNG_HANDLE_AS_UNKNOWN_SUPPORTED)
+PNG_INTERNAL_FUNCTION(int,png_chunk_unknown_handling,
+ (png_const_structrp png_ptr, png_uint_32 chunk_name),PNG_EMPTY);
+ /* Exactly as the API png_handle_as_unknown() except that the argument is a
+ * 32-bit chunk name, not a string.
+ */
+#endif /* READ_UNKNOWN_CHUNKS || HANDLE_AS_UNKNOWN */
/* Handle the transformations for reading and writing */
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_do_read_transformations PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_do_read_transformations,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
#endif
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_do_write_transformations PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_do_write_transformations,(png_structrp png_ptr,
+ png_row_infop row_info),PNG_EMPTY);
#endif
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-PNG_EXTERN void png_init_read_transformations PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_init_read_transformations,(png_structrp png_ptr),
+ PNG_EMPTY);
#endif
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
-PNG_EXTERN void png_push_read_chunk PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_read_sig PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_check_crc PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_crc_skip PNGARG((png_structp png_ptr,
- png_uint_32 length));
-PNG_EXTERN void png_push_crc_finish PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_save_buffer PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_restore_buffer PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_read_IDAT PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_process_IDAT_data PNGARG((png_structp png_ptr,
- png_bytep buffer, png_size_t buffer_length));
-PNG_EXTERN void png_push_process_row PNGARG((png_structp png_ptr));
-PNG_EXTERN void png_push_handle_unknown PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_have_info PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_have_end PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_push_have_row PNGARG((png_structp png_ptr, png_bytep row));
-PNG_EXTERN void png_push_read_end PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_process_some_data PNGARG((png_structp png_ptr,
- png_infop info_ptr));
-PNG_EXTERN void png_read_push_finish_row PNGARG((png_structp png_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_crc_skip,(png_structrp png_ptr,
+ png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_crc_finish,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr,
+ png_bytep buffer, png_size_t buffer_length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_IDAT,(png_structrp png_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_process_IDAT_data,(png_structrp png_ptr,
+ png_bytep buffer, png_size_t buffer_length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_process_row,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_handle_unknown,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_info,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_end,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_have_row,(png_structrp png_ptr,
+ png_bytep row),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_end,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_process_some_data,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_read_push_finish_row,(png_structrp png_ptr),
+ PNG_EMPTY);
# ifdef PNG_READ_tEXt_SUPPORTED
-PNG_EXTERN void png_push_handle_tEXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_tEXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_tEXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
# ifdef PNG_READ_zTXt_SUPPORTED
-PNG_EXTERN void png_push_handle_zTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_zTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_zTXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
# ifdef PNG_READ_iTXt_SUPPORTED
-PNG_EXTERN void png_push_handle_iTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_uint_32 length));
-PNG_EXTERN void png_push_read_iTXt PNGARG((png_structp png_ptr,
- png_infop info_ptr));
+PNG_INTERNAL_FUNCTION(void,png_push_handle_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr, png_uint_32 length),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_push_read_iTXt,(png_structrp png_ptr,
+ png_inforp info_ptr),PNG_EMPTY);
# endif
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-PNG_EXTERN void png_do_read_intrapixel PNGARG((png_row_infop row_info,
- png_bytep row));
-PNG_EXTERN void png_do_write_intrapixel PNGARG((png_row_infop row_info,
- png_bytep row));
-#endif
+/* Added at libpng version 1.6.0 */
+#ifdef PNG_GAMMA_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_colorspace_set_gamma,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_fixed_point gAMA), PNG_EMPTY);
+ /* Set the colorspace gamma with a value provided by the application or by
+ * the gAMA chunk on read. The value will override anything set by an ICC
+ * profile.
+ */
-/* Added at libpng version 1.4.0 */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-PNG_EXTERN int png_check_cHRM_fixed PNGARG((png_structp png_ptr,
- png_fixed_point int_white_x, png_fixed_point int_white_y,
- png_fixed_point int_red_x, png_fixed_point int_red_y, png_fixed_point
- int_green_x, png_fixed_point int_green_y, png_fixed_point int_blue_x,
- png_fixed_point int_blue_y));
-#endif
+PNG_INTERNAL_FUNCTION(void,png_colorspace_sync_info,(png_const_structrp png_ptr,
+ png_inforp info_ptr), PNG_EMPTY);
+ /* Synchronize the info 'valid' flags with the colorspace */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
-/* Added at libpng version 1.2.34 and 1.4.0 */
-/* Currently only used by png_check_cHRM_fixed */
-PNG_EXTERN void png_64bit_product PNGARG((long v1, long v2,
- unsigned long *hi_product, unsigned long *lo_product));
+PNG_INTERNAL_FUNCTION(void,png_colorspace_sync,(png_const_structrp png_ptr,
+ png_inforp info_ptr), PNG_EMPTY);
+ /* Copy the png_struct colorspace to the info_struct and call the above to
+ * synchronize the flags. Checks for NULL info_ptr and does nothing.
+ */
#endif
-#ifdef PNG_cHRM_SUPPORTED
-/* Added at libpng version 1.5.5 */
-typedef struct png_xy
-{
- png_fixed_point redx, redy;
- png_fixed_point greenx, greeny;
- png_fixed_point bluex, bluey;
- png_fixed_point whitex, whitey;
-} png_xy;
-
-typedef struct png_XYZ
-{
- png_fixed_point redX, redY, redZ;
- png_fixed_point greenX, greenY, greenZ;
- png_fixed_point blueX, blueY, blueZ;
-} png_XYZ;
-
-/* The conversion APIs return 0 on success, non-zero on a parameter error. They
- * allow conversion between the above representations of a color encoding. When
- * converting from XYZ end points to chromaticities the absolute magnitude of
- * the end points is lost, when converting back the sum of the Y values of the
- * three end points will be 1.0
+/* Added at libpng version 1.4.0 */
+#ifdef PNG_COLORSPACE_SUPPORTED
+/* These internal functions are for maintaining the colorspace structure within
+ * a png_info or png_struct (or, indeed, both).
*/
-PNG_EXTERN int png_xy_from_XYZ PNGARG((png_xy *xy, png_XYZ XYZ));
-PNG_EXTERN int png_XYZ_from_xy PNGARG((png_XYZ *XYZ, png_xy xy));
-PNG_EXTERN int png_XYZ_from_xy_checked PNGARG((png_structp png_ptr,
- png_XYZ *XYZ, png_xy xy));
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_chromaticities,
+ (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_xy *xy,
+ int preferred), PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_endpoints,
+ (png_const_structrp png_ptr, png_colorspacerp colorspace, const png_XYZ *XYZ,
+ int preferred), PNG_EMPTY);
+
+#ifdef PNG_sRGB_SUPPORTED
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_sRGB,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, int intent), PNG_EMPTY);
+ /* This does set the colorspace gAMA and cHRM values too, but doesn't set the
+ * flags to write them, if it returns false there was a problem and an error
+ * message has already been output (but the colorspace may still need to be
+ * synced to record the invalid flag).
+ */
+#endif /* sRGB */
+
+#ifdef PNG_iCCP_SUPPORTED
+PNG_INTERNAL_FUNCTION(int,png_colorspace_set_ICC,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length, png_const_bytep profile, int color_type),
+ PNG_EMPTY);
+ /* The 'name' is used for information only */
+
+/* Routines for checking parts of an ICC profile. */
+PNG_INTERNAL_FUNCTION(int,png_icc_check_length,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length), PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,png_icc_check_header,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length,
+ png_const_bytep profile /* first 132 bytes only */, int color_type),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(int,png_icc_check_tag_table,(png_const_structrp png_ptr,
+ png_colorspacerp colorspace, png_const_charp name,
+ png_uint_32 profile_length,
+ png_const_bytep profile /* header plus whole tag table */), PNG_EMPTY);
+#ifdef PNG_sRGB_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_icc_set_sRGB,(
+ png_const_structrp png_ptr, png_colorspacerp colorspace,
+ png_const_bytep profile, uLong adler), PNG_EMPTY);
+ /* 'adler' is the Adler32 checksum of the uncompressed profile data. It may
+ * be zero to indicate that it is not available. It is used, if provided,
+ * as a fast check on the profile when checking to see if it is sRGB.
+ */
#endif
+#endif /* iCCP */
+
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+PNG_INTERNAL_FUNCTION(void,png_colorspace_set_rgb_coefficients,
+ (png_structrp png_ptr), PNG_EMPTY);
+ /* Set the rgb_to_gray coefficients from the colorspace Y values */
+#endif /* READ_RGB_TO_GRAY */
+#endif /* COLORSPACE */
/* Added at libpng version 1.4.0 */
-PNG_EXTERN void png_check_IHDR PNGARG((png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_check_IHDR,(png_const_structrp png_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
- int filter_type));
+ int filter_type),PNG_EMPTY);
/* Added at libpng version 1.5.10 */
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
-PNG_EXTERN void png_do_check_palette_indexes PNGARG((png_structp png_ptr,
- png_row_infop row_info));
+PNG_INTERNAL_FUNCTION(void,png_do_check_palette_indexes,
+ (png_structrp png_ptr, png_row_infop row_info),PNG_EMPTY);
#endif
-/* Free all memory used by the read (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_read_destroy PNGARG((png_structp png_ptr,
- png_infop info_ptr, png_infop end_info_ptr));
-
-/* Free any memory used in png_ptr struct (old method - NOT DLL EXPORTED) */
-PNG_EXTERN void png_write_destroy PNGARG((png_structp png_ptr));
-
-#ifdef USE_FAR_KEYWORD /* memory model conversion function */
-PNG_EXTERN void *png_far_to_near PNGARG((png_structp png_ptr, png_voidp ptr,
- int check));
-#endif /* USE_FAR_KEYWORD */
-
#if defined(PNG_FLOATING_POINT_SUPPORTED) && defined(PNG_ERROR_TEXT_SUPPORTED)
-PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr,
+PNG_INTERNAL_FUNCTION(void,png_fixed_error,(png_const_structrp png_ptr,
png_const_charp name),PNG_NORETURN);
#endif
@@ -1438,8 +1537,8 @@ PNG_EXTERN PNG_FUNCTION(void, png_fixed_error, (png_structp png_ptr,
* the end. Always leaves the buffer nul terminated. Never errors out (and
* there is no error code.)
*/
-PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos,
- png_const_charp string);
+PNG_INTERNAL_FUNCTION(size_t,png_safecat,(png_charp buffer, size_t bufsize,
+ size_t pos, png_const_charp string),PNG_EMPTY);
/* Various internal functions to handle formatted warning messages, currently
* only implemented for warnings.
@@ -1450,8 +1549,8 @@ PNG_EXTERN size_t png_safecat(png_charp buffer, size_t bufsize, size_t pos,
* Returns the pointer to the start of the formatted string. This utility only
* does unsigned values.
*/
-PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
- int format, png_alloc_size_t number);
+PNG_INTERNAL_FUNCTION(png_charp,png_format_number,(png_const_charp start,
+ png_charp end, int format, png_alloc_size_t number),PNG_EMPTY);
/* Convenience macro that takes an array: */
#define PNG_FORMAT_NUMBER(buffer,format,number) \
@@ -1475,7 +1574,7 @@ PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
#ifdef PNG_WARNINGS_SUPPORTED
/* New defines and members adding in libpng-1.5.4 */
# define PNG_WARNING_PARAMETER_SIZE 32
-# define PNG_WARNING_PARAMETER_COUNT 8
+# define PNG_WARNING_PARAMETER_COUNT 8 /* Maximum 9; see pngerror.c */
/* An l-value of this type has to be passed to the APIs below to cache the
* values of the parameters to a formatted warning message.
@@ -1483,48 +1582,97 @@ PNG_EXTERN png_charp png_format_number(png_const_charp start, png_charp end,
typedef char png_warning_parameters[PNG_WARNING_PARAMETER_COUNT][
PNG_WARNING_PARAMETER_SIZE];
-PNG_EXTERN void png_warning_parameter(png_warning_parameters p, int number,
- png_const_charp string);
- /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
- * including the trailing '\0'.
- */
-PNG_EXTERN void png_warning_parameter_unsigned(png_warning_parameters p,
- int number, int format, png_alloc_size_t value);
- /* Use png_alloc_size_t because it is an unsigned type as big as any we
- * need to output. Use the following for a signed value.
- */
-PNG_EXTERN void png_warning_parameter_signed(png_warning_parameters p,
- int number, int format, png_int_32 value);
-
-PNG_EXTERN void png_formatted_warning(png_structp png_ptr,
- png_warning_parameters p, png_const_charp message);
- /* 'message' follows the X/Open approach of using @1, @2 to insert
- * parameters previously supplied using the above functions. Errors in
- * specifying the paramters will simple result in garbage substitutions.
- */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter,(png_warning_parameters p,
+ int number, png_const_charp string),PNG_EMPTY);
+ /* Parameters are limited in size to PNG_WARNING_PARAMETER_SIZE characters,
+ * including the trailing '\0'.
+ */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter_unsigned,
+ (png_warning_parameters p, int number, int format, png_alloc_size_t value),
+ PNG_EMPTY);
+ /* Use png_alloc_size_t because it is an unsigned type as big as any we
+ * need to output. Use the following for a signed value.
+ */
+PNG_INTERNAL_FUNCTION(void,png_warning_parameter_signed,
+ (png_warning_parameters p, int number, int format, png_int_32 value),
+ PNG_EMPTY);
+
+PNG_INTERNAL_FUNCTION(void,png_formatted_warning,(png_const_structrp png_ptr,
+ png_warning_parameters p, png_const_charp message),PNG_EMPTY);
+ /* 'message' follows the X/Open approach of using @1, @2 to insert
+ * parameters previously supplied using the above functions. Errors in
+ * specifying the parameters will simply result in garbage substitutions.
+ */
#endif
+#ifdef PNG_BENIGN_ERRORS_SUPPORTED
+/* Application errors (new in 1.6); use these functions (declared below) for
+ * errors in the parameters or order of API function calls on read. The
+ * 'warning' should be used for an error that can be handled completely; the
+ * 'error' for one which can be handled safely but which may lose application
+ * information or settings.
+ *
+ * By default these both result in a png_error call prior to release, while in a
+ * released version the 'warning' is just a warning. However if the application
+ * explicitly disables benign errors (explicitly permitting the code to lose
+ * information) they both turn into warnings.
+ *
+ * If benign errors aren't supported they end up as the corresponding base call
+ * (png_warning or png_error.)
+ */
+PNG_INTERNAL_FUNCTION(void,png_app_warning,(png_const_structrp png_ptr,
+ png_const_charp message),PNG_EMPTY);
+ /* The application provided invalid parameters to an API function or called
+ * an API function at the wrong time, libpng can completely recover.
+ */
+
+PNG_INTERNAL_FUNCTION(void,png_app_error,(png_const_structrp png_ptr,
+ png_const_charp message),PNG_EMPTY);
+ /* As above but libpng will ignore the call, or attempt some other partial
+ * recovery from the error.
+ */
+#else
+# define png_app_warning(pp,s) png_warning(pp,s)
+# define png_app_error(pp,s) png_error(pp,s)
+#endif
+
+PNG_INTERNAL_FUNCTION(void,png_chunk_report,(png_const_structrp png_ptr,
+ png_const_charp message, int error),PNG_EMPTY);
+ /* Report a recoverable issue in chunk data. On read this is used to report
+ * a problem found while reading a particular chunk and the
+ * png_chunk_benign_error or png_chunk_warning function is used as
+ * appropriate. On write this is used to report an error that comes from
+ * data set via an application call to a png_set_ API and png_app_error or
+ * png_app_warning is used as appropriate.
+ *
+ * The 'error' parameter must have one of the following values:
+ */
+#define PNG_CHUNK_WARNING 0 /* never an error */
+#define PNG_CHUNK_WRITE_ERROR 1 /* an error only on write */
+#define PNG_CHUNK_ERROR 2 /* always an error */
+
/* ASCII to FP interfaces, currently only implemented if sCAL
* support is required.
*/
-#if defined(PNG_READ_sCAL_SUPPORTED)
+#if defined(PNG_sCAL_SUPPORTED)
/* MAX_DIGITS is actually the maximum number of characters in an sCAL
* width or height, derived from the precision (number of significant
- * digits - a build time settable option) and assumpitions about the
+ * digits - a build time settable option) and assumptions about the
* maximum ridiculous exponent.
*/
#define PNG_sCAL_MAX_DIGITS (PNG_sCAL_PRECISION+1/*.*/+1/*E*/+10/*exponent*/)
#ifdef PNG_FLOATING_POINT_SUPPORTED
-PNG_EXTERN void png_ascii_from_fp PNGARG((png_structp png_ptr, png_charp ascii,
- png_size_t size, double fp, unsigned int precision));
+PNG_INTERNAL_FUNCTION(void,png_ascii_from_fp,(png_const_structrp png_ptr,
+ png_charp ascii, png_size_t size, double fp, unsigned int precision),
+ PNG_EMPTY);
#endif /* FLOATING_POINT */
#ifdef PNG_FIXED_POINT_SUPPORTED
-PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
- png_charp ascii, png_size_t size, png_fixed_point fp));
+PNG_INTERNAL_FUNCTION(void,png_ascii_from_fixed,(png_const_structrp png_ptr,
+ png_charp ascii, png_size_t size, png_fixed_point fp),PNG_EMPTY);
#endif /* FIXED_POINT */
-#endif /* READ_sCAL */
+#endif /* sCAL */
#if defined(PNG_sCAL_SUPPORTED) || defined(PNG_pCAL_SUPPORTED)
/* An internal API to validate the format of a floating point number.
@@ -1548,7 +1696,7 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
* NOTE: The dangling E problem.
* There is a PNG valid floating point number in the following:
*
- * PNG floating point numb1.ers are not greedy.
+ * PNG floating point numbers are not greedy.
*
* Working this out requires *TWO* character lookahead (because of the
* sign), the parser does not do this - it will fail at the 'r' - this
@@ -1598,15 +1746,15 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
#define PNG_FP_IS_ZERO(state) (((state) & PNG_FP_Z_MASK) == PNG_FP_SAW_DIGIT)
#define PNG_FP_IS_POSITIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_Z_MASK)
#define PNG_FP_IS_NEGATIVE(state) (((state) & PNG_FP_NZ_MASK) == PNG_FP_NZ_MASK)
-
-/* The actual parser. This can be called repeatedly, it updates
+
+/* The actual parser. This can be called repeatedly. It updates
* the index into the string and the state variable (which must
- * be initialzed to 0). It returns a result code, as above. There
+ * be initialized to 0). It returns a result code, as above. There
* is no point calling the parser any more if it fails to advance to
* the end of the string - it is stuck on an invalid character (or
* terminated by '\0').
*
- * Note that the pointer will consume an E or even an E+ then leave
+ * Note that the pointer will consume an E or even an E+ and then leave
* a 'maybe' state even though a preceding integer.fraction is valid.
* The PNG_FP_WAS_VALID flag indicates that a preceding substring was
* a valid number. It's possible to recover from this by calling
@@ -1614,8 +1762,8 @@ PNG_EXTERN void png_ascii_from_fixed PNGARG((png_structp png_ptr,
* that omits the last character (i.e. set the size to the index of
* the problem character.) This has not been tested within libpng.
*/
-PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string,
- png_size_t size, int *statep, png_size_tp whereami));
+PNG_INTERNAL_FUNCTION(int,png_check_fp_number,(png_const_charp string,
+ png_size_t size, int *statep, png_size_tp whereami),PNG_EMPTY);
/* This is the same but it checks a complete string and returns true
* only if it just contains a floating point number. As of 1.5.4 this
@@ -1623,11 +1771,11 @@ PNG_EXTERN int png_check_fp_number PNGARG((png_const_charp string,
* it was valid (otherwise it returns 0.) This can be used for testing
* for negative or zero values using the sticky flag.
*/
-PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string,
- png_size_t size));
+PNG_INTERNAL_FUNCTION(int,png_check_fp_string,(png_const_charp string,
+ png_size_t size),PNG_EMPTY);
#endif /* pCAL || sCAL */
-#if defined(PNG_READ_GAMMA_SUPPORTED) ||\
+#if defined(PNG_GAMMA_SUPPORTED) ||\
defined(PNG_INCH_CONVERSIONS_SUPPORTED) || defined(PNG_READ_pHYs_SUPPORTED)
/* Added at libpng version 1.5.0 */
/* This is a utility to provide a*times/div (rounded) and indicate
@@ -1635,29 +1783,37 @@ PNG_EXTERN int png_check_fp_string PNGARG((png_const_charp string,
* for overflow, true (1) if no overflow, in which case *res
* holds the result.
*/
-PNG_EXTERN int png_muldiv PNGARG((png_fixed_point_p res, png_fixed_point a,
- png_int_32 multiplied_by, png_int_32 divided_by));
+PNG_INTERNAL_FUNCTION(int,png_muldiv,(png_fixed_point_p res, png_fixed_point a,
+ png_int_32 multiplied_by, png_int_32 divided_by),PNG_EMPTY);
#endif
#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
/* Same deal, but issue a warning on overflow and return 0. */
-PNG_EXTERN png_fixed_point png_muldiv_warn PNGARG((png_structp png_ptr,
- png_fixed_point a, png_int_32 multiplied_by, png_int_32 divided_by));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_muldiv_warn,
+ (png_const_structrp png_ptr, png_fixed_point a, png_int_32 multiplied_by,
+ png_int_32 divided_by),PNG_EMPTY);
#endif
-#ifdef PNG_READ_GAMMA_SUPPORTED
+#ifdef PNG_GAMMA_SUPPORTED
/* Calculate a reciprocal - used for gamma values. This returns
- * 0 if the argument is 0 in order to maintain an undefined value,
+ * 0 if the argument is 0 in order to maintain an undefined value;
* there are no warnings.
*/
-PNG_EXTERN png_fixed_point png_reciprocal PNGARG((png_fixed_point a));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal,(png_fixed_point a),
+ PNG_EMPTY);
+#ifdef PNG_READ_GAMMA_SUPPORTED
/* The same but gives a reciprocal of the product of two fixed point
* values. Accuracy is suitable for gamma calculations but this is
- * not exact - use png_muldiv for that.
+ * not exact - use png_muldiv for that. Only required at present on read.
*/
-PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a,
- png_fixed_point b));
+PNG_INTERNAL_FUNCTION(png_fixed_point,png_reciprocal2,(png_fixed_point a,
+ png_fixed_point b),PNG_EMPTY);
+#endif
+
+/* Return true if the gamma value is significantly different from 1.0 */
+PNG_INTERNAL_FUNCTION(int,png_gamma_significant,(png_fixed_point gamma_value),
+ PNG_EMPTY);
#endif
#ifdef PNG_READ_GAMMA_SUPPORTED
@@ -1668,19 +1824,93 @@ PNG_EXTERN png_fixed_point png_reciprocal2 PNGARG((png_fixed_point a,
* While the input is an 'unsigned' value it must actually be the
* correct bit value - 0..255 or 0..65535 as required.
*/
-PNG_EXTERN png_uint_16 png_gamma_correct PNGARG((png_structp png_ptr,
- unsigned int value, png_fixed_point gamma_value));
-PNG_EXTERN int png_gamma_significant PNGARG((png_fixed_point gamma_value));
-PNG_EXTERN png_uint_16 png_gamma_16bit_correct PNGARG((unsigned int value,
- png_fixed_point gamma_value));
-PNG_EXTERN png_byte png_gamma_8bit_correct PNGARG((unsigned int value,
- png_fixed_point gamma_value));
-PNG_EXTERN void png_destroy_gamma_table(png_structp png_ptr);
-PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
- int bit_depth));
+PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_correct,(png_structrp png_ptr,
+ unsigned int value, png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_uint_16,png_gamma_16bit_correct,(unsigned int value,
+ png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(png_byte,png_gamma_8bit_correct,(unsigned int value,
+ png_fixed_point gamma_value),PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_destroy_gamma_table,(png_structrp png_ptr),
+ PNG_EMPTY);
+PNG_INTERNAL_FUNCTION(void,png_build_gamma_table,(png_structrp png_ptr,
+ int bit_depth),PNG_EMPTY);
+#endif
+
+/* SIMPLIFIED READ/WRITE SUPPORT */
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) ||\
+ defined(PNG_SIMPLIFIED_WRITE_SUPPORTED)
+/* The internal structure that png_image::opaque points to. */
+typedef struct png_control
+{
+ png_structp png_ptr;
+ png_infop info_ptr;
+ png_voidp error_buf; /* Always a jmp_buf at present. */
+
+ png_const_bytep memory; /* Memory buffer. */
+ png_size_t size; /* Size of the memory buffer. */
+
+ unsigned int for_write :1; /* Otherwise it is a read structure */
+ unsigned int owned_file :1; /* We own the file in io_ptr */
+} png_control;
+
+/* Return the pointer to the jmp_buf from a png_control: necessary because C
+ * does not reveal the type of the elements of jmp_buf.
+ */
+#ifdef __cplusplus
+# define png_control_jmp_buf(pc) (((jmp_buf*)((pc)->error_buf))[0])
+#else
+# define png_control_jmp_buf(pc) ((pc)->error_buf)
+#endif
+
+/* Utility to safely execute a piece of libpng code catching and logging any
+ * errors that might occur. Returns true on success, false on failure (either
+ * of the function or as a result of a png_error.)
+ */
+PNG_INTERNAL_CALLBACK(void,png_safe_error,(png_structp png_ptr,
+ png_const_charp error_message),PNG_NORETURN);
+
+#ifdef PNG_WARNINGS_SUPPORTED
+PNG_INTERNAL_CALLBACK(void,png_safe_warning,(png_structp png_ptr,
+ png_const_charp warning_message),PNG_EMPTY);
+#else
+# define png_safe_warning 0/*dummy argument*/
+#endif
+
+PNG_INTERNAL_FUNCTION(int,png_safe_execute,(png_imagep image,
+ int (*function)(png_voidp), png_voidp arg),PNG_EMPTY);
+
+/* Utility to log an error; this also cleans up the png_image; the function
+ * always returns 0 (false).
+ */
+PNG_INTERNAL_FUNCTION(int,png_image_error,(png_imagep image,
+ png_const_charp error_message),PNG_EMPTY);
+
+#ifndef PNG_SIMPLIFIED_READ_SUPPORTED
+/* png_image_free is used by the write code but not exported */
+PNG_INTERNAL_FUNCTION(void, png_image_free, (png_imagep image), PNG_EMPTY);
+#endif /* !SIMPLIFIED_READ */
+
+#endif /* SIMPLIFIED READ/WRITE */
+
+/* These are initialization functions for hardware specific PNG filter
+ * optimizations; list these here then select the appropriate one at compile
+ * time using the macro PNG_FILTER_OPTIMIZATIONS. If the macro is not defined
+ * the generic code is used.
+ */
+#ifdef PNG_FILTER_OPTIMIZATIONS
+PNG_INTERNAL_FUNCTION(void, PNG_FILTER_OPTIMIZATIONS, (png_structp png_ptr,
+ unsigned int bpp), PNG_EMPTY);
+ /* Just declare the optimization that will be used */
+#else
+ /* List *all* the possible optimizations here - this branch is required if
+ * the builder of libpng passes the definition of PNG_FILTER_OPTIMIZATIONS in
+ * CFLAGS in place of CPPFLAGS *and* uses symbol prefixing.
+ */
+PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
+ (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
#endif
-/* Maintainer: Put new private prototypes here ^ and in libpngpf.3 */
+/* Maintainer: Put new private prototypes here ^ */
#include "pngdebug.h"
@@ -1688,4 +1918,5 @@ PNG_EXTERN void png_build_gamma_table PNGARG((png_structp png_ptr,
}
#endif
+#endif /* PNG_VERSION_INFO_ONLY */
#endif /* PNGPRIV_H */
diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c
index 1d8c6b3346..6764dbe561 100644
--- a/src/3rdparty/libpng/pngread.c
+++ b/src/3rdparty/libpng/pngread.c
@@ -1,8 +1,8 @@
/* pngread.c - read a PNG file
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -15,6 +15,9 @@
*/
#include "pngpriv.h"
+#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+# include <errno.h>
+#endif
#ifdef PNG_READ_SUPPORTED
@@ -23,10 +26,12 @@ PNG_FUNCTION(png_structp,PNGAPI
png_create_read_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
{
-
-#ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
- warn_fn, NULL, NULL, NULL));
+#ifndef PNG_USER_MEM_SUPPORTED
+ png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, NULL, NULL, NULL);
+#else
+ return png_create_read_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, NULL, NULL, NULL);
}
/* Alternate create PNG structure for reading, and allocate any memory
@@ -37,131 +42,40 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
{
-#endif /* PNG_USER_MEM_SUPPORTED */
-
-#ifdef PNG_SETJMP_SUPPORTED
- volatile
-#endif
- png_structp png_ptr;
- volatile int png_cleanup_needed = 0;
-
-#ifdef PNG_SETJMP_SUPPORTED
-#ifdef USE_FAR_KEYWORD
- jmp_buf tmp_jmpbuf;
-#endif
-#endif
-
- png_debug(1, "in png_create_read_struct");
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
- malloc_fn, mem_ptr);
-#else
- png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-#endif
- if (png_ptr == NULL)
- return (NULL);
-
- /* Added at libpng-1.2.6 */
-#ifdef PNG_USER_LIMITS_SUPPORTED
- png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
- png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
-
- /* Added at libpng-1.2.43 and 1.4.0 */
- png_ptr->user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX;
-
- /* Added at libpng-1.2.43 and 1.4.1 */
- png_ptr->user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX;
-#endif
-
-#ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then
- * encounter a png_error() will longjmp here. Since the jmpbuf is
- * then meaningless we abort instead of returning.
- */
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_jmpbuf))
-#else
- if (setjmp(png_jmpbuf(png_ptr))) /* Sets longjmp to match setjmp */
-#endif
- PNG_ABORT();
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
-#endif /* PNG_SETJMP_SUPPORTED */
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-#endif
-
- png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
- /* Call the general version checker (shared with read and write code): */
- if (!png_user_version_check(png_ptr, user_png_ver))
- png_cleanup_needed = 1;
-
- if (!png_cleanup_needed)
- {
- /* Initialize zbuf - compression buffer */
- png_ptr->zbuf_size = PNG_ZBUF_SIZE;
- png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr, png_ptr->zbuf_size);
-
- if (png_ptr->zbuf == NULL)
- png_cleanup_needed = 1;
- }
-
- png_ptr->zstream.zalloc = png_zalloc;
- png_ptr->zstream.zfree = png_zfree;
- png_ptr->zstream.opaque = (voidpf)png_ptr;
+ png_structp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+#endif /* USER_MEM */
- if (!png_cleanup_needed)
+ if (png_ptr != NULL)
{
- switch (inflateInit(&png_ptr->zstream))
- {
- case Z_OK:
- break; /* Do nothing */
-
- case Z_MEM_ERROR:
- png_warning(png_ptr, "zlib memory error");
- png_cleanup_needed = 1;
- break;
+ png_ptr->mode = PNG_IS_READ_STRUCT;
- case Z_STREAM_ERROR:
- png_warning(png_ptr, "zlib stream error");
- png_cleanup_needed = 1;
- break;
-
- case Z_VERSION_ERROR:
- png_warning(png_ptr, "zlib version error");
- png_cleanup_needed = 1;
- break;
+ /* Added in libpng-1.6.0; this can be used to detect a read structure if
+ * required (it will be zero in a write structure.)
+ */
+# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ png_ptr->IDAT_read_size = PNG_IDAT_READ_SIZE;
+# endif
- default: png_warning(png_ptr, "Unknown zlib error");
- png_cleanup_needed = 1;
- }
- }
+# ifdef PNG_BENIGN_READ_ERRORS_SUPPORTED
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
- if (png_cleanup_needed)
- {
- /* Clean up PNG structure and deallocate any memory. */
- png_free(png_ptr, png_ptr->zbuf);
- png_ptr->zbuf = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr,
- (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- return (NULL);
+ /* In stable builds only warn if an application error can be completely
+ * handled.
+ */
+# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
+# endif
+# endif
+
+ /* TODO: delay this, it can be done in png_init_io (if the app doesn't
+ * do it itself) avoiding setting the default function if it is not
+ * required.
+ */
+ png_set_read_fn(png_ptr, NULL, NULL);
}
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
-
- png_set_read_fn(png_ptr, NULL, NULL);
-
-
- return (png_ptr);
+ return png_ptr;
}
@@ -175,8 +89,12 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* read if it is determined that this isn't a valid PNG file.
*/
void PNGAPI
-png_read_info(png_structp png_ptr, png_infop info_ptr)
+png_read_info(png_structrp png_ptr, png_inforp info_ptr)
{
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep;
+#endif
+
png_debug(1, "in png_read_info");
if (png_ptr == NULL || info_ptr == NULL)
@@ -190,13 +108,30 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
- /* This should be a binary subdivision search or a hash for
- * matching the chunk name rather than a linear search.
+ /* IDAT logic needs to happen here to simplify getting the two flags
+ * right.
*/
if (chunk_name == png_IDAT)
- if (png_ptr->mode & PNG_AFTER_IDAT)
- png_ptr->mode |= PNG_HAVE_CHUNK_AFTER_IDAT;
+ {
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "Missing IHDR before IDAT");
+
+ else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
+ png_chunk_error(png_ptr, "Missing PLTE before IDAT");
+
+ else if ((png_ptr->mode & PNG_AFTER_IDAT) != 0)
+ png_chunk_benign_error(png_ptr, "Too many IDATs found");
+
+ png_ptr->mode |= PNG_HAVE_IDAT;
+ }
+
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ /* This should be a binary subdivision search or a hash for
+ * matching the chunk name rather than a linear search.
+ */
if (chunk_name == png_IHDR)
png_handle_IHDR(png_ptr, info_ptr, length);
@@ -204,26 +139,16 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
png_handle_IEND(png_ptr, info_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_AS_DEFAULT)
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
- if (chunk_name == png_IDAT)
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
else if (chunk_name == png_IDAT)
{
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
+ png_ptr->idat_size = 0; /* It has been consumed */
break;
}
}
@@ -233,15 +158,7 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
else if (chunk_name == png_IDAT)
{
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before IDAT");
-
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
- png_error(png_ptr, "Missing PLTE before IDAT");
-
png_ptr->idat_size = length;
- png_ptr->mode |= PNG_HAVE_IDAT;
break;
}
@@ -331,27 +248,36 @@ png_read_info(png_structp png_ptr, png_infop info_ptr)
#endif
else
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
/* Optional call to update the users info_ptr structure */
void PNGAPI
-png_read_update_info(png_structp png_ptr, png_infop info_ptr)
+png_read_update_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_update_info");
- if (png_ptr == NULL)
- return;
+ if (png_ptr != NULL)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ {
+ png_read_start_row(png_ptr);
- png_read_start_row(png_ptr);
+# ifdef PNG_READ_TRANSFORMS_SUPPORTED
+ png_read_transform_info(png_ptr, info_ptr);
+# else
+ PNG_UNUSED(info_ptr)
+# endif
+ }
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
- png_read_transform_info(png_ptr, info_ptr);
-#else
- PNG_UNUSED(info_ptr)
-#endif
+ /* New in 1.6.0 this avoids the bug of doing the initializations twice */
+ else
+ png_app_error(png_ptr,
+ "png_read_update_info/png_start_read_image: duplicate call");
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
@@ -361,21 +287,93 @@ png_read_update_info(png_structp png_ptr, png_infop info_ptr)
* If the user doesn't call this, we will do it ourselves.
*/
void PNGAPI
-png_start_read_image(png_structp png_ptr)
+png_start_read_image(png_structrp png_ptr)
{
png_debug(1, "in png_start_read_image");
if (png_ptr != NULL)
- png_read_start_row(png_ptr);
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ png_read_start_row(png_ptr);
+
+ /* New in 1.6.0 this avoids the bug of doing the initializations twice */
+ else
+ png_app_error(png_ptr,
+ "png_start_read_image/png_read_update_info: duplicate call");
+ }
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
-void PNGAPI
-png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Undoes intrapixel differencing,
+ * NOTE: this is apparently only supported in the 'sequential' reader.
+ */
+static void
+png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
{
- int ret;
+ png_debug(1, "in png_do_read_intrapixel");
+
+ if (
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
+ *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
+ }
+ }
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
+ png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
+ *(rp ) = (png_byte)((red >> 8) & 0xff);
+ *(rp + 1) = (png_byte)(red & 0xff);
+ *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
+ *(rp + 5) = (png_byte)(blue & 0xff);
+ }
+ }
+ }
+}
+#endif /* MNG_FEATURES */
+
+void PNGAPI
+png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
+{
png_row_info row_info;
if (png_ptr == NULL)
@@ -387,7 +385,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
/* png_read_start_row sets the information (in particular iwidth) for this
* interlace pass.
*/
- if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
png_read_start_row(png_ptr);
/* 1.5.6: row_info moved out of png_struct to a local here. */
@@ -398,45 +396,47 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
row_info.pixel_depth = png_ptr->pixel_depth;
row_info.rowbytes = PNG_ROWBYTES(row_info.pixel_depth, row_info.width);
+#ifdef PNG_WARNINGS_SUPPORTED
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{
/* Check for transforms that have been set but were defined out */
#if defined(PNG_WRITE_INVERT_SUPPORTED) && !defined(PNG_READ_INVERT_SUPPORTED)
- if (png_ptr->transformations & PNG_INVERT_MONO)
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_warning(png_ptr, "PNG_READ_INVERT_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_FILLER_SUPPORTED) && !defined(PNG_READ_FILLER_SUPPORTED)
- if (png_ptr->transformations & PNG_FILLER)
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
png_warning(png_ptr, "PNG_READ_FILLER_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
!defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_warning(png_ptr, "PNG_READ_PACKSWAP_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_PACK_SUPPORTED) && !defined(PNG_READ_PACK_SUPPORTED)
- if (png_ptr->transformations & PNG_PACK)
+ if ((png_ptr->transformations & PNG_PACK) != 0)
png_warning(png_ptr, "PNG_READ_PACK_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_SHIFT_SUPPORTED) && !defined(PNG_READ_SHIFT_SUPPORTED)
- if (png_ptr->transformations & PNG_SHIFT)
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_warning(png_ptr, "PNG_READ_SHIFT_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_BGR_SUPPORTED) && !defined(PNG_READ_BGR_SUPPORTED)
- if (png_ptr->transformations & PNG_BGR)
+ if ((png_ptr->transformations & PNG_BGR) != 0)
png_warning(png_ptr, "PNG_READ_BGR_SUPPORTED is not defined");
#endif
#if defined(PNG_WRITE_SWAP_SUPPORTED) && !defined(PNG_READ_SWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_SWAP_BYTES)
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_warning(png_ptr, "PNG_READ_SWAP_SUPPORTED is not defined");
#endif
}
+#endif /* WARNINGS */
#ifdef PNG_READ_INTERLACING_SUPPORTED
/* If interlaced and we do not need a new row, combine row and return.
@@ -445,7 +445,8 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
* untransformed) and, because of the libpng API for interlaced images, this
* means we must transform before de-interlacing.
*/
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
switch (png_ptr->pass)
{
@@ -502,6 +503,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
return;
}
break;
+
case 5:
if ((png_ptr->row_number & 1) || png_ptr->width < 2)
{
@@ -515,7 +517,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
default:
case 6:
- if (!(png_ptr->row_number & 1))
+ if ((png_ptr->row_number & 1) == 0)
{
png_read_finish_row(png_ptr);
return;
@@ -525,52 +527,11 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
png_error(png_ptr, "Invalid attempt to read row data");
- png_ptr->zstream.next_out = png_ptr->row_buf;
- png_ptr->zstream.avail_out =
- (uInt)(PNG_ROWBYTES(png_ptr->pixel_depth,
- png_ptr->iwidth) + 1);
-
- do
- {
- if (!(png_ptr->zstream.avail_in))
- {
- while (!png_ptr->idat_size)
- {
- png_crc_finish(png_ptr, 0);
-
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
- png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_in = png_ptr->zbuf;
- if (png_ptr->zbuf_size > png_ptr->idat_size)
- png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
- png_crc_read(png_ptr, png_ptr->zbuf,
- (png_size_t)png_ptr->zstream.avail_in);
- png_ptr->idat_size -= png_ptr->zstream.avail_in;
- }
-
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-
- if (ret == Z_STREAM_END)
- {
- if (png_ptr->zstream.avail_out || png_ptr->zstream.avail_in ||
- png_ptr->idat_size)
- png_benign_error(png_ptr, "Extra compressed data");
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- if (ret != Z_OK)
- png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
- "Decompression error");
-
- } while (png_ptr->zstream.avail_out);
+ /* Fill the row with IDAT data: */
+ png_read_IDAT_data(png_ptr, png_ptr->row_buf, row_info.rowbytes + 1);
if (png_ptr->row_buf[0] > PNG_FILTER_VALUE_NONE)
{
@@ -586,10 +547,10 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
* it may not be in the future, so this was changed just to copy the
* interlaced count:
*/
- png_memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
+ memcpy(png_ptr->prev_row, png_ptr->row_buf, row_info.rowbytes + 1);
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
{
/* Intrapixel differencing */
@@ -597,7 +558,6 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
}
#endif
-
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
if (png_ptr->transformations)
png_do_read_transformations(png_ptr, &row_info);
@@ -615,9 +575,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
png_error(png_ptr, "internal sequential row size calculation error");
#ifdef PNG_READ_INTERLACING_SUPPORTED
- /* Blow up interlaced rows to full size */
- if (png_ptr->interlaced &&
- (png_ptr->transformations & PNG_INTERLACE))
+ /* Expand interlaced rows to full size */
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
if (png_ptr->pass < 6)
png_do_read_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass,
@@ -643,8 +603,9 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
if (png_ptr->read_row_fn != NULL)
(*(png_ptr->read_row_fn))(png_ptr, png_ptr->row_number, png_ptr->pass);
+
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read one or more rows of image data. If the image is interlaced,
@@ -672,7 +633,7 @@ png_read_row(png_structp png_ptr, png_bytep row, png_bytep dsp_row)
*/
void PNGAPI
-png_read_rows(png_structp png_ptr, png_bytepp row,
+png_read_rows(png_structrp png_ptr, png_bytepp row,
png_bytepp display_row, png_uint_32 num_rows)
{
png_uint_32 i;
@@ -711,7 +672,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
dp++;
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the entire image. If the image has an alpha channel or a tRNS
@@ -727,7 +688,7 @@ png_read_rows(png_structp png_ptr, png_bytepp row,
* [*] png_handle_alpha() does not exist yet, as of this version of libpng
*/
void PNGAPI
-png_read_image(png_structp png_ptr, png_bytepp image)
+png_read_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i, image_height;
int pass, j;
@@ -739,7 +700,7 @@ png_read_image(png_structp png_ptr, png_bytepp image)
return;
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (!(png_ptr->flags & PNG_FLAG_ROW_INIT))
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
{
pass = png_set_interlace_handling(png_ptr);
/* And make sure transforms are initialized. */
@@ -747,7 +708,8 @@ png_read_image(png_structp png_ptr, png_bytepp image)
}
else
{
- if (png_ptr->interlaced && !(png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) == 0)
{
/* Caller called png_start_read_image or png_read_update_info without
* first turning on the PNG_INTERLACE transform. We can fix this here,
@@ -784,7 +746,7 @@ png_read_image(png_structp png_ptr, png_bytepp image)
}
}
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
/* Read the end of the PNG file. Will not read past the end of the
@@ -792,14 +754,24 @@ png_read_image(png_structp png_ptr, png_bytepp image)
* or time information at the end of the file, if info is not NULL.
*/
void PNGAPI
-png_read_end(png_structp png_ptr, png_infop info_ptr)
+png_read_end(png_structrp png_ptr, png_inforp info_ptr)
{
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ int keep;
+#endif
+
png_debug(1, "in png_read_end");
if (png_ptr == NULL)
return;
- png_crc_finish(png_ptr, 0); /* Finish off CRC from last IDAT chunk */
+ /* If png_read_end is called in the middle of reading the rows there may
+ * still be pending IDAT data and an owned zstream. Deal with this here.
+ */
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+ if (png_chunk_unknown_handling(png_ptr, png_IDAT) == 0)
+#endif
+ png_read_finish_IDAT(png_ptr);
#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
/* Report invalid palette index; added at libng-1.5.10 */
@@ -813,22 +785,25 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
png_uint_32 length = png_read_chunk_header(png_ptr);
png_uint_32 chunk_name = png_ptr->chunk_name;
- if (chunk_name == png_IHDR)
+ if (chunk_name == png_IEND)
+ png_handle_IEND(png_ptr, info_ptr, length);
+
+ else if (chunk_name == png_IHDR)
png_handle_IHDR(png_ptr, info_ptr, length);
- else if (chunk_name == png_IEND)
- png_handle_IEND(png_ptr, info_ptr, length);
+ else if (info_ptr == NULL)
+ png_crc_finish(png_ptr, length);
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- else if (png_chunk_unknown_handling(png_ptr, chunk_name) !=
- PNG_HANDLE_CHUNK_AS_DEFAULT)
+ else if ((keep = png_chunk_unknown_handling(png_ptr, chunk_name)) != 0)
{
if (chunk_name == png_IDAT)
{
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ if ((length > 0) ||
+ (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found");
}
- png_handle_unknown(png_ptr, info_ptr, length);
+ png_handle_unknown(png_ptr, info_ptr, length, keep);
if (chunk_name == png_PLTE)
png_ptr->mode |= PNG_HAVE_PLTE;
}
@@ -839,7 +814,7 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
/* Zero length IDATs are legal after the last IDAT has been
* read, but not after other chunks have been read.
*/
- if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT))
+ if ((length > 0) || (png_ptr->mode & PNG_HAVE_CHUNK_AFTER_IDAT) != 0)
png_benign_error(png_ptr, "Too many IDATs found");
png_crc_finish(png_ptr, length);
@@ -933,181 +908,106 @@ png_read_end(png_structp png_ptr, png_infop info_ptr)
#endif
else
- png_handle_unknown(png_ptr, info_ptr, length);
- } while (!(png_ptr->mode & PNG_HAVE_IEND));
-}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
-
-/* Free all memory used by the read */
-void PNGAPI
-png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
- png_infopp end_info_ptr_ptr)
-{
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL, end_info_ptr = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn = NULL;
- png_voidp mem_ptr = NULL;
-#endif
-
- png_debug(1, "in png_destroy_read_struct");
-
- if (png_ptr_ptr != NULL)
- png_ptr = *png_ptr_ptr;
- if (png_ptr == NULL)
- return;
-
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
- mem_ptr = png_ptr->mem_ptr;
-#endif
-
- if (info_ptr_ptr != NULL)
- info_ptr = *info_ptr_ptr;
-
- if (end_info_ptr_ptr != NULL)
- end_info_ptr = *end_info_ptr_ptr;
-
- png_read_destroy(png_ptr, info_ptr, end_info_ptr);
-
- if (info_ptr != NULL)
- {
-#ifdef PNG_TEXT_SUPPORTED
- png_free_data(png_ptr, info_ptr, PNG_FREE_TEXT, -1);
-#endif
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
- *info_ptr_ptr = NULL;
- }
-
- if (end_info_ptr != NULL)
- {
-#ifdef PNG_READ_TEXT_SUPPORTED
- png_free_data(png_ptr, end_info_ptr, PNG_FREE_TEXT, -1);
-#endif
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)end_info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)end_info_ptr);
-#endif
- *end_info_ptr_ptr = NULL;
- }
-
- if (png_ptr != NULL)
- {
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- *png_ptr_ptr = NULL;
- }
+ png_handle_unknown(png_ptr, info_ptr, length,
+ PNG_HANDLE_CHUNK_AS_DEFAULT);
+ } while ((png_ptr->mode & PNG_HAVE_IEND) == 0);
}
+#endif /* SEQUENTIAL_READ */
-/* Free all memory used by the read (old method) */
-void /* PRIVATE */
-png_read_destroy(png_structp png_ptr, png_infop info_ptr,
- png_infop end_info_ptr)
+/* Free all memory used in the read struct */
+static void
+png_read_destroy(png_structrp png_ptr)
{
-#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf tmp_jmp;
-#endif
- png_error_ptr error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_error_ptr warning_fn;
-#endif
- png_voidp error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn;
-#endif
-
png_debug(1, "in png_read_destroy");
- if (info_ptr != NULL)
- png_info_destroy(png_ptr, info_ptr);
-
- if (end_info_ptr != NULL)
- png_info_destroy(png_ptr, end_info_ptr);
-
#ifdef PNG_READ_GAMMA_SUPPORTED
png_destroy_gamma_table(png_ptr);
#endif
- png_free(png_ptr, png_ptr->zbuf);
png_free(png_ptr, png_ptr->big_row_buf);
+ png_ptr->big_row_buf = NULL;
png_free(png_ptr, png_ptr->big_prev_row);
- png_free(png_ptr, png_ptr->chunkdata);
+ png_ptr->big_prev_row = NULL;
+ png_free(png_ptr, png_ptr->read_buffer);
+ png_ptr->read_buffer = NULL;
#ifdef PNG_READ_QUANTIZE_SUPPORTED
png_free(png_ptr, png_ptr->palette_lookup);
+ png_ptr->palette_lookup = NULL;
png_free(png_ptr, png_ptr->quantize_index);
+ png_ptr->quantize_index = NULL;
#endif
- if (png_ptr->free_me & PNG_FREE_PLTE)
+ if ((png_ptr->free_me & PNG_FREE_PLTE) != 0)
+ {
png_zfree(png_ptr, png_ptr->palette);
+ png_ptr->palette = NULL;
+ }
png_ptr->free_me &= ~PNG_FREE_PLTE;
#if defined(PNG_tRNS_SUPPORTED) || \
defined(PNG_READ_EXPAND_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
- if (png_ptr->free_me & PNG_FREE_TRNS)
+ if ((png_ptr->free_me & PNG_FREE_TRNS) != 0)
+ {
png_free(png_ptr, png_ptr->trans_alpha);
+ png_ptr->trans_alpha = NULL;
+ }
png_ptr->free_me &= ~PNG_FREE_TRNS;
#endif
-#ifdef PNG_READ_hIST_SUPPORTED
- if (png_ptr->free_me & PNG_FREE_HIST)
- png_free(png_ptr, png_ptr->hist);
- png_ptr->free_me &= ~PNG_FREE_HIST;
-#endif
-
inflateEnd(&png_ptr->zstream);
#ifdef PNG_PROGRESSIVE_READ_SUPPORTED
png_free(png_ptr, png_ptr->save_buffer);
+ png_ptr->save_buffer = NULL;
#endif
- /* Save the important info out of the png_struct, in case it is
- * being used again.
- */
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+#if defined(PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
#endif
- error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- warning_fn = png_ptr->warning_fn;
-#endif
- error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
#endif
- png_memset(png_ptr, 0, png_sizeof(png_struct));
+ /* NOTE: the 'setjmp' buffer may still be allocated and the memory and error
+ * callbacks are still set at this point. They are required to complete the
+ * destruction of the png_struct itself.
+ */
+}
- png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_ptr->warning_fn = warning_fn;
-#endif
- png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr->free_fn = free_fn;
-#endif
+/* Free all memory used by the read */
+void PNGAPI
+png_destroy_read_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr,
+ png_infopp end_info_ptr_ptr)
+{
+ png_structrp png_ptr = NULL;
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+ png_debug(1, "in png_destroy_read_struct");
+
+ if (png_ptr_ptr != NULL)
+ png_ptr = *png_ptr_ptr;
+
+ if (png_ptr == NULL)
+ return;
+ /* libpng 1.6.0: use the API to destroy info structs to ensure consistent
+ * behavior. Prior to 1.6.0 libpng did extra 'info' destruction in this API.
+ * The extra was, apparently, unnecessary yet this hides memory leak bugs.
+ */
+ png_destroy_info_struct(png_ptr, end_info_ptr_ptr);
+ png_destroy_info_struct(png_ptr, info_ptr_ptr);
+
+ *png_ptr_ptr = NULL;
+ png_read_destroy(png_ptr);
+ png_destroy_png_struct(png_ptr);
}
void PNGAPI
-png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
+png_set_read_status_fn(png_structrp png_ptr, png_read_status_ptr read_row_fn)
{
if (png_ptr == NULL)
return;
@@ -1119,12 +1019,10 @@ png_set_read_status_fn(png_structp png_ptr, png_read_status_ptr read_row_fn)
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_read_png(png_structp png_ptr, png_infop info_ptr,
+png_read_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms,
voidp params)
{
- int row;
-
if (png_ptr == NULL || info_ptr == NULL)
return;
@@ -1132,130 +1030,153 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
* PNG file before the first IDAT (image data chunk).
*/
png_read_info(png_ptr, info_ptr);
- if (info_ptr->height > PNG_UINT_32_MAX/png_sizeof(png_bytep))
+ if (info_ptr->height > PNG_UINT_32_MAX/(sizeof (png_bytep)))
png_error(png_ptr, "Image is too high to process with png_read_png()");
/* -------------- image transformations start here ------------------- */
+ /* libpng 1.6.10: add code to cause a png_app_error if a selected TRANSFORM
+ * is not implemented. This will only happen in de-configured (non-default)
+ * libpng builds. The results can be unexpected - png_read_png may return
+ * short or mal-formed rows because the transform is skipped.
+ */
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Tell libpng to strip 16-bit/color files down to 8 bits per color.
*/
- if (transforms & PNG_TRANSFORM_SCALE_16)
- {
+ if ((transforms & PNG_TRANSFORM_SCALE_16) != 0)
/* Added at libpng-1.5.4. "strip_16" produces the same result that it
* did in earlier versions, while "scale_16" is now more accurate.
*/
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
png_set_scale_16(png_ptr);
- }
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SCALE_16 not supported");
#endif
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
/* If both SCALE and STRIP are required pngrtran will effectively cancel the
* latter by doing SCALE first. This is ok and allows apps not to check for
* which is supported to get the right answer.
*/
- if (transforms & PNG_TRANSFORM_STRIP_16)
+ if ((transforms & PNG_TRANSFORM_STRIP_16) != 0)
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
png_set_strip_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_16 not supported");
#endif
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
/* Strip alpha bytes from the input data without combining with
* the background (not recommended).
*/
- if (transforms & PNG_TRANSFORM_STRIP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_STRIP_ALPHA) != 0)
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
png_set_strip_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_ALPHA not supported");
#endif
-#if defined(PNG_READ_PACK_SUPPORTED) && !defined(PNG_READ_EXPAND_SUPPORTED)
/* Extract multiple pixels with bit depths of 1, 2, or 4 from a single
* byte into separate bytes (useful for paletted and grayscale images).
*/
- if (transforms & PNG_TRANSFORM_PACKING)
+ if ((transforms & PNG_TRANSFORM_PACKING) != 0)
+#ifdef PNG_READ_PACK_SUPPORTED
png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
/* Change the order of packed pixels to least significant bit first
* (not useful if you are using png_set_packing).
*/
- if (transforms & PNG_TRANSFORM_PACKSWAP)
+ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_READ_EXPAND_SUPPORTED
/* Expand paletted colors into true RGB triplets
* Expand grayscale images to full 8 bits from 1, 2, or 4 bits/pixel
* Expand paletted or RGB images with transparency to full alpha
* channels so the data will be available as RGBA quartets.
*/
- if (transforms & PNG_TRANSFORM_EXPAND)
- if ((png_ptr->bit_depth < 8) ||
- (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ||
- (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)))
- png_set_expand(png_ptr);
+ if ((transforms & PNG_TRANSFORM_EXPAND) != 0)
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ png_set_expand(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND not supported");
#endif
/* We don't handle background color or gamma transformation or quantizing.
*/
-#ifdef PNG_READ_INVERT_SUPPORTED
/* Invert monochrome files to have 0 as white and 1 as black
*/
- if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
+#ifdef PNG_READ_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#endif
-#ifdef PNG_READ_SHIFT_SUPPORTED
/* If you want to shift the pixel values from the range [0,255] or
* [0,65535] to the original [0,7] or [0,31], or whatever range the
* colors were originally in:
*/
- if ((transforms & PNG_TRANSFORM_SHIFT)
- && png_get_valid(png_ptr, info_ptr, PNG_INFO_sBIT))
- {
- png_color_8p sig_bit;
-
- png_get_sBIT(png_ptr, info_ptr, &sig_bit);
- png_set_shift(png_ptr, sig_bit);
- }
+ if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_READ_BGR_SUPPORTED
/* Flip the RGB pixels to BGR (or RGBA to BGRA) */
- if (transforms & PNG_TRANSFORM_BGR)
+ if ((transforms & PNG_TRANSFORM_BGR) != 0)
+#ifdef PNG_READ_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
/* Swap the RGBA or GA data to ARGB or AG (or BGRA to ABGR) */
- if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
-#ifdef PNG_READ_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to least significant byte first */
- if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
+#ifdef PNG_READ_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
/* Added at libpng-1.2.41 */
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
- if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* Added at libpng-1.2.41 */
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale image to RGB */
- if (transforms & PNG_TRANSFORM_GRAY_TO_RGB)
+ if ((transforms & PNG_TRANSFORM_GRAY_TO_RGB) != 0)
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
png_set_gray_to_rgb(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_GRAY_TO_RGB not supported");
#endif
/* Added at libpng-1.5.4 */
+ if ((transforms & PNG_TRANSFORM_EXPAND_16) != 0)
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (transforms & PNG_TRANSFORM_EXPAND_16)
png_set_expand_16(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_EXPAND_16 not supported");
#endif
/* We don't handle adding filler bytes */
@@ -1278,16 +1199,17 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
{
png_uint_32 iptr;
- info_ptr->row_pointers = (png_bytepp)png_malloc(png_ptr,
- info_ptr->height * png_sizeof(png_bytep));
+ info_ptr->row_pointers = png_voidcast(png_bytepp, png_malloc(png_ptr,
+ info_ptr->height * (sizeof (png_bytep))));
+
for (iptr=0; iptr<info_ptr->height; iptr++)
info_ptr->row_pointers[iptr] = NULL;
info_ptr->free_me |= PNG_FREE_ROWS;
- for (row = 0; row < (int)info_ptr->height; row++)
- info_ptr->row_pointers[row] = (png_bytep)png_malloc(png_ptr,
- png_get_rowbytes(png_ptr, info_ptr));
+ for (iptr = 0; iptr < info_ptr->height; iptr++)
+ info_ptr->row_pointers[iptr] = png_voidcast(png_bytep,
+ png_malloc(png_ptr, info_ptr->rowbytes));
}
png_read_image(png_ptr, info_ptr->row_pointers);
@@ -1296,10 +1218,2917 @@ png_read_png(png_structp png_ptr, png_infop info_ptr,
/* Read rest of file, and get additional chunks in info_ptr - REQUIRED */
png_read_end(png_ptr, info_ptr);
- PNG_UNUSED(transforms) /* Quiet compiler warnings */
PNG_UNUSED(params)
+}
+#endif /* INFO_IMAGE */
+#endif /* SEQUENTIAL_READ */
+
+#ifdef PNG_SIMPLIFIED_READ_SUPPORTED
+/* SIMPLIFIED READ
+ *
+ * This code currently relies on the sequential reader, though it could easily
+ * be made to work with the progressive one.
+ */
+/* Arguments to png_image_finish_read: */
+
+/* Encoding of PNG data (used by the color-map code) */
+# define P_NOTSET 0 /* File encoding not yet known */
+# define P_sRGB 1 /* 8-bit encoded to sRGB gamma */
+# define P_LINEAR 2 /* 16-bit linear: not encoded, NOT pre-multiplied! */
+# define P_FILE 3 /* 8-bit encoded to file gamma, not sRGB or linear */
+# define P_LINEAR8 4 /* 8-bit linear: only from a file value */
+
+/* Color-map processing: after libpng has run on the PNG image further
+ * processing may be needed to convert the data to color-map indices.
+ */
+#define PNG_CMAP_NONE 0
+#define PNG_CMAP_GA 1 /* Process GA data to a color-map with alpha */
+#define PNG_CMAP_TRANS 2 /* Process GA data to a background index */
+#define PNG_CMAP_RGB 3 /* Process RGB data */
+#define PNG_CMAP_RGB_ALPHA 4 /* Process RGBA data */
+
+/* The following document where the background is for each processing case. */
+#define PNG_CMAP_NONE_BACKGROUND 256
+#define PNG_CMAP_GA_BACKGROUND 231
+#define PNG_CMAP_TRANS_BACKGROUND 254
+#define PNG_CMAP_RGB_BACKGROUND 256
+#define PNG_CMAP_RGB_ALPHA_BACKGROUND 216
+
+typedef struct
+{
+ /* Arguments: */
+ png_imagep image;
+ png_voidp buffer;
+ png_int_32 row_stride;
+ png_voidp colormap;
+ png_const_colorp background;
+ /* Local variables: */
+ png_voidp local_row;
+ png_voidp first_row;
+ ptrdiff_t row_bytes; /* step between rows */
+ int file_encoding; /* E_ values above */
+ png_fixed_point gamma_to_linear; /* For P_FILE, reciprocal of gamma */
+ int colormap_processing; /* PNG_CMAP_ values above */
+} png_image_read_control;
+
+/* Do all the *safe* initialization - 'safe' means that png_error won't be
+ * called, so setting up the jmp_buf is not required. This means that anything
+ * called from here must *not* call png_malloc - it has to call png_malloc_warn
+ * instead so that control is returned safely back to this routine.
+ */
+static int
+png_image_read_init(png_imagep image)
+{
+ if (image->opaque == NULL)
+ {
+ png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, image,
+ png_safe_error, png_safe_warning);
+
+ /* And set the rest of the structure to NULL to ensure that the various
+ * fields are consistent.
+ */
+ memset(image, 0, (sizeof *image));
+ image->version = PNG_IMAGE_VERSION;
+
+ if (png_ptr != NULL)
+ {
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr != NULL)
+ {
+ png_controlp control = png_voidcast(png_controlp,
+ png_malloc_warn(png_ptr, (sizeof *control)));
+
+ if (control != NULL)
+ {
+ memset(control, 0, (sizeof *control));
+
+ control->png_ptr = png_ptr;
+ control->info_ptr = info_ptr;
+ control->for_write = 0;
+
+ image->opaque = control;
+ return 1;
+ }
+
+ /* Error clean up */
+ png_destroy_info_struct(png_ptr, &info_ptr);
+ }
+
+ png_destroy_read_struct(&png_ptr, NULL, NULL);
+ }
+
+ return png_image_error(image, "png_image_read: out of memory");
+ }
+
+ return png_image_error(image, "png_image_read: opaque pointer not NULL");
+}
+
+/* Utility to find the base format of a PNG file from a png_struct. */
+static png_uint_32
+png_image_format(png_structrp png_ptr)
+{
+ png_uint_32 format = 0;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ format |= PNG_FORMAT_FLAG_COLOR;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ format |= PNG_FORMAT_FLAG_ALPHA;
+
+ /* Use png_ptr here, not info_ptr, because by examination png_handle_tRNS
+ * sets the png_struct fields; that's all we are interested in here. The
+ * precise interaction with an app call to png_set_tRNS and PNG file reading
+ * is unclear.
+ */
+ else if (png_ptr->num_trans > 0)
+ format |= PNG_FORMAT_FLAG_ALPHA;
+
+ if (png_ptr->bit_depth == 16)
+ format |= PNG_FORMAT_FLAG_LINEAR;
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_PALETTE) != 0)
+ format |= PNG_FORMAT_FLAG_COLORMAP;
+
+ return format;
+}
+
+/* Is the given gamma significantly different from sRGB? The test is the same
+ * one used in pngrtran.c when deciding whether to do gamma correction. The
+ * arithmetic optimizes the division by using the fact that the inverse of the
+ * file sRGB gamma is 2.2
+ */
+static int
+png_gamma_not_sRGB(png_fixed_point g)
+{
+ if (g < PNG_FP_1)
+ {
+ /* An uninitialized gamma is assumed to be sRGB for the simplified API. */
+ if (g == 0)
+ return 0;
+
+ return png_gamma_significant((g * 11 + 2)/5 /* i.e. *2.2, rounded */);
+ }
+
+ return 1;
+}
+
+/* Do the main body of a 'png_image_begin_read' function; read the PNG file
+ * header and fill in all the information. This is executed in a safe context,
+ * unlike the init routine above.
+ */
+static int
+png_image_read_header(png_voidp argument)
+{
+ png_imagep image = png_voidcast(png_imagep, argument);
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+
+ png_set_benign_errors(png_ptr, 1/*warn*/);
+ png_read_info(png_ptr, info_ptr);
+
+ /* Do this the fast way; just read directly out of png_struct. */
+ image->width = png_ptr->width;
+ image->height = png_ptr->height;
+
+ {
+ png_uint_32 format = png_image_format(png_ptr);
+
+ image->format = format;
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+ /* Does the colorspace match sRGB? If there is no color endpoint
+ * (colorant) information assume yes, otherwise require the
+ * 'ENDPOINTS_MATCHP_sRGB' colorspace flag to have been set. If the
+ * colorspace has been determined to be invalid ignore it.
+ */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0 && ((png_ptr->colorspace.flags
+ & (PNG_COLORSPACE_HAVE_ENDPOINTS|PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB|
+ PNG_COLORSPACE_INVALID)) == PNG_COLORSPACE_HAVE_ENDPOINTS))
+ image->flags |= PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB;
+#endif
+ }
+
+ /* We need the maximum number of entries regardless of the format the
+ * application sets here.
+ */
+ {
+ png_uint_32 cmap_entries;
+
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ cmap_entries = 1U << png_ptr->bit_depth;
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ cmap_entries = png_ptr->num_palette;
+ break;
+
+ default:
+ cmap_entries = 256;
+ break;
+ }
+
+ if (cmap_entries > 256)
+ cmap_entries = 256;
+
+ image->colormap_entries = cmap_entries;
+ }
+
+ return 1;
+}
+
+#ifdef PNG_STDIO_SUPPORTED
+int PNGAPI
+png_image_begin_read_from_stdio(png_imagep image, FILE* file)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file != NULL)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ /* This is slightly evil, but png_init_io doesn't do anything other
+ * than this and we haven't changed the standard IO functions so
+ * this saves a 'safe' function.
+ */
+ image->opaque->png_ptr->io_ptr = file;
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_stdio: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_stdio: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+int PNGAPI
+png_image_begin_read_from_file(png_imagep image, const char *file_name)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file_name != NULL)
+ {
+ FILE *fp = fopen(file_name, "rb");
+
+ if (fp != NULL)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ image->opaque->png_ptr->io_ptr = fp;
+ image->opaque->owned_file = 1;
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+
+ /* Clean up: just the opened file. */
+ (void)fclose(fp);
+ }
+
+ else
+ return png_image_error(image, strerror(errno));
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_file: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_file: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+#endif /* STDIO */
+
+static void PNGCBAPI
+png_image_memory_read(png_structp png_ptr, png_bytep out, png_size_t need)
+{
+ if (png_ptr != NULL)
+ {
+ png_imagep image = png_voidcast(png_imagep, png_ptr->io_ptr);
+ if (image != NULL)
+ {
+ png_controlp cp = image->opaque;
+ if (cp != NULL)
+ {
+ png_const_bytep memory = cp->memory;
+ png_size_t size = cp->size;
+
+ if (memory != NULL && size >= need)
+ {
+ memcpy(out, memory, need);
+ cp->memory = memory + need;
+ cp->size = size - need;
+ return;
+ }
+
+ png_error(png_ptr, "read beyond end of data");
+ }
+ }
+
+ png_error(png_ptr, "invalid memory read");
+ }
+}
+
+int PNGAPI png_image_begin_read_from_memory(png_imagep image,
+ png_const_voidp memory, png_size_t size)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (memory != NULL && size > 0)
+ {
+ if (png_image_read_init(image) != 0)
+ {
+ /* Now set the IO functions to read from the memory buffer and
+ * store it into io_ptr. Again do this in-place to avoid calling a
+ * libpng function that requires error handling.
+ */
+ image->opaque->memory = png_voidcast(png_const_bytep, memory);
+ image->opaque->size = size;
+ image->opaque->png_ptr->io_ptr = image;
+ image->opaque->png_ptr->read_data_fn = png_image_memory_read;
+
+ return png_safe_execute(image, png_image_read_header, image);
+ }
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_begin_read_from_memory: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_begin_read_from_memory: incorrect PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+/* Utility function to skip chunks that are not used by the simplified image
+ * read functions and an appropriate macro to call it.
+ */
+#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+static void
+png_image_skip_unused_chunks(png_structrp png_ptr)
+{
+ /* Prepare the reader to ignore all recognized chunks whose data will not
+ * be used, i.e., all chunks recognized by libpng except for those
+ * involved in basic image reading:
+ *
+ * IHDR, PLTE, IDAT, IEND
+ *
+ * Or image data handling:
+ *
+ * tRNS, bKGD, gAMA, cHRM, sRGB, [iCCP] and sBIT.
+ *
+ * This provides a small performance improvement and eliminates any
+ * potential vulnerability to security problems in the unused chunks.
+ *
+ * At present the iCCP chunk data isn't used, so iCCP chunk can be ignored
+ * too. This allows the simplified API to be compiled without iCCP support,
+ * however if the support is there the chunk is still checked to detect
+ * errors (which are unfortunately quite common.)
+ */
+ {
+ static PNG_CONST png_byte chunks_to_process[] = {
+ 98, 75, 71, 68, '\0', /* bKGD */
+ 99, 72, 82, 77, '\0', /* cHRM */
+ 103, 65, 77, 65, '\0', /* gAMA */
+# ifdef PNG_READ_iCCP_SUPPORTED
+ 105, 67, 67, 80, '\0', /* iCCP */
+# endif
+ 115, 66, 73, 84, '\0', /* sBIT */
+ 115, 82, 71, 66, '\0', /* sRGB */
+ };
+
+ /* Ignore unknown chunks and all other chunks except for the
+ * IHDR, PLTE, tRNS, IDAT, and IEND chunks.
+ */
+ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_NEVER,
+ NULL, -1);
+
+ /* But do not ignore image data handling chunks */
+ png_set_keep_unknown_chunks(png_ptr, PNG_HANDLE_CHUNK_AS_DEFAULT,
+ chunks_to_process, (int)/*SAFE*/(sizeof chunks_to_process)/5);
+ }
+}
+
+# define PNG_SKIP_CHUNKS(p) png_image_skip_unused_chunks(p)
+#else
+# define PNG_SKIP_CHUNKS(p) ((void)0)
+#endif /* HANDLE_AS_UNKNOWN */
+
+/* The following macro gives the exact rounded answer for all values in the
+ * range 0..255 (it actually divides by 51.2, but the rounding still generates
+ * the correct numbers 0..5
+ */
+#define PNG_DIV51(v8) (((v8) * 5 + 130) >> 8)
+
+/* Utility functions to make particular color-maps */
+static void
+set_file_encoding(png_image_read_control *display)
+{
+ png_fixed_point g = display->image->opaque->png_ptr->colorspace.gamma;
+ if (png_gamma_significant(g) != 0)
+ {
+ if (png_gamma_not_sRGB(g) != 0)
+ {
+ display->file_encoding = P_FILE;
+ display->gamma_to_linear = png_reciprocal(g);
+ }
+
+ else
+ display->file_encoding = P_sRGB;
+ }
+
+ else
+ display->file_encoding = P_LINEAR8;
+}
+
+static unsigned int
+decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding)
+{
+ if (encoding == P_FILE) /* double check */
+ encoding = display->file_encoding;
+
+ if (encoding == P_NOTSET) /* must be the file encoding */
+ {
+ set_file_encoding(display);
+ encoding = display->file_encoding;
+ }
+
+ switch (encoding)
+ {
+ case P_FILE:
+ value = png_gamma_16bit_correct(value*257, display->gamma_to_linear);
+ break;
+
+ case P_sRGB:
+ value = png_sRGB_table[value];
+ break;
+
+ case P_LINEAR:
+ break;
+
+ case P_LINEAR8:
+ value *= 257;
+ break;
+
+ default:
+ png_error(display->image->opaque->png_ptr,
+ "unexpected encoding (internal error)");
+ break;
+ }
+
+ return value;
+}
+
+static png_uint_32
+png_colormap_compose(png_image_read_control *display,
+ png_uint_32 foreground, int foreground_encoding, png_uint_32 alpha,
+ png_uint_32 background, int encoding)
+{
+ /* The file value is composed on the background, the background has the given
+ * encoding and so does the result, the file is encoded with P_FILE and the
+ * file and alpha are 8-bit values. The (output) encoding will always be
+ * P_LINEAR or P_sRGB.
+ */
+ png_uint_32 f = decode_gamma(display, foreground, foreground_encoding);
+ png_uint_32 b = decode_gamma(display, background, encoding);
+
+ /* The alpha is always an 8-bit value (it comes from the palette), the value
+ * scaled by 255 is what PNG_sRGB_FROM_LINEAR requires.
+ */
+ f = f * alpha + b * (255-alpha);
+
+ if (encoding == P_LINEAR)
+ {
+ /* Scale to 65535; divide by 255, approximately (in fact this is extremely
+ * accurate, it divides by 255.00000005937181414556, with no overflow.)
+ */
+ f *= 257; /* Now scaled by 65535 */
+ f += f >> 16;
+ f = (f+32768) >> 16;
+ }
+
+ else /* P_sRGB */
+ f = PNG_sRGB_FROM_LINEAR(f);
+
+ return f;
+}
+
+/* NOTE: P_LINEAR values to this routine must be 16-bit, but P_FILE values must
+ * be 8-bit.
+ */
+static void
+png_create_colormap_entry(png_image_read_control *display,
+ png_uint_32 ip, png_uint_32 red, png_uint_32 green, png_uint_32 blue,
+ png_uint_32 alpha, int encoding)
+{
+ png_imagep image = display->image;
+ const int output_encoding = (image->format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ P_LINEAR : P_sRGB;
+ const int convert_to_Y = (image->format & PNG_FORMAT_FLAG_COLOR) == 0 &&
+ (red != green || green != blue);
+
+ if (ip > 255)
+ png_error(image->opaque->png_ptr, "color-map index out of range");
+
+ /* Update the cache with whether the file gamma is significantly different
+ * from sRGB.
+ */
+ if (encoding == P_FILE)
+ {
+ if (display->file_encoding == P_NOTSET)
+ set_file_encoding(display);
+
+ /* Note that the cached value may be P_FILE too, but if it is then the
+ * gamma_to_linear member has been set.
+ */
+ encoding = display->file_encoding;
+ }
+
+ if (encoding == P_FILE)
+ {
+ png_fixed_point g = display->gamma_to_linear;
+
+ red = png_gamma_16bit_correct(red*257, g);
+ green = png_gamma_16bit_correct(green*257, g);
+ blue = png_gamma_16bit_correct(blue*257, g);
+
+ if (convert_to_Y != 0 || output_encoding == P_LINEAR)
+ {
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ else
+ {
+ red = PNG_sRGB_FROM_LINEAR(red * 255);
+ green = PNG_sRGB_FROM_LINEAR(green * 255);
+ blue = PNG_sRGB_FROM_LINEAR(blue * 255);
+ encoding = P_sRGB;
+ }
+ }
+
+ else if (encoding == P_LINEAR8)
+ {
+ /* This encoding occurs quite frequently in test cases because PngSuite
+ * includes a gAMA 1.0 chunk with most images.
+ */
+ red *= 257;
+ green *= 257;
+ blue *= 257;
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ else if (encoding == P_sRGB &&
+ (convert_to_Y != 0 || output_encoding == P_LINEAR))
+ {
+ /* The values are 8-bit sRGB values, but must be converted to 16-bit
+ * linear.
+ */
+ red = png_sRGB_table[red];
+ green = png_sRGB_table[green];
+ blue = png_sRGB_table[blue];
+ alpha *= 257;
+ encoding = P_LINEAR;
+ }
+
+ /* This is set if the color isn't gray but the output is. */
+ if (encoding == P_LINEAR)
+ {
+ if (convert_to_Y != 0)
+ {
+ /* NOTE: these values are copied from png_do_rgb_to_gray */
+ png_uint_32 y = (png_uint_32)6968 * red + (png_uint_32)23434 * green +
+ (png_uint_32)2366 * blue;
+
+ if (output_encoding == P_LINEAR)
+ y = (y + 16384) >> 15;
+
+ else
+ {
+ /* y is scaled by 32768, we need it scaled by 255: */
+ y = (y + 128) >> 8;
+ y *= 255;
+ y = PNG_sRGB_FROM_LINEAR((y + 64) >> 7);
+ alpha = PNG_DIV257(alpha);
+ encoding = P_sRGB;
+ }
+ blue = red = green = y;
+ }
+
+ else if (output_encoding == P_sRGB)
+ {
+ red = PNG_sRGB_FROM_LINEAR(red * 255);
+ green = PNG_sRGB_FROM_LINEAR(green * 255);
+ blue = PNG_sRGB_FROM_LINEAR(blue * 255);
+ alpha = PNG_DIV257(alpha);
+ encoding = P_sRGB;
+ }
+ }
+
+ if (encoding != output_encoding)
+ png_error(image->opaque->png_ptr, "bad encoding (internal error)");
+
+ /* Store the value. */
+ {
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ const int afirst = (image->format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
+# else
+# define afirst 0
+# endif
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ const int bgr = (image->format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+# else
+# define bgr 0
+# endif
+
+ if (output_encoding == P_LINEAR)
+ {
+ png_uint_16p entry = png_voidcast(png_uint_16p, display->colormap);
+
+ entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
+
+ /* The linear 16-bit values must be pre-multiplied by the alpha channel
+ * value, if less than 65535 (this is, effectively, composite on black
+ * if the alpha channel is removed.)
+ */
+ switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
+ {
+ case 4:
+ entry[afirst ? 0 : 3] = (png_uint_16)alpha;
+ /* FALL THROUGH */
+
+ case 3:
+ if (alpha < 65535)
+ {
+ if (alpha > 0)
+ {
+ blue = (blue * alpha + 32767U)/65535U;
+ green = (green * alpha + 32767U)/65535U;
+ red = (red * alpha + 32767U)/65535U;
+ }
+
+ else
+ red = green = blue = 0;
+ }
+ entry[afirst + (2 ^ bgr)] = (png_uint_16)blue;
+ entry[afirst + 1] = (png_uint_16)green;
+ entry[afirst + bgr] = (png_uint_16)red;
+ break;
+
+ case 2:
+ entry[1 ^ afirst] = (png_uint_16)alpha;
+ /* FALL THROUGH */
+
+ case 1:
+ if (alpha < 65535)
+ {
+ if (alpha > 0)
+ green = (green * alpha + 32767U)/65535U;
+
+ else
+ green = 0;
+ }
+ entry[afirst] = (png_uint_16)green;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ else /* output encoding is P_sRGB */
+ {
+ png_bytep entry = png_voidcast(png_bytep, display->colormap);
+
+ entry += ip * PNG_IMAGE_SAMPLE_CHANNELS(image->format);
+
+ switch (PNG_IMAGE_SAMPLE_CHANNELS(image->format))
+ {
+ case 4:
+ entry[afirst ? 0 : 3] = (png_byte)alpha;
+ case 3:
+ entry[afirst + (2 ^ bgr)] = (png_byte)blue;
+ entry[afirst + 1] = (png_byte)green;
+ entry[afirst + bgr] = (png_byte)red;
+ break;
+
+ case 2:
+ entry[1 ^ afirst] = (png_byte)alpha;
+ case 1:
+ entry[afirst] = (png_byte)green;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+# ifdef afirst
+# undef afirst
+# endif
+# ifdef bgr
+# undef bgr
+# endif
+ }
+}
+
+static int
+make_gray_file_colormap(png_image_read_control *display)
+{
+ unsigned int i;
+
+ for (i=0; i<256; ++i)
+ png_create_colormap_entry(display, i, i, i, i, 255, P_FILE);
+
+ return i;
+}
+
+static int
+make_gray_colormap(png_image_read_control *display)
+{
+ unsigned int i;
+
+ for (i=0; i<256; ++i)
+ png_create_colormap_entry(display, i, i, i, i, 255, P_sRGB);
+
+ return i;
+}
+#define PNG_GRAY_COLORMAP_ENTRIES 256
+
+static int
+make_ga_colormap(png_image_read_control *display)
+{
+ unsigned int i, a;
+
+ /* Alpha is retained, the output will be a color-map with entries
+ * selected by six levels of alpha. One transparent entry, 6 gray
+ * levels for all the intermediate alpha values, leaving 230 entries
+ * for the opaque grays. The color-map entries are the six values
+ * [0..5]*51, the GA processing uses PNG_DIV51(value) to find the
+ * relevant entry.
+ *
+ * if (alpha > 229) // opaque
+ * {
+ * // The 231 entries are selected to make the math below work:
+ * base = 0;
+ * entry = (231 * gray + 128) >> 8;
+ * }
+ * else if (alpha < 26) // transparent
+ * {
+ * base = 231;
+ * entry = 0;
+ * }
+ * else // partially opaque
+ * {
+ * base = 226 + 6 * PNG_DIV51(alpha);
+ * entry = PNG_DIV51(gray);
+ * }
+ */
+ i = 0;
+ while (i < 231)
+ {
+ unsigned int gray = (i * 256 + 115) / 231;
+ png_create_colormap_entry(display, i++, gray, gray, gray, 255, P_sRGB);
+ }
+
+ /* 255 is used here for the component values for consistency with the code
+ * that undoes premultiplication in pngwrite.c.
+ */
+ png_create_colormap_entry(display, i++, 255, 255, 255, 0, P_sRGB);
+
+ for (a=1; a<5; ++a)
+ {
+ unsigned int g;
+
+ for (g=0; g<6; ++g)
+ png_create_colormap_entry(display, i++, g*51, g*51, g*51, a*51,
+ P_sRGB);
+ }
+
+ return i;
+}
+
+#define PNG_GA_COLORMAP_ENTRIES 256
+
+static int
+make_rgb_colormap(png_image_read_control *display)
+{
+ unsigned int i, r;
+
+ /* Build a 6x6x6 opaque RGB cube */
+ for (i=r=0; r<6; ++r)
+ {
+ unsigned int g;
+
+ for (g=0; g<6; ++g)
+ {
+ unsigned int b;
+
+ for (b=0; b<6; ++b)
+ png_create_colormap_entry(display, i++, r*51, g*51, b*51, 255,
+ P_sRGB);
+ }
+ }
+
+ return i;
+}
+
+#define PNG_RGB_COLORMAP_ENTRIES 216
+
+/* Return a palette index to the above palette given three 8-bit sRGB values. */
+#define PNG_RGB_INDEX(r,g,b) \
+ ((png_byte)(6 * (6 * PNG_DIV51(r) + PNG_DIV51(g)) + PNG_DIV51(b)))
+
+static int
+png_image_read_colormap(png_voidp argument)
+{
+ png_image_read_control *display =
+ png_voidcast(png_image_read_control*, argument);
+ const png_imagep image = display->image;
+
+ const png_structrp png_ptr = image->opaque->png_ptr;
+ const png_uint_32 output_format = image->format;
+ const int output_encoding = (output_format & PNG_FORMAT_FLAG_LINEAR) != 0 ?
+ P_LINEAR : P_sRGB;
+
+ unsigned int cmap_entries;
+ unsigned int output_processing; /* Output processing option */
+ unsigned int data_encoding = P_NOTSET; /* Encoding libpng must produce */
+
+ /* Background information; the background color and the index of this color
+ * in the color-map if it exists (else 256).
+ */
+ unsigned int background_index = 256;
+ png_uint_32 back_r, back_g, back_b;
+
+ /* Flags to accumulate things that need to be done to the input. */
+ int expand_tRNS = 0;
+
+ /* Exclude the NYI feature of compositing onto a color-mapped buffer; it is
+ * very difficult to do, the results look awful, and it is difficult to see
+ * what possible use it is because the application can't control the
+ * color-map.
+ */
+ if (((png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0 ||
+ png_ptr->num_trans > 0) /* alpha in input */ &&
+ ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0) /* no alpha in output */)
+ {
+ if (output_encoding == P_LINEAR) /* compose on black */
+ back_b = back_g = back_r = 0;
+
+ else if (display->background == NULL /* no way to remove it */)
+ png_error(png_ptr,
+ "a background color must be supplied to remove alpha/transparency");
+
+ /* Get a copy of the background color (this avoids repeating the checks
+ * below.) The encoding is 8-bit sRGB or 16-bit linear, depending on the
+ * output format.
+ */
+ else
+ {
+ back_g = display->background->green;
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) != 0)
+ {
+ back_r = display->background->red;
+ back_b = display->background->blue;
+ }
+ else
+ back_b = back_r = back_g;
+ }
+ }
+
+ else if (output_encoding == P_LINEAR)
+ back_b = back_r = back_g = 65535;
+
+ else
+ back_b = back_r = back_g = 255;
+
+ /* Default the input file gamma if required - this is necessary because
+ * libpng assumes that if no gamma information is present the data is in the
+ * output format, but the simplified API deduces the gamma from the input
+ * format.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) == 0)
+ {
+ /* Do this directly, not using the png_colorspace functions, to ensure
+ * that it happens even if the colorspace is invalid (though probably if
+ * it is the setting will be ignored) Note that the same thing can be
+ * achieved at the application interface with png_set_gAMA.
+ */
+ if (png_ptr->bit_depth == 16 &&
+ (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+ png_ptr->colorspace.gamma = PNG_GAMMA_LINEAR;
+
+ else
+ png_ptr->colorspace.gamma = PNG_GAMMA_sRGB_INVERSE;
+
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+ }
+
+ /* Decide what to do based on the PNG color type of the input data. The
+ * utility function png_create_colormap_entry deals with most aspects of the
+ * output transformations; this code works out how to produce bytes of
+ * color-map entries from the original format.
+ */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_ptr->bit_depth <= 8)
+ {
+ /* There at most 256 colors in the output, regardless of
+ * transparency.
+ */
+ unsigned int step, i, val, trans = 256/*ignore*/, back_alpha = 0;
+
+ cmap_entries = 1U << png_ptr->bit_depth;
+ if (cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "gray[8] color-map: too few entries");
+
+ step = 255 / (cmap_entries - 1);
+ output_processing = PNG_CMAP_NONE;
+
+ /* If there is a tRNS chunk then this either selects a transparent
+ * value or, if the output has no alpha, the background color.
+ */
+ if (png_ptr->num_trans > 0)
+ {
+ trans = png_ptr->trans_color.gray;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) == 0)
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
+ }
+
+ /* png_create_colormap_entry just takes an RGBA and writes the
+ * corresponding color-map entry using the format from 'image',
+ * including the required conversion to sRGB or linear as
+ * appropriate. The input values are always either sRGB (if the
+ * gamma correction flag is 0) or 0..255 scaled file encoded values
+ * (if the function must gamma correct them).
+ */
+ for (i=val=0; i<cmap_entries; ++i, val += step)
+ {
+ /* 'i' is a file value. While this will result in duplicated
+ * entries for 8-bit non-sRGB encoded files it is necessary to
+ * have non-gamma corrected values to do tRNS handling.
+ */
+ if (i != trans)
+ png_create_colormap_entry(display, i, val, val, val, 255,
+ P_FILE/*8-bit with file gamma*/);
+
+ /* Else this entry is transparent. The colors don't matter if
+ * there is an alpha channel (back_alpha == 0), but it does no
+ * harm to pass them in; the values are not set above so this
+ * passes in white.
+ *
+ * NOTE: this preserves the full precision of the application
+ * supplied background color when it is used.
+ */
+ else
+ png_create_colormap_entry(display, i, back_r, back_g, back_b,
+ back_alpha, output_encoding);
+ }
+
+ /* We need libpng to preserve the original encoding. */
+ data_encoding = P_FILE;
+
+ /* The rows from libpng, while technically gray values, are now also
+ * color-map indices; however, they may need to be expanded to 1
+ * byte per pixel. This is what png_set_packing does (i.e., it
+ * unpacks the bit values into bytes.)
+ */
+ if (png_ptr->bit_depth < 8)
+ png_set_packing(png_ptr);
+ }
+
+ else /* bit depth is 16 */
+ {
+ /* The 16-bit input values can be converted directly to 8-bit gamma
+ * encoded values; however, if a tRNS chunk is present 257 color-map
+ * entries are required. This means that the extra entry requires
+ * special processing; add an alpha channel, sacrifice gray level
+ * 254 and convert transparent (alpha==0) entries to that.
+ *
+ * Use libpng to chop the data to 8 bits. Convert it to sRGB at the
+ * same time to minimize quality loss. If a tRNS chunk is present
+ * this means libpng must handle it too; otherwise it is impossible
+ * to do the exact match on the 16-bit value.
+ *
+ * If the output has no alpha channel *and* the background color is
+ * gray then it is possible to let libpng handle the substitution by
+ * ensuring that the corresponding gray level matches the background
+ * color exactly.
+ */
+ data_encoding = P_sRGB;
+
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray[16] color-map: too few entries");
+
+ cmap_entries = make_gray_colormap(display);
+
+ if (png_ptr->num_trans > 0)
+ {
+ unsigned int back_alpha;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ back_alpha = 0;
+
+ else
+ {
+ if (back_r == back_g && back_g == back_b)
+ {
+ /* Background is gray; no special processing will be
+ * required.
+ */
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry
+ * matches.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 65535, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the
+ * sRGB value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ /* NOTE: does this work without expanding tRNS to alpha?
+ * It should be the color->gray case below apparently
+ * doesn't.
+ */
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_NONE;
+ break;
+ }
+#ifdef __COVERITY__
+ /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
+ * here.
+ */
+ back_alpha = 255;
+#else
+ back_alpha = output_encoding == P_LINEAR ? 65535 : 255;
+#endif
+ }
+
+ /* output_processing means that the libpng-processed row will be
+ * 8-bit GA and it has to be processing to single byte color-map
+ * values. Entry 254 is replaced by either a completely
+ * transparent entry or by the background color at full
+ * precision (and the background color is not a simple gray
+ * level in this case.)
+ */
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_TRANS;
+ background_index = 254;
+
+ /* And set (overwrite) color-map entry 254 to the actual
+ * background color at full precision.
+ */
+ png_create_colormap_entry(display, 254, back_r, back_g, back_b,
+ back_alpha, output_encoding);
+ }
+
+ else
+ output_processing = PNG_CMAP_NONE;
+ }
+ break;
+
+ case PNG_COLOR_TYPE_GRAY_ALPHA:
+ /* 8-bit or 16-bit PNG with two channels - gray and alpha. A minimum
+ * of 65536 combinations. If, however, the alpha channel is to be
+ * removed there are only 256 possibilities if the background is gray.
+ * (Otherwise there is a subset of the 65536 possibilities defined by
+ * the triangle between black, white and the background color.)
+ *
+ * Reduce 16-bit files to 8-bit and sRGB encode the result. No need to
+ * worry about tRNS matching - tRNS is ignored if there is an alpha
+ * channel.
+ */
+ data_encoding = P_sRGB;
+
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray+alpha color-map: too few entries");
+
+ cmap_entries = make_ga_colormap(display);
+
+ background_index = PNG_CMAP_GA_BACKGROUND;
+ output_processing = PNG_CMAP_GA;
+ }
+
+ else /* alpha is removed */
+ {
+ /* Alpha must be removed as the PNG data is processed when the
+ * background is a color because the G and A channels are
+ * independent and the vector addition (non-parallel vectors) is a
+ * 2-D problem.
+ *
+ * This can be reduced to the same algorithm as above by making a
+ * colormap containing gray levels (for the opaque grays), a
+ * background entry (for a transparent pixel) and a set of four six
+ * level color values, one set for each intermediate alpha value.
+ * See the comments in make_ga_colormap for how this works in the
+ * per-pixel processing.
+ *
+ * If the background is gray, however, we only need a 256 entry gray
+ * level color map. It is sufficient to make the entry generated
+ * for the background color be exactly the color specified.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0 ||
+ (back_r == back_g && back_g == back_b))
+ {
+ /* Background is gray; no special processing will be required. */
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "gray-alpha color-map: too few entries");
+
+ cmap_entries = make_gray_colormap(display);
+
+ if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry matches. */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 65535, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the sRGB
+ * value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_NONE;
+ }
+
+ else
+ {
+ png_uint_32 i, a;
+
+ /* This is the same as png_make_ga_colormap, above, except that
+ * the entries are all opaque.
+ */
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "ga-alpha color-map: too few entries");
+
+ i = 0;
+ while (i < 231)
+ {
+ png_uint_32 gray = (i * 256 + 115) / 231;
+ png_create_colormap_entry(display, i++, gray, gray, gray,
+ 255, P_sRGB);
+ }
+
+ /* NOTE: this preserves the full precision of the application
+ * background color.
+ */
+ background_index = i;
+ png_create_colormap_entry(display, i++, back_r, back_g, back_b,
+#ifdef __COVERITY__
+ /* Coverity claims that output_encoding cannot be 2 (P_LINEAR)
+ * here.
+ */ 255U,
+#else
+ output_encoding == P_LINEAR ? 65535U : 255U,
+#endif
+ output_encoding);
+
+ /* For non-opaque input composite on the sRGB background - this
+ * requires inverting the encoding for each component. The input
+ * is still converted to the sRGB encoding because this is a
+ * reasonable approximate to the logarithmic curve of human
+ * visual sensitivity, at least over the narrow range which PNG
+ * represents. Consequently 'G' is always sRGB encoded, while
+ * 'A' is linear. We need the linear background colors.
+ */
+ if (output_encoding == P_sRGB) /* else already linear */
+ {
+ /* This may produce a value not exactly matching the
+ * background, but that's ok because these numbers are only
+ * used when alpha != 0
+ */
+ back_r = png_sRGB_table[back_r];
+ back_g = png_sRGB_table[back_g];
+ back_b = png_sRGB_table[back_b];
+ }
+
+ for (a=1; a<5; ++a)
+ {
+ unsigned int g;
+
+ /* PNG_sRGB_FROM_LINEAR expects a 16-bit linear value scaled
+ * by an 8-bit alpha value (0..255).
+ */
+ png_uint_32 alpha = 51 * a;
+ png_uint_32 back_rx = (255-alpha) * back_r;
+ png_uint_32 back_gx = (255-alpha) * back_g;
+ png_uint_32 back_bx = (255-alpha) * back_b;
+
+ for (g=0; g<6; ++g)
+ {
+ png_uint_32 gray = png_sRGB_table[g*51] * alpha;
+
+ png_create_colormap_entry(display, i++,
+ PNG_sRGB_FROM_LINEAR(gray + back_rx),
+ PNG_sRGB_FROM_LINEAR(gray + back_gx),
+ PNG_sRGB_FROM_LINEAR(gray + back_bx), 255, P_sRGB);
+ }
+ }
+
+ cmap_entries = i;
+ output_processing = PNG_CMAP_GA;
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_RGB:
+ case PNG_COLOR_TYPE_RGB_ALPHA:
+ /* Exclude the case where the output is gray; we can always handle this
+ * with the cases above.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_COLOR) == 0)
+ {
+ /* The color-map will be grayscale, so we may as well convert the
+ * input RGB values to a simple grayscale and use the grayscale
+ * code above.
+ *
+ * NOTE: calling this apparently damages the recognition of the
+ * transparent color in background color handling; call
+ * png_set_tRNS_to_alpha before png_set_background_fixed.
+ */
+ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE, -1,
+ -1);
+ data_encoding = P_sRGB;
+
+ /* The output will now be one or two 8-bit gray or gray+alpha
+ * channels. The more complex case arises when the input has alpha.
+ */
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0) &&
+ (output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Both input and output have an alpha channel, so no background
+ * processing is required; just map the GA bytes to the right
+ * color-map entry.
+ */
+ expand_tRNS = 1;
+
+ if (PNG_GA_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb[ga] color-map: too few entries");
+
+ cmap_entries = make_ga_colormap(display);
+ background_index = PNG_CMAP_GA_BACKGROUND;
+ output_processing = PNG_CMAP_GA;
+ }
+
+ else
+ {
+ /* Either the input or the output has no alpha channel, so there
+ * will be no non-opaque pixels in the color-map; it will just be
+ * grayscale.
+ */
+ if (PNG_GRAY_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb[gray] color-map: too few entries");
+
+ /* Ideally this code would use libpng to do the gamma correction,
+ * but if an input alpha channel is to be removed we will hit the
+ * libpng bug in gamma+compose+rgb-to-gray (the double gamma
+ * correction bug). Fix this by dropping the gamma correction in
+ * this case and doing it in the palette; this will result in
+ * duplicate palette entries, but that's better than the
+ * alternative of double gamma correction.
+ */
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0) &&
+ png_gamma_not_sRGB(png_ptr->colorspace.gamma) != 0)
+ {
+ cmap_entries = make_gray_file_colormap(display);
+ data_encoding = P_FILE;
+ }
+
+ else
+ cmap_entries = make_gray_colormap(display);
+
+ /* But if the input has alpha or transparency it must be removed
+ */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0)
+ {
+ png_color_16 c;
+ png_uint_32 gray = back_g;
+
+ /* We need to ensure that the application background exists in
+ * the colormap and that completely transparent pixels map to
+ * it. Achieve this simply by ensuring that the entry
+ * selected for the background really is the background color.
+ */
+ if (data_encoding == P_FILE) /* from the fixup above */
+ {
+ /* The app supplied a gray which is in output_encoding, we
+ * need to convert it to a value of the input (P_FILE)
+ * encoding then set this palette entry to the required
+ * output encoding.
+ */
+ if (output_encoding == P_sRGB)
+ gray = png_sRGB_table[gray]; /* now P_LINEAR */
+
+ gray = PNG_DIV257(png_gamma_16bit_correct(gray,
+ png_ptr->colorspace.gamma)); /* now P_FILE */
+
+ /* And make sure the corresponding palette entry contains
+ * exactly the required sRGB value.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 0/*unused*/, output_encoding);
+ }
+
+ else if (output_encoding == P_LINEAR)
+ {
+ gray = PNG_sRGB_FROM_LINEAR(gray * 255);
+
+ /* And make sure the corresponding palette entry matches.
+ */
+ png_create_colormap_entry(display, gray, back_g, back_g,
+ back_g, 0/*unused*/, P_LINEAR);
+ }
+
+ /* The background passed to libpng, however, must be the
+ * output (normally sRGB) value.
+ */
+ c.index = 0; /*unused*/
+ c.gray = c.red = c.green = c.blue = (png_uint_16)gray;
+
+ /* NOTE: the following is apparently a bug in libpng. Without
+ * it the transparent color recognition in
+ * png_set_background_fixed seems to go wrong.
+ */
+ expand_tRNS = 1;
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+ }
+
+ output_processing = PNG_CMAP_NONE;
+ }
+ }
+
+ else /* output is color */
+ {
+ /* We could use png_quantize here so long as there is no transparent
+ * color or alpha; png_quantize ignores alpha. Easier overall just
+ * to do it once and using PNG_DIV51 on the 6x6x6 reduced RGB cube.
+ * Consequently we always want libpng to produce sRGB data.
+ */
+ data_encoding = P_sRGB;
+
+ /* Is there any transparency or alpha? */
+ if (png_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ png_ptr->num_trans > 0)
+ {
+ /* Is there alpha in the output too? If so all four channels are
+ * processed into a special RGB cube with alpha support.
+ */
+ if ((output_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ png_uint_32 r;
+
+ if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
+ png_error(png_ptr, "rgb+alpha color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+
+ /* Add a transparent entry. */
+ png_create_colormap_entry(display, cmap_entries, 255, 255,
+ 255, 0, P_sRGB);
+
+ /* This is stored as the background index for the processing
+ * algorithm.
+ */
+ background_index = cmap_entries++;
+
+ /* Add 27 r,g,b entries each with alpha 0.5. */
+ for (r=0; r<256; r = (r << 1) | 0x7f)
+ {
+ png_uint_32 g;
+
+ for (g=0; g<256; g = (g << 1) | 0x7f)
+ {
+ png_uint_32 b;
+
+ /* This generates components with the values 0, 127 and
+ * 255
+ */
+ for (b=0; b<256; b = (b << 1) | 0x7f)
+ png_create_colormap_entry(display, cmap_entries++,
+ r, g, b, 128, P_sRGB);
+ }
+ }
+
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_RGB_ALPHA;
+ }
+
+ else
+ {
+ /* Alpha/transparency must be removed. The background must
+ * exist in the color map (achieved by setting adding it after
+ * the 666 color-map). If the standard processing code will
+ * pick up this entry automatically that's all that is
+ * required; libpng can be called to do the background
+ * processing.
+ */
+ unsigned int sample_size =
+ PNG_IMAGE_SAMPLE_SIZE(output_format);
+ png_uint_32 r, g, b; /* sRGB background */
+
+ if (PNG_RGB_COLORMAP_ENTRIES+1+27 > image->colormap_entries)
+ png_error(png_ptr, "rgb-alpha color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+
+ png_create_colormap_entry(display, cmap_entries, back_r,
+ back_g, back_b, 0/*unused*/, output_encoding);
+
+ if (output_encoding == P_LINEAR)
+ {
+ r = PNG_sRGB_FROM_LINEAR(back_r * 255);
+ g = PNG_sRGB_FROM_LINEAR(back_g * 255);
+ b = PNG_sRGB_FROM_LINEAR(back_b * 255);
+ }
+
+ else
+ {
+ r = back_r;
+ g = back_g;
+ b = back_g;
+ }
+
+ /* Compare the newly-created color-map entry with the one the
+ * PNG_CMAP_RGB algorithm will use. If the two entries don't
+ * match, add the new one and set this as the background
+ * index.
+ */
+ if (memcmp((png_const_bytep)display->colormap +
+ sample_size * cmap_entries,
+ (png_const_bytep)display->colormap +
+ sample_size * PNG_RGB_INDEX(r,g,b),
+ sample_size) != 0)
+ {
+ /* The background color must be added. */
+ background_index = cmap_entries++;
+
+ /* Add 27 r,g,b entries each with created by composing with
+ * the background at alpha 0.5.
+ */
+ for (r=0; r<256; r = (r << 1) | 0x7f)
+ {
+ for (g=0; g<256; g = (g << 1) | 0x7f)
+ {
+ /* This generates components with the values 0, 127
+ * and 255
+ */
+ for (b=0; b<256; b = (b << 1) | 0x7f)
+ png_create_colormap_entry(display, cmap_entries++,
+ png_colormap_compose(display, r, P_sRGB, 128,
+ back_r, output_encoding),
+ png_colormap_compose(display, g, P_sRGB, 128,
+ back_g, output_encoding),
+ png_colormap_compose(display, b, P_sRGB, 128,
+ back_b, output_encoding),
+ 0/*unused*/, output_encoding);
+ }
+ }
+
+ expand_tRNS = 1;
+ output_processing = PNG_CMAP_RGB_ALPHA;
+ }
+
+ else /* background color is in the standard color-map */
+ {
+ png_color_16 c;
+
+ c.index = 0; /*unused*/
+ c.red = (png_uint_16)back_r;
+ c.gray = c.green = (png_uint_16)back_g;
+ c.blue = (png_uint_16)back_b;
+
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+
+ output_processing = PNG_CMAP_RGB;
+ }
+ }
+ }
+
+ else /* no alpha or transparency in the input */
+ {
+ /* Alpha in the output is irrelevant, simply map the opaque input
+ * pixels to the 6x6x6 color-map.
+ */
+ if (PNG_RGB_COLORMAP_ENTRIES > image->colormap_entries)
+ png_error(png_ptr, "rgb color-map: too few entries");
+
+ cmap_entries = make_rgb_colormap(display);
+ output_processing = PNG_CMAP_RGB;
+ }
+ }
+ break;
+
+ case PNG_COLOR_TYPE_PALETTE:
+ /* It's already got a color-map. It may be necessary to eliminate the
+ * tRNS entries though.
+ */
+ {
+ unsigned int num_trans = png_ptr->num_trans;
+ png_const_bytep trans = num_trans > 0 ? png_ptr->trans_alpha : NULL;
+ png_const_colorp colormap = png_ptr->palette;
+ const int do_background = trans != NULL &&
+ (output_format & PNG_FORMAT_FLAG_ALPHA) == 0;
+ unsigned int i;
+
+ /* Just in case: */
+ if (trans == NULL)
+ num_trans = 0;
+
+ output_processing = PNG_CMAP_NONE;
+ data_encoding = P_FILE; /* Don't change from color-map indices */
+ cmap_entries = png_ptr->num_palette;
+ if (cmap_entries > 256)
+ cmap_entries = 256;
+
+ if (cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "palette color-map: too few entries");
+
+ for (i=0; i < cmap_entries; ++i)
+ {
+ if (do_background != 0 && i < num_trans && trans[i] < 255)
+ {
+ if (trans[i] == 0)
+ png_create_colormap_entry(display, i, back_r, back_g,
+ back_b, 0, output_encoding);
+
+ else
+ {
+ /* Must compose the PNG file color in the color-map entry
+ * on the sRGB color in 'back'.
+ */
+ png_create_colormap_entry(display, i,
+ png_colormap_compose(display, colormap[i].red, P_FILE,
+ trans[i], back_r, output_encoding),
+ png_colormap_compose(display, colormap[i].green, P_FILE,
+ trans[i], back_g, output_encoding),
+ png_colormap_compose(display, colormap[i].blue, P_FILE,
+ trans[i], back_b, output_encoding),
+ output_encoding == P_LINEAR ? trans[i] * 257U :
+ trans[i],
+ output_encoding);
+ }
+ }
+
+ else
+ png_create_colormap_entry(display, i, colormap[i].red,
+ colormap[i].green, colormap[i].blue,
+ i < num_trans ? trans[i] : 255U, P_FILE/*8-bit*/);
+ }
+
+ /* The PNG data may have indices packed in fewer than 8 bits, it
+ * must be expanded if so.
+ */
+ if (png_ptr->bit_depth < 8)
+ png_set_packing(png_ptr);
+ }
+ break;
+
+ default:
+ png_error(png_ptr, "invalid PNG color type");
+ /*NOT REACHED*/
+ break;
+ }
+
+ /* Now deal with the output processing */
+ if (expand_tRNS != 0 && png_ptr->num_trans > 0 &&
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) == 0)
+ png_set_tRNS_to_alpha(png_ptr);
+
+ switch (data_encoding)
+ {
+ default:
+ png_error(png_ptr, "bad data option (internal error)");
+ break;
+
+ case P_sRGB:
+ /* Change to 8-bit sRGB */
+ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB);
+ /* FALL THROUGH */
+
+ case P_FILE:
+ if (png_ptr->bit_depth > 8)
+ png_set_scale_16(png_ptr);
+ break;
+ }
+
+ if (cmap_entries > 256 || cmap_entries > image->colormap_entries)
+ png_error(png_ptr, "color map overflow (BAD internal error)");
+
+ image->colormap_entries = cmap_entries;
+
+ /* Double check using the recorded background index */
+ switch (output_processing)
+ {
+ case PNG_CMAP_NONE:
+ if (background_index != PNG_CMAP_NONE_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_GA:
+ if (background_index != PNG_CMAP_GA_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_TRANS:
+ if (background_index >= cmap_entries ||
+ background_index != PNG_CMAP_TRANS_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_RGB:
+ if (background_index != PNG_CMAP_RGB_BACKGROUND)
+ goto bad_background;
+ break;
+
+ case PNG_CMAP_RGB_ALPHA:
+ if (background_index != PNG_CMAP_RGB_ALPHA_BACKGROUND)
+ goto bad_background;
+ break;
+
+ default:
+ png_error(png_ptr, "bad processing option (internal error)");
+
+ bad_background:
+ png_error(png_ptr, "bad background index (internal error)");
+ }
+
+ display->colormap_processing = output_processing;
+
+ return 1/*ok*/;
+}
+
+/* The final part of the color-map read called from png_image_finish_read. */
+static int
+png_image_read_and_map(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ int passes;
+
+ /* Called when the libpng data must be transformed into the color-mapped
+ * form. There is a local row buffer in display->local and this routine must
+ * do the interlace handling.
+ */
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ {
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ int proc = display->colormap_processing;
+ png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+ ptrdiff_t step_row = display->row_bytes;
+ int pass;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass);
+ stepx = PNG_PASS_COL_OFFSET(pass);
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep, display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read read the libpng data into the temporary buffer. */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now process the row according to the processing option, note
+ * that the caller verifies that the format of the libpng output
+ * data is as required.
+ */
+ outrow += startx;
+ switch (proc)
+ {
+ case PNG_CMAP_GA:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ /* The data is always in the PNG order */
+ unsigned int gray = *inrow++;
+ unsigned int alpha = *inrow++;
+ unsigned int entry;
+
+ /* NOTE: this code is copied as a comment in
+ * make_ga_colormap above. Please update the
+ * comment if you change this code!
+ */
+ if (alpha > 229) /* opaque */
+ {
+ entry = (231 * gray + 128) >> 8;
+ }
+ else if (alpha < 26) /* transparent */
+ {
+ entry = 231;
+ }
+ else /* partially opaque */
+ {
+ entry = 226 + 6 * PNG_DIV51(alpha) + PNG_DIV51(gray);
+ }
+
+ *outrow = (png_byte)entry;
+ }
+ break;
+
+ case PNG_CMAP_TRANS:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte gray = *inrow++;
+ png_byte alpha = *inrow++;
+
+ if (alpha == 0)
+ *outrow = PNG_CMAP_TRANS_BACKGROUND;
+
+ else if (gray != PNG_CMAP_TRANS_BACKGROUND)
+ *outrow = gray;
+
+ else
+ *outrow = (png_byte)(PNG_CMAP_TRANS_BACKGROUND+1);
+ }
+ break;
+
+ case PNG_CMAP_RGB:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ *outrow = PNG_RGB_INDEX(inrow[0], inrow[1], inrow[2]);
+ inrow += 3;
+ }
+ break;
+
+ case PNG_CMAP_RGB_ALPHA:
+ for (; outrow < end_row; outrow += stepx)
+ {
+ unsigned int alpha = inrow[3];
+
+ /* Because the alpha entries only hold alpha==0.5 values
+ * split the processing at alpha==0.25 (64) and 0.75
+ * (196).
+ */
+
+ if (alpha >= 196)
+ *outrow = PNG_RGB_INDEX(inrow[0], inrow[1],
+ inrow[2]);
+
+ else if (alpha < 64)
+ *outrow = PNG_CMAP_RGB_ALPHA_BACKGROUND;
+
+ else
+ {
+ /* Likewise there are three entries for each of r, g
+ * and b. We could select the entry by popcount on
+ * the top two bits on those architectures that
+ * support it, this is what the code below does,
+ * crudely.
+ */
+ unsigned int back_i = PNG_CMAP_RGB_ALPHA_BACKGROUND+1;
+
+ /* Here are how the values map:
+ *
+ * 0x00 .. 0x3f -> 0
+ * 0x40 .. 0xbf -> 1
+ * 0xc0 .. 0xff -> 2
+ *
+ * So, as above with the explicit alpha checks, the
+ * breakpoints are at 64 and 196.
+ */
+ if (inrow[0] & 0x80) back_i += 9; /* red */
+ if (inrow[0] & 0x40) back_i += 9;
+ if (inrow[0] & 0x80) back_i += 3; /* green */
+ if (inrow[0] & 0x40) back_i += 3;
+ if (inrow[0] & 0x80) back_i += 1; /* blue */
+ if (inrow[0] & 0x40) back_i += 1;
+
+ *outrow = (png_byte)back_i;
+ }
+
+ inrow += 4;
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+static int
+png_image_read_colormapped(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_controlp control = image->opaque;
+ png_structrp png_ptr = control->png_ptr;
+ png_inforp info_ptr = control->info_ptr;
+
+ int passes = 0; /* As a flag */
+
+ PNG_SKIP_CHUNKS(png_ptr);
+
+ /* Update the 'info' structure and make sure the result is as required; first
+ * make sure to turn on the interlace handling if it will be required
+ * (because it can't be turned on *after* the call to png_read_update_info!)
+ */
+ if (display->colormap_processing == PNG_CMAP_NONE)
+ passes = png_set_interlace_handling(png_ptr);
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ /* The expected output can be deduced from the colormap_processing option. */
+ switch (display->colormap_processing)
+ {
+ case PNG_CMAP_NONE:
+ /* Output must be one channel and one byte per pixel, the output
+ * encoding can be anything.
+ */
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY) &&
+ info_ptr->bit_depth == 8)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_TRANS:
+ case PNG_CMAP_GA:
+ /* Output must be two channels and the 'G' one must be sRGB, the latter
+ * can be checked with an exact number because it should have been set
+ * to this number above!
+ */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 256)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_RGB:
+ /* Output must be 8-bit sRGB encoded RGB */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 216)
+ break;
+
+ goto bad_output;
+
+ case PNG_CMAP_RGB_ALPHA:
+ /* Output must be 8-bit sRGB encoded RGBA */
+ if (info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA &&
+ info_ptr->bit_depth == 8 &&
+ png_ptr->screen_gamma == PNG_GAMMA_sRGB &&
+ image->colormap_entries == 244 /* 216 + 1 + 27 */)
+ break;
+
+ /* goto bad_output; */
+ /* FALL THROUGH */
+
+ default:
+ bad_output:
+ png_error(png_ptr, "bad color-map processing (internal error)");
+ }
+
+ /* Now read the rows. Do this here if it is possible to read directly into
+ * the output buffer, otherwise allocate a local row buffer of the maximum
+ * size libpng requires and call the relevant processing routine safely.
+ */
+ {
+ png_voidp first_row = display->buffer;
+ ptrdiff_t row_bytes = display->row_stride;
+
+ /* The following expression is designed to work correctly whether it gives
+ * a signed or an unsigned result.
+ */
+ if (row_bytes < 0)
+ {
+ char *ptr = png_voidcast(char*, first_row);
+ ptr += (image->height-1) * (-row_bytes);
+ first_row = png_voidcast(png_voidp, ptr);
+ }
+
+ display->first_row = first_row;
+ display->row_bytes = row_bytes;
+ }
+
+ if (passes == 0)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_and_map, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else
+ {
+ png_alloc_size_t row_bytes = display->row_bytes;
+
+ while (--passes >= 0)
+ {
+ png_uint_32 y = image->height;
+ png_bytep row = png_voidcast(png_bytep, display->first_row);
+
+ while (y-- > 0)
+ {
+ png_read_row(png_ptr, row, NULL);
+ row += row_bytes;
+ }
+ }
+
+ return 1;
+ }
+}
+
+/* Just the row reading part of png_image_read. */
+static int
+png_image_read_composite(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ int passes;
+
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ {
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ ptrdiff_t step_row = display->row_bytes;
+ unsigned int channels =
+ (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ int pass;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass) * channels;
+ stepx = PNG_PASS_COL_OFFSET(pass) * channels;
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = channels;
+ stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep, display->local_row);
+ png_bytep outrow;
+ png_const_bytep end_row;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ outrow = png_voidcast(png_bytep, display->first_row);
+ outrow += y * step_row;
+ end_row = outrow + width * channels;
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[channels];
+
+ if (alpha > 0) /* else no change to the output */
+ {
+ unsigned int c;
+
+ for (c=0; c<channels; ++c)
+ {
+ png_uint_32 component = inrow[c];
+
+ if (alpha < 255) /* else just use component */
+ {
+ /* This is PNG_OPTIMIZED_ALPHA, the component value
+ * is a linear 8-bit value. Combine this with the
+ * current outrow[c] value which is sRGB encoded.
+ * Arithmetic here is 16-bits to preserve the output
+ * values correctly.
+ */
+ component *= 257*255; /* =65535 */
+ component += (255-alpha)*png_sRGB_table[outrow[c]];
+
+ /* So 'component' is scaled by 255*65535 and is
+ * therefore appropriate for the sRGB to linear
+ * conversion table.
+ */
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[c] = (png_byte)component;
+ }
+ }
+
+ inrow += channels+1; /* components and alpha channel */
+ }
+ }
+ }
+ }
+
+ return 1;
+}
+
+/* The do_local_background case; called when all the following transforms are to
+ * be done:
+ *
+ * PNG_RGB_TO_GRAY
+ * PNG_COMPOSITE
+ * PNG_GAMMA
+ *
+ * This is a work-around for the fact that both the PNG_RGB_TO_GRAY and
+ * PNG_COMPOSITE code performs gamma correction, so we get double gamma
+ * correction. The fix-up is to prevent the PNG_COMPOSITE operation from
+ * happening inside libpng, so this routine sees an 8 or 16-bit gray+alpha
+ * row and handles the removal or pre-multiplication of the alpha channel.
+ */
+static int
+png_image_read_background(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+ png_uint_32 height = image->height;
+ png_uint_32 width = image->width;
+ int pass, passes;
+
+ /* Double check the convoluted logic below. We expect to get here with
+ * libpng doing rgb to gray and gamma correction but background processing
+ * left to the png_image_read_background function. The rows libpng produce
+ * might be 8 or 16-bit but should always have two channels; gray plus alpha.
+ */
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) == 0)
+ png_error(png_ptr, "lost rgb to gray");
+
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
+ png_error(png_ptr, "unexpected compose");
+
+ if (png_get_channels(png_ptr, info_ptr) != 2)
+ png_error(png_ptr, "lost/gained channels");
+
+ /* Expect the 8-bit case to always remove the alpha channel */
+ if ((image->format & PNG_FORMAT_FLAG_LINEAR) == 0 &&
+ (image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ png_error(png_ptr, "unexpected 8-bit transformation");
+
+ switch (png_ptr->interlaced)
+ {
+ case PNG_INTERLACE_NONE:
+ passes = 1;
+ break;
+
+ case PNG_INTERLACE_ADAM7:
+ passes = PNG_INTERLACE_ADAM7_PASSES;
+ break;
+
+ default:
+ png_error(png_ptr, "unknown interlace type");
+ }
+
+ /* Use direct access to info_ptr here because otherwise the simplified API
+ * would require PNG_EASY_ACCESS_SUPPORTED (just for this.) Note this is
+ * checking the value after libpng expansions, not the original value in the
+ * PNG.
+ */
+ switch (info_ptr->bit_depth)
+ {
+ default:
+ png_error(png_ptr, "unexpected bit depth");
+ break;
+
+ case 8:
+ /* 8-bit sRGB gray values with an alpha channel; the alpha channel is
+ * to be removed by composing on a background: either the row if
+ * display->background is NULL or display->background->green if not.
+ * Unlike the code above ALPHA_OPTIMIZED has *not* been done.
+ */
+ {
+ png_bytep first_row = png_voidcast(png_bytep, display->first_row);
+ ptrdiff_t step_row = display->row_bytes;
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ png_bytep row = png_voidcast(png_bytep,
+ display->first_row);
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass);
+ stepx = PNG_PASS_COL_OFFSET(pass);
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = stepy = 1;
+ }
+
+ if (display->background == NULL)
+ {
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep,
+ display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[1];
+
+ if (alpha > 0) /* else no change to the output */
+ {
+ png_uint_32 component = inrow[0];
+
+ if (alpha < 255) /* else just use component */
+ {
+ /* Since PNG_OPTIMIZED_ALPHA was not set it is
+ * necessary to invert the sRGB transfer
+ * function and multiply the alpha out.
+ */
+ component = png_sRGB_table[component] * alpha;
+ component += png_sRGB_table[outrow[0]] *
+ (255-alpha);
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[0] = (png_byte)component;
+ }
+
+ inrow += 2; /* gray and alpha channel */
+ }
+ }
+ }
+
+ else /* constant background value */
+ {
+ png_byte background8 = display->background->green;
+ png_uint_16 background = png_sRGB_table[background8];
+
+ for (; y<height; y += stepy)
+ {
+ png_bytep inrow = png_voidcast(png_bytep,
+ display->local_row);
+ png_bytep outrow = first_row + y * step_row;
+ png_const_bytep end_row = outrow + width;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, inrow, NULL);
+
+ /* Now do the composition on each pixel in this row. */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_byte alpha = inrow[1];
+
+ if (alpha > 0) /* else use background */
+ {
+ png_uint_32 component = inrow[0];
+
+ if (alpha < 255) /* else just use component */
+ {
+ component = png_sRGB_table[component] * alpha;
+ component += background * (255-alpha);
+ component = PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ outrow[0] = (png_byte)component;
+ }
+
+ else
+ outrow[0] = background8;
+
+ inrow += 2; /* gray and alpha channel */
+ }
+
+ row += display->row_bytes;
+ }
+ }
+ }
+ }
+ break;
+
+ case 16:
+ /* 16-bit linear with pre-multiplied alpha; the pre-multiplication must
+ * still be done and, maybe, the alpha channel removed. This code also
+ * handles the alpha-first option.
+ */
+ {
+ png_uint_16p first_row = png_voidcast(png_uint_16p,
+ display->first_row);
+ /* The division by two is safe because the caller passed in a
+ * stride which was multiplied by 2 (below) to get row_bytes.
+ */
+ ptrdiff_t step_row = display->row_bytes / 2;
+ int preserve_alpha = (image->format & PNG_FORMAT_FLAG_ALPHA) != 0;
+ unsigned int outchannels = 1+preserve_alpha;
+ int swap_alpha = 0;
+
+# ifdef PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+ if (preserve_alpha != 0 &&
+ (image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ swap_alpha = 1;
+# endif
+
+ for (pass = 0; pass < passes; ++pass)
+ {
+ unsigned int startx, stepx, stepy;
+ png_uint_32 y;
+
+ /* The 'x' start and step are adjusted to output components here.
+ */
+ if (png_ptr->interlaced == PNG_INTERLACE_ADAM7)
+ {
+ /* The row may be empty for a short image: */
+ if (PNG_PASS_COLS(width, pass) == 0)
+ continue;
+
+ startx = PNG_PASS_START_COL(pass) * outchannels;
+ stepx = PNG_PASS_COL_OFFSET(pass) * outchannels;
+ y = PNG_PASS_START_ROW(pass);
+ stepy = PNG_PASS_ROW_OFFSET(pass);
+ }
+
+ else
+ {
+ y = 0;
+ startx = 0;
+ stepx = outchannels;
+ stepy = 1;
+ }
+
+ for (; y<height; y += stepy)
+ {
+ png_const_uint_16p inrow;
+ png_uint_16p outrow = first_row + y*step_row;
+ png_uint_16p end_row = outrow + width * outchannels;
+
+ /* Read the row, which is packed: */
+ png_read_row(png_ptr, png_voidcast(png_bytep,
+ display->local_row), NULL);
+ inrow = png_voidcast(png_const_uint_16p, display->local_row);
+
+ /* Now do the pre-multiplication on each pixel in this row.
+ */
+ outrow += startx;
+ for (; outrow < end_row; outrow += stepx)
+ {
+ png_uint_32 component = inrow[0];
+ png_uint_16 alpha = inrow[1];
+
+ if (alpha > 0) /* else 0 */
+ {
+ if (alpha < 65535) /* else just use component */
+ {
+ component *= alpha;
+ component += 32767;
+ component /= 65535;
+ }
+ }
+
+ else
+ component = 0;
+
+ outrow[swap_alpha] = (png_uint_16)component;
+ if (preserve_alpha != 0)
+ outrow[1 ^ swap_alpha] = alpha;
+
+ inrow += 2; /* components and alpha channel */
+ }
+ }
+ }
+ }
+ break;
+ }
+
+ return 1;
+}
+
+/* The guts of png_image_finish_read as a png_safe_execute callback. */
+static int
+png_image_read_direct(png_voidp argument)
+{
+ png_image_read_control *display = png_voidcast(png_image_read_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+
+ png_uint_32 format = image->format;
+ int linear = (format & PNG_FORMAT_FLAG_LINEAR) != 0;
+ int do_local_compose = 0;
+ int do_local_background = 0; /* to avoid double gamma correction bug */
+ int passes = 0;
+
+ /* Add transforms to ensure the correct output format is produced then check
+ * that the required implementation support is there. Always expand; always
+ * need 8 bits minimum, no palette and expanded tRNS.
+ */
+ png_set_expand(png_ptr);
+
+ /* Now check the format to see if it was modified. */
+ {
+ png_uint_32 base_format = png_image_format(png_ptr) &
+ ~PNG_FORMAT_FLAG_COLORMAP /* removed by png_set_expand */;
+ png_uint_32 change = format ^ base_format;
+ png_fixed_point output_gamma;
+ int mode; /* alpha mode */
+
+ /* Do this first so that we have a record if rgb to gray is happening. */
+ if ((change & PNG_FORMAT_FLAG_COLOR) != 0)
+ {
+ /* gray<->color transformation required. */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_gray_to_rgb(png_ptr);
+
+ else
+ {
+ /* libpng can't do both rgb to gray and
+ * background/pre-multiplication if there is also significant gamma
+ * correction, because both operations require linear colors and
+ * the code only supports one transform doing the gamma correction.
+ * Handle this by doing the pre-multiplication or background
+ * operation in this code, if necessary.
+ *
+ * TODO: fix this by rewriting pngrtran.c (!)
+ *
+ * For the moment (given that fixing this in pngrtran.c is an
+ * enormous change) 'do_local_background' is used to indicate that
+ * the problem exists.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ do_local_background = 1/*maybe*/;
+
+ png_set_rgb_to_gray_fixed(png_ptr, PNG_ERROR_ACTION_NONE,
+ PNG_RGB_TO_GRAY_DEFAULT, PNG_RGB_TO_GRAY_DEFAULT);
+ }
+
+ change &= ~PNG_FORMAT_FLAG_COLOR;
+ }
+
+ /* Set the gamma appropriately, linear for 16-bit input, sRGB otherwise.
+ */
+ {
+ png_fixed_point input_gamma_default;
+
+ if ((base_format & PNG_FORMAT_FLAG_LINEAR) != 0 &&
+ (image->flags & PNG_IMAGE_FLAG_16BIT_sRGB) == 0)
+ input_gamma_default = PNG_GAMMA_LINEAR;
+ else
+ input_gamma_default = PNG_DEFAULT_sRGB;
+
+ /* Call png_set_alpha_mode to set the default for the input gamma; the
+ * output gamma is set by a second call below.
+ */
+ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, input_gamma_default);
+ }
+
+ if (linear != 0)
+ {
+ /* If there *is* an alpha channel in the input it must be multiplied
+ * out; use PNG_ALPHA_STANDARD, otherwise just use PNG_ALPHA_PNG.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ mode = PNG_ALPHA_STANDARD; /* associated alpha */
+
+ else
+ mode = PNG_ALPHA_PNG;
+
+ output_gamma = PNG_GAMMA_LINEAR;
+ }
+
+ else
+ {
+ mode = PNG_ALPHA_PNG;
+ output_gamma = PNG_DEFAULT_sRGB;
+ }
+
+ /* If 'do_local_background' is set check for the presence of gamma
+ * correction; this is part of the work-round for the libpng bug
+ * described above.
+ *
+ * TODO: fix libpng and remove this.
+ */
+ if (do_local_background != 0)
+ {
+ png_fixed_point gtest;
+
+ /* This is 'png_gamma_threshold' from pngrtran.c; the test used for
+ * gamma correction, the screen gamma hasn't been set on png_struct
+ * yet; it's set below. png_struct::gamma, however, is set to the
+ * final value.
+ */
+ if (png_muldiv(&gtest, output_gamma, png_ptr->colorspace.gamma,
+ PNG_FP_1) != 0 && png_gamma_significant(gtest) == 0)
+ do_local_background = 0;
+
+ else if (mode == PNG_ALPHA_STANDARD)
+ {
+ do_local_background = 2/*required*/;
+ mode = PNG_ALPHA_PNG; /* prevent libpng doing it */
+ }
+
+ /* else leave as 1 for the checks below */
+ }
+
+ /* If the bit-depth changes then handle that here. */
+ if ((change & PNG_FORMAT_FLAG_LINEAR) != 0)
+ {
+ if (linear != 0 /*16-bit output*/)
+ png_set_expand_16(png_ptr);
+
+ else /* 8-bit output */
+ png_set_scale_16(png_ptr);
+
+ change &= ~PNG_FORMAT_FLAG_LINEAR;
+ }
+
+ /* Now the background/alpha channel changes. */
+ if ((change & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Removing an alpha channel requires composition for the 8-bit
+ * formats; for the 16-bit it is already done, above, by the
+ * pre-multiplication and the channel just needs to be stripped.
+ */
+ if ((base_format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* If RGB->gray is happening the alpha channel must be left and the
+ * operation completed locally.
+ *
+ * TODO: fix libpng and remove this.
+ */
+ if (do_local_background != 0)
+ do_local_background = 2/*required*/;
+
+ /* 16-bit output: just remove the channel */
+ else if (linear != 0) /* compose on black (well, pre-multiply) */
+ png_set_strip_alpha(png_ptr);
+
+ /* 8-bit output: do an appropriate compose */
+ else if (display->background != NULL)
+ {
+ png_color_16 c;
+
+ c.index = 0; /*unused*/
+ c.red = display->background->red;
+ c.green = display->background->green;
+ c.blue = display->background->blue;
+ c.gray = display->background->green;
+
+ /* This is always an 8-bit sRGB value, using the 'green' channel
+ * for gray is much better than calculating the luminance here;
+ * we can get off-by-one errors in that calculation relative to
+ * the app expectations and that will show up in transparent
+ * pixels.
+ */
+ png_set_background_fixed(png_ptr, &c,
+ PNG_BACKGROUND_GAMMA_SCREEN, 0/*need_expand*/,
+ 0/*gamma: not used*/);
+ }
+
+ else /* compose on row: implemented below. */
+ {
+ do_local_compose = 1;
+ /* This leaves the alpha channel in the output, so it has to be
+ * removed by the code below. Set the encoding to the 'OPTIMIZE'
+ * one so the code only has to hack on the pixels that require
+ * composition.
+ */
+ mode = PNG_ALPHA_OPTIMIZED;
+ }
+ }
+
+ else /* output needs an alpha channel */
+ {
+ /* This is tricky because it happens before the swap operation has
+ * been accomplished; however, the swap does *not* swap the added
+ * alpha channel (weird API), so it must be added in the correct
+ * place.
+ */
+ png_uint_32 filler; /* opaque filler */
+ int where;
+
+ if (linear != 0)
+ filler = 65535;
+
+ else
+ filler = 255;
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ where = PNG_FILLER_BEFORE;
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+
+ else
+# endif
+ where = PNG_FILLER_AFTER;
+
+ png_set_add_alpha(png_ptr, filler, where);
+ }
+
+ /* This stops the (irrelevant) call to swap_alpha below. */
+ change &= ~PNG_FORMAT_FLAG_ALPHA;
+ }
+
+ /* Now set the alpha mode correctly; this is always done, even if there is
+ * no alpha channel in either the input or the output because it correctly
+ * sets the output gamma.
+ */
+ png_set_alpha_mode_fixed(png_ptr, mode, output_gamma);
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((change & PNG_FORMAT_FLAG_BGR) != 0)
+ {
+ /* Check only the output format; PNG is never BGR; don't do this if
+ * the output is gray, but fix up the 'format' value in that case.
+ */
+ if ((format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_bgr(png_ptr);
+
+ else
+ format &= ~PNG_FORMAT_FLAG_BGR;
+
+ change &= ~PNG_FORMAT_FLAG_BGR;
+ }
+# endif
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if ((change & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ /* Only relevant if there is an alpha channel - it's particularly
+ * important to handle this correctly because do_local_compose may
+ * be set above and then libpng will keep the alpha channel for this
+ * code to remove.
+ */
+ if ((format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ /* Disable this if doing a local background,
+ * TODO: remove this when local background is no longer required.
+ */
+ if (do_local_background != 2)
+ png_set_swap_alpha(png_ptr);
+ }
+
+ else
+ format &= ~PNG_FORMAT_FLAG_AFIRST;
+
+ change &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* If the *output* is 16-bit then we need to check for a byte-swap on this
+ * architecture.
+ */
+ if (linear != 0)
+ {
+ PNG_CONST png_uint_16 le = 0x0001;
+
+ if ((*(png_const_bytep) & le) != 0)
+ png_set_swap(png_ptr);
+ }
+
+ /* If change is not now 0 some transformation is missing - error out. */
+ if (change != 0)
+ png_error(png_ptr, "png_read_image: unsupported transformation");
+ }
+
+ PNG_SKIP_CHUNKS(png_ptr);
+
+ /* Update the 'info' structure and make sure the result is as required; first
+ * make sure to turn on the interlace handling if it will be required
+ * (because it can't be turned on *after* the call to png_read_update_info!)
+ *
+ * TODO: remove the do_local_background fixup below.
+ */
+ if (do_local_compose == 0 && do_local_background != 2)
+ passes = png_set_interlace_handling(png_ptr);
+
+ png_read_update_info(png_ptr, info_ptr);
+
+ {
+ png_uint_32 info_format = 0;
+
+ if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ info_format |= PNG_FORMAT_FLAG_COLOR;
+
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ {
+ /* do_local_compose removes this channel below. */
+ if (do_local_compose == 0)
+ {
+ /* do_local_background does the same if required. */
+ if (do_local_background != 2 ||
+ (format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ info_format |= PNG_FORMAT_FLAG_ALPHA;
+ }
+ }
+
+ else if (do_local_compose != 0) /* internal error */
+ png_error(png_ptr, "png_image_read: alpha channel lost");
+
+ if (info_ptr->bit_depth == 16)
+ info_format |= PNG_FORMAT_FLAG_LINEAR;
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ info_format |= PNG_FORMAT_FLAG_BGR;
+# endif
+
+# ifdef PNG_FORMAT_AFIRST_SUPPORTED
+ if (do_local_background == 2)
+ {
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ info_format |= PNG_FORMAT_FLAG_AFIRST;
+ }
+
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0 ||
+ ((png_ptr->transformations & PNG_ADD_ALPHA) != 0 &&
+ (png_ptr->flags & PNG_FLAG_FILLER_AFTER) == 0))
+ {
+ if (do_local_background == 2)
+ png_error(png_ptr, "unexpected alpha swap transformation");
+
+ info_format |= PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* This is actually an internal error. */
+ if (info_format != format)
+ png_error(png_ptr, "png_read_image: invalid transformations");
+ }
+
+ /* Now read the rows. If do_local_compose is set then it is necessary to use
+ * a local row buffer. The output will be GA, RGBA or BGRA and must be
+ * converted to G, RGB or BGR as appropriate. The 'local_row' member of the
+ * display acts as a flag.
+ */
+ {
+ png_voidp first_row = display->buffer;
+ ptrdiff_t row_bytes = display->row_stride;
+
+ if (linear != 0)
+ row_bytes *= 2;
+
+ /* The following expression is designed to work correctly whether it gives
+ * a signed or an unsigned result.
+ */
+ if (row_bytes < 0)
+ {
+ char *ptr = png_voidcast(char*, first_row);
+ ptr += (image->height-1) * (-row_bytes);
+ first_row = png_voidcast(png_voidp, ptr);
+ }
+
+ display->first_row = first_row;
+ display->row_bytes = row_bytes;
+ }
+
+ if (do_local_compose != 0)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_composite, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else if (do_local_background == 2)
+ {
+ int result;
+ png_voidp row = png_malloc(png_ptr, png_get_rowbytes(png_ptr, info_ptr));
+
+ display->local_row = row;
+ result = png_safe_execute(image, png_image_read_background, display);
+ display->local_row = NULL;
+ png_free(png_ptr, row);
+
+ return result;
+ }
+
+ else
+ {
+ png_alloc_size_t row_bytes = display->row_bytes;
+
+ while (--passes >= 0)
+ {
+ png_uint_32 y = image->height;
+ png_bytep row = png_voidcast(png_bytep, display->first_row);
+
+ while (y-- > 0)
+ {
+ png_read_row(png_ptr, row, NULL);
+ row += row_bytes;
+ }
+ }
+
+ return 1;
+ }
}
-#endif /* PNG_INFO_IMAGE_SUPPORTED */
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+
+int PNGAPI
+png_image_finish_read(png_imagep image, png_const_colorp background,
+ void *buffer, png_int_32 row_stride, void *colormap)
+{
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ png_uint_32 check;
+
+ if (row_stride == 0)
+ row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+
+ if (row_stride < 0)
+ check = -row_stride;
+
+ else
+ check = row_stride;
+
+ if (image->opaque != NULL && buffer != NULL &&
+ check >= PNG_IMAGE_ROW_STRIDE(*image))
+ {
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) == 0 ||
+ (image->colormap_entries > 0 && colormap != NULL))
+ {
+ int result;
+ png_image_read_control display;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.background = background;
+ display.local_row = NULL;
+
+ /* Choose the correct 'end' routine; for the color-map case all the
+ * setup has already been done.
+ */
+ if ((image->format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ result =
+ png_safe_execute(image, png_image_read_colormap, &display) &&
+ png_safe_execute(image, png_image_read_colormapped, &display);
+
+ else
+ result =
+ png_safe_execute(image, png_image_read_direct, &display);
+
+ png_image_free(image);
+ return result;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read[color-map]: no color-map");
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_finish_read: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_finish_read: damaged PNG_IMAGE_VERSION");
+
+ return 0;
+}
+
+#endif /* SIMPLIFIED_READ */
+#endif /* READ */
diff --git a/src/3rdparty/libpng/pngrio.c b/src/3rdparty/libpng/pngrio.c
index e9c381c5ba..bb5c825109 100644
--- a/src/3rdparty/libpng/pngrio.c
+++ b/src/3rdparty/libpng/pngrio.c
@@ -1,8 +1,8 @@
/* pngrio.c - functions for data input
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -26,10 +26,10 @@
* reads from a file pointer. Note that this routine sometimes gets called
* with very small lengths, so you should implement some kind of simple
* buffering if you are using unbuffered reads. This should never be asked
- * to read more then 64K on a 16 bit machine.
+ * to read more than 64K on a 16 bit machine.
*/
void /* PRIVATE */
-png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
+png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length)
{
png_debug1(4, "reading %d bytes", (int)length);
@@ -46,7 +46,6 @@ png_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* read_data function and use it at run time with png_set_read_fn(), rather
* than changing the library.
*/
-# ifndef USE_FAR_KEYWORD
void PNGCBAPI
png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
@@ -58,68 +57,11 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
/* fread() returns 0 on error, so it is OK to store this in a png_size_t
* instead of an int, which is what fread() actually returns.
*/
- check = fread(data, 1, length, (png_FILE_p)png_ptr->io_ptr);
+ check = fread(data, 1, length, png_voidcast(png_FILE_p, png_ptr->io_ptr));
if (check != length)
png_error(png_ptr, "Read Error");
}
-# else
-/* This is the model-independent version. Since the standard I/O library
- can't handle far buffers in the medium and small models, we have to copy
- the data.
-*/
-
-#define NEAR_BUF_SIZE 1024
-#define MIN(a,b) (a <= b ? a : b)
-
-static void PNGCBAPI
-png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- png_size_t check;
- png_byte *n_data;
- png_FILE_p io_ptr;
-
- if (png_ptr == NULL)
- return;
-
- /* Check if data really is near. If so, use usual code. */
- n_data = (png_byte *)CVT_PTR_NOCHECK(data);
- io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
-
- if ((png_bytep)n_data == data)
- {
- check = fread(n_data, 1, length, io_ptr);
- }
-
- else
- {
- png_byte buf[NEAR_BUF_SIZE];
- png_size_t read, remaining, err;
- check = 0;
- remaining = length;
-
- do
- {
- read = MIN(NEAR_BUF_SIZE, remaining);
- err = fread(buf, 1, read, io_ptr);
- png_memcpy(data, buf, read); /* copy far buffer to near buffer */
-
- if (err != read)
- break;
-
- else
- check += err;
-
- data += read;
- remaining -= read;
- }
- while (remaining != 0);
- }
-
- if ((png_uint_32)check != (png_uint_32)length)
- png_error(png_ptr, "read Error");
-}
-# endif
#endif
/* This function allows the application to supply a new input function
@@ -142,7 +84,7 @@ png_default_read_data(png_structp png_ptr, png_bytep data, png_size_t length)
* be used.
*/
void PNGAPI
-png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
+png_set_read_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr read_data_fn)
{
if (png_ptr == NULL)
@@ -160,6 +102,7 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
png_ptr->read_data_fn = read_data_fn;
#endif
+#ifdef PNG_WRITE_SUPPORTED
/* It is an error to write to a read device */
if (png_ptr->write_data_fn != NULL)
{
@@ -168,9 +111,10 @@ png_set_read_fn(png_structp png_ptr, png_voidp io_ptr,
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
+#endif
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_ptr->output_flush_fn = NULL;
#endif
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c
index 5561852860..cad7a8daa5 100644
--- a/src/3rdparty/libpng/pngrtran.c
+++ b/src/3rdparty/libpng/pngrtran.c
@@ -1,8 +1,8 @@
/* pngrtran.c - transforms the data in a row for PNG readers
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -22,7 +22,7 @@
/* Set the action on getting a CRC error for an ancillary or critical chunk. */
void PNGAPI
-png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
+png_set_crc_action(png_structrp png_ptr, int crit_action, int ancil_action)
{
png_debug(1, "in png_set_crc_action");
@@ -88,16 +88,47 @@ png_set_crc_action(png_structp png_ptr, int crit_action, int ancil_action)
}
}
+#ifdef PNG_READ_TRANSFORMS_SUPPORTED
+/* Is it OK to set a transformation now? Only if png_start_read_image or
+ * png_read_update_info have not been called. It is not necessary for the IHDR
+ * to have been read in all cases; the need_IHDR parameter allows for this
+ * check too.
+ */
+static int
+png_rtran_ok(png_structrp png_ptr, int need_IHDR)
+{
+ if (png_ptr != NULL)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
+ png_app_error(png_ptr,
+ "invalid after png_start_read_image or png_read_update_info");
+
+ else if (need_IHDR && (png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_app_error(png_ptr, "invalid before the PNG header has been read");
+
+ else
+ {
+ /* Turn on failure to initialize correctly for all transforms. */
+ png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
+
+ return 1; /* Ok */
+ }
+ }
+
+ return 0; /* no png_error possible! */
+}
+#endif
+
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* Handle alpha and tRNS via a background color */
void PNGFAPI
-png_set_background_fixed(png_structp png_ptr,
+png_set_background_fixed(png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
int need_expand, png_fixed_point background_gamma)
{
png_debug(1, "in png_set_background_fixed");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0 || background_color == NULL)
return;
if (background_gamma_code == PNG_BACKGROUND_GAMMA_UNKNOWN)
@@ -110,11 +141,10 @@ png_set_background_fixed(png_structp png_ptr,
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
- png_memcpy(&(png_ptr->background), background_color,
- png_sizeof(png_color_16));
+ png_ptr->background = *background_color;
png_ptr->background_gamma = background_gamma;
png_ptr->background_gamma_type = (png_byte)(background_gamma_code);
- if (need_expand)
+ if (need_expand != 0)
png_ptr->transformations |= PNG_BACKGROUND_EXPAND;
else
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
@@ -122,7 +152,7 @@ png_set_background_fixed(png_structp png_ptr,
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_background(png_structp png_ptr,
+png_set_background(png_structrp png_ptr,
png_const_color_16p background_color, int background_gamma_code,
int need_expand, double background_gamma)
{
@@ -138,11 +168,11 @@ png_set_background(png_structp png_ptr,
*/
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
void PNGAPI
-png_set_scale_16(png_structp png_ptr)
+png_set_scale_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_scale_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_SCALE_16_TO_8;
@@ -152,11 +182,11 @@ png_set_scale_16(png_structp png_ptr)
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
/* Chop 16-bit depth files to 8-bit depth */
void PNGAPI
-png_set_strip_16(png_structp png_ptr)
+png_set_strip_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_strip_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_16_TO_8;
@@ -165,11 +195,11 @@ png_set_strip_16(png_structp png_ptr)
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
void PNGAPI
-png_set_strip_alpha(png_structp png_ptr)
+png_set_strip_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_strip_alpha");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_STRIP_ALPHA;
@@ -178,7 +208,7 @@ png_set_strip_alpha(png_structp png_ptr)
#if defined(PNG_READ_ALPHA_MODE_SUPPORTED) || defined(PNG_READ_GAMMA_SUPPORTED)
static png_fixed_point
-translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
+translate_gamma_flags(png_structrp png_ptr, png_fixed_point output_gamma,
int is_screen)
{
/* Check for flag values. The main reason for having the old Mac value as a
@@ -194,8 +224,10 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
*/
# ifdef PNG_READ_sRGB_SUPPORTED
png_ptr->flags |= PNG_FLAG_ASSUME_sRGB;
+# else
+ PNG_UNUSED(png_ptr)
# endif
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_sRGB;
else
output_gamma = PNG_GAMMA_sRGB_INVERSE;
@@ -204,7 +236,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
else if (output_gamma == PNG_GAMMA_MAC_18 ||
output_gamma == PNG_FP_1 / PNG_GAMMA_MAC_18)
{
- if (is_screen)
+ if (is_screen != 0)
output_gamma = PNG_GAMMA_MAC_OLD;
else
output_gamma = PNG_GAMMA_MAC_INVERSE;
@@ -215,7 +247,7 @@ translate_gamma_flags(png_structp png_ptr, png_fixed_point output_gamma,
# ifdef PNG_FLOATING_POINT_SUPPORTED
static png_fixed_point
-convert_gamma_value(png_structp png_ptr, double output_gamma)
+convert_gamma_value(png_structrp png_ptr, double output_gamma)
{
/* The following silently ignores cases where fixed point (times 100,000)
* gamma values are passed to the floating point API. This is safe and it
@@ -240,7 +272,7 @@ convert_gamma_value(png_structp png_ptr, double output_gamma)
#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
void PNGFAPI
-png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
+png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
png_fixed_point output_gamma)
{
int compose = 0;
@@ -248,7 +280,7 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
png_debug(1, "in png_set_alpha_mode");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
@@ -320,8 +352,11 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
* the side effect that the gamma in a second call to png_set_alpha_mode will
* be ignored.)
*/
- if (png_ptr->gamma == 0)
- png_ptr->gamma = file_gamma;
+ if (png_ptr->colorspace.gamma == 0)
+ {
+ png_ptr->colorspace.gamma = file_gamma;
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
+ }
/* But always set the output gamma: */
png_ptr->screen_gamma = output_gamma;
@@ -329,28 +364,25 @@ png_set_alpha_mode_fixed(png_structp png_ptr, int mode,
/* Finally, if pre-multiplying, set the background fields to achieve the
* desired result.
*/
- if (compose)
+ if (compose != 0)
{
/* And obtain alpha pre-multiplication by composing on black: */
- png_memset(&png_ptr->background, 0, sizeof png_ptr->background);
- png_ptr->background_gamma = png_ptr->gamma; /* just in case */
+ memset(&png_ptr->background, 0, (sizeof png_ptr->background));
+ png_ptr->background_gamma = png_ptr->colorspace.gamma; /* just in case */
png_ptr->background_gamma_type = PNG_BACKGROUND_GAMMA_FILE;
png_ptr->transformations &= ~PNG_BACKGROUND_EXPAND;
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
png_error(png_ptr,
"conflicting calls to set alpha mode and background");
png_ptr->transformations |= PNG_COMPOSE;
}
-
- /* New API, make sure apps call the correct initializers: */
- png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
+png_set_alpha_mode(png_structrp png_ptr, int mode, double output_gamma)
{
png_set_alpha_mode_fixed(png_ptr, mode, convert_gamma_value(png_ptr,
output_gamma));
@@ -362,7 +394,7 @@ png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
/* Dither file to 8-bit. Supply a palette, the current number
* of elements in the palette, the maximum number of elements
* allowed, and a histogram if possible. If the current number
- * of colors is greater then the maximum number, the palette will be
+ * of colors is greater than the maximum number, the palette will be
* modified to fit in the maximum number. "full_quantize" indicates
* whether we need a quantizing cube set up for RGB images, or if we
* simply are reducing the number of colors in a paletted image.
@@ -370,31 +402,31 @@ png_set_alpha_mode(png_structp png_ptr, int mode, double output_gamma)
typedef struct png_dsort_struct
{
- struct png_dsort_struct FAR * next;
+ struct png_dsort_struct * next;
png_byte left;
png_byte right;
} png_dsort;
-typedef png_dsort FAR * png_dsortp;
-typedef png_dsort FAR * FAR * png_dsortpp;
+typedef png_dsort * png_dsortp;
+typedef png_dsort * * png_dsortpp;
void PNGAPI
-png_set_quantize(png_structp png_ptr, png_colorp palette,
+png_set_quantize(png_structrp png_ptr, png_colorp palette,
int num_palette, int maximum_colors, png_const_uint_16p histogram,
int full_quantize)
{
png_debug(1, "in png_set_quantize");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_QUANTIZE;
- if (!full_quantize)
+ if (full_quantize == 0)
{
int i;
png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
for (i = 0; i < num_palette; i++)
png_ptr->quantize_index[i] = (png_byte)i;
}
@@ -411,7 +443,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
/* Initialize an array to sort colors */
png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
/* Initialize the quantize_sort array */
for (i = 0; i < num_palette; i++)
@@ -444,12 +476,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
}
- if (done)
+ if (done != 0)
break;
}
/* Swap the palette around, and set up a table, if necessary */
- if (full_quantize)
+ if (full_quantize != 0)
{
int j = num_palette;
@@ -545,9 +577,9 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
/* Initialize palette index arrays */
png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(num_palette * png_sizeof(png_byte)));
+ (png_uint_32)(num_palette * (sizeof (png_byte))));
/* Initialize the sort array */
for (i = 0; i < num_palette; i++)
@@ -557,7 +589,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
hash = (png_dsortpp)png_calloc(png_ptr, (png_uint_32)(769 *
- png_sizeof(png_dsortp)));
+ (sizeof (png_dsortp))));
num_new_palette = num_palette;
@@ -587,7 +619,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
{
t = (png_dsortp)png_malloc_warn(png_ptr,
- (png_uint_32)(png_sizeof(png_dsort)));
+ (png_uint_32)(sizeof (png_dsort)));
if (t == NULL)
break;
@@ -632,7 +664,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
num_new_palette--;
palette[png_ptr->index_to_palette[j]]
= palette[num_new_palette];
- if (!full_quantize)
+ if (full_quantize == 0)
{
int k;
@@ -700,7 +732,7 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
}
png_ptr->num_palette = (png_uint_16)num_palette;
- if (full_quantize)
+ if (full_quantize != 0)
{
int i;
png_bytep distance;
@@ -712,12 +744,12 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
png_size_t num_entries = ((png_size_t)1 << total_bits);
png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
- (png_uint_32)(num_entries * png_sizeof(png_byte)));
+ (png_uint_32)(num_entries * (sizeof (png_byte))));
distance = (png_bytep)png_malloc(png_ptr, (png_uint_32)(num_entries *
- png_sizeof(png_byte)));
+ (sizeof (png_byte))));
- png_memset(distance, 0xff, num_entries * png_sizeof(png_byte));
+ memset(distance, 0xff, num_entries * (sizeof (png_byte)));
for (i = 0; i < num_palette; i++)
{
@@ -762,23 +794,22 @@ png_set_quantize(png_structp png_ptr, png_colorp palette,
png_free(png_ptr, distance);
}
}
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
+#endif /* READ_QUANTIZE */
#ifdef PNG_READ_GAMMA_SUPPORTED
void PNGFAPI
-png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
+png_set_gamma_fixed(png_structrp png_ptr, png_fixed_point scrn_gamma,
png_fixed_point file_gamma)
{
png_debug(1, "in png_set_gamma_fixed");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
/* New in libpng-1.5.4 - reserve particular negative values as flags. */
scrn_gamma = translate_gamma_flags(png_ptr, scrn_gamma, 1/*screen*/);
file_gamma = translate_gamma_flags(png_ptr, file_gamma, 0/*file*/);
-#if PNG_LIBPNG_VER >= 10600
/* Checking the gamma values for being >0 was added in 1.5.4 along with the
* premultiplied alpha support; this actually hides an undocumented feature
* of the previous implementation which allowed gamma processing to be
@@ -787,31 +818,32 @@ png_set_gamma_fixed(png_structp png_ptr, png_fixed_point scrn_gamma,
* accept '0' for the gamma value it takes, because it isn't always used.
*
* Since this is an API change (albeit a very minor one that removes an
- * undocumented API feature) it will not be made until libpng-1.6.0.
+ * undocumented API feature) the following checks were only enabled in
+ * libpng-1.6.0.
*/
if (file_gamma <= 0)
png_error(png_ptr, "invalid file gamma in png_set_gamma");
if (scrn_gamma <= 0)
png_error(png_ptr, "invalid screen gamma in png_set_gamma");
-#endif
/* Set the gamma values unconditionally - this overrides the value in the PNG
* file if a gAMA chunk was present. png_set_alpha_mode provides a
* different, easier, way to default the file gamma.
*/
- png_ptr->gamma = file_gamma;
+ png_ptr->colorspace.gamma = file_gamma;
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
png_ptr->screen_gamma = scrn_gamma;
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
+png_set_gamma(png_structrp png_ptr, double scrn_gamma, double file_gamma)
{
png_set_gamma_fixed(png_ptr, convert_gamma_value(png_ptr, scrn_gamma),
convert_gamma_value(png_ptr, file_gamma));
}
-# endif /* FLOATING_POINT_SUPPORTED */
+# endif /* FLOATING_POINT */
#endif /* READ_GAMMA */
#ifdef PNG_READ_EXPAND_SUPPORTED
@@ -820,15 +852,14 @@ png_set_gamma(png_structp png_ptr, double scrn_gamma, double file_gamma)
* to alpha channels.
*/
void PNGAPI
-png_set_expand(png_structp png_ptr)
+png_set_expand(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
/* GRR 19990627: the following three functions currently are identical
@@ -851,90 +882,85 @@ png_set_expand(png_structp png_ptr)
/* Expand paletted images to RGB. */
void PNGAPI
-png_set_palette_to_rgb(png_structp png_ptr)
+png_set_palette_to_rgb(png_structrp png_ptr)
{
png_debug(1, "in png_set_palette_to_rgb");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
/* Expand grayscale images of less than 8-bit depth to 8 bits. */
void PNGAPI
-png_set_expand_gray_1_2_4_to_8(png_structp png_ptr)
+png_set_expand_gray_1_2_4_to_8(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand_gray_1_2_4_to_8");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= PNG_EXPAND;
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
-
-
/* Expand tRNS chunks to alpha channels. */
void PNGAPI
-png_set_tRNS_to_alpha(png_structp png_ptr)
+png_set_tRNS_to_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_tRNS_to_alpha");
+ if (png_rtran_ok(png_ptr, 0) == 0)
+ return;
+
png_ptr->transformations |= (PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
}
-#endif /* defined(PNG_READ_EXPAND_SUPPORTED) */
+#endif /* READ_EXPAND */
#ifdef PNG_READ_EXPAND_16_SUPPORTED
/* Expand to 16-bit channels, expand the tRNS chunk too (because otherwise
* it may not work correctly.)
*/
void PNGAPI
-png_set_expand_16(png_structp png_ptr)
+png_set_expand_16(png_structrp png_ptr)
{
png_debug(1, "in png_set_expand_16");
- if (png_ptr == NULL)
+ if (png_rtran_ok(png_ptr, 0) == 0)
return;
png_ptr->transformations |= (PNG_EXPAND_16 | PNG_EXPAND | PNG_EXPAND_tRNS);
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
-
- /* New API, make sure apps call the correct initializers: */
- png_ptr->flags |= PNG_FLAG_DETECT_UNINITIALIZED;
}
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
void PNGAPI
-png_set_gray_to_rgb(png_structp png_ptr)
+png_set_gray_to_rgb(png_structrp png_ptr)
{
png_debug(1, "in png_set_gray_to_rgb");
- if (png_ptr != NULL)
- {
- /* Because rgb must be 8 bits or more: */
- png_set_expand_gray_1_2_4_to_8(png_ptr);
- png_ptr->transformations |= PNG_GRAY_TO_RGB;
- png_ptr->flags &= ~PNG_FLAG_ROW_INIT;
- }
+ if (png_rtran_ok(png_ptr, 0) == 0)
+ return;
+
+ /* Because rgb must be 8 bits or more: */
+ png_set_expand_gray_1_2_4_to_8(png_ptr);
+ png_ptr->transformations |= PNG_GRAY_TO_RGB;
}
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
void PNGFAPI
-png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
+png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
png_fixed_point red, png_fixed_point green)
{
png_debug(1, "in png_set_rgb_to_gray");
- if (png_ptr == NULL)
+ /* Need the IHDR here because of the check on color_type below. */
+ /* TODO: fix this */
+ if (png_rtran_ok(png_ptr, 1) == 0)
return;
- switch(error_action)
+ switch (error_action)
{
case PNG_ERROR_ACTION_NONE:
png_ptr->transformations |= PNG_RGB_TO_GRAY;
@@ -952,15 +978,19 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
png_error(png_ptr, "invalid error action to rgb_to_gray");
break;
}
+
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
#ifdef PNG_READ_EXPAND_SUPPORTED
png_ptr->transformations |= PNG_EXPAND;
#else
{
- png_warning(png_ptr,
+ /* Make this an error in 1.6 because otherwise the application may assume
+ * that it just worked and get a memory overwrite.
+ */
+ png_error(png_ptr,
"Cannot do RGB_TO_GRAY without EXPAND_SUPPORTED");
- png_ptr->transformations &= ~PNG_RGB_TO_GRAY;
+ /* png_ptr->transformations &= ~PNG_RGB_TO_GRAY; */
}
#endif
{
@@ -969,7 +999,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
png_uint_16 red_int, green_int;
/* NOTE: this calculation does not round, but this behavior is retained
- * for consistency, the inaccuracy is very small. The code here always
+ * for consistency; the inaccuracy is very small. The code here always
* overwrites the coefficients, regardless of whether they have been
* defaulted or set already.
*/
@@ -984,7 +1014,7 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
else
{
if (red >= 0 && green >= 0)
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"ignoring out of range rgb_to_gray coefficients");
/* Use the defaults, from the cHRM chunk if set, else the historical
@@ -1010,31 +1040,25 @@ png_set_rgb_to_gray_fixed(png_structp png_ptr, int error_action,
*/
void PNGAPI
-png_set_rgb_to_gray(png_structp png_ptr, int error_action, double red,
+png_set_rgb_to_gray(png_structrp png_ptr, int error_action, double red,
double green)
{
- if (png_ptr == NULL)
- return;
-
png_set_rgb_to_gray_fixed(png_ptr, error_action,
png_fixed(png_ptr, red, "rgb to gray red coefficient"),
png_fixed(png_ptr, green, "rgb to gray green coefficient"));
}
#endif /* FLOATING POINT */
-#endif
+#endif /* RGB_TO_GRAY */
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
void PNGAPI
-png_set_read_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+png_set_read_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
read_user_transform_fn)
{
png_debug(1, "in png_set_read_user_transform_fn");
- if (png_ptr == NULL)
- return;
-
#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
png_ptr->transformations |= PNG_USER_TRANSFORM;
png_ptr->read_user_transform_fn = read_user_transform_fn;
@@ -1068,13 +1092,13 @@ png_gamma_threshold(png_fixed_point screen_gamma, png_fixed_point file_gamma)
* the palette.
*/
-/*For the moment 'png_init_palette_transformations' and
+/* For the moment 'png_init_palette_transformations' and
* 'png_init_rgb_transformations' only do some flag canceling optimizations.
* The intent is that these two routines should have palette or rgb operations
* extracted from 'png_init_read_transformations'.
*/
static void /* PRIVATE */
-png_init_palette_transformations(png_structp png_ptr)
+png_init_palette_transformations(png_structrp png_ptr)
{
/* Called to handle the (input) palette case. In png_do_read_transformations
* the first step is to expand the palette if requested, so this code must
@@ -1093,25 +1117,31 @@ png_init_palette_transformations(png_structp png_ptr)
/* Ignore if all the entries are opaque (unlikely!) */
for (i=0; i<png_ptr->num_trans; ++i)
+ {
if (png_ptr->trans_alpha[i] == 255)
continue;
else if (png_ptr->trans_alpha[i] == 0)
input_has_transparency = 1;
else
+ {
+ input_has_transparency = 1;
input_has_alpha = 1;
+ break;
+ }
+ }
}
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1124,8 +1154,8 @@ png_init_palette_transformations(png_structp png_ptr)
/* The following code cannot be entered in the alpha pre-multiplication case
* because PNG_BACKGROUND_EXPAND is cancelled below.
*/
- if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- (png_ptr->transformations & PNG_EXPAND))
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0)
{
{
png_ptr->background.red =
@@ -1136,9 +1166,9 @@ png_init_palette_transformations(png_structp png_ptr)
png_ptr->palette[png_ptr->background.index].blue;
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
{
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
{
/* Invert the alpha channel (in tRNS) unless the pixels are
* going to be expanded, in which case leave it for later
@@ -1150,14 +1180,14 @@ png_init_palette_transformations(png_structp png_ptr)
png_ptr->trans_alpha[i]);
}
}
-#endif /* PNG_READ_INVERT_ALPHA_SUPPORTED */
+#endif /* READ_INVERT_ALPHA */
}
} /* background expand and (therefore) no alpha association. */
-#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_EXPAND && READ_BACKGROUND */
}
static void /* PRIVATE */
-png_init_rgb_transformations(png_structp png_ptr)
+png_init_rgb_transformations(png_structrp png_ptr)
{
/* Added to libpng-1.5.4: check the color type to determine whether there
* is any alpha or transparency in the image and simply cancel the
@@ -1167,10 +1197,10 @@ png_init_rgb_transformations(png_structp png_ptr)
int input_has_transparency = png_ptr->num_trans > 0;
/* If no alpha we can optimize. */
- if (!input_has_alpha)
+ if (input_has_alpha == 0)
{
/* Any alpha means background and associative alpha processing is
- * required, however if the alpha is 0 or 1 throughout OPTIIMIZE_ALPHA
+ * required, however if the alpha is 0 or 1 throughout OPTIMIZE_ALPHA
* and ENCODE_ALPHA are irrelevant.
*/
# ifdef PNG_READ_ALPHA_MODE_SUPPORTED
@@ -1178,7 +1208,7 @@ png_init_rgb_transformations(png_structp png_ptr)
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
# endif
- if (!input_has_transparency)
+ if (input_has_transparency == 0)
png_ptr->transformations &= ~(PNG_COMPOSE | PNG_BACKGROUND_EXPAND);
}
@@ -1191,9 +1221,9 @@ png_init_rgb_transformations(png_structp png_ptr)
/* The following code cannot be entered in the alpha pre-multiplication case
* because PNG_BACKGROUND_EXPAND is cancelled below.
*/
- if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- (png_ptr->transformations & PNG_EXPAND) &&
- !(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0 &&
+ (png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
/* i.e., GRAY or GRAY_ALPHA */
{
{
@@ -1221,7 +1251,7 @@ png_init_rgb_transformations(png_structp png_ptr)
default:
case 8:
- /* Already 8 bits, fall through */
+ /* FALL THROUGH (Already 8 bits) */
case 16:
/* Already a full 16 bits */
@@ -1231,18 +1261,18 @@ png_init_rgb_transformations(png_structp png_ptr)
png_ptr->background.red = png_ptr->background.green =
png_ptr->background.blue = (png_uint_16)gray;
- if (!(png_ptr->transformations & PNG_EXPAND_tRNS))
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) == 0)
{
png_ptr->trans_color.red = png_ptr->trans_color.green =
png_ptr->trans_color.blue = (png_uint_16)trans_gray;
}
}
} /* background expand and (therefore) no alpha association. */
-#endif /* PNG_READ_EXPAND_SUPPORTED && PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_EXPAND && READ_BACKGROUND */
}
void /* PRIVATE */
-png_init_read_transformations(png_structp png_ptr)
+png_init_read_transformations(png_structrp png_ptr)
{
png_debug(1, "in png_init_read_transformations");
@@ -1267,17 +1297,17 @@ png_init_read_transformations(png_structp png_ptr)
*/
int gamma_correction = 0;
- if (png_ptr->gamma != 0) /* has been set */
+ if (png_ptr->colorspace.gamma != 0) /* has been set */
{
if (png_ptr->screen_gamma != 0) /* screen set too */
- gamma_correction = png_gamma_threshold(png_ptr->gamma,
+ gamma_correction = png_gamma_threshold(png_ptr->colorspace.gamma,
png_ptr->screen_gamma);
else
/* Assume the output matches the input; a long time default behavior
* of libpng, although the standard has nothing to say about this.
*/
- png_ptr->screen_gamma = png_reciprocal(png_ptr->gamma);
+ png_ptr->screen_gamma = png_reciprocal(png_ptr->colorspace.gamma);
}
else if (png_ptr->screen_gamma != 0)
@@ -1286,7 +1316,7 @@ png_init_read_transformations(png_structp png_ptr)
* png_set_alpha_mode (even if the alpha handling mode isn't required
* or isn't changed from the default.)
*/
- png_ptr->gamma = png_reciprocal(png_ptr->screen_gamma);
+ png_ptr->colorspace.gamma = png_reciprocal(png_ptr->screen_gamma);
else /* neither are set */
/* Just in case the following prevents any processing - file and screen
@@ -1294,7 +1324,10 @@ png_init_read_transformations(png_structp png_ptr)
* third gamma value other than png_set_background with 'UNIQUE', and,
* prior to 1.5.4
*/
- png_ptr->screen_gamma = png_ptr->gamma = PNG_FP_1;
+ png_ptr->screen_gamma = png_ptr->colorspace.gamma = PNG_FP_1;
+
+ /* We have a gamma value now. */
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_HAVE_GAMMA;
/* Now turn the gamma transformation on or off as appropriate. Notice
* that PNG_GAMMA just refers to the file->screen correction. Alpha
@@ -1304,7 +1337,7 @@ png_init_read_transformations(png_structp png_ptr)
* the code immediately below if the transform can be handled outside the
* row loop.
*/
- if (gamma_correction)
+ if (gamma_correction != 0)
png_ptr->transformations |= PNG_GAMMA;
else
@@ -1313,7 +1346,7 @@ png_init_read_transformations(png_structp png_ptr)
#endif
/* Certain transformations have the effect of preventing other
- * transformations that happen afterward in png_do_read_transformations,
+ * transformations that happen afterward in png_do_read_transformations;
* resolve the interdependencies here. From the code of
* png_do_read_transformations the order is:
*
@@ -1331,19 +1364,19 @@ png_init_read_transformations(png_structp png_ptr)
* 12) PNG_EXPAND_16
* 13) PNG_GRAY_TO_RGB iff PNG_BACKGROUND_IS_GRAY
* 14) PNG_INVERT_MONO
- * 15) PNG_SHIFT
- * 16) PNG_PACK
- * 17) PNG_BGR
- * 18) PNG_PACKSWAP
- * 19) PNG_FILLER (includes PNG_ADD_ALPHA)
- * 20) PNG_INVERT_ALPHA
+ * 15) PNG_INVERT_ALPHA
+ * 16) PNG_SHIFT
+ * 17) PNG_PACK
+ * 18) PNG_BGR
+ * 19) PNG_PACKSWAP
+ * 20) PNG_FILLER (includes PNG_ADD_ALPHA)
* 21) PNG_SWAP_ALPHA
* 22) PNG_SWAP_BYTES
* 23) PNG_USER_TRANSFORM [must be last]
*/
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- !(png_ptr->transformations & PNG_COMPOSE))
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) == 0)
{
/* Stripping the alpha channel happens immediately after the 'expand'
* transformations, before all other transformation, so it cancels out
@@ -1369,16 +1402,23 @@ png_init_read_transformations(png_structp png_ptr)
/* If the screen gamma is about 1.0 then the OPTIMIZE_ALPHA and ENCODE_ALPHA
* settings will have no effect.
*/
- if (!png_gamma_significant(png_ptr->screen_gamma))
+ if (png_gamma_significant(png_ptr->screen_gamma) == 0)
{
png_ptr->transformations &= ~PNG_ENCODE_ALPHA;
png_ptr->flags &= ~PNG_FLAG_OPTIMIZE_ALPHA;
}
#endif
-#if defined(PNG_READ_EXPAND_SUPPORTED) && \
- defined(PNG_READ_BACKGROUND_SUPPORTED) && \
- defined(PNG_READ_GRAY_TO_RGB_SUPPORTED)
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Make sure the coefficients for the rgb to gray conversion are set
+ * appropriately.
+ */
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ png_colorspace_set_rgb_coefficients(png_ptr);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+#if defined(PNG_READ_EXPAND_SUPPORTED) && defined(PNG_READ_BACKGROUND_SUPPORTED)
/* Detect gray background and attempt to enable optimization for
* gray --> RGB case.
*
@@ -1394,23 +1434,23 @@ png_init_read_transformations(png_structp png_ptr)
* png_set_background, along with the bit depth, then the code has a record
* of exactly what color space the background is currently in.
*/
- if (png_ptr->transformations & PNG_BACKGROUND_EXPAND)
+ if ((png_ptr->transformations & PNG_BACKGROUND_EXPAND) != 0)
{
/* PNG_BACKGROUND_EXPAND: the background is in the file color space, so if
* the file was grayscale the background value is gray.
*/
- if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
png_ptr->mode |= PNG_BACKGROUND_IS_GRAY;
}
- else if (png_ptr->transformations & PNG_COMPOSE)
+ else if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
/* PNG_COMPOSE: png_set_background was called with need_expand false,
* so the color is in the color space of the output or png_set_alpha_mode
* was called and the color is black. Ignore RGB_TO_GRAY because that
* happens before GRAY_TO_RGB.
*/
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (png_ptr->background.red == png_ptr->background.green &&
png_ptr->background.red == png_ptr->background.blue)
@@ -1420,7 +1460,8 @@ png_init_read_transformations(png_structp png_ptr)
}
}
}
-#endif /* PNG_READ_GRAY_TO_RGB_SUPPORTED (etc) */
+#endif /* READ_EXPAND && READ_BACKGROUND */
+#endif /* READ_GRAY_TO_RGB */
/* For indexed PNG data (PNG_COLOR_TYPE_PALETTE) many of the transformations
* can be performed directly on the palette, and some (such as rgb to gray)
@@ -1441,10 +1482,10 @@ png_init_read_transformations(png_structp png_ptr)
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
defined(PNG_READ_EXPAND_16_SUPPORTED)
- if ((png_ptr->transformations & PNG_EXPAND_16) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- png_ptr->bit_depth != 16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth != 16)
{
/* TODO: fix this. Because the expand_16 operation is after the compose
* handling the background color must be 8, not 16, bits deep, but the
@@ -1456,22 +1497,22 @@ png_init_read_transformations(png_structp png_ptr)
* NOTE: this discards the low 16 bits of the user supplied background
* color, but until expand_16 works properly there is no choice!
*/
-# define CHOP(x) (x)=((png_uint_16)(((png_uint_32)(x)*255+32895) >> 16))
+# define CHOP(x) (x)=((png_uint_16)PNG_DIV257(x))
CHOP(png_ptr->background.red);
CHOP(png_ptr->background.green);
CHOP(png_ptr->background.blue);
CHOP(png_ptr->background.gray);
# undef CHOP
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED && PNG_READ_EXPAND_16_SUPPORTED */
+#endif /* READ_BACKGROUND && READ_EXPAND_16 */
#if defined(PNG_READ_BACKGROUND_SUPPORTED) && \
(defined(PNG_READ_SCALE_16_TO_8_SUPPORTED) || \
defined(PNG_READ_STRIP_16_TO_8_SUPPORTED))
- if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- !(png_ptr->transformations & PNG_BACKGROUND_EXPAND) &&
- png_ptr->bit_depth == 16)
+ if ((png_ptr->transformations & (PNG_16_TO_8|PNG_SCALE_16_TO_8)) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_ptr->transformations & PNG_BACKGROUND_EXPAND) == 0 &&
+ png_ptr->bit_depth == 16)
{
/* On the other hand, if a 16-bit file is to be reduced to 8-bits per
* component this will also happen after PNG_COMPOSE and so the background
@@ -1514,25 +1555,24 @@ png_init_read_transformations(png_structp png_ptr)
* file gamma - if it is not 1.0 both RGB_TO_GRAY and COMPOSE need the
* tables.
*/
- if ((png_ptr->transformations & PNG_GAMMA)
- || ((png_ptr->transformations & PNG_RGB_TO_GRAY)
- && (png_gamma_significant(png_ptr->gamma) ||
- png_gamma_significant(png_ptr->screen_gamma)))
- || ((png_ptr->transformations & PNG_COMPOSE)
- && (png_gamma_significant(png_ptr->gamma)
- || png_gamma_significant(png_ptr->screen_gamma)
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 ||
+ ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0)) ||
+ ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (png_gamma_significant(png_ptr->colorspace.gamma) != 0 ||
+ png_gamma_significant(png_ptr->screen_gamma) != 0
# ifdef PNG_READ_BACKGROUND_SUPPORTED
- || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE
- && png_gamma_significant(png_ptr->background_gamma))
+ || (png_ptr->background_gamma_type == PNG_BACKGROUND_GAMMA_UNIQUE &&
+ png_gamma_significant(png_ptr->background_gamma) != 0)
# endif
- )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA)
- && png_gamma_significant(png_ptr->screen_gamma))
- )
+ )) || ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ png_gamma_significant(png_ptr->screen_gamma) != 0))
{
png_build_gamma_table(png_ptr, png_ptr->bit_depth);
#ifdef PNG_READ_BACKGROUND_SUPPORTED
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
{
/* Issue a warning about this combination: because RGB_TO_GRAY is
* optimized to do the gamma transform if present yet do_background has
@@ -1540,11 +1580,11 @@ png_init_read_transformations(png_structp png_ptr)
* double-gamma-correction happens. This is true in all versions of
* libpng to date.
*/
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
png_warning(png_ptr,
"libpng does not support gamma+background+rgb_to_gray");
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if ((png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) != 0)
{
/* We don't get to here unless there is a tRNS chunk with non-opaque
* entries - see the checking code at the start of this function.
@@ -1576,8 +1616,8 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma,
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
png_ptr->screen_gamma);
break;
@@ -1592,7 +1632,7 @@ png_init_read_transformations(png_structp png_ptr)
break;
}
- if (png_gamma_significant(gs))
+ if (png_gamma_significant(gs) != 0)
{
back.red = png_gamma_8bit_correct(png_ptr->background.red,
gs);
@@ -1609,7 +1649,7 @@ png_init_read_transformations(png_structp png_ptr)
back.blue = (png_byte)png_ptr->background.blue;
}
- if (png_gamma_significant(g))
+ if (png_gamma_significant(g) != 0)
{
back_1.red = png_gamma_8bit_correct(png_ptr->background.red,
g);
@@ -1685,8 +1725,9 @@ png_init_read_transformations(png_structp png_ptr)
break;
case PNG_BACKGROUND_GAMMA_FILE:
- g = png_reciprocal(png_ptr->gamma);
- gs = png_reciprocal2(png_ptr->gamma, png_ptr->screen_gamma);
+ g = png_reciprocal(png_ptr->colorspace.gamma);
+ gs = png_reciprocal2(png_ptr->colorspace.gamma,
+ png_ptr->screen_gamma);
break;
case PNG_BACKGROUND_GAMMA_UNIQUE:
@@ -1702,11 +1743,11 @@ png_init_read_transformations(png_structp png_ptr)
g_sig = png_gamma_significant(g);
gs_sig = png_gamma_significant(gs);
- if (g_sig)
+ if (g_sig != 0)
png_ptr->background_1.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, g);
- if (gs_sig)
+ if (gs_sig != 0)
png_ptr->background.gray = png_gamma_correct(png_ptr,
png_ptr->background.gray, gs);
@@ -1715,7 +1756,7 @@ png_init_read_transformations(png_structp png_ptr)
(png_ptr->background.red != png_ptr->background.gray))
{
/* RGB or RGBA with color background */
- if (g_sig)
+ if (g_sig != 0)
{
png_ptr->background_1.red = png_gamma_correct(png_ptr,
png_ptr->background.red, g);
@@ -1727,7 +1768,7 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->background.blue, g);
}
- if (gs_sig)
+ if (gs_sig != 0)
{
png_ptr->background.red = png_gamma_correct(png_ptr,
png_ptr->background.red, gs);
@@ -1757,7 +1798,7 @@ png_init_read_transformations(png_structp png_ptr)
else
/* Transformation does not include PNG_BACKGROUND */
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_BACKGROUND */
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
/* RGB_TO_GRAY needs to have non-gamma-corrected values! */
@@ -1770,8 +1811,8 @@ png_init_read_transformations(png_structp png_ptr)
int num_palette = png_ptr->num_palette;
int i;
- /*NOTE: there are other transformations that should probably be in here
- * too.
+ /* NOTE: there are other transformations that should probably be in
+ * here too.
*/
for (i = 0; i < num_palette; i++)
{
@@ -1787,11 +1828,11 @@ png_init_read_transformations(png_structp png_ptr)
#ifdef PNG_READ_BACKGROUND_SUPPORTED
else
#endif
-#endif /* PNG_READ_GAMMA_SUPPORTED */
+#endif /* READ_GAMMA */
#ifdef PNG_READ_BACKGROUND_SUPPORTED
/* No GAMMA transformation (see the hanging else 4 lines above) */
- if ((png_ptr->transformations & PNG_COMPOSE) &&
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
@@ -1826,11 +1867,11 @@ png_init_read_transformations(png_structp png_ptr)
png_ptr->transformations &= ~PNG_COMPOSE;
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED */
+#endif /* READ_BACKGROUND */
#ifdef PNG_READ_SHIFT_SUPPORTED
- if ((png_ptr->transformations & PNG_SHIFT) &&
- !(png_ptr->transformations & PNG_EXPAND) &&
+ if ((png_ptr->transformations & PNG_SHIFT) != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) == 0 &&
(png_ptr->color_type == PNG_COLOR_TYPE_PALETTE))
{
int i;
@@ -1843,33 +1884,36 @@ png_init_read_transformations(png_structp png_ptr)
* the number of significant bits is 0 then no shift is done (this is an
* error condition which is silently ignored.)
*/
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].red;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].red;
- component >>= shift;
- png_ptr->palette[i].red = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].red = (png_byte)component;
+ }
shift = 8 - png_ptr->sig_bit.green;
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].green;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].green;
- component >>= shift;
- png_ptr->palette[i].green = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].green = (png_byte)component;
+ }
shift = 8 - png_ptr->sig_bit.blue;
- if (shift > 0 && shift < 8) for (i=0; i<istop; ++i)
- {
- int component = png_ptr->palette[i].blue;
+ if (shift > 0 && shift < 8)
+ for (i=0; i<istop; ++i)
+ {
+ int component = png_ptr->palette[i].blue;
- component >>= shift;
- png_ptr->palette[i].blue = (png_byte)component;
- }
+ component >>= shift;
+ png_ptr->palette[i].blue = (png_byte)component;
+ }
}
-#endif /* PNG_READ_SHIFT_SUPPORTED */
+#endif /* READ_SHIFT */
}
/* Modify the info structure to reflect the transformations. The
@@ -1877,12 +1921,12 @@ png_init_read_transformations(png_structp png_ptr)
* assuming the transformations result in valid PNG data.
*/
void /* PRIVATE */
-png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
+png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_read_transform_info");
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
@@ -1898,12 +1942,15 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth = 8;
info_ptr->num_trans = 0;
+
+ if (png_ptr->palette == NULL)
+ png_error (png_ptr, "Palette is NULL in indexed image");
}
else
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
- if (png_ptr->transformations & PNG_EXPAND_tRNS)
+ if ((png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
}
if (info_ptr->bit_depth < 8)
@@ -1919,7 +1966,7 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
/* The following is almost certainly wrong unless the background value is in
* the screen space!
*/
- if (png_ptr->transformations & PNG_COMPOSE)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
info_ptr->background = png_ptr->background;
#endif
@@ -1928,20 +1975,24 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
* however it seems that the code in png_init_read_transformations, which has
* been called before this from png_read_update_info->png_read_start_row
* sometimes does the gamma transform and cancels the flag.
+ *
+ * TODO: this looks wrong; the info_ptr should end up with a gamma equal to
+ * the screen_gamma value. The following probably results in weirdness if
+ * the info_ptr is used by the app after the rows have been read.
*/
- info_ptr->gamma = png_ptr->gamma;
+ info_ptr->colorspace.gamma = png_ptr->colorspace.gamma;
#endif
if (info_ptr->bit_depth == 16)
{
# ifdef PNG_READ_16BIT_SUPPORTED
# ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
# ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_16_TO_8)
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
info_ptr->bit_depth = 8;
# endif
@@ -1967,27 +2018,27 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
CONFIGURATION ERROR: you must enable at least one 16 to 8 method
# endif
# endif
-#endif /* !READ_16BIT_SUPPORTED */
+#endif /* !READ_16BIT */
}
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
info_ptr->color_type = (png_byte)(info_ptr->color_type |
PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
info_ptr->color_type = (png_byte)(info_ptr->color_type &
~PNG_COLOR_MASK_COLOR);
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
- if (png_ptr->transformations & PNG_QUANTIZE)
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
{
if (((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
(info_ptr->color_type == PNG_COLOR_TYPE_RGB_ALPHA)) &&
- png_ptr->palette_lookup && info_ptr->bit_depth == 8)
+ png_ptr->palette_lookup != 0 && info_ptr->bit_depth == 8)
{
info_ptr->color_type = PNG_COLOR_TYPE_PALETTE;
}
@@ -1995,29 +2046,31 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16 && info_ptr->bit_depth == 8 &&
- info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0 &&
+ info_ptr->bit_depth == 8 &&
+ info_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
{
info_ptr->bit_depth = 16;
}
#endif
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && (info_ptr->bit_depth < 8))
+ if ((png_ptr->transformations & PNG_PACK) != 0 &&
+ (info_ptr->bit_depth < 8))
info_ptr->bit_depth = 8;
#endif
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
- else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_STRIP_ALPHA)
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0)
{
info_ptr->color_type = (png_byte)(info_ptr->color_type &
~PNG_COLOR_MASK_ALPHA);
@@ -2025,25 +2078,25 @@ png_read_transform_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
info_ptr->channels++;
#ifdef PNG_READ_FILLER_SUPPORTED
/* STRIP_ALPHA and FILLER allowed: MASK_ALPHA bit stripped above */
- if ((png_ptr->transformations & PNG_FILLER) &&
- ((info_ptr->color_type == PNG_COLOR_TYPE_RGB) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_GRAY)))
+ if ((png_ptr->transformations & PNG_FILLER) != 0 &&
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB ||
+ info_ptr->color_type == PNG_COLOR_TYPE_GRAY))
{
info_ptr->channels++;
/* If adding a true alpha channel not just filler */
- if (png_ptr->transformations & PNG_ADD_ALPHA)
+ if ((png_ptr->transformations & PNG_ADD_ALPHA) != 0)
info_ptr->color_type |= PNG_COLOR_MASK_ALPHA;
}
#endif
#if defined(PNG_USER_TRANSFORM_PTR_SUPPORTED) && \
defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
if (info_ptr->bit_depth < png_ptr->user_transform_depth)
info_ptr->bit_depth = png_ptr->user_transform_depth;
@@ -2067,306 +2120,11 @@ defined(PNG_READ_USER_TRANSFORM_SUPPORTED)
png_ptr->info_rowbytes = info_ptr->rowbytes;
#ifndef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr)
+ if (png_ptr != NULL)
return;
#endif
}
-/* Transform the row. The order of transformations is significant,
- * and is very touchy. If you add a transformation, take care to
- * decide how it fits in with the other transformations here.
- */
-void /* PRIVATE */
-png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
-{
- png_debug(1, "in png_do_read_transformations");
-
- if (png_ptr->row_buf == NULL)
- {
- /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
- * error is incredibly rare and incredibly easy to debug without this
- * information.
- */
- png_error(png_ptr, "NULL row buffer");
- }
-
- /* The following is debugging; prior to 1.5.4 the code was never compiled in;
- * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
- * PNG_WARN_UNINITIALIZED_ROW removed. In 1.5 the new flag is set only for
- * selected new APIs to ensure that there is no API change.
- */
- if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
- !(png_ptr->flags & PNG_FLAG_ROW_INIT))
- {
- /* Application has failed to call either png_read_start_image() or
- * png_read_update_info() after setting transforms that expand pixels.
- * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
- */
- png_error(png_ptr, "Uninitialized row");
- }
-
-#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
- {
- if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
- {
- png_do_expand_palette(row_info, png_ptr->row_buf + 1,
- png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
- }
-
- else
- {
- if (png_ptr->num_trans &&
- (png_ptr->transformations & PNG_EXPAND_tRNS))
- png_do_expand(row_info, png_ptr->row_buf + 1,
- &(png_ptr->trans_color));
-
- else
- png_do_expand(row_info, png_ptr->row_buf + 1,
- NULL);
- }
- }
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- !(png_ptr->transformations & PNG_COMPOSE) &&
- (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- if (png_ptr->transformations & PNG_RGB_TO_GRAY)
- {
- int rgb_error =
- png_do_rgb_to_gray(png_ptr, row_info,
- png_ptr->row_buf + 1);
-
- if (rgb_error)
- {
- png_ptr->rgb_to_gray_status=1;
- if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
- PNG_RGB_TO_GRAY_WARN)
- png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
-
- if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
- PNG_RGB_TO_GRAY_ERR)
- png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
- }
- }
-#endif
-
-/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
- *
- * In most cases, the "simple transparency" should be done prior to doing
- * gray-to-RGB, or you will have to test 3x as many bytes to check if a
- * pixel is transparent. You would also need to make sure that the
- * transparency information is upgraded to RGB.
- *
- * To summarize, the current flow is:
- * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
- * with background "in place" if transparent,
- * convert to RGB if necessary
- * - Gray + alpha -> composite with gray background and remove alpha bytes,
- * convert to RGB if necessary
- *
- * To support RGB backgrounds for gray images we need:
- * - Gray + simple transparency -> convert to RGB + simple transparency,
- * compare 3 or 6 bytes and composite with
- * background "in place" if transparent
- * (3x compare/pixel compared to doing
- * composite with gray bkgrnd)
- * - Gray + alpha -> convert to RGB + alpha, composite with background and
- * remove alpha bytes (3x float
- * operations/pixel compared with composite
- * on gray background)
- *
- * Greg's change will do this. The reason it wasn't done before is for
- * performance, as this increases the per-pixel operations. If we would check
- * in advance if the background was gray or RGB, and position the gray-to-RGB
- * transform appropriately, then it would save a lot of work/time.
- */
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /* If gray -> RGB, do so now only if background is non-gray; else do later
- * for performance reasons
- */
- if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
- !(png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- if (png_ptr->transformations & PNG_COMPOSE)
- png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_GAMMA_SUPPORTED
- if ((png_ptr->transformations & PNG_GAMMA) &&
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Because RGB_TO_GRAY does the gamma transform. */
- !(png_ptr->transformations & PNG_RGB_TO_GRAY) &&
-#endif
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
- /* Because PNG_COMPOSE does the gamma transform if there is something to
- * do (if there is an alpha channel or transparency.)
- */
- !((png_ptr->transformations & PNG_COMPOSE) &&
- ((png_ptr->num_trans != 0) ||
- (png_ptr->color_type & PNG_COLOR_MASK_ALPHA))) &&
-#endif
- /* Because png_init_read_transformations transforms the palette, unless
- * RGB_TO_GRAY will do the transform.
- */
- (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
- png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
- if ((png_ptr->transformations & PNG_STRIP_ALPHA) &&
- (png_ptr->transformations & PNG_COMPOSE) &&
- (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
- row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- 0 /* at_start == false, because SWAP_ALPHA happens later */);
-#endif
-
-#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
- if ((png_ptr->transformations & PNG_ENCODE_ALPHA) &&
- (row_info->color_type & PNG_COLOR_MASK_ALPHA))
- png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
-#endif
-
-#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
- if (png_ptr->transformations & PNG_SCALE_16_TO_8)
- png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
- /* There is no harm in doing both of these because only one has any effect,
- * by putting the 'scale' option first if the app asks for scale (either by
- * calling the API or in a TRANSFORM flag) this is what happens.
- */
- if (png_ptr->transformations & PNG_16_TO_8)
- png_do_chop(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_QUANTIZE_SUPPORTED
- if (png_ptr->transformations & PNG_QUANTIZE)
- {
- png_do_quantize(row_info, png_ptr->row_buf + 1,
- png_ptr->palette_lookup, png_ptr->quantize_index);
-
- if (row_info->rowbytes == 0)
- png_error(png_ptr, "png_do_quantize returned rowbytes=0");
- }
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-
-#ifdef PNG_READ_EXPAND_16_SUPPORTED
- /* Do the expansion now, after all the arithmetic has been done. Notice
- * that previous transformations can handle the PNG_EXPAND_16 flag if this
- * is efficient (particularly true in the case of gamma correction, where
- * better accuracy results faster!)
- */
- if (png_ptr->transformations & PNG_EXPAND_16)
- png_do_expand_16(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- /*NOTE: moved here in 1.5.4 (from much later in this list.) */
- if ((png_ptr->transformations & PNG_GRAY_TO_RGB) &&
- (png_ptr->mode & PNG_BACKGROUND_IS_GRAY))
- png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_INVERT_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_MONO)
- png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_SHIFT_SUPPORTED
- if (png_ptr->transformations & PNG_SHIFT)
- png_do_unshift(row_info, png_ptr->row_buf + 1,
- &(png_ptr->shift));
-#endif
-
-#ifdef PNG_READ_PACK_SUPPORTED
- if (png_ptr->transformations & PNG_PACK)
- png_do_unpack(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
- /* Added at libpng-1.5.10 */
- if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
- png_do_check_palette_indexes(png_ptr, row_info);
-#endif
-
-#ifdef PNG_READ_BGR_SUPPORTED
- if (png_ptr->transformations & PNG_BGR)
- png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_FILLER_SUPPORTED
- if (png_ptr->transformations & PNG_FILLER)
- png_do_read_filler(row_info, png_ptr->row_buf + 1,
- (png_uint_32)png_ptr->filler, png_ptr->flags);
-#endif
-
-#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
- png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_ALPHA)
- png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_READ_16BIT_SUPPORTED
-#ifdef PNG_READ_SWAP_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_BYTES)
- png_do_swap(row_info, png_ptr->row_buf + 1);
-#endif
-#endif
-
-#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
- {
- if (png_ptr->read_user_transform_fn != NULL)
- (*(png_ptr->read_user_transform_fn)) /* User read transform function */
- (png_ptr, /* png_ptr */
- row_info, /* row_info: */
- /* png_uint_32 width; width of row */
- /* png_size_t rowbytes; number of bytes in row */
- /* png_byte color_type; color type of pixels */
- /* png_byte bit_depth; bit depth of samples */
- /* png_byte channels; number of channels (1-4) */
- /* png_byte pixel_depth; bits per pixel (depth*channels) */
- png_ptr->row_buf + 1); /* start of pixel data for row */
-#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
- if (png_ptr->user_transform_depth)
- row_info->bit_depth = png_ptr->user_transform_depth;
-
- if (png_ptr->user_transform_channels)
- row_info->channels = png_ptr->user_transform_channels;
-#endif
- row_info->pixel_depth = (png_byte)(row_info->bit_depth *
- row_info->channels);
-
- row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
- }
-#endif
-}
-
#ifdef PNG_READ_PACK_SUPPORTED
/* Unpack pixels of 1, 2, or 4 bits per pixel into 1 byte per pixel,
* without changing the actual values. Thus, if you had a row with
@@ -2374,7 +2132,7 @@ png_do_read_transformations(png_structp png_ptr, png_row_infop row_info)
* the numbers 0 or 1. If you would rather they contain 0 and 255, use
* png_do_shift() after this.
*/
-void /* PRIVATE */
+static void
png_do_unpack(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_unpack");
@@ -2472,7 +2230,7 @@ png_do_unpack(png_row_infop row_info, png_bytep row)
* a row of bit depth 8, but only 5 are significant, this will shift
* the values back to 0 through 31.
*/
-void /* PRIVATE */
+static void
png_do_unshift(png_row_infop row_info, png_bytep row,
png_const_color_8p sig_bits)
{
@@ -2489,7 +2247,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
int channels = 0;
int bit_depth = row_info->bit_depth;
- if (color_type & PNG_COLOR_MASK_COLOR)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift[channels++] = bit_depth - sig_bits->red;
shift[channels++] = bit_depth - sig_bits->green;
@@ -2501,7 +2259,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
shift[channels++] = bit_depth - sig_bits->gray;
}
- if (color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift[channels++] = bit_depth - sig_bits->alpha;
}
@@ -2521,7 +2279,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
have_shift = 1;
}
- if (!have_shift)
+ if (have_shift == 0)
return;
}
@@ -2599,7 +2357,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
if (++channel >= channels)
channel = 0;
*bp++ = (png_byte)(value >> 8);
- *bp++ = (png_byte)(value & 0xff);
+ *bp++ = (png_byte)value;
}
break;
}
@@ -2611,7 +2369,7 @@ png_do_unshift(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
/* Scale rows of bit depth 16 down to 8 accurately */
-void /* PRIVATE */
+static void
png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_scale_16_to_8");
@@ -2669,7 +2427,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
-void /* PRIVATE */
+static void
/* Simply discard the low byte. This was the default behavior prior
* to libpng-1.5.4.
*/
@@ -2697,7 +2455,7 @@ png_do_chop(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_read_swap_alpha");
@@ -2794,7 +2552,7 @@ png_do_read_swap_alpha(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_uint_32 row_width;
@@ -2896,7 +2654,7 @@ png_do_read_invert_alpha(png_row_infop row_info, png_bytep row)
#ifdef PNG_READ_FILLER_SUPPORTED
/* Add filler channel if we have RGB color */
-void /* PRIVATE */
+static void
png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 filler, png_uint_32 flags)
{
@@ -2904,9 +2662,9 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
png_uint_32 row_width = row_info->width;
#ifdef PNG_READ_16BIT_SUPPORTED
- png_byte hi_filler = (png_byte)((filler>>8) & 0xff);
+ png_byte hi_filler = (png_byte)(filler>>8);
#endif
- png_byte lo_filler = (png_byte)(filler & 0xff);
+ png_byte lo_filler = (png_byte)filler;
png_debug(1, "in png_do_read_filler");
@@ -2915,7 +2673,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from G to GX */
png_bytep sp = row + (png_size_t)row_width;
@@ -2950,20 +2708,20 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from GG to GGXX */
png_bytep sp = row + (png_size_t)row_width * 2;
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 2;
row_info->pixel_depth = 32;
row_info->rowbytes = row_width * 4;
@@ -2978,8 +2736,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 2;
row_info->pixel_depth = 32;
@@ -2992,7 +2750,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
{
if (row_info->bit_depth == 8)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RGB to RGBX */
png_bytep sp = row + (png_size_t)row_width * 3;
@@ -3031,15 +2789,15 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_16BIT_SUPPORTED
else if (row_info->bit_depth == 16)
{
- if (flags & PNG_FLAG_FILLER_AFTER)
+ if ((flags & PNG_FLAG_FILLER_AFTER) != 0)
{
/* This changes the data from RRGGBB to RRGGBBXX */
png_bytep sp = row + (png_size_t)row_width * 6;
png_bytep dp = sp + (png_size_t)row_width * 2;
for (i = 1; i < row_width; i++)
{
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
@@ -3047,8 +2805,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
}
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
row_info->channels = 4;
row_info->pixel_depth = 64;
row_info->rowbytes = row_width * 8;
@@ -3067,8 +2825,8 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
*(--dp) = *(--sp);
*(--dp) = *(--sp);
*(--dp) = *(--sp);
- *(--dp) = hi_filler;
*(--dp) = lo_filler;
+ *(--dp) = hi_filler;
}
row_info->channels = 4;
@@ -3083,7 +2841,7 @@ png_do_read_filler(png_row_infop row_info, png_bytep row,
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
/* Expand grayscale files to RGB, with or without alpha */
-void /* PRIVATE */
+static void
png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
{
png_uint_32 i;
@@ -3092,7 +2850,7 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
png_debug(1, "in png_do_gray_to_rgb");
if (row_info->bit_depth >= 8 &&
- !(row_info->color_type & PNG_COLOR_MASK_COLOR))
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -3222,16 +2980,16 @@ png_do_gray_to_rgb(png_row_infop row_info, png_bytep row)
* calculated to make the sum 32768. This will result in different rounding
* to that used above.
*/
-int /* PRIVATE */
-png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
+static int
+png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row)
{
int rgb_error = 0;
png_debug(1, "in png_do_rgb_to_gray");
- if (!(row_info->color_type & PNG_COLOR_MASK_PALETTE) &&
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if ((row_info->color_type & PNG_COLOR_MASK_PALETTE) == 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
PNG_CONST png_uint_32 rc = png_ptr->rgb_to_gray_red_coeff;
PNG_CONST png_uint_32 gc = png_ptr->rgb_to_gray_green_coeff;
@@ -3242,7 +3000,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (row_info->bit_depth == 8)
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
/* Notice that gamma to/from 1 are not necessarily inverses (if
* there is an overall gamma correction). Prior to 1.5.5 this code
* checked the linearized values for equality; this doesn't match
@@ -3282,7 +3040,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = red;
}
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3302,7 +3060,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
if (red != green || red != blue)
{
rgb_error |= 1;
- /*NOTE: this is the historical approach which simply
+ /* NOTE: this is the historical approach which simply
* truncates the results.
*/
*(dp++) = (png_byte)((rc*red + gc*green + bc*blue)>>15);
@@ -3311,7 +3069,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else
*(dp++) = red;
- if (have_alpha)
+ if (have_alpha != 0)
*(dp++) = *(sp++);
}
}
@@ -3319,7 +3077,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else /* RGB bit_depth == 16 */
{
-#if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_READ_BACKGROUND_SUPPORTED)
+#ifdef PNG_READ_GAMMA_SUPPORTED
if (png_ptr->gamma_16_to_1 != NULL && png_ptr->gamma_16_from_1 != NULL)
{
png_bytep sp = row;
@@ -3329,16 +3087,17 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, w;
+ png_byte hi,lo;
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
if (red == green && red == blue)
{
if (png_ptr->gamma_16_table != NULL)
- w = png_ptr->gamma_16_table[(red&0xff)
- >> png_ptr->gamma_shift][red>>8];
+ w = png_ptr->gamma_16_table[(red & 0xff)
+ >> png_ptr->gamma_shift][red >> 8];
else
w = red;
@@ -3346,16 +3105,16 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
else
{
- png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red&0xff)
+ png_uint_16 red_1 = png_ptr->gamma_16_to_1[(red & 0xff)
>> png_ptr->gamma_shift][red>>8];
png_uint_16 green_1 =
- png_ptr->gamma_16_to_1[(green&0xff) >>
+ png_ptr->gamma_16_to_1[(green & 0xff) >>
png_ptr->gamma_shift][green>>8];
- png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue&0xff)
+ png_uint_16 blue_1 = png_ptr->gamma_16_to_1[(blue & 0xff)
>> png_ptr->gamma_shift][blue>>8];
png_uint_16 gray16 = (png_uint_16)((rc*red_1 + gc*green_1
+ bc*blue_1 + 16384)>>15);
- w = png_ptr->gamma_16_from_1[(gray16&0xff) >>
+ w = png_ptr->gamma_16_from_1[(gray16 & 0xff) >>
png_ptr->gamma_shift][gray16 >> 8];
rgb_error |= 1;
}
@@ -3363,7 +3122,7 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)((w>>8) & 0xff);
*(dp++) = (png_byte)(w & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3380,10 +3139,11 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
for (i = 0; i < row_width; i++)
{
png_uint_16 red, green, blue, gray16;
+ png_byte hi,lo;
- red = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- green = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
- blue = (png_uint_16)(((*(sp))<<8) | *(sp + 1)); sp += 2;
+ hi=*(sp)++; lo=*(sp)++; red = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; green = (png_uint_16)((hi << 8) | (lo));
+ hi=*(sp)++; lo=*(sp)++; blue = (png_uint_16)((hi << 8) | (lo));
if (red != green || red != blue)
rgb_error |= 1;
@@ -3394,10 +3154,10 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
*/
gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >>
15);
- *(dp++) = (png_byte)((gray16>>8) & 0xff);
+ *(dp++) = (png_byte)((gray16 >> 8) & 0xff);
*(dp++) = (png_byte)(gray16 & 0xff);
- if (have_alpha)
+ if (have_alpha != 0)
{
*(dp++) = *(sp++);
*(dp++) = *(sp++);
@@ -3416,74 +3176,15 @@ png_do_rgb_to_gray(png_structp png_ptr, png_row_infop row_info, png_bytep row)
return rgb_error;
}
#endif
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
-
-#ifdef PNG_BUILD_GRAYSCALE_PALETTE_SUPPORTED
-/* Build a grayscale palette. Palette is assumed to be 1 << bit_depth
- * large of png_color. This lets grayscale images be treated as
- * paletted. Most useful for gamma correction and simplification
- * of code. This API is not used internally.
- */
-void PNGAPI
-png_build_grayscale_palette(int bit_depth, png_colorp palette)
-{
- int num_palette;
- int color_inc;
- int i;
- int v;
-
- png_debug(1, "in png_do_build_grayscale_palette");
-
- if (palette == NULL)
- return;
-
- switch (bit_depth)
- {
- case 1:
- num_palette = 2;
- color_inc = 0xff;
- break;
-
- case 2:
- num_palette = 4;
- color_inc = 0x55;
- break;
-
- case 4:
- num_palette = 16;
- color_inc = 0x11;
- break;
-
- case 8:
- num_palette = 256;
- color_inc = 1;
- break;
-
- default:
- num_palette = 0;
- color_inc = 0;
- break;
- }
-
- for (i = 0, v = 0; i < num_palette; i++, v += color_inc)
- {
- palette[i].red = (png_byte)v;
- palette[i].green = (png_byte)v;
- palette[i].blue = (png_byte)v;
- }
-}
-#endif
-
-#ifdef PNG_READ_TRANSFORMS_SUPPORTED
-#if (defined PNG_READ_BACKGROUND_SUPPORTED) ||\
- (defined PNG_READ_ALPHA_MODE_SUPPORTED)
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
/* Replace any alpha or transparency with the supplied background color.
* "background" is already in the screen gamma, while "background_1" is
* at a gamma of 1.0. Paletted files have already been taken care of.
*/
-void /* PRIVATE */
-png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
#ifdef PNG_READ_GAMMA_SUPPORTED
png_const_bytep gamma_table = png_ptr->gamma_table;
@@ -3493,12 +3194,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_const_uint_16pp gamma_16_from_1 = png_ptr->gamma_16_from_1;
png_const_uint_16pp gamma_16_to_1 = png_ptr->gamma_16_to_1;
int gamma_shift = png_ptr->gamma_shift;
+ int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
#endif
png_bytep sp;
png_uint_32 i;
png_uint_32 row_width = row_info->width;
- int optimize = (png_ptr->flags & PNG_FLAG_OPTIMIZE_ALPHA) != 0;
int shift;
png_debug(1, "in png_do_compose");
@@ -3519,11 +3220,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x01)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x7f7f >> (7 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x7f7f >> (7 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 7;
sp++;
@@ -3547,20 +3249,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
else
{
- png_byte p = (png_byte)((*sp >> shift) & 0x03);
- png_byte g = (png_byte)((gamma_table [p | (p << 2) |
- (p << 4) | (p << 6)] >> 6) & 0x03);
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(g << shift);
+ unsigned int p = (*sp >> shift) & 0x03;
+ unsigned int g = (gamma_table [p | (p << 2) |
+ (p << 4) | (p << 6)] >> 6) & 0x03;
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3581,11 +3285,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x03)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0x3f3f >> (6 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0x3f3f >> (6 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 6;
sp++;
@@ -3610,20 +3315,22 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
else
{
- png_byte p = (png_byte)((*sp >> shift) & 0x0f);
- png_byte g = (png_byte)((gamma_table[p |
- (p << 4)] >> 4) & 0x0f);
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(g << shift);
+ unsigned int p = (*sp >> shift) & 0x0f;
+ unsigned int g = (gamma_table[p | (p << 4)] >> 4) &
+ 0x0f;
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= g << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3644,11 +3351,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if ((png_uint_16)((*sp >> shift) & 0x0f)
== png_ptr->trans_color.gray)
{
- *sp &= (png_byte)((0xf0f >> (4 - shift)) & 0xff);
- *sp |= (png_byte)(png_ptr->background.gray << shift);
+ unsigned int tmp = *sp & (0xf0f >> (4 - shift));
+ tmp |= png_ptr->background.gray << shift;
+ *sp = (png_byte)(tmp & 0xff);
}
- if (!shift)
+ if (shift == 0)
{
shift = 4;
sp++;
@@ -3704,8 +3412,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
else
@@ -3728,8 +3438,10 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (v == png_ptr->trans_color.gray)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
- *(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
+ *(sp + 1) = (png_byte)(png_ptr->background.gray
+ & 0xff);
}
}
}
@@ -3809,9 +3521,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -3852,9 +3567,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
}
@@ -3891,7 +3609,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.gray);
- if (!optimize)
+ if (optimize == 0)
w = gamma_from_1[w];
*sp = w;
}
@@ -3909,7 +3627,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
*sp = (png_byte)png_ptr->background.gray;
else if (a < 0xff)
- png_composite(*sp, *sp, a, png_ptr->background_1.gray);
+ png_composite(*sp, *sp, a, png_ptr->background.gray);
}
}
}
@@ -3937,7 +3655,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
else if (a == 0)
{
/* Background is already in screen gamma */
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3947,10 +3666,11 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
g = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(v, g, a, png_ptr->background_1.gray);
- if (optimize)
+ if (optimize != 0)
w = v;
else
- w = gamma_16_from_1[(v&0xff) >> gamma_shift][v >> 8];
+ w = gamma_16_from_1[(v & 0xff) >>
+ gamma_shift][v >> 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
}
@@ -3967,7 +3687,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
if (a == 0)
{
- *sp = (png_byte)((png_ptr->background.gray >> 8) & 0xff);
+ *sp = (png_byte)((png_ptr->background.gray >> 8)
+ & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.gray & 0xff);
}
@@ -3976,7 +3697,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
png_uint_16 g, v;
g = (png_uint_16)(((*sp) << 8) + *(sp + 1));
- png_composite_16(v, g, a, png_ptr->background_1.gray);
+ png_composite_16(v, g, a, png_ptr->background.gray);
*sp = (png_byte)((v >> 8) & 0xff);
*(sp + 1) = (png_byte)(v & 0xff);
}
@@ -4020,17 +3741,17 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_to_1[*sp];
png_composite(w, v, a, png_ptr->background_1.red);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*sp = w;
v = gamma_to_1[*(sp + 1)];
png_composite(w, v, a, png_ptr->background_1.green);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 1) = w;
v = gamma_to_1[*(sp + 2)];
png_composite(w, v, a, png_ptr->background_1.blue);
- if (!optimize) w = gamma_from_1[w];
+ if (optimize == 0) w = gamma_from_1[w];
*(sp + 2) = w;
}
}
@@ -4097,9 +3818,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Background is already in screen gamma */
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4109,23 +3833,26 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
v = gamma_16_to_1[*(sp + 1) >> gamma_shift][*sp];
png_composite_16(w, v, a, png_ptr->background_1.red);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*sp = (png_byte)((w >> 8) & 0xff);
*(sp + 1) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 3) >> gamma_shift][*(sp + 2)];
png_composite_16(w, v, a, png_ptr->background_1.green);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 2) = (png_byte)((w >> 8) & 0xff);
*(sp + 3) = (png_byte)(w & 0xff);
v = gamma_16_to_1[*(sp + 5) >> gamma_shift][*(sp + 4)];
png_composite_16(w, v, a, png_ptr->background_1.blue);
- if (!optimize)
- w = gamma_16_from_1[((w&0xff) >> gamma_shift)][w >> 8];
+ if (optimize == 0)
+ w = gamma_16_from_1[((w & 0xff) >> gamma_shift)][w >>
+ 8];
*(sp + 4) = (png_byte)((w >> 8) & 0xff);
*(sp + 5) = (png_byte)(w & 0xff);
@@ -4146,9 +3873,12 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
{
*sp = (png_byte)((png_ptr->background.red >> 8) & 0xff);
*(sp + 1) = (png_byte)(png_ptr->background.red & 0xff);
- *(sp + 2) = (png_byte)((png_ptr->background.green >> 8) & 0xff);
- *(sp + 3) = (png_byte)(png_ptr->background.green & 0xff);
- *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8) & 0xff);
+ *(sp + 2) = (png_byte)((png_ptr->background.green >> 8)
+ & 0xff);
+ *(sp + 3) = (png_byte)(png_ptr->background.green
+ & 0xff);
+ *(sp + 4) = (png_byte)((png_ptr->background.blue >> 8)
+ & 0xff);
*(sp + 5) = (png_byte)(png_ptr->background.blue & 0xff);
}
@@ -4185,7 +3915,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
}
}
}
-#endif /* PNG_READ_BACKGROUND_SUPPORTED || PNG_READ_ALPHA_MODE_SUPPORTED */
+#endif /* READ_BACKGROUND || READ_ALPHA_MODE */
#ifdef PNG_READ_GAMMA_SUPPORTED
/* Gamma correct the image, avoiding the alpha channel. Make sure
@@ -4194,8 +3924,8 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* is 16, use gamma_16_table and gamma_shift. Build these with
* build_gamma_table().
*/
-void /* PRIVATE */
-png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_gamma(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_const_bytep gamma_table = png_ptr->gamma_table;
png_const_uint_16pp gamma_16_table = png_ptr->gamma_16_table;
@@ -4395,14 +4125,14 @@ png_do_gamma(png_row_infop row_info, png_bytep row, png_structp png_ptr)
* linear.) Called only with color types that have an alpha channel. Needs the
* from_1 tables.
*/
-void /* PRIVATE */
-png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
+static void
+png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structrp png_ptr)
{
png_uint_32 row_width = row_info->width;
png_debug(1, "in png_do_encode_alpha");
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (row_info->bit_depth == 8)
{
@@ -4461,7 +4191,7 @@ png_do_encode_alpha(png_row_infop row_info, png_bytep row, png_structp png_ptr)
/* Expands a palette row to an RGB or RGBA row depending
* upon whether you supply trans and num_trans.
*/
-void /* PRIVATE */
+static void
png_do_expand_palette(png_row_infop row_info, png_bytep row,
png_const_colorp palette, png_const_bytep trans_alpha, int num_trans)
{
@@ -4614,7 +4344,7 @@ png_do_expand_palette(png_row_infop row_info, png_bytep row,
/* If the bit depth < 8, it is expanded to 8. Also, if the already
* expanded transparency value is supplied, an alpha channel is built.
*/
-void /* PRIVATE */
+static void
png_do_expand(png_row_infop row_info, png_bytep row,
png_const_color_16p trans_color)
{
@@ -4628,7 +4358,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
if (row_info->color_type == PNG_COLOR_TYPE_GRAY)
{
- png_uint_16 gray = (png_uint_16)(trans_color ? trans_color->gray : 0);
+ unsigned int gray = trans_color != NULL ? trans_color->gray : 0;
if (row_info->bit_depth < 8)
{
@@ -4636,7 +4366,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
{
case 1:
{
- gray = (png_uint_16)((gray & 0x01) * 0xff);
+ gray = (gray & 0x01) * 0xff;
sp = row + (png_size_t)((row_width - 1) >> 3);
dp = row + (png_size_t)row_width - 1;
shift = 7 - (int)((row_width + 7) & 0x07);
@@ -4664,7 +4394,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 2:
{
- gray = (png_uint_16)((gray & 0x03) * 0x55);
+ gray = (gray & 0x03) * 0x55;
sp = row + (png_size_t)((row_width - 1) >> 2);
dp = row + (png_size_t)row_width - 1;
shift = (int)((3 - ((row_width + 3) & 0x03)) << 1);
@@ -4689,7 +4419,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
case 4:
{
- gray = (png_uint_16)((gray & 0x0f) * 0x11);
+ gray = (gray & 0x0f) * 0x11;
sp = row + (png_size_t)((row_width - 1) >> 1);
dp = row + (png_size_t)row_width - 1;
shift = (int)((1 - ((row_width + 1) & 0x01)) << 2);
@@ -4742,8 +4472,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
else if (row_info->bit_depth == 16)
{
- png_byte gray_high = (png_byte)((gray >> 8) & 0xff);
- png_byte gray_low = (png_byte)(gray & 0xff);
+ unsigned int gray_high = (gray >> 8) & 0xff;
+ unsigned int gray_low = gray & 0xff;
sp = row + row_info->rowbytes - 1;
dp = row + (row_info->rowbytes << 1) - 1;
for (i = 0; i < row_width; i++)
@@ -4772,7 +4502,8 @@ png_do_expand(png_row_infop row_info, png_bytep row,
row_width);
}
}
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB && trans_color)
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB &&
+ trans_color != NULL)
{
if (row_info->bit_depth == 8)
{
@@ -4844,7 +4575,7 @@ png_do_expand(png_row_infop row_info, png_bytep row,
/* If the bit depth is 8 and the color type is not a palette type expand the
* whole row to 16 bits. Has no effect otherwise.
*/
-void /* PRIVATE */
+static void
png_do_expand_16(png_row_infop row_info, png_bytep row)
{
if (row_info->bit_depth == 8 &&
@@ -4872,7 +4603,7 @@ png_do_expand_16(png_row_infop row_info, png_bytep row)
#endif
#ifdef PNG_READ_QUANTIZE_SUPPORTED
-void /* PRIVATE */
+static void
png_do_quantize(png_row_infop row_info, png_bytep row,
png_const_bytep palette_lookup, png_const_bytep quantize_lookup)
{
@@ -4963,70 +4694,304 @@ png_do_quantize(png_row_infop row_info, png_bytep row,
}
}
}
-#endif /* PNG_READ_QUANTIZE_SUPPORTED */
-#endif /* PNG_READ_TRANSFORMS_SUPPORTED */
+#endif /* READ_QUANTIZE */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the row. The order of transformations is significant,
+ * and is very touchy. If you add a transformation, take care to
+ * decide how it fits in with the other transformations here.
+ */
void /* PRIVATE */
-png_do_read_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_read_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_read_intrapixel");
+ png_debug(1, "in png_do_read_transformations");
- if (
- (row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if (png_ptr->row_buf == NULL)
{
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
+ /* Prior to 1.5.4 this output row/pass where the NULL pointer is, but this
+ * error is incredibly rare and incredibly easy to debug without this
+ * information.
+ */
+ png_error(png_ptr, "NULL row buffer");
+ }
- if (row_info->bit_depth == 8)
- {
- png_bytep rp;
- png_uint_32 i;
+ /* The following is debugging; prior to 1.5.4 the code was never compiled in;
+ * in 1.5.4 PNG_FLAG_DETECT_UNINITIALIZED was added and the macro
+ * PNG_WARN_UNINITIALIZED_ROW removed. In 1.6 the new flag is set only for
+ * all transformations, however in practice the ROW_INIT always gets done on
+ * demand, if necessary.
+ */
+ if ((png_ptr->flags & PNG_FLAG_DETECT_UNINITIALIZED) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) == 0)
+ {
+ /* Application has failed to call either png_read_start_image() or
+ * png_read_update_info() after setting transforms that expand pixels.
+ * This check added to libpng-1.2.19 (but not enabled until 1.5.4).
+ */
+ png_error(png_ptr, "Uninitialized row");
+ }
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#ifdef PNG_READ_EXPAND_SUPPORTED
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
+ {
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
+ png_do_expand_palette(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette, png_ptr->trans_alpha, png_ptr->num_trans);
+ }
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+ else
+ {
+ if (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND_tRNS) != 0)
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->trans_color));
else
- return;
-
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- *(rp) = (png_byte)((256 + *rp + *(rp + 1)) & 0xff);
- *(rp+2) = (png_byte)((256 + *(rp + 2) + *(rp + 1)) & 0xff);
- }
+ png_do_expand(row_info, png_ptr->row_buf + 1,
+ NULL);
}
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+ }
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) == 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) != 0)
+ {
+ int rgb_error =
+ png_do_rgb_to_gray(png_ptr, row_info,
+ png_ptr->row_buf + 1);
- else
- return;
+ if (rgb_error != 0)
+ {
+ png_ptr->rgb_to_gray_status=1;
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_WARN)
+ png_warning(png_ptr, "png_do_rgb_to_gray found nongray pixel");
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
- png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
- png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
- png_uint_32 red = (s0 + s1 + 65536) & 0xffff;
- png_uint_32 blue = (s2 + s1 + 65536) & 0xffff;
- *(rp ) = (png_byte)((red >> 8) & 0xff);
- *(rp + 1) = (png_byte)(red & 0xff);
- *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
- *(rp + 5) = (png_byte)(blue & 0xff);
- }
+ if ((png_ptr->transformations & PNG_RGB_TO_GRAY) ==
+ PNG_RGB_TO_GRAY_ERR)
+ png_error(png_ptr, "png_do_rgb_to_gray found nongray pixel");
}
}
+#endif
+
+/* From Andreas Dilger e-mail to png-implement, 26 March 1998:
+ *
+ * In most cases, the "simple transparency" should be done prior to doing
+ * gray-to-RGB, or you will have to test 3x as many bytes to check if a
+ * pixel is transparent. You would also need to make sure that the
+ * transparency information is upgraded to RGB.
+ *
+ * To summarize, the current flow is:
+ * - Gray + simple transparency -> compare 1 or 2 gray bytes and composite
+ * with background "in place" if transparent,
+ * convert to RGB if necessary
+ * - Gray + alpha -> composite with gray background and remove alpha bytes,
+ * convert to RGB if necessary
+ *
+ * To support RGB backgrounds for gray images we need:
+ * - Gray + simple transparency -> convert to RGB + simple transparency,
+ * compare 3 or 6 bytes and composite with
+ * background "in place" if transparent
+ * (3x compare/pixel compared to doing
+ * composite with gray bkgrnd)
+ * - Gray + alpha -> convert to RGB + alpha, composite with background and
+ * remove alpha bytes (3x float
+ * operations/pixel compared with composite
+ * on gray background)
+ *
+ * Greg's change will do this. The reason it wasn't done before is for
+ * performance, as this increases the per-pixel operations. If we would check
+ * in advance if the background was gray or RGB, and position the gray-to-RGB
+ * transform appropriately, then it would save a lot of work/time.
+ */
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* If gray -> RGB, do so now only if background is non-gray; else do later
+ * for performance reasons
+ */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) == 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ if ((png_ptr->transformations & PNG_COMPOSE) != 0)
+ png_do_compose(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_GAMMA_SUPPORTED
+ if ((png_ptr->transformations & PNG_GAMMA) != 0 &&
+#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
+ /* Because RGB_TO_GRAY does the gamma transform. */
+ (png_ptr->transformations & PNG_RGB_TO_GRAY) == 0 &&
+#endif
+#if defined(PNG_READ_BACKGROUND_SUPPORTED) ||\
+ defined(PNG_READ_ALPHA_MODE_SUPPORTED)
+ /* Because PNG_COMPOSE does the gamma transform if there is something to
+ * do (if there is an alpha channel or transparency.)
+ */
+ !((png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ ((png_ptr->num_trans != 0) ||
+ (png_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)) &&
+#endif
+ /* Because png_init_read_transformations transforms the palette, unless
+ * RGB_TO_GRAY will do the transform.
+ */
+ (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE))
+ png_do_gamma(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_STRIP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_STRIP_ALPHA) != 0 &&
+ (png_ptr->transformations & PNG_COMPOSE) != 0 &&
+ (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA))
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ 0 /* at_start == false, because SWAP_ALPHA happens later */);
+#endif
+
+#ifdef PNG_READ_ALPHA_MODE_SUPPORTED
+ if ((png_ptr->transformations & PNG_ENCODE_ALPHA) != 0 &&
+ (row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
+ png_do_encode_alpha(row_info, png_ptr->row_buf + 1, png_ptr);
+#endif
+
+#ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED
+ if ((png_ptr->transformations & PNG_SCALE_16_TO_8) != 0)
+ png_do_scale_16_to_8(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_STRIP_16_TO_8_SUPPORTED
+ /* There is no harm in doing both of these because only one has any effect,
+ * by putting the 'scale' option first if the app asks for scale (either by
+ * calling the API or in a TRANSFORM flag) this is what happens.
+ */
+ if ((png_ptr->transformations & PNG_16_TO_8) != 0)
+ png_do_chop(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_QUANTIZE_SUPPORTED
+ if ((png_ptr->transformations & PNG_QUANTIZE) != 0)
+ {
+ png_do_quantize(row_info, png_ptr->row_buf + 1,
+ png_ptr->palette_lookup, png_ptr->quantize_index);
+
+ if (row_info->rowbytes == 0)
+ png_error(png_ptr, "png_do_quantize returned rowbytes=0");
+ }
+#endif /* READ_QUANTIZE */
+
+#ifdef PNG_READ_EXPAND_16_SUPPORTED
+ /* Do the expansion now, after all the arithmetic has been done. Notice
+ * that previous transformations can handle the PNG_EXPAND_16 flag if this
+ * is efficient (particularly true in the case of gamma correction, where
+ * better accuracy results faster!)
+ */
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
+ png_do_expand_16(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
+ /* NOTE: moved here in 1.5.4 (from much later in this list.) */
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0 &&
+ (png_ptr->mode & PNG_BACKGROUND_IS_GRAY) != 0)
+ png_do_gray_to_rgb(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_read_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_unshift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
+
+#ifdef PNG_READ_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_unpack(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Added at libpng-1.5.10 */
+ if (row_info->color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
+ png_do_check_palette_indexes(png_ptr, row_info);
+#endif
+
+#ifdef PNG_READ_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_read_filler(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->filler, png_ptr->flags);
+#endif
+
+#ifdef PNG_READ_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_read_swap_alpha(row_info, png_ptr->row_buf + 1);
+#endif
+
+#ifdef PNG_READ_16BIT_SUPPORTED
+#ifdef PNG_READ_SWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+#endif
+#endif
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ {
+ if (png_ptr->read_user_transform_fn != NULL)
+ (*(png_ptr->read_user_transform_fn)) /* User read transform function */
+ (png_ptr, /* png_ptr */
+ row_info, /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_size_t rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
+ if (png_ptr->user_transform_depth != 0)
+ row_info->bit_depth = png_ptr->user_transform_depth;
+
+ if (png_ptr->user_transform_channels != 0)
+ row_info->channels = png_ptr->user_transform_channels;
+#endif
+ row_info->pixel_depth = (png_byte)(row_info->bit_depth *
+ row_info->channels);
+
+ row_info->rowbytes = PNG_ROWBYTES(row_info->pixel_depth, row_info->width);
+ }
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED */
+
+#endif /* READ_TRANSFORMS */
+#endif /* READ */
diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c
index aa592ccfbd..6c5c37526b 100644
--- a/src/3rdparty/libpng/pngrutil.c
+++ b/src/3rdparty/libpng/pngrutil.c
@@ -1,8 +1,8 @@
/* pngrutil.c - utilities to read a PNG file
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,10 +18,8 @@
#ifdef PNG_READ_SUPPORTED
-#define png_strtod(p,a,b) strtod(a,b)
-
png_uint_32 PNGAPI
-png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
+png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -40,7 +38,7 @@ png_get_uint_31(png_structp png_ptr, png_const_bytep buf)
#define PNG_FIXED_ERROR (-1)
static png_fixed_point /* PRIVATE */
-png_get_fixed_point(png_structp png_ptr, png_const_bytep buf)
+png_get_fixed_point(png_structrp png_ptr, png_const_bytep buf)
{
png_uint_32 uval = png_get_uint_32(buf);
@@ -110,11 +108,11 @@ png_get_uint_16)(png_const_bytep buf)
return (png_uint_16)val;
}
-#endif /* PNG_READ_INT_FUNCTIONS_SUPPORTED */
+#endif /* READ_INT_FUNCTIONS */
/* Read and check the PNG file signature */
void /* PRIVATE */
-png_read_sig(png_structp png_ptr, png_infop info_ptr)
+png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
{
png_size_t num_checked, num_to_check;
@@ -133,7 +131,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
png_read_data(png_ptr, &(info_ptr->signature[num_checked]), num_to_check);
png_ptr->sig_bytes = 8;
- if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
+ if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
{
if (num_checked < 4 &&
png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
@@ -149,7 +147,7 @@ png_read_sig(png_structp png_ptr, png_infop info_ptr)
* Put the type name into png_ptr->chunk_name, and return the length.
*/
png_uint_32 /* PRIVATE */
-png_read_chunk_header(png_structp png_ptr)
+png_read_chunk_header(png_structrp png_ptr)
{
png_byte buf[8];
png_uint_32 length;
@@ -186,7 +184,7 @@ png_read_chunk_header(png_structp png_ptr)
/* Read data, and (optionally) run it through the CRC. */
void /* PRIVATE */
-png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
+png_crc_read(png_structrp png_ptr, png_bytep buf, png_uint_32 length)
{
if (png_ptr == NULL)
return;
@@ -196,40 +194,40 @@ png_crc_read(png_structp png_ptr, png_bytep buf, png_size_t length)
}
/* Optionally skip data and then check the CRC. Depending on whether we
- * are reading a ancillary or critical chunk, and how the program has set
+ * are reading an ancillary or critical chunk, and how the program has set
* things up, we may calculate the CRC on the data and print a message.
* Returns '1' if there was a CRC error, '0' otherwise.
*/
int /* PRIVATE */
-png_crc_finish(png_structp png_ptr, png_uint_32 skip)
+png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
{
- png_size_t i;
- png_size_t istop = png_ptr->zbuf_size;
-
- for (i = (png_size_t)skip; i > istop; i -= istop)
+ /* The size of the local buffer for inflate is a good guess as to a
+ * reasonable size to use for buffering reads from the application.
+ */
+ while (skip > 0)
{
- png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- }
+ png_uint_32 len;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
- if (i)
- {
- png_crc_read(png_ptr, png_ptr->zbuf, i);
+ len = (sizeof tmpbuf);
+ if (len > skip)
+ len = skip;
+ skip -= len;
+
+ png_crc_read(png_ptr, tmpbuf, len);
}
- if (png_crc_error(png_ptr))
+ if (png_crc_error(png_ptr) != 0)
{
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name) ?
- !(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) :
- (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0 ?
+ (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0 :
+ (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_USE) != 0)
{
png_chunk_warning(png_ptr, "CRC error");
}
else
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- return (0);
- }
+ png_chunk_error(png_ptr, "CRC error");
return (1);
}
@@ -241,13 +239,13 @@ png_crc_finish(png_structp png_ptr, png_uint_32 skip)
* the data it has read thus far.
*/
int /* PRIVATE */
-png_crc_error(png_structp png_ptr)
+png_crc_error(png_structrp png_ptr)
{
png_byte crc_bytes[4];
png_uint_32 crc;
int need_crc = 1;
- if (PNG_CHUNK_ANCILLIARY(png_ptr->chunk_name))
+ if (PNG_CHUNK_ANCILLARY(png_ptr->chunk_name) != 0)
{
if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_MASK) ==
(PNG_FLAG_CRC_ANCILLARY_USE | PNG_FLAG_CRC_ANCILLARY_NOWARN))
@@ -256,7 +254,7 @@ png_crc_error(png_structp png_ptr)
else /* critical */
{
- if (png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE)
+ if ((png_ptr->flags & PNG_FLAG_CRC_CRITICAL_IGNORE) != 0)
need_crc = 0;
}
@@ -267,7 +265,7 @@ png_crc_error(png_structp png_ptr)
/* The chunk CRC must be serialized in a single I/O call. */
png_read_data(png_ptr, crc_bytes, 4);
- if (need_crc)
+ if (need_crc != 0)
{
crc = png_get_uint_32(crc_bytes);
return ((int)(crc != png_ptr->crc));
@@ -277,248 +275,522 @@ png_crc_error(png_structp png_ptr)
return (0);
}
-#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
-static png_size_t
-png_inflate(png_structp png_ptr, png_bytep data, png_size_t size,
- png_bytep output, png_size_t output_size)
+#if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
+ defined(PNG_READ_pCAL_SUPPORTED) || defined(PNG_READ_sCAL_SUPPORTED) ||\
+ defined(PNG_READ_sPLT_SUPPORTED) || defined(PNG_READ_tEXt_SUPPORTED) ||\
+ defined(PNG_READ_zTXt_SUPPORTED) || defined(PNG_SEQUENTIAL_READ_SUPPORTED)
+/* Manage the read buffer; this simply reallocates the buffer if it is not small
+ * enough (or if it is not allocated). The routine returns a pointer to the
+ * buffer; if an error occurs and 'warn' is set the routine returns NULL, else
+ * it will call png_error (via png_malloc) on failure. (warn == 2 means
+ * 'silent').
+ */
+static png_bytep
+png_read_buffer(png_structrp png_ptr, png_alloc_size_t new_size, int warn)
{
- png_size_t count = 0;
-
- /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it can't
- * even necessarily handle 65536 bytes) because the type uInt is "16 bits or
- * more". Consequently it is necessary to chunk the input to zlib. This
- * code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the maximum value
- * that can be stored in a uInt.) It is possible to set ZLIB_IO_MAX to a
- * lower value in pngpriv.h and this may sometimes have a performance
- * advantage, because it forces access of the input data to be separated from
- * at least some of the use by some period of time.
- */
- png_ptr->zstream.next_in = data;
- /* avail_in is set below from 'size' */
- png_ptr->zstream.avail_in = 0;
+ png_bytep buffer = png_ptr->read_buffer;
- while (1)
+ if (buffer != NULL && new_size > png_ptr->read_buffer_size)
{
- int ret, avail;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer = NULL;
+ png_ptr->read_buffer_size = 0;
+ png_free(png_ptr, buffer);
+ buffer = NULL;
+ }
- /* The setting of 'avail_in' used to be outside the loop; by setting it
- * inside it is possible to chunk the input to zlib and simply rely on
- * zlib to advance the 'next_in' pointer. This allows arbitrary amounts o
- * data to be passed through zlib at the unavoidable cost of requiring a
- * window save (memcpy of up to 32768 output bytes) every ZLIB_IO_MAX
- * input bytes.
- */
- if (png_ptr->zstream.avail_in == 0 && size > 0)
+ if (buffer == NULL)
+ {
+ buffer = png_voidcast(png_bytep, png_malloc_base(png_ptr, new_size));
+
+ if (buffer != NULL)
{
- if (size <= ZLIB_IO_MAX)
- {
- /* The value is less than ZLIB_IO_MAX so the cast is safe: */
- png_ptr->zstream.avail_in = (uInt)size;
- size = 0;
- }
+ png_ptr->read_buffer = buffer;
+ png_ptr->read_buffer_size = new_size;
+ }
+
+ else if (warn < 2) /* else silent */
+ {
+ if (warn != 0)
+ png_chunk_warning(png_ptr, "insufficient memory to read chunk");
else
- {
- png_ptr->zstream.avail_in = ZLIB_IO_MAX;
- size -= ZLIB_IO_MAX;
- }
+ png_chunk_error(png_ptr, "insufficient memory to read chunk");
}
+ }
- /* Reset the output buffer each time round - we empty it
- * after every inflate call.
+ return buffer;
+}
+#endif /* READ_iCCP|iTXt|pCAL|sCAL|sPLT|tEXt|zTXt|SEQUENTIAL_READ */
+
+/* png_inflate_claim: claim the zstream for some nefarious purpose that involves
+ * decompression. Returns Z_OK on success, else a zlib error code. It checks
+ * the owner but, in final release builds, just issues a warning if some other
+ * chunk apparently owns the stream. Prior to release it does a png_error.
+ */
+static int
+png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
+{
+ if (png_ptr->zowner != 0)
+ {
+ char msg[64];
+
+ PNG_STRING_FROM_CHUNK(msg, png_ptr->zowner);
+ /* So the message that results is "<chunk> using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
*/
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = png_ptr->zbuf_size;
+ (void)png_safecat(msg, (sizeof msg), 4, " using zstream");
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_chunk_warning(png_ptr, msg);
+ png_ptr->zowner = 0;
+#else
+ png_chunk_error(png_ptr, msg);
+#endif
+ }
- ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
- avail = png_ptr->zbuf_size - png_ptr->zstream.avail_out;
+ /* Implementation note: unlike 'png_deflate_claim' this internal function
+ * does not take the size of the data as an argument. Some efficiency could
+ * be gained by using this when it is known *if* the zlib stream itself does
+ * not record the number; however, this is an illusion: the original writer
+ * of the PNG may have selected a lower window size, and we really must
+ * follow that because, for systems with with limited capabilities, we
+ * would otherwise reject the application's attempts to use a smaller window
+ * size (zlib doesn't have an interface to say "this or lower"!).
+ *
+ * inflateReset2 was added to zlib 1.2.4; before this the window could not be
+ * reset, therefore it is necessary to always allocate the maximum window
+ * size with earlier zlibs just in case later compressed chunks need it.
+ */
+ {
+ int ret; /* zlib return code */
+#if PNG_ZLIB_VERNUM >= 0x1240
- /* First copy/count any new output - but only if we didn't
- * get an error code.
+# if defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_MAXIMUM_INFLATE_WINDOW)
+ int window_bits;
+
+ if (((png_ptr->options >> PNG_MAXIMUM_INFLATE_WINDOW) & 3) ==
+ PNG_OPTION_ON)
+ window_bits = 15;
+
+ else
+ window_bits = 0;
+# else
+# define window_bits 0
+# endif
+#endif
+
+ /* Set this for safety, just in case the previous owner left pointers to
+ * memory allocations.
*/
- if ((ret == Z_OK || ret == Z_STREAM_END) && avail > 0)
- {
- png_size_t space = avail; /* > 0, see above */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
- if (output != 0 && output_size > count)
- {
- png_size_t copy = output_size - count;
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateReset(&png_ptr->zstream);
+#else
+ ret = inflateReset2(&png_ptr->zstream, window_bits);
+#endif
+ }
- if (space < copy)
- copy = space;
+ else
+ {
+#if PNG_ZLIB_VERNUM < 0x1240
+ ret = inflateInit(&png_ptr->zstream);
+#else
+ ret = inflateInit2(&png_ptr->zstream, window_bits);
+#endif
- png_memcpy(output + count, png_ptr->zbuf, copy);
- }
- count += space;
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
}
if (ret == Z_OK)
- continue;
+ png_ptr->zowner = owner;
+
+ else
+ png_zstream_error(png_ptr, ret);
+
+ return ret;
+ }
+
+#ifdef window_bits
+# undef window_bits
+#endif
+}
- /* Termination conditions - always reset the zstream, it
- * must be left in inflateInit state.
+#ifdef PNG_READ_COMPRESSED_TEXT_SUPPORTED
+/* png_inflate now returns zlib error codes including Z_OK and Z_STREAM_END to
+ * allow the caller to do multiple calls if required. If the 'finish' flag is
+ * set Z_FINISH will be passed to the final inflate() call and Z_STREAM_END must
+ * be returned or there has been a problem, otherwise Z_SYNC_FLUSH is used and
+ * Z_OK or Z_STREAM_END will be returned on success.
+ *
+ * The input and output sizes are updated to the actual amounts of data consumed
+ * or written, not the amount available (as in a z_stream). The data pointers
+ * are not changed, so the next input is (data+input_size) and the next
+ * available output is (output+output_size).
+ */
+static int
+png_inflate(png_structrp png_ptr, png_uint_32 owner, int finish,
+ /* INPUT: */ png_const_bytep input, png_uint_32p input_size_ptr,
+ /* OUTPUT: */ png_bytep output, png_alloc_size_t *output_size_ptr)
+{
+ if (png_ptr->zowner == owner) /* Else not claimed */
+ {
+ int ret;
+ png_alloc_size_t avail_out = *output_size_ptr;
+ png_uint_32 avail_in = *input_size_ptr;
+
+ /* zlib can't necessarily handle more than 65535 bytes at once (i.e. it
+ * can't even necessarily handle 65536 bytes) because the type uInt is
+ * "16 bits or more". Consequently it is necessary to chunk the input to
+ * zlib. This code uses ZLIB_IO_MAX, from pngpriv.h, as the maximum (the
+ * maximum value that can be stored in a uInt.) It is possible to set
+ * ZLIB_IO_MAX to a lower value in pngpriv.h and this may sometimes have
+ * a performance advantage, because it reduces the amount of data accessed
+ * at each step and that may give the OS more time to page it in.
*/
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ /* avail_in and avail_out are set below from 'size' */
png_ptr->zstream.avail_in = 0;
- inflateReset(&png_ptr->zstream);
-
- if (ret == Z_STREAM_END)
- return count; /* NOTE: may be zero. */
+ png_ptr->zstream.avail_out = 0;
- /* Now handle the error codes - the API always returns 0
- * and the error message is dumped into the uncompressed
- * buffer if available.
+ /* Read directly into the output if it is available (this is set to
+ * a local buffer below if output is NULL).
*/
-# ifdef PNG_WARNINGS_SUPPORTED
+ if (output != NULL)
+ png_ptr->zstream.next_out = output;
+
+ do
{
- png_const_charp msg;
+ uInt avail;
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
+
+ /* zlib INPUT BUFFER */
+ /* The setting of 'avail_in' used to be outside the loop; by setting it
+ * inside it is possible to chunk the input to zlib and simply rely on
+ * zlib to advance the 'next_in' pointer. This allows arbitrary
+ * amounts of data to be passed through zlib at the unavoidable cost of
+ * requiring a window save (memcpy of up to 32768 output bytes)
+ * every ZLIB_IO_MAX input bytes.
+ */
+ avail_in += png_ptr->zstream.avail_in; /* not consumed last time */
- if (png_ptr->zstream.msg != 0)
- msg = png_ptr->zstream.msg;
+ avail = ZLIB_IO_MAX;
- else switch (ret)
- {
- case Z_BUF_ERROR:
- msg = "Buffer error in compressed datastream";
- break;
+ if (avail_in < avail)
+ avail = (uInt)avail_in; /* safe: < than ZLIB_IO_MAX */
- case Z_DATA_ERROR:
- msg = "Data error in compressed datastream";
- break;
+ avail_in -= avail;
+ png_ptr->zstream.avail_in = avail;
- default:
- msg = "Incomplete compressed datastream";
- break;
+ /* zlib OUTPUT BUFFER */
+ avail_out += png_ptr->zstream.avail_out; /* not written last time */
+
+ avail = ZLIB_IO_MAX; /* maximum zlib can process */
+
+ if (output == NULL)
+ {
+ /* Reset the output buffer each time round if output is NULL and
+ * make available the full buffer, up to 'remaining_space'
+ */
+ png_ptr->zstream.next_out = local_buffer;
+ if ((sizeof local_buffer) < avail)
+ avail = (sizeof local_buffer);
}
- png_chunk_warning(png_ptr, msg);
- }
-# endif
+ if (avail_out < avail)
+ avail = (uInt)avail_out; /* safe: < ZLIB_IO_MAX */
- /* 0 means an error - notice that this code simply ignores
- * zero length compressed chunks as a result.
+ png_ptr->zstream.avail_out = avail;
+ avail_out -= avail;
+
+ /* zlib inflate call */
+ /* In fact 'avail_out' may be 0 at this point, that happens at the end
+ * of the read when the final LZ end code was not passed at the end of
+ * the previous chunk of input data. Tell zlib if we have reached the
+ * end of the output buffer.
+ */
+ ret = inflate(&png_ptr->zstream, avail_out > 0 ? Z_NO_FLUSH :
+ (finish ? Z_FINISH : Z_SYNC_FLUSH));
+ } while (ret == Z_OK);
+
+ /* For safety kill the local buffer pointer now */
+ if (output == NULL)
+ png_ptr->zstream.next_out = NULL;
+
+ /* Claw back the 'size' and 'remaining_space' byte counts. */
+ avail_in += png_ptr->zstream.avail_in;
+ avail_out += png_ptr->zstream.avail_out;
+
+ /* Update the input and output sizes; the updated values are the amount
+ * consumed or written, effectively the inverse of what zlib uses.
*/
- return 0;
+ if (avail_out > 0)
+ *output_size_ptr -= avail_out;
+
+ if (avail_in > 0)
+ *input_size_ptr -= avail_in;
+
+ /* Ensure png_ptr->zstream.msg is set (even in the success case!) */
+ png_zstream_error(png_ptr, ret);
+ return ret;
+ }
+
+ else
+ {
+ /* This is a bad internal error. The recovery assigns to the zstream msg
+ * pointer, which is not owned by the caller, but this is safe; it's only
+ * used on errors!
+ */
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
}
}
/*
- * Decompress trailing data in a chunk. The assumption is that chunkdata
+ * Decompress trailing data in a chunk. The assumption is that read_buffer
* points at an allocated area holding the contents of a chunk with a
* trailing compressed part. What we get back is an allocated area
* holding the original prefix part and an uncompressed version of the
* trailing part (the malloc area passed in is freed).
*/
-void /* PRIVATE */
-png_decompress_chunk(png_structp png_ptr, int comp_type,
- png_size_t chunklength,
- png_size_t prefix_size, png_size_t *newlength)
+static int
+png_decompress_chunk(png_structrp png_ptr,
+ png_uint_32 chunklength, png_uint_32 prefix_size,
+ png_alloc_size_t *newlength /* must be initialized to the maximum! */,
+ int terminate /*add a '\0' to the end of the uncompressed data*/)
{
- /* The caller should guarantee this */
- if (prefix_size > chunklength)
- {
- /* The recovery is to delete the chunk. */
- png_warning(png_ptr, "invalid chunklength");
- prefix_size = 0; /* To delete everything */
- }
+ /* TODO: implement different limits for different types of chunk.
+ *
+ * The caller supplies *newlength set to the maximum length of the
+ * uncompressed data, but this routine allocates space for the prefix and
+ * maybe a '\0' terminator too. We have to assume that 'prefix_size' is
+ * limited only by the maximum chunk size.
+ */
+ png_alloc_size_t limit = PNG_SIZE_MAX;
- else if (comp_type == PNG_COMPRESSION_TYPE_BASE)
+# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+
+ if (limit >= prefix_size + (terminate != 0))
{
- png_size_t expanded_size = png_inflate(png_ptr,
- (png_bytep)(png_ptr->chunkdata + prefix_size),
- chunklength - prefix_size,
- 0, /* output */
- 0); /* output size */
+ int ret;
- /* Now check the limits on this chunk - if the limit fails the
- * compressed data will be removed, the prefix will remain.
- */
- if (prefix_size >= (~(png_size_t)0) - 1 ||
- expanded_size >= (~(png_size_t)0) - 1 - prefix_size
-#ifdef PNG_USER_LIMITS_SUPPORTED
- || (png_ptr->user_chunk_malloc_max &&
- (prefix_size + expanded_size >= png_ptr->user_chunk_malloc_max - 1))
-#else
- || ((PNG_USER_CHUNK_MALLOC_MAX > 0) &&
- prefix_size + expanded_size >= PNG_USER_CHUNK_MALLOC_MAX - 1)
-#endif
- )
- png_warning(png_ptr, "Exceeded size limit while expanding chunk");
+ limit -= prefix_size + (terminate != 0);
- /* If the size is zero either there was an error and a message
- * has already been output (warning) or the size really is zero
- * and we have nothing to do - the code will exit through the
- * error case below.
- */
- else if (expanded_size > 0)
+ if (limit < *newlength)
+ *newlength = limit;
+
+ /* Now try to claim the stream. */
+ ret = png_inflate_claim(png_ptr, png_ptr->chunk_name);
+
+ if (ret == Z_OK)
{
- /* Success (maybe) - really uncompress the chunk. */
- png_size_t new_size = 0;
- png_charp text = (png_charp)png_malloc_warn(png_ptr,
- prefix_size + expanded_size + 1);
+ png_uint_32 lzsize = chunklength - prefix_size;
+
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ /* input: */ png_ptr->read_buffer + prefix_size, &lzsize,
+ /* output: */ NULL, newlength);
- if (text != NULL)
+ if (ret == Z_STREAM_END)
{
- png_memcpy(text, png_ptr->chunkdata, prefix_size);
- new_size = png_inflate(png_ptr,
- (png_bytep)(png_ptr->chunkdata + prefix_size),
- chunklength - prefix_size,
- (png_bytep)(text + prefix_size), expanded_size);
- text[prefix_size + expanded_size] = 0; /* just in case */
-
- if (new_size == expanded_size)
+ /* Use 'inflateReset' here, not 'inflateReset2' because this
+ * preserves the previously decided window size (otherwise it would
+ * be necessary to store the previous window size.) In practice
+ * this doesn't matter anyway, because png_inflate will call inflate
+ * with Z_FINISH in almost all cases, so the window will not be
+ * maintained.
+ */
+ if (inflateReset(&png_ptr->zstream) == Z_OK)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = text;
- *newlength = prefix_size + expanded_size;
- return; /* The success return! */
+ /* Because of the limit checks above we know that the new,
+ * expanded, size will fit in a size_t (let alone an
+ * png_alloc_size_t). Use png_malloc_base here to avoid an
+ * extra OOM message.
+ */
+ png_alloc_size_t new_size = *newlength;
+ png_alloc_size_t buffer_size = prefix_size + new_size +
+ (terminate != 0);
+ png_bytep text = png_voidcast(png_bytep, png_malloc_base(png_ptr,
+ buffer_size));
+
+ if (text != NULL)
+ {
+ ret = png_inflate(png_ptr, png_ptr->chunk_name, 1/*finish*/,
+ png_ptr->read_buffer + prefix_size, &lzsize,
+ text + prefix_size, newlength);
+
+ if (ret == Z_STREAM_END)
+ {
+ if (new_size == *newlength)
+ {
+ if (terminate != 0)
+ text[prefix_size + *newlength] = 0;
+
+ if (prefix_size > 0)
+ memcpy(text, png_ptr->read_buffer, prefix_size);
+
+ {
+ png_bytep old_ptr = png_ptr->read_buffer;
+
+ png_ptr->read_buffer = text;
+ png_ptr->read_buffer_size = buffer_size;
+ text = old_ptr; /* freed below */
+ }
+ }
+
+ else
+ {
+ /* The size changed on the second read, there can be no
+ * guarantee that anything is correct at this point.
+ * The 'msg' pointer has been set to "unexpected end of
+ * LZ stream", which is fine, but return an error code
+ * that the caller won't accept.
+ */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
+ }
+
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN; /* for safety */
+
+ /* Free the text pointer (this is the old read_buffer on
+ * success)
+ */
+ png_free(png_ptr, text);
+ text = NULL;
+
+ /* This really is very benign, but it's still an error because
+ * the extra space may otherwise be used as a Trojan Horse.
+ */
+ if (ret == Z_STREAM_END &&
+ chunklength - prefix_size != lzsize)
+ png_chunk_benign_error(png_ptr, "extra compressed data");
+ }
+
+ else
+ {
+ /* Out of memory allocating the buffer */
+ ret = Z_MEM_ERROR;
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ }
}
- png_warning(png_ptr, "png_inflate logic error");
- png_free(png_ptr, text);
+ else
+ {
+ /* inflateReset failed, store the error message */
+ png_zstream_error(png_ptr, ret);
+
+ if (ret == Z_STREAM_END)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+ }
}
- else
- png_warning(png_ptr, "Not enough memory to decompress chunk");
+ else if (ret == Z_OK)
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ /* Release the claimed stream */
+ png_ptr->zowner = 0;
}
+
+ else /* the claim failed */ if (ret == Z_STREAM_END) /* impossible! */
+ ret = PNG_UNEXPECTED_ZLIB_RETURN;
+
+ return ret;
}
- else /* if (comp_type != PNG_COMPRESSION_TYPE_BASE) */
+ else
{
- PNG_WARNING_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, comp_type);
- png_formatted_warning(png_ptr, p, "Unknown compression type @1");
-
- /* The recovery is to simply drop the data. */
+ /* Application/configuration limits exceeded */
+ png_zstream_error(png_ptr, Z_MEM_ERROR);
+ return Z_MEM_ERROR;
}
+}
+#endif /* READ_COMPRESSED_TEXT */
- /* Generic error return - leave the prefix, delete the compressed
- * data, reallocate the chunkdata to remove the potentially large
- * amount of compressed data.
- */
+#ifdef PNG_READ_iCCP_SUPPORTED
+/* Perform a partial read and decompress, producing 'avail_out' bytes and
+ * reading from the current chunk as required.
+ */
+static int
+png_inflate_read(png_structrp png_ptr, png_bytep read_buffer, uInt read_size,
+ png_uint_32p chunk_bytes, png_bytep next_out, png_alloc_size_t *out_size,
+ int finish)
+{
+ if (png_ptr->zowner == png_ptr->chunk_name)
{
- png_charp text = (png_charp)png_malloc_warn(png_ptr, prefix_size + 1);
+ int ret;
+
+ /* next_in and avail_in must have been initialized by the caller. */
+ png_ptr->zstream.next_out = next_out;
+ png_ptr->zstream.avail_out = 0; /* set in the loop */
- if (text != NULL)
+ do
{
- if (prefix_size > 0)
- png_memcpy(text, png_ptr->chunkdata, prefix_size);
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ if (read_size > *chunk_bytes)
+ read_size = (uInt)*chunk_bytes;
+ *chunk_bytes -= read_size;
+
+ if (read_size > 0)
+ png_crc_read(png_ptr, read_buffer, read_size);
+
+ png_ptr->zstream.next_in = read_buffer;
+ png_ptr->zstream.avail_in = read_size;
+ }
+
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ uInt avail = ZLIB_IO_MAX;
+ if (avail > *out_size)
+ avail = (uInt)*out_size;
+ *out_size -= avail;
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = text;
+ png_ptr->zstream.avail_out = avail;
+ }
- /* This is an extra zero in the 'uncompressed' part. */
- *(png_ptr->chunkdata + prefix_size) = 0x00;
+ /* Use Z_SYNC_FLUSH when there is no more chunk data to ensure that all
+ * the available output is produced; this allows reading of truncated
+ * streams.
+ */
+ ret = inflate(&png_ptr->zstream,
+ *chunk_bytes > 0 ? Z_NO_FLUSH : (finish ? Z_FINISH : Z_SYNC_FLUSH));
}
- /* Ignore a malloc error here - it is safe. */
+ while (ret == Z_OK && (*out_size > 0 || png_ptr->zstream.avail_out > 0));
+
+ *out_size += png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* Should not be required, but is safe */
+
+ /* Ensure the error message pointer is always set: */
+ png_zstream_error(png_ptr, ret);
+ return ret;
}
- *newlength = prefix_size;
+ else
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("zstream unclaimed");
+ return Z_STREAM_ERROR;
+ }
}
-#endif /* PNG_READ_COMPRESSED_TEXT_SUPPORTED */
+#endif
/* Read and check the IDHR chunk */
+
void /* PRIVATE */
-png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_IHDR(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[13];
png_uint_32 width, height;
@@ -527,12 +799,12 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_IHDR");
- if (png_ptr->mode & PNG_HAVE_IHDR)
- png_error(png_ptr, "Out of place IHDR");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) != 0)
+ png_chunk_error(png_ptr, "out of place");
/* Check the length */
if (length != 13)
- png_error(png_ptr, "Invalid IHDR chunk");
+ png_chunk_error(png_ptr, "invalid");
png_ptr->mode |= PNG_HAVE_IHDR;
@@ -581,8 +853,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
/* Set up other useful info */
- png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth *
- png_ptr->channels);
+ png_ptr->pixel_depth = (png_byte)(png_ptr->bit_depth * png_ptr->channels);
png_ptr->rowbytes = PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->width);
png_debug1(3, "bit_depth = %d", png_ptr->bit_depth);
png_debug1(3, "channels = %d", png_ptr->channels);
@@ -593,7 +864,7 @@ png_handle_IHDR(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
/* Read and check the palette */
void /* PRIVATE */
-png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_color palette[PNG_MAX_PALETTE_LENGTH];
int num, i;
@@ -603,26 +874,33 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_PLTE");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before PLTE");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ /* Moved to before the 'after IDAT' check below because otherwise duplicate
+ * PLTE chunks are potentially ignored (the spec says there shall not be more
+ * than one PLTE, the error is not treated as benign, so this check trumps
+ * the requirement that PLTE appears before IDAT.)
+ */
+ else if ((png_ptr->mode & PNG_HAVE_PLTE) != 0)
+ png_chunk_error(png_ptr, "duplicate");
+
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid PLTE after IDAT");
+ /* This is benign because the non-benign error happened before, when an
+ * IDAT was encountered in a color-mapped image with no PLTE.
+ */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- png_error(png_ptr, "Duplicate PLTE chunk");
-
png_ptr->mode |= PNG_HAVE_PLTE;
- if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
- png_warning(png_ptr,
- "Ignoring PLTE chunk in grayscale PNG");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "ignored in grayscale PNG");
return;
}
@@ -636,19 +914,18 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length > 3*PNG_MAX_PALETTE_LENGTH || length % 3)
{
+ png_crc_finish(png_ptr, length);
+
if (png_ptr->color_type != PNG_COLOR_TYPE_PALETTE)
- {
- png_warning(png_ptr, "Invalid palette chunk");
- png_crc_finish(png_ptr, length);
- return;
- }
+ png_chunk_benign_error(png_ptr, "invalid");
else
- {
- png_error(png_ptr, "Invalid palette chunk");
- }
+ png_chunk_error(png_ptr, "invalid");
+
+ return;
}
+ /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */
num = (int)length / 3;
#ifdef PNG_POINTER_INDEXING_SUPPORTED
@@ -687,214 +964,196 @@ png_handle_PLTE(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#ifndef PNG_READ_OPT_PLTE_SUPPORTED
- else if (png_crc_error(png_ptr)) /* Only if we have a CRC error */
+ else if (png_crc_error(png_ptr) != 0) /* Only if we have a CRC error */
{
/* If we don't want to use the data from an ancillary chunk,
* we have two options: an error abort, or a warning and we
* ignore the data in this chunk (which should be OK, since
* it's considered ancillary for a RGB or RGBA image).
+ *
+ * IMPLEMENTATION NOTE: this is only here because png_crc_finish uses the
+ * chunk type to determine whether to check the ancillary or the critical
+ * flags.
*/
- if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE))
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_USE) == 0)
{
- if (png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN)
- {
- png_chunk_benign_error(png_ptr, "CRC error");
- }
+ if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) != 0)
+ return;
else
- {
- png_chunk_warning(png_ptr, "CRC error");
- return;
- }
+ png_chunk_error(png_ptr, "CRC error");
}
/* Otherwise, we (optionally) emit a warning and use the chunk. */
- else if (!(png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN))
- {
+ else if ((png_ptr->flags & PNG_FLAG_CRC_ANCILLARY_NOWARN) == 0)
png_chunk_warning(png_ptr, "CRC error");
- }
}
#endif
+ /* TODO: png_set_PLTE has the side effect of setting png_ptr->palette to its
+ * own copy of the palette. This has the side effect that when png_start_row
+ * is called (this happens after any call to png_read_update_info) the
+ * info_ptr palette gets changed. This is extremely unexpected and
+ * confusing.
+ *
+ * Fix this by not sharing the palette in this way.
+ */
png_set_PLTE(png_ptr, info_ptr, palette, num);
+ /* The three chunks, bKGD, hIST and tRNS *must* appear after PLTE and before
+ * IDAT. Prior to 1.6.0 this was not checked; instead the code merely
+ * checked the apparent validity of a tRNS chunk inserted before PLTE on a
+ * palette PNG. 1.6.0 attempts to rigorously follow the standard and
+ * therefore does a benign error if the erroneous condition is detected *and*
+ * cancels the tRNS if the benign error returns. The alternative is to
+ * amend the standard since it would be rather hypocritical of the standards
+ * maintainers to ignore it.
+ */
#ifdef PNG_READ_tRNS_SUPPORTED
- if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ if (png_ptr->num_trans > 0 ||
+ (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0))
{
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
- {
- if (png_ptr->num_trans > (png_uint_16)num)
- {
- png_warning(png_ptr, "Truncating incorrect tRNS chunk length");
- png_ptr->num_trans = (png_uint_16)num;
- }
+ /* Cancel this because otherwise it would be used if the transforms
+ * require it. Don't cancel the 'valid' flag because this would prevent
+ * detection of duplicate chunks.
+ */
+ png_ptr->num_trans = 0;
- if (info_ptr->num_trans > (png_uint_16)num)
- {
- png_warning(png_ptr, "Truncating incorrect info tRNS chunk length");
- info_ptr->num_trans = (png_uint_16)num;
- }
- }
+ if (info_ptr != NULL)
+ info_ptr->num_trans = 0;
+
+ png_chunk_benign_error(png_ptr, "tRNS must be after");
}
#endif
+#ifdef PNG_READ_hIST_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
+ png_chunk_benign_error(png_ptr, "hIST must be after");
+#endif
+
+#ifdef PNG_READ_bKGD_SUPPORTED
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
+ png_chunk_benign_error(png_ptr, "bKGD must be after");
+#endif
}
void /* PRIVATE */
-png_handle_IEND(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_IEND(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_debug(1, "in png_handle_IEND");
- if (!(png_ptr->mode & PNG_HAVE_IHDR) || !(png_ptr->mode & PNG_HAVE_IDAT))
- {
- png_error(png_ptr, "No image in file");
- }
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0 ||
+ (png_ptr->mode & PNG_HAVE_IDAT) == 0)
+ png_chunk_error(png_ptr, "out of place");
png_ptr->mode |= (PNG_AFTER_IDAT | PNG_HAVE_IEND);
- if (length != 0)
- {
- png_warning(png_ptr, "Incorrect IEND chunk length");
- }
-
png_crc_finish(png_ptr, length);
- PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
+ if (length != 0)
+ png_chunk_benign_error(png_ptr, "invalid");
+
+ PNG_UNUSED(info_ptr)
}
#ifdef PNG_READ_gAMA_SUPPORTED
void /* PRIVATE */
-png_handle_gAMA(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_gAMA(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_fixed_point igamma;
png_byte buf[4];
png_debug(1, "in png_handle_gAMA");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before gAMA");
-
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- png_warning(png_ptr, "Invalid gAMA after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place gAMA chunk");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA)
-#ifdef PNG_READ_sRGB_SUPPORTED
- && !(info_ptr->valid & PNG_INFO_sRGB)
-#endif
- )
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Duplicate gAMA chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 4)
{
- png_warning(png_ptr, "Incorrect gAMA chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 4);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
igamma = png_get_fixed_point(NULL, buf);
- /* Check for zero gamma or an error. */
- if (igamma <= 0)
- {
- png_warning(png_ptr,
- "Ignoring gAMA chunk with out of range gamma");
-
- return;
- }
-
-# ifdef PNG_READ_sRGB_SUPPORTED
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
- {
- if (PNG_OUT_OF_RANGE(igamma, 45500, 500))
- {
- PNG_WARNING_PARAMETERS(p)
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, igamma);
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- return;
- }
- }
-# endif /* PNG_READ_sRGB_SUPPORTED */
-
-# ifdef PNG_READ_GAMMA_SUPPORTED
- /* Gamma correction on read is supported. */
- png_ptr->gamma = igamma;
-# endif
- /* And set the 'info' structure members. */
- png_set_gAMA_fixed(png_ptr, info_ptr, igamma);
+ png_colorspace_set_gamma(png_ptr, &png_ptr->colorspace, igamma);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sBIT_SUPPORTED
void /* PRIVATE */
-png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen, i;
+ png_byte sample_depth;
png_byte buf[4];
png_debug(1, "in png_handle_sBIT");
- buf[0] = buf[1] = buf[2] = buf[3] = 0;
-
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sBIT");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid sBIT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- {
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place sBIT chunk");
- }
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT))
+ if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sBIT) != 0)
{
- png_warning(png_ptr, "Duplicate sBIT chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ {
truelen = 3;
+ sample_depth = 8;
+ }
else
- truelen = (png_size_t)png_ptr->channels;
+ {
+ truelen = png_ptr->channels;
+ sample_depth = png_ptr->bit_depth;
+ }
if (length != truelen || length > 4)
{
- png_warning(png_ptr, "Incorrect sBIT chunk length");
+ png_chunk_benign_error(png_ptr, "invalid");
png_crc_finish(png_ptr, length);
return;
}
+ buf[0] = buf[1] = buf[2] = buf[3] = sample_depth;
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ for (i=0; i<truelen; ++i)
+ if (buf[i] == 0 || buf[i] > sample_depth)
+ {
+ png_chunk_benign_error(png_ptr, "invalid");
+ return;
+ }
+
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_ptr->sig_bit.red = buf[0];
png_ptr->sig_bit.green = buf[1];
@@ -917,474 +1176,418 @@ png_handle_sBIT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_cHRM_SUPPORTED
void /* PRIVATE */
-png_handle_cHRM(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_cHRM(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[32];
- png_fixed_point x_white, y_white, x_red, y_red, x_green, y_green, x_blue,
- y_blue;
+ png_xy xy;
png_debug(1, "in png_handle_cHRM");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before cHRM");
-
- else if (png_ptr->mode & PNG_HAVE_IDAT)
- {
- png_warning(png_ptr, "Invalid cHRM after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place cHRM chunk");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM)
-# ifdef PNG_READ_sRGB_SUPPORTED
- && !(info_ptr->valid & PNG_INFO_sRGB)
-# endif
- )
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Duplicate cHRM chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 32)
{
- png_warning(png_ptr, "Incorrect cHRM chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 32);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- x_white = png_get_fixed_point(NULL, buf);
- y_white = png_get_fixed_point(NULL, buf + 4);
- x_red = png_get_fixed_point(NULL, buf + 8);
- y_red = png_get_fixed_point(NULL, buf + 12);
- x_green = png_get_fixed_point(NULL, buf + 16);
- y_green = png_get_fixed_point(NULL, buf + 20);
- x_blue = png_get_fixed_point(NULL, buf + 24);
- y_blue = png_get_fixed_point(NULL, buf + 28);
-
- if (x_white == PNG_FIXED_ERROR ||
- y_white == PNG_FIXED_ERROR ||
- x_red == PNG_FIXED_ERROR ||
- y_red == PNG_FIXED_ERROR ||
- x_green == PNG_FIXED_ERROR ||
- y_green == PNG_FIXED_ERROR ||
- x_blue == PNG_FIXED_ERROR ||
- y_blue == PNG_FIXED_ERROR)
- {
- png_warning(png_ptr, "Ignoring cHRM chunk with negative chromaticities");
+ xy.whitex = png_get_fixed_point(NULL, buf);
+ xy.whitey = png_get_fixed_point(NULL, buf + 4);
+ xy.redx = png_get_fixed_point(NULL, buf + 8);
+ xy.redy = png_get_fixed_point(NULL, buf + 12);
+ xy.greenx = png_get_fixed_point(NULL, buf + 16);
+ xy.greeny = png_get_fixed_point(NULL, buf + 20);
+ xy.bluex = png_get_fixed_point(NULL, buf + 24);
+ xy.bluey = png_get_fixed_point(NULL, buf + 28);
+
+ if (xy.whitex == PNG_FIXED_ERROR ||
+ xy.whitey == PNG_FIXED_ERROR ||
+ xy.redx == PNG_FIXED_ERROR ||
+ xy.redy == PNG_FIXED_ERROR ||
+ xy.greenx == PNG_FIXED_ERROR ||
+ xy.greeny == PNG_FIXED_ERROR ||
+ xy.bluex == PNG_FIXED_ERROR ||
+ xy.bluey == PNG_FIXED_ERROR)
+ {
+ png_chunk_benign_error(png_ptr, "invalid values");
return;
}
-#ifdef PNG_READ_sRGB_SUPPORTED
- if ((info_ptr != NULL) && (info_ptr->valid & PNG_INFO_sRGB))
- {
- if (PNG_OUT_OF_RANGE(x_white, 31270, 1000) ||
- PNG_OUT_OF_RANGE(y_white, 32900, 1000) ||
- PNG_OUT_OF_RANGE(x_red, 64000, 1000) ||
- PNG_OUT_OF_RANGE(y_red, 33000, 1000) ||
- PNG_OUT_OF_RANGE(x_green, 30000, 1000) ||
- PNG_OUT_OF_RANGE(y_green, 60000, 1000) ||
- PNG_OUT_OF_RANGE(x_blue, 15000, 1000) ||
- PNG_OUT_OF_RANGE(y_blue, 6000, 1000))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed, x_white);
- png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_fixed, y_white);
- png_warning_parameter_signed(p, 3, PNG_NUMBER_FORMAT_fixed, x_red);
- png_warning_parameter_signed(p, 4, PNG_NUMBER_FORMAT_fixed, y_red);
- png_warning_parameter_signed(p, 5, PNG_NUMBER_FORMAT_fixed, x_green);
- png_warning_parameter_signed(p, 6, PNG_NUMBER_FORMAT_fixed, y_green);
- png_warning_parameter_signed(p, 7, PNG_NUMBER_FORMAT_fixed, x_blue);
- png_warning_parameter_signed(p, 8, PNG_NUMBER_FORMAT_fixed, y_blue);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect cHRM white(@1,@2) r(@3,@4)g(@5,@6)b(@7,@8) "
- "when sRGB is also present");
- }
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
return;
- }
-#endif /* PNG_READ_sRGB_SUPPORTED */
-#ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Store the _white values as default coefficients for the rgb to gray
- * operation if it is supported. Check if the transform is already set to
- * avoid destroying the transform values.
- */
- if (!png_ptr->rgb_to_gray_coefficients_set)
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0)
{
- /* png_set_background has not been called and we haven't seen an sRGB
- * chunk yet. Find the XYZ of the three end points.
- */
- png_XYZ XYZ;
- png_xy xy;
-
- xy.redx = x_red;
- xy.redy = y_red;
- xy.greenx = x_green;
- xy.greeny = y_green;
- xy.bluex = x_blue;
- xy.bluey = y_blue;
- xy.whitex = x_white;
- xy.whitey = y_white;
-
- if (png_XYZ_from_xy_checked(png_ptr, &XYZ, xy))
- {
- /* The success case, because XYZ_from_xy normalises to a reference
- * white Y of 1.0 we just need to scale the numbers. This should
- * always work just fine. It is an internal error if this overflows.
- */
- {
- png_fixed_point r, g, b;
- if (png_muldiv(&r, XYZ.redY, 32768, PNG_FP_1) &&
- r >= 0 && r <= 32768 &&
- png_muldiv(&g, XYZ.greenY, 32768, PNG_FP_1) &&
- g >= 0 && g <= 32768 &&
- png_muldiv(&b, XYZ.blueY, 32768, PNG_FP_1) &&
- b >= 0 && b <= 32768 &&
- r+g+b <= 32769)
- {
- /* We allow 0 coefficients here. r+g+b may be 32769 if two or
- * all of the coefficients were rounded up. Handle this by
- * reducing the *largest* coefficient by 1; this matches the
- * approach used for the default coefficients in pngrtran.c
- */
- int add = 0;
-
- if (r+g+b > 32768)
- add = -1;
- else if (r+g+b < 32768)
- add = 1;
-
- if (add != 0)
- {
- if (g >= r && g >= b)
- g += add;
- else if (r >= g && r >= b)
- r += add;
- else
- b += add;
- }
-
- /* Check for an internal error. */
- if (r+g+b != 32768)
- png_error(png_ptr,
- "internal error handling cHRM coefficients");
-
- png_ptr->rgb_to_gray_red_coeff = (png_uint_16)r;
- png_ptr->rgb_to_gray_green_coeff = (png_uint_16)g;
- }
-
- /* This is a png_error at present even though it could be ignored -
- * it should never happen, but it is important that if it does, the
- * bug is fixed.
- */
- else
- png_error(png_ptr, "internal error handling cHRM->XYZ");
- }
- }
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "duplicate");
+ return;
}
-#endif
- png_set_cHRM_fixed(png_ptr, info_ptr, x_white, y_white, x_red, y_red,
- x_green, y_green, x_blue, y_blue);
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+ (void)png_colorspace_set_chromaticities(png_ptr, &png_ptr->colorspace, &xy,
+ 1/*prefer cHRM values*/);
+ png_colorspace_sync(png_ptr, info_ptr);
}
#endif
#ifdef PNG_READ_sRGB_SUPPORTED
void /* PRIVATE */
-png_handle_sRGB(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sRGB(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- int intent;
- png_byte buf[1];
+ png_byte intent;
png_debug(1, "in png_handle_sRGB");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sRGB");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid sRGB after IDAT");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place sRGB chunk");
-
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sRGB))
- {
- png_warning(png_ptr, "Duplicate sRGB chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
if (length != 1)
{
- png_warning(png_ptr, "Incorrect sRGB chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, 1);
+ png_crc_read(png_ptr, &intent, 1);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- intent = buf[0];
-
- /* Check for bad intent */
- if (intent >= PNG_sRGB_INTENT_LAST)
- {
- png_warning(png_ptr, "Unknown sRGB intent");
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
return;
- }
-#if defined(PNG_READ_gAMA_SUPPORTED) && defined(PNG_READ_GAMMA_SUPPORTED)
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_gAMA))
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) != 0)
{
- if (PNG_OUT_OF_RANGE(info_ptr->gamma, 45500, 500))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_fixed,
- info_ptr->gamma);
-
- png_formatted_warning(png_ptr, p,
- "Ignoring incorrect gAMA value @1 when sRGB is also present");
- }
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ png_chunk_benign_error(png_ptr, "too many profiles");
+ return;
}
-#endif /* PNG_READ_gAMA_SUPPORTED */
-
-#ifdef PNG_READ_cHRM_SUPPORTED
- if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_cHRM))
- if (PNG_OUT_OF_RANGE(info_ptr->x_white, 31270, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_white, 32900, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_red, 64000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_red, 33000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_green, 30000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_green, 60000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->x_blue, 15000, 1000) ||
- PNG_OUT_OF_RANGE(info_ptr->y_blue, 6000, 1000))
- {
- png_warning(png_ptr,
- "Ignoring incorrect cHRM value when sRGB is also present");
- }
-#endif /* PNG_READ_cHRM_SUPPORTED */
-
- /* This is recorded for use when handling the cHRM chunk above. An sRGB
- * chunk unconditionally overwrites the coefficients for grayscale conversion
- * too.
- */
- png_ptr->is_sRGB = 1;
-
-# ifdef PNG_READ_RGB_TO_GRAY_SUPPORTED
- /* Don't overwrite user supplied values: */
- if (!png_ptr->rgb_to_gray_coefficients_set)
- {
- /* These numbers come from the sRGB specification (or, since one has to
- * pay much money to get a copy, the wikipedia sRGB page) the
- * chromaticity values quoted have been inverted to get the reverse
- * transformation from RGB to XYZ and the 'Y' coefficients scaled by
- * 32768 (then rounded).
- *
- * sRGB and ITU Rec-709 both truncate the values for the D65 white
- * point to four digits and, even though it actually stores five
- * digits, the PNG spec gives the truncated value.
- *
- * This means that when the chromaticities are converted back to XYZ
- * end points we end up with (6968,23435,2366), which, as described in
- * pngrtran.c, would overflow. If the five digit precision and up is
- * used we get, instead:
- *
- * 6968*R + 23435*G + 2365*B
- *
- * (Notice that this rounds the blue coefficient down, rather than the
- * choice used in pngrtran.c which is to round the green one down.)
- */
- png_ptr->rgb_to_gray_red_coeff = 6968; /* 0.212639005871510 */
- png_ptr->rgb_to_gray_green_coeff = 23434; /* 0.715168678767756 */
- /* png_ptr->rgb_to_gray_blue_coeff = 2366; 0.072192315360734 */
-
- /* The following keeps the cHRM chunk from destroying the
- * coefficients again in the event that it follows the sRGB chunk.
- */
- png_ptr->rgb_to_gray_coefficients_set = 1;
- }
-# endif
- png_set_sRGB_gAMA_and_cHRM(png_ptr, info_ptr, intent);
+ (void)png_colorspace_set_sRGB(png_ptr, &png_ptr->colorspace, intent);
+ png_colorspace_sync(png_ptr, info_ptr);
}
-#endif /* PNG_READ_sRGB_SUPPORTED */
+#endif /* READ_sRGB */
#ifdef PNG_READ_iCCP_SUPPORTED
void /* PRIVATE */
-png_handle_iCCP(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
-/* Note: this does not properly handle chunks that are > 64K under DOS */
+png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
+/* Note: this does not properly handle profiles that are > 64K under DOS */
{
- png_byte compression_type;
- png_bytep pC;
- png_charp profile;
- png_uint_32 skip = 0;
- png_uint_32 profile_size;
- png_alloc_size_t profile_length;
- png_size_t slength, prefix_length, data_length;
+ png_const_charp errmsg = NULL; /* error message output, or no error */
+ int finished = 0; /* crc checked */
png_debug(1, "in png_handle_iCCP");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iCCP");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & (PNG_HAVE_IDAT|PNG_HAVE_PLTE)) != 0)
{
- png_warning(png_ptr, "Invalid iCCP after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->mode & PNG_HAVE_PLTE)
- /* Should be an error, but we can cope with it */
- png_warning(png_ptr, "Out of place iCCP chunk");
-
- if ((png_ptr->mode & PNG_HAVE_iCCP) || (info_ptr != NULL &&
- (info_ptr->valid & (PNG_INFO_iCCP|PNG_INFO_sRGB))))
+ /* Consistent with all the above colorspace handling an obviously *invalid*
+ * chunk is just ignored, so does not invalidate the color space. An
+ * alternative is to set the 'invalid' flags at the start of this routine
+ * and only clear them in they were not set before and all the tests pass.
+ * The minimum 'deflate' stream is assumed to be just the 2 byte header and
+ * 4 byte checksum. The keyword must be at least one character and there is
+ * a terminator (0) byte and the compression method.
+ */
+ if (length < 9)
{
- png_warning(png_ptr, "Duplicate iCCP chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too short");
return;
}
- png_ptr->mode |= PNG_HAVE_iCCP;
-
-#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ /* If a colorspace error has already been output skip this chunk */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) != 0)
{
- png_warning(png_ptr, "iCCP chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ return;
}
-#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
-
- if (png_crc_finish(png_ptr, skip))
+ /* Only one sRGB or iCCP chunk is allowed, use the HAVE_INTENT flag to detect
+ * this.
+ */
+ if ((png_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_INTENT) == 0)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ uInt read_length, keyword_length;
+ char keyword[81];
- png_ptr->chunkdata[slength] = 0x00;
+ /* Find the keyword; the keyword plus separator and compression method
+ * bytes can be at most 81 characters long.
+ */
+ read_length = 81; /* maximum */
+ if (read_length > length)
+ read_length = (uInt)length;
- for (profile = png_ptr->chunkdata; *profile; profile++)
- /* Empty loop to find end of name */ ;
+ png_crc_read(png_ptr, (png_bytep)keyword, read_length);
+ length -= read_length;
- ++profile;
+ keyword_length = 0;
+ while (keyword_length < 80 && keyword_length < read_length &&
+ keyword[keyword_length] != 0)
+ ++keyword_length;
- /* There should be at least one zero (the compression type byte)
- * following the separator, and we should be on it
- */
- if (profile >= png_ptr->chunkdata + slength - 1)
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "Malformed iCCP chunk");
- return;
- }
+ /* TODO: make the keyword checking common */
+ if (keyword_length >= 1 && keyword_length <= 79)
+ {
+ /* We only understand '0' compression - deflate - so if we get a
+ * different value we can't safely decode the chunk.
+ */
+ if (keyword_length+1 < read_length &&
+ keyword[keyword_length+1] == PNG_COMPRESSION_TYPE_BASE)
+ {
+ read_length -= keyword_length+2;
- /* Compression_type should always be zero */
- compression_type = *profile++;
+ if (png_inflate_claim(png_ptr, png_iCCP) == Z_OK)
+ {
+ Byte profile_header[132];
+ Byte local_buffer[PNG_INFLATE_BUF_SIZE];
+ png_alloc_size_t size = (sizeof profile_header);
- if (compression_type)
- {
- png_warning(png_ptr, "Ignoring nonzero compression type in iCCP chunk");
- compression_type = 0x00; /* Reset it to zero (libpng-1.0.6 through 1.0.8
- wrote nonzero) */
- }
+ png_ptr->zstream.next_in = (Bytef*)keyword + (keyword_length+2);
+ png_ptr->zstream.avail_in = read_length;
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length, profile_header, &size,
+ 0/*finish: don't, because the output is too small*/);
- prefix_length = profile - png_ptr->chunkdata;
- png_decompress_chunk(png_ptr, compression_type,
- slength, prefix_length, &data_length);
+ if (size == 0)
+ {
+ /* We have the ICC profile header; do the basic header checks.
+ */
+ const png_uint_32 profile_length =
+ png_get_uint_32(profile_header);
- profile_length = data_length - prefix_length;
+ if (png_icc_check_length(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length) != 0)
+ {
+ /* The length is apparently ok, so we can check the 132
+ * byte header.
+ */
+ if (png_icc_check_header(png_ptr, &png_ptr->colorspace,
+ keyword, profile_length, profile_header,
+ png_ptr->color_type) != 0)
+ {
+ /* Now read the tag table; a variable size buffer is
+ * needed at this point, allocate one for the whole
+ * profile. The header check has already validated
+ * that none of these stuff will overflow.
+ */
+ const png_uint_32 tag_count = png_get_uint_32(
+ profile_header+128);
+ png_bytep profile = png_read_buffer(png_ptr,
+ profile_length, 2/*silent*/);
+
+ if (profile != NULL)
+ {
+ memcpy(profile, profile_header,
+ (sizeof profile_header));
+
+ size = 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header), &size, 0);
+
+ /* Still expect a buffer error because we expect
+ * there to be some tag data!
+ */
+ if (size == 0)
+ {
+ if (png_icc_check_tag_table(png_ptr,
+ &png_ptr->colorspace, keyword, profile_length,
+ profile) != 0)
+ {
+ /* The profile has been validated for basic
+ * security issues, so read the whole thing in.
+ */
+ size = profile_length - (sizeof profile_header)
+ - 12 * tag_count;
+
+ (void)png_inflate_read(png_ptr, local_buffer,
+ (sizeof local_buffer), &length,
+ profile + (sizeof profile_header) +
+ 12 * tag_count, &size, 1/*finish*/);
+
+ if (length > 0 && !(png_ptr->flags &
+ PNG_FLAG_BENIGN_ERRORS_WARN))
+ errmsg = "extra compressed data";
+
+ /* But otherwise allow extra data: */
+ else if (size == 0)
+ {
+ if (length > 0)
+ {
+ /* This can be handled completely, so
+ * keep going.
+ */
+ png_chunk_warning(png_ptr,
+ "extra compressed data");
+ }
+
+ png_crc_finish(png_ptr, length);
+ finished = 1;
+
+# ifdef PNG_sRGB_SUPPORTED
+ /* Check for a match against sRGB */
+ png_icc_set_sRGB(png_ptr,
+ &png_ptr->colorspace, profile,
+ png_ptr->zstream.adler);
+# endif
+
+ /* Steal the profile for info_ptr. */
+ if (info_ptr != NULL)
+ {
+ png_free_data(png_ptr, info_ptr,
+ PNG_FREE_ICCP, 0);
+
+ info_ptr->iccp_name = png_voidcast(char*,
+ png_malloc_base(png_ptr,
+ keyword_length+1));
+ if (info_ptr->iccp_name != NULL)
+ {
+ memcpy(info_ptr->iccp_name, keyword,
+ keyword_length+1);
+ info_ptr->iccp_proflen =
+ profile_length;
+ info_ptr->iccp_profile = profile;
+ png_ptr->read_buffer = NULL; /*steal*/
+ info_ptr->free_me |= PNG_FREE_ICCP;
+ info_ptr->valid |= PNG_INFO_iCCP;
+ }
+
+ else
+ {
+ png_ptr->colorspace.flags |=
+ PNG_COLORSPACE_INVALID;
+ errmsg = "out of memory";
+ }
+ }
+
+ /* else the profile remains in the read
+ * buffer which gets reused for subsequent
+ * chunks.
+ */
+
+ if (info_ptr != NULL)
+ png_colorspace_sync(png_ptr, info_ptr);
+
+ if (errmsg == NULL)
+ {
+ png_ptr->zowner = 0;
+ return;
+ }
+ }
+
+ else if (size > 0)
+ errmsg = "truncated";
+
+#ifndef __COVERITY__
+ else
+ errmsg = png_ptr->zstream.msg;
+#endif
+ }
- if (prefix_length > data_length || profile_length < 4)
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "Profile size field missing from iCCP chunk");
- return;
- }
+ /* else png_icc_check_tag_table output an error */
+ }
- /* Check the profile_size recorded in the first 32 bits of the ICC profile */
- pC = (png_bytep)(png_ptr->chunkdata + prefix_length);
- profile_size = ((*(pC )) << 24) |
- ((*(pC + 1)) << 16) |
- ((*(pC + 2)) << 8) |
- ((*(pC + 3)) );
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+ }
- /* NOTE: the following guarantees that 'profile_length' fits into 32 bits,
- * because profile_size is a 32 bit value.
- */
- if (profile_size < profile_length)
- profile_length = profile_size;
+ else
+ errmsg = "out of memory";
+ }
- /* And the following guarantees that profile_size == profile_length. */
- if (profile_size > profile_length)
- {
- PNG_WARNING_PARAMETERS(p)
+ /* else png_icc_check_header output an error */
+ }
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ /* else png_icc_check_length output an error */
+ }
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_u, profile_size);
- png_warning_parameter_unsigned(p, 2, PNG_NUMBER_FORMAT_u, profile_length);
- png_formatted_warning(png_ptr, p,
- "Ignoring iCCP chunk with declared size = @1 and actual length = @2");
- return;
+ else /* profile truncated */
+ errmsg = png_ptr->zstream.msg;
+
+ /* Release the stream */
+ png_ptr->zowner = 0;
+ }
+
+ else /* png_inflate_claim failed */
+ errmsg = png_ptr->zstream.msg;
+ }
+
+ else
+ errmsg = "bad compression method"; /* or missing */
+ }
+
+ else
+ errmsg = "bad keyword";
}
- png_set_iCCP(png_ptr, info_ptr, png_ptr->chunkdata,
- compression_type, (png_bytep)png_ptr->chunkdata + prefix_length,
- profile_size);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ else
+ errmsg = "too many profiles";
+
+ /* Failure: the reason is in 'errmsg' */
+ if (finished == 0)
+ png_crc_finish(png_ptr, length);
+
+ png_ptr->colorspace.flags |= PNG_COLORSPACE_INVALID;
+ png_colorspace_sync(png_ptr, info_ptr);
+ if (errmsg != NULL) /* else already output */
+ png_chunk_benign_error(png_ptr, errmsg);
}
-#endif /* PNG_READ_iCCP_SUPPORTED */
+#endif /* READ_iCCP */
#ifdef PNG_READ_sPLT_SUPPORTED
void /* PRIVATE */
-png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
/* Note: this does not properly handle chunks that are > 64K under DOS */
{
- png_bytep entry_start;
+ png_bytep entry_start, buffer;
png_sPLT_t new_palette;
png_sPLT_entryp pp;
png_uint_32 data_length;
int entry_size, i;
png_uint_32 skip = 0;
- png_size_t slength;
png_uint_32 dl;
png_size_t max_dl;
png_debug(1, "in png_handle_sPLT");
#ifdef PNG_USER_LIMITS_SUPPORTED
-
if (png_ptr->user_chunk_cache_max != 0)
{
if (png_ptr->user_chunk_cache_max == 1)
@@ -1402,55 +1605,53 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sPLT");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sPLT after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "sPLT chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+ if (buffer == NULL)
+ {
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
+ return;
+ }
+
/* WARNING: this may break if size_t is less than 32 bits; it is assumed
* that the PNG_MAX_MALLOC_64K test is enabled in this case, but this is a
* potential breakage point if the types in pngconf.h aren't exactly right.
*/
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
+ buffer[length] = 0;
- for (entry_start = (png_bytep)png_ptr->chunkdata; *entry_start;
- entry_start++)
+ for (entry_start = buffer; *entry_start; entry_start++)
/* Empty loop to find end of name */ ;
++entry_start;
/* A sample depth should follow the separator, and we should be on it */
- if (entry_start > (png_bytep)png_ptr->chunkdata + slength - 2)
+ if (entry_start > buffer + length - 2)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_warning(png_ptr, "malformed sPLT chunk");
return;
}
@@ -1458,23 +1659,19 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
new_palette.depth = *entry_start++;
entry_size = (new_palette.depth == 8 ? 6 : 10);
/* This must fit in a png_uint_32 because it is derived from the original
- * chunk data length (and use 'length', not 'slength' here for clarity -
- * they are guaranteed to be the same, see the tests above.)
+ * chunk data length.
*/
- data_length = length - (png_uint_32)(entry_start -
- (png_bytep)png_ptr->chunkdata);
+ data_length = length - (png_uint_32)(entry_start - buffer);
/* Integrity-check the data length */
- if (data_length % entry_size)
+ if ((data_length % entry_size) != 0)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_warning(png_ptr, "sPLT chunk has bad length");
return;
}
dl = (png_int_32)(data_length / entry_size);
- max_dl = PNG_SIZE_MAX / png_sizeof(png_sPLT_entry);
+ max_dl = PNG_SIZE_MAX / (sizeof (png_sPLT_entry));
if (dl > max_dl)
{
@@ -1485,7 +1682,7 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
new_palette.nentries = (png_int_32)(data_length / entry_size);
new_palette.entries = (png_sPLT_entryp)png_malloc_warn(
- png_ptr, new_palette.nentries * png_sizeof(png_sPLT_entry));
+ png_ptr, new_palette.nentries * (sizeof (png_sPLT_entry)));
if (new_palette.entries == NULL)
{
@@ -1543,38 +1740,36 @@ png_handle_sPLT(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#endif
/* Discard all chunk data except the name and stash that */
- new_palette.name = png_ptr->chunkdata;
+ new_palette.name = (png_charp)buffer;
png_set_sPLT(png_ptr, info_ptr, &new_palette, 1);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, new_palette.entries);
}
-#endif /* PNG_READ_sPLT_SUPPORTED */
+#endif /* READ_sPLT */
#ifdef PNG_READ_tRNS_SUPPORTED
void /* PRIVATE */
-png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte readbuf[PNG_MAX_PALETTE_LENGTH];
png_debug(1, "in png_handle_tRNS");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before tRNS");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid tRNS after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tRNS) != 0)
{
- png_warning(png_ptr, "Duplicate tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
@@ -1584,8 +1779,8 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 2)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -1600,12 +1795,12 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != 6)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, buf, (png_size_t)length);
+ png_crc_read(png_ptr, buf, length);
png_ptr->num_trans = 1;
png_ptr->trans_color.red = png_get_uint_16(buf);
png_ptr->trans_color.green = png_get_uint_16(buf + 2);
@@ -1614,44 +1809,43 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (!(png_ptr->mode & PNG_HAVE_PLTE))
- {
- /* Should be an error, but we can cope with it. */
- png_warning(png_ptr, "Missing PLTE before tRNS");
- }
-
- if (length > (png_uint_32)png_ptr->num_palette ||
- length > PNG_MAX_PALETTE_LENGTH)
+ if ((png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- png_warning(png_ptr, "Incorrect tRNS chunk length");
+ /* TODO: is this actually an error in the ISO spec? */
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- if (length == 0)
+ if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH ||
+ length == 0)
{
- png_warning(png_ptr, "Zero length tRNS chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- png_crc_read(png_ptr, readbuf, (png_size_t)length);
+ png_crc_read(png_ptr, readbuf, length);
png_ptr->num_trans = (png_uint_16)length;
}
else
{
- png_warning(png_ptr, "tRNS chunk not allowed with alpha channel");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid with alpha channel");
return;
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
{
png_ptr->num_trans = 0;
return;
}
+ /* TODO: this is a horrible side effect in the palette case because the
+ * png_struct ends up with a pointer to the tRNS buffer owned by the
+ * png_info. Fix this.
+ */
png_set_tRNS(png_ptr, info_ptr, readbuf, png_ptr->num_trans,
&(png_ptr->trans_color));
}
@@ -1659,43 +1853,37 @@ png_handle_tRNS(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_bKGD_SUPPORTED
void /* PRIVATE */
-png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_bKGD(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t truelen;
+ unsigned int truelen;
png_byte buf[6];
png_color_16 background;
png_debug(1, "in png_handle_bKGD");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before bKGD");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0))
{
- png_warning(png_ptr, "Invalid bKGD after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
- !(png_ptr->mode & PNG_HAVE_PLTE))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD) != 0)
{
- png_warning(png_ptr, "Missing PLTE before bKGD");
- png_crc_finish(png_ptr, length);
- return;
- }
-
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_bKGD))
- {
- png_warning(png_ptr, "Duplicate bKGD chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
truelen = 1;
- else if (png_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
truelen = 6;
else
@@ -1703,14 +1891,14 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (length != truelen)
{
- png_warning(png_ptr, "Incorrect bKGD chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, truelen);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
/* We convert the index value into RGB components so that we can allow
@@ -1722,11 +1910,11 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
{
background.index = buf[0];
- if (info_ptr && info_ptr->num_palette)
+ if (info_ptr != NULL && info_ptr->num_palette != 0)
{
if (buf[0] >= info_ptr->num_palette)
{
- png_warning(png_ptr, "Incorrect bKGD chunk index value");
+ png_chunk_benign_error(png_ptr, "invalid index");
return;
}
@@ -1741,7 +1929,7 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
background.gray = 0;
}
- else if (!(png_ptr->color_type & PNG_COLOR_MASK_COLOR)) /* GRAY */
+ else if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0) /* GRAY */
{
background.index = 0;
background.red =
@@ -1765,47 +1953,40 @@ png_handle_bKGD(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_hIST_SUPPORTED
void /* PRIVATE */
-png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
unsigned int num, i;
png_uint_16 readbuf[PNG_MAX_PALETTE_LENGTH];
png_debug(1, "in png_handle_hIST");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before hIST");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0 ||
+ (png_ptr->mode & PNG_HAVE_PLTE) == 0)
{
- png_warning(png_ptr, "Invalid hIST after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (!(png_ptr->mode & PNG_HAVE_PLTE))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST) != 0)
{
- png_warning(png_ptr, "Missing PLTE before hIST");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_hIST))
- {
- png_warning(png_ptr, "Duplicate hIST chunk");
- png_crc_finish(png_ptr, length);
- return;
- }
+ num = length / 2 ;
- if (length > 2*PNG_MAX_PALETTE_LENGTH ||
- length != (unsigned int) (2*png_ptr->num_palette))
+ if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH)
{
- png_warning(png_ptr, "Incorrect hIST chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
- num = length / 2 ;
-
for (i = 0; i < num; i++)
{
png_byte buf[2];
@@ -1814,7 +1995,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
readbuf[i] = png_get_uint_16(buf);
}
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
png_set_hIST(png_ptr, info_ptr, readbuf);
@@ -1823,7 +2004,7 @@ png_handle_hIST(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_pHYs_SUPPORTED
void /* PRIVATE */
-png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_pHYs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_uint_32 res_x, res_y;
@@ -1831,33 +2012,33 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_pHYs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before pHYs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pHYs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pHYs) != 0)
{
- png_warning(png_ptr, "Duplicate pHYs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect pHYs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
res_x = png_get_uint_32(buf);
@@ -1869,7 +2050,7 @@ png_handle_pHYs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_oFFs_SUPPORTED
void /* PRIVATE */
-png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_oFFs(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[9];
png_int_32 offset_x, offset_y;
@@ -1877,33 +2058,33 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(1, "in png_handle_oFFs");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before oFFs");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid oFFs after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_oFFs) != 0)
{
- png_warning(png_ptr, "Duplicate oFFs chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
if (length != 9)
{
- png_warning(png_ptr, "Incorrect oFFs chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 9);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
offset_x = png_get_int_32(buf);
@@ -1916,71 +2097,64 @@ png_handle_oFFs(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_pCAL_SUPPORTED
/* Read the pCAL chunk (described in the PNG Extensions document) */
void /* PRIVATE */
-png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_pCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_int_32 X0, X1;
png_byte type, nparams;
- png_charp buf, units, endptr;
+ png_bytep buffer, buf, units, endptr;
png_charpp params;
- png_size_t slength;
int i;
png_debug(1, "in png_handle_pCAL");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before pCAL");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid pCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_pCAL) != 0)
{
- png_warning(png_ptr, "Duplicate pCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
png_debug1(2, "Allocating and reading pCAL chunk data (%u bytes)",
length + 1);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
- if (png_ptr->chunkdata == NULL)
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
+
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory for pCAL purpose");
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+ buffer[length] = 0; /* Null terminate the last string */
png_debug(3, "Finding end of pCAL purpose string");
- for (buf = png_ptr->chunkdata; *buf; buf++)
+ for (buf = buffer; *buf; buf++)
/* Empty loop */ ;
- endptr = png_ptr->chunkdata + slength;
+ endptr = buffer + length;
/* We need to have at least 12 bytes after the purpose string
* in order to get the parameter information.
*/
if (endptr <= buf + 12)
{
- png_warning(png_ptr, "Invalid pCAL data");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
@@ -2000,15 +2174,13 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
(type == PNG_EQUATION_ARBITRARY && nparams != 3) ||
(type == PNG_EQUATION_HYPERBOLIC && nparams != 4))
{
- png_warning(png_ptr, "Invalid pCAL parameters for equation type");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid parameter count");
return;
}
else if (type >= PNG_EQUATION_LAST)
{
- png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ png_chunk_benign_error(png_ptr, "unrecognized equation type");
}
for (buf = units; *buf; buf++)
@@ -2016,43 +2188,37 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
png_debug(3, "Allocating pCAL parameters array");
- params = (png_charpp)png_malloc_warn(png_ptr,
- (png_size_t)(nparams * png_sizeof(png_charp)));
+ params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ nparams * (sizeof (png_charp))));
if (params == NULL)
{
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_warning(png_ptr, "No memory for pCAL params");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
/* Get pointers to the start of each parameter string. */
- for (i = 0; i < (int)nparams; i++)
+ for (i = 0; i < nparams; i++)
{
buf++; /* Skip the null string terminator from previous parameter. */
png_debug1(3, "Reading pCAL parameter %d", i);
- for (params[i] = buf; buf <= endptr && *buf != 0x00; buf++)
+ for (params[i] = (png_charp)buf; buf <= endptr && *buf != 0; buf++)
/* Empty loop to move past each parameter string */ ;
/* Make sure we haven't run out of data yet */
if (buf > endptr)
{
- png_warning(png_ptr, "Invalid pCAL data");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, params);
+ png_chunk_benign_error(png_ptr, "invalid data");
return;
}
}
- png_set_pCAL(png_ptr, info_ptr, png_ptr->chunkdata, X0, X1, type, nparams,
- units, params);
+ png_set_pCAL(png_ptr, info_ptr, (png_charp)buffer, X0, X1, type, nparams,
+ (png_charp)units, params);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
png_free(png_ptr, params);
}
#endif
@@ -2060,67 +2226,61 @@ png_handle_pCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_sCAL_SUPPORTED
/* Read the sCAL chunk */
void /* PRIVATE */
-png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_sCAL(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_size_t slength, i;
+ png_bytep buffer;
+ png_size_t i;
int state;
png_debug(1, "in png_handle_sCAL");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before sCAL");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (png_ptr->mode & PNG_HAVE_IDAT)
+ else if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
{
- png_warning(png_ptr, "Invalid sCAL after IDAT");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of place");
return;
}
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_sCAL) != 0)
{
- png_warning(png_ptr, "Duplicate sCAL chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
/* Need unit type, width, \0, height: minimum 4 bytes */
else if (length < 4)
{
- png_warning(png_ptr, "sCAL chunk too short");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_debug1(2, "Allocating and reading sCAL chunk data (%u bytes)",
length + 1);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 2/*silent*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "Out of memory while processing sCAL chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
png_crc_finish(png_ptr, length);
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
- png_ptr->chunkdata[slength] = 0x00; /* Null terminate the last string */
+ png_crc_read(png_ptr, buffer, length);
+ buffer[length] = 0; /* Null terminate the last string */
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
/* Validate the unit. */
- if (png_ptr->chunkdata[0] != 1 && png_ptr->chunkdata[0] != 2)
+ if (buffer[0] != 1 && buffer[0] != 2)
{
- png_warning(png_ptr, "Invalid sCAL ignored: invalid unit");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ png_chunk_benign_error(png_ptr, "invalid unit");
return;
}
@@ -2130,70 +2290,65 @@ png_handle_sCAL(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
i = 1;
state = 0;
- if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
- i >= slength || png_ptr->chunkdata[i++] != 0)
- png_warning(png_ptr, "Invalid sCAL chunk ignored: bad width format");
+ if (png_check_fp_number((png_const_charp)buffer, length, &state, &i) == 0 ||
+ i >= length || buffer[i++] != 0)
+ png_chunk_benign_error(png_ptr, "bad width format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr, "Invalid sCAL chunk ignored: non-positive width");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive width");
else
{
png_size_t heighti = i;
state = 0;
- if (!png_check_fp_number(png_ptr->chunkdata, slength, &state, &i) ||
- i != slength)
- png_warning(png_ptr, "Invalid sCAL chunk ignored: bad height format");
+ if (png_check_fp_number((png_const_charp)buffer, length,
+ &state, &i) == 0 || i != length)
+ png_chunk_benign_error(png_ptr, "bad height format");
- else if (!PNG_FP_IS_POSITIVE(state))
- png_warning(png_ptr,
- "Invalid sCAL chunk ignored: non-positive height");
+ else if (PNG_FP_IS_POSITIVE(state) == 0)
+ png_chunk_benign_error(png_ptr, "non-positive height");
else
/* This is the (only) success case. */
- png_set_sCAL_s(png_ptr, info_ptr, png_ptr->chunkdata[0],
- png_ptr->chunkdata+1, png_ptr->chunkdata+heighti);
+ png_set_sCAL_s(png_ptr, info_ptr, buffer[0],
+ (png_charp)buffer+1, (png_charp)buffer+heighti);
}
-
- /* Clean up - just free the temporarily allocated buffer. */
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
}
#endif
#ifdef PNG_READ_tIME_SUPPORTED
void /* PRIVATE */
-png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tIME(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
png_byte buf[7];
png_time mod_time;
png_debug(1, "in png_handle_tIME");
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Out of place tIME chunk");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME))
+ else if (info_ptr != NULL && (info_ptr->valid & PNG_INFO_tIME) != 0)
{
- png_warning(png_ptr, "Duplicate tIME chunk");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "duplicate");
return;
}
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
if (length != 7)
{
- png_warning(png_ptr, "Incorrect tIME chunk length");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "invalid");
return;
}
png_crc_read(png_ptr, buf, 7);
- if (png_crc_finish(png_ptr, 0))
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
mod_time.second = buf[6];
@@ -2210,14 +2365,13 @@ png_handle_tIME(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_tEXt_SUPPORTED
/* Note: this does not properly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_tEXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
+ png_text text_info;
+ png_bytep buffer;
png_charp key;
png_charp text;
png_uint_32 skip = 0;
- png_size_t slength;
- int ret;
png_debug(1, "in png_handle_tEXt");
@@ -2232,84 +2386,59 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for tEXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before tEXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
#ifdef PNG_MAX_MALLOC_64K
- if (length > (png_uint_32)65535L)
+ if (length > 65535U)
{
- png_warning(png_ptr, "tEXt chunk too large to fit in memory");
- skip = length - (png_uint_32)65535L;
- length = (png_uint_32)65535L;
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "too large to fit in memory");
+ return;
}
#endif
- png_free(png_ptr, png_ptr->chunkdata);
-
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory to process text chunk");
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, skip))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, skip) != 0)
return;
- }
-
- key = png_ptr->chunkdata;
- key[slength] = 0x00;
+ key = (png_charp)buffer;
+ key[length] = 0;
for (text = key; *text; text++)
/* Empty loop to find end of key */ ;
- if (text != key + slength)
+ if (text != key + length)
text++;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
-
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process text chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
-
- text_ptr->compression = PNG_TEXT_COMPRESSION_NONE;
- text_ptr->key = key;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->itxt_length = 0;
- text_ptr->text = text;
- text_ptr->text_length = png_strlen(text);
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- png_free(png_ptr, text_ptr);
+ text_info.compression = PNG_TEXT_COMPRESSION_NONE;
+ text_info.key = key;
+ text_info.lang = NULL;
+ text_info.lang_key = NULL;
+ text_info.itxt_length = 0;
+ text_info.text = text;
+ text_info.text_length = strlen(text);
- if (ret)
+ if (png_set_text_2(png_ptr, info_ptr, &text_info, 1) != 0)
png_warning(png_ptr, "Insufficient memory to process text chunk");
}
#endif
@@ -2317,13 +2446,11 @@ png_handle_tEXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
#ifdef PNG_READ_zTXt_SUPPORTED
/* Note: this does not correctly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_zTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
- png_charp text;
- int comp_type;
- int ret;
- png_size_t slength, prefix_len, data_len;
+ png_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 keyword_length;
png_debug(1, "in png_handle_zTXt");
@@ -2338,123 +2465,101 @@ png_handle_zTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for zTXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before zTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
-#ifdef PNG_MAX_MALLOC_64K
- /* We will no doubt have problems with chunks even half this size, but
- * there is no hard and fast rule to tell us where to stop.
- */
- if (length > (png_uint_32)65535L)
+ buffer = png_read_buffer(png_ptr, length, 2/*silent*/);
+
+ if (buffer == NULL)
{
- png_warning(png_ptr, "zTXt chunk too large to fit in memory");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
-#endif
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ png_crc_read(png_ptr, buffer, length);
- if (png_ptr->chunkdata == NULL)
- {
- png_warning(png_ptr, "Out of memory processing zTXt chunk");
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
-
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* TODO: also check that the keyword contents match the spec! */
+ for (keyword_length = 0;
+ keyword_length < length && buffer[keyword_length] != 0;
+ ++keyword_length)
+ /* Empty loop to find end of name */ ;
- png_ptr->chunkdata[slength] = 0x00;
+ if (keyword_length > 79 || keyword_length < 1)
+ errmsg = "bad keyword";
- for (text = png_ptr->chunkdata; *text; text++)
- /* Empty loop */ ;
+ /* zTXt must have some LZ data after the keyword, although it may expand to
+ * zero bytes; we need a '\0' at the end of the keyword, the compression type
+ * then the LZ data:
+ */
+ else if (keyword_length + 3 > length)
+ errmsg = "truncated";
- /* zTXt must have some text after the chunkdataword */
- if (text >= png_ptr->chunkdata + slength - 2)
- {
- png_warning(png_ptr, "Truncated zTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ else if (buffer[keyword_length+1] != PNG_COMPRESSION_TYPE_BASE)
+ errmsg = "unknown compression type";
else
{
- comp_type = *(++text);
-
- if (comp_type != PNG_TEXT_COMPRESSION_zTXt)
- {
- png_warning(png_ptr, "Unknown compression type in zTXt chunk");
- comp_type = PNG_TEXT_COMPRESSION_zTXt;
- }
+ png_alloc_size_t uncompressed_length = PNG_SIZE_MAX;
- text++; /* Skip the compression_method byte */
- }
-
- prefix_len = text - png_ptr->chunkdata;
-
- png_decompress_chunk(png_ptr, comp_type,
- (png_size_t)length, prefix_len, &data_len);
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for iCCP
+ * and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, keyword_length+2,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ {
+ png_text text;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
+ /* It worked; png_ptr->read_buffer now looks like a tEXt chunk except
+ * for the extra compression type byte and the fact that it isn't
+ * necessarily '\0' terminated.
+ */
+ buffer = png_ptr->read_buffer;
+ buffer[uncompressed_length+(keyword_length+2)] = 0;
+
+ text.compression = PNG_TEXT_COMPRESSION_zTXt;
+ text.key = (png_charp)buffer;
+ text.text = (png_charp)(buffer + keyword_length+2);
+ text.text_length = uncompressed_length;
+ text.itxt_length = 0;
+ text.lang = NULL;
+ text.lang_key = NULL;
+
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process zTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
+ else
+ errmsg = png_ptr->zstream.msg;
}
- text_ptr->compression = comp_type;
- text_ptr->key = png_ptr->chunkdata;
- text_ptr->lang = NULL;
- text_ptr->lang_key = NULL;
- text_ptr->itxt_length = 0;
- text_ptr->text = png_ptr->chunkdata + prefix_len;
- text_ptr->text_length = data_len;
-
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
-
- png_free(png_ptr, text_ptr);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
-
- if (ret)
- png_error(png_ptr, "Insufficient memory to store zTXt chunk");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#endif
#ifdef PNG_READ_iTXt_SUPPORTED
/* Note: this does not correctly handle chunks that are > 64K under DOS */
void /* PRIVATE */
-png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+png_handle_iTXt(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length)
{
- png_textp text_ptr;
- png_charp key, lang, text, lang_key;
- int comp_flag;
- int comp_type = 0;
- int ret;
- png_size_t slength, prefix_len, data_len;
+ png_const_charp errmsg = NULL;
+ png_bytep buffer;
+ png_uint_32 prefix_length;
png_debug(1, "in png_handle_iTXt");
@@ -2469,279 +2574,393 @@ png_handle_iTXt(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
if (--png_ptr->user_chunk_cache_max == 1)
{
- png_warning(png_ptr, "No space in chunk cache for iTXt");
png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
return;
}
}
#endif
- if (!(png_ptr->mode & PNG_HAVE_IHDR))
- png_error(png_ptr, "Missing IHDR before iTXt");
+ if ((png_ptr->mode & PNG_HAVE_IHDR) == 0)
+ png_chunk_error(png_ptr, "missing IHDR");
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if ((png_ptr->mode & PNG_HAVE_IDAT) != 0)
png_ptr->mode |= PNG_AFTER_IDAT;
-#ifdef PNG_MAX_MALLOC_64K
- /* We will no doubt have problems with chunks even half this size, but
- * there is no hard and fast rule to tell us where to stop.
- */
- if (length > (png_uint_32)65535L)
- {
- png_warning(png_ptr, "iTXt chunk too large to fit in memory");
- png_crc_finish(png_ptr, length);
- return;
- }
-#endif
-
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = (png_charp)png_malloc_warn(png_ptr, length + 1);
+ buffer = png_read_buffer(png_ptr, length+1, 1/*warn*/);
- if (png_ptr->chunkdata == NULL)
+ if (buffer == NULL)
{
- png_warning(png_ptr, "No memory to process iTXt chunk");
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "out of memory");
return;
}
- slength = length;
- png_crc_read(png_ptr, (png_bytep)png_ptr->chunkdata, slength);
+ png_crc_read(png_ptr, buffer, length);
- if (png_crc_finish(png_ptr, 0))
- {
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ if (png_crc_finish(png_ptr, 0) != 0)
return;
- }
- png_ptr->chunkdata[slength] = 0x00;
-
- for (lang = png_ptr->chunkdata; *lang; lang++)
+ /* First the keyword. */
+ for (prefix_length=0;
+ prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
/* Empty loop */ ;
- lang++; /* Skip NUL separator */
+ /* Perform a basic check on the keyword length here. */
+ if (prefix_length > 79 || prefix_length < 1)
+ errmsg = "bad keyword";
- /* iTXt must have a language tag (possibly empty), two compression bytes,
- * translated keyword (possibly empty), and possibly some text after the
- * keyword
+ /* Expect keyword, compression flag, compression type, language, translated
+ * keyword (both may be empty but are 0 terminated) then the text, which may
+ * be empty.
*/
+ else if (prefix_length + 5 > length)
+ errmsg = "truncated";
- if (lang >= png_ptr->chunkdata + slength - 3)
+ else if (buffer[prefix_length+1] == 0 ||
+ (buffer[prefix_length+1] == 1 &&
+ buffer[prefix_length+2] == PNG_COMPRESSION_TYPE_BASE))
{
- png_warning(png_ptr, "Truncated iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ int compressed = buffer[prefix_length+1] != 0;
+ png_uint_32 language_offset, translated_keyword_offset;
+ png_alloc_size_t uncompressed_length = 0;
- else
- {
- comp_flag = *lang++;
- comp_type = *lang++;
- }
+ /* Now the language tag */
+ prefix_length += 3;
+ language_offset = prefix_length;
- if (comp_type || (comp_flag && comp_flag != PNG_TEXT_COMPRESSION_zTXt))
- {
- png_warning(png_ptr, "Unknown iTXt compression type or method");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
- for (lang_key = lang; *lang_key; lang_key++)
- /* Empty loop */ ;
+ /* WARNING: the length may be invalid here, this is checked below. */
+ translated_keyword_offset = ++prefix_length;
- lang_key++; /* Skip NUL separator */
+ for (; prefix_length < length && buffer[prefix_length] != 0;
+ ++prefix_length)
+ /* Empty loop */ ;
- if (lang_key >= png_ptr->chunkdata + slength)
- {
- png_warning(png_ptr, "Truncated iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* prefix_length should now be at the trailing '\0' of the translated
+ * keyword, but it may already be over the end. None of this arithmetic
+ * can overflow because chunks are at most 2^31 bytes long, but on 16-bit
+ * systems the available allocation may overflow.
+ */
+ ++prefix_length;
- for (text = lang_key; *text; text++)
- /* Empty loop */ ;
+ if (compressed == 0 && prefix_length <= length)
+ uncompressed_length = length - prefix_length;
- text++; /* Skip NUL separator */
+ else if (compressed != 0 && prefix_length < length)
+ {
+ uncompressed_length = PNG_SIZE_MAX;
- if (text >= png_ptr->chunkdata + slength)
- {
- png_warning(png_ptr, "Malformed iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ /* TODO: at present png_decompress_chunk imposes a single application
+ * level memory limit, this should be split to different values for
+ * iCCP and text chunks.
+ */
+ if (png_decompress_chunk(png_ptr, length, prefix_length,
+ &uncompressed_length, 1/*terminate*/) == Z_STREAM_END)
+ buffer = png_ptr->read_buffer;
- prefix_len = text - png_ptr->chunkdata;
+ else
+ errmsg = png_ptr->zstream.msg;
+ }
- key=png_ptr->chunkdata;
+ else
+ errmsg = "truncated";
- if (comp_flag)
- png_decompress_chunk(png_ptr, comp_type,
- (size_t)length, prefix_len, &data_len);
+ if (errmsg == NULL)
+ {
+ png_text text;
- else
- data_len = png_strlen(png_ptr->chunkdata + prefix_len);
+ buffer[uncompressed_length+prefix_length] = 0;
- text_ptr = (png_textp)png_malloc_warn(png_ptr,
- png_sizeof(png_text));
+ if (compressed == 0)
+ text.compression = PNG_ITXT_COMPRESSION_NONE;
- if (text_ptr == NULL)
- {
- png_warning(png_ptr, "Not enough memory to process iTXt chunk");
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
- return;
- }
+ else
+ text.compression = PNG_ITXT_COMPRESSION_zTXt;
- text_ptr->compression = (int)comp_flag + 1;
- text_ptr->lang_key = png_ptr->chunkdata + (lang_key - key);
- text_ptr->lang = png_ptr->chunkdata + (lang - key);
- text_ptr->itxt_length = data_len;
- text_ptr->text_length = 0;
- text_ptr->key = png_ptr->chunkdata;
- text_ptr->text = png_ptr->chunkdata + prefix_len;
+ text.key = (png_charp)buffer;
+ text.lang = (png_charp)buffer + language_offset;
+ text.lang_key = (png_charp)buffer + translated_keyword_offset;
+ text.text = (png_charp)buffer + prefix_length;
+ text.text_length = 0;
+ text.itxt_length = uncompressed_length;
- ret = png_set_text_2(png_ptr, info_ptr, text_ptr, 1);
+ if (png_set_text_2(png_ptr, info_ptr, &text, 1) != 0)
+ errmsg = "insufficient memory";
+ }
+ }
- png_free(png_ptr, text_ptr);
- png_free(png_ptr, png_ptr->chunkdata);
- png_ptr->chunkdata = NULL;
+ else
+ errmsg = "bad compression info";
- if (ret)
- png_error(png_ptr, "Insufficient memory to store iTXt chunk");
+ if (errmsg != NULL)
+ png_chunk_benign_error(png_ptr, errmsg);
}
#endif
-/* This function is called when we haven't found a handler for a
- * chunk. If there isn't a problem with the chunk itself (ie bad
- * chunk name, CRC, or a critical chunk), the chunk is silently ignored
- * -- unless the PNG_FLAG_UNKNOWN_CHUNKS_SUPPORTED flag is on in which
- * case it will be saved away to be written out later.
- */
-void /* PRIVATE */
-png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+/* Utility function for png_handle_unknown; set up png_ptr::unknown_chunk */
+static int
+png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length)
{
- png_uint_32 skip = 0;
+ png_alloc_size_t limit = PNG_SIZE_MAX;
- png_debug(1, "in png_handle_unknown");
+ if (png_ptr->unknown_chunk.data != NULL)
+ {
+ png_free(png_ptr, png_ptr->unknown_chunk.data);
+ png_ptr->unknown_chunk.data = NULL;
+ }
-#ifdef PNG_USER_LIMITS_SUPPORTED
- if (png_ptr->user_chunk_cache_max != 0)
+# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED
+ if (png_ptr->user_chunk_malloc_max > 0 &&
+ png_ptr->user_chunk_malloc_max < limit)
+ limit = png_ptr->user_chunk_malloc_max;
+
+# elif PNG_USER_CHUNK_MALLOC_MAX > 0
+ if (PNG_USER_CHUNK_MALLOC_MAX < limit)
+ limit = PNG_USER_CHUNK_MALLOC_MAX;
+# endif
+
+ if (length <= limit)
{
- if (png_ptr->user_chunk_cache_max == 1)
- {
- png_crc_finish(png_ptr, length);
- return;
- }
+ PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
+ /* The following is safe because of the PNG_SIZE_MAX init above */
+ png_ptr->unknown_chunk.size = (png_size_t)length/*SAFE*/;
+ /* 'mode' is a flag array, only the bottom four bits matter here */
+ png_ptr->unknown_chunk.location = (png_byte)png_ptr->mode/*SAFE*/;
- if (--png_ptr->user_chunk_cache_max == 1)
+ if (length == 0)
+ png_ptr->unknown_chunk.data = NULL;
+
+ else
{
- png_warning(png_ptr, "No space in chunk cache for unknown chunk");
- png_crc_finish(png_ptr, length);
- return;
+ /* Do a 'warn' here - it is handled below. */
+ png_ptr->unknown_chunk.data = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, length));
}
}
-#endif
- if (png_ptr->mode & PNG_HAVE_IDAT)
+ if (png_ptr->unknown_chunk.data == NULL && length > 0)
{
- if (png_ptr->chunk_name != png_IDAT)
- png_ptr->mode |= PNG_AFTER_IDAT;
+ /* This is benign because we clean up correctly */
+ png_crc_finish(png_ptr, length);
+ png_chunk_benign_error(png_ptr, "unknown chunk exceeds memory limits");
+ return 0;
}
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ else
{
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- && png_ptr->read_user_chunk_fn == NULL
-#endif
- )
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
+ if (length > 0)
+ png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
+ png_crc_finish(png_ptr, 0);
+ return 1;
}
+}
+#endif /* READ_UNKNOWN_CHUNKS */
+
+/* Handle an unknown, or known but disabled, chunk */
+void /* PRIVATE */
+png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr,
+ png_uint_32 length, int keep)
+{
+ int handled = 0; /* the chunk was handled */
+
+ png_debug(1, "in png_handle_unknown");
#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
- if ((png_ptr->flags & PNG_FLAG_KEEP_UNKNOWN_CHUNKS)
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- || (png_ptr->read_user_chunk_fn != NULL)
-#endif
- )
- {
-#ifdef PNG_MAX_MALLOC_64K
- if (length > 65535)
- {
- png_warning(png_ptr, "unknown chunk too large to fit in memory");
- skip = length - 65535;
- length = 65535;
- }
-#endif
+ /* NOTE: this code is based on the code in libpng-1.4.12 except for fixing
+ * the bug which meant that setting a non-default behavior for a specific
+ * chunk would be ignored (the default was always used unless a user
+ * callback was installed).
+ *
+ * 'keep' is the value from the png_chunk_unknown_handling, the setting for
+ * this specific chunk_name, if PNG_HANDLE_AS_UNKNOWN_SUPPORTED, if not it
+ * will always be PNG_HANDLE_CHUNK_AS_DEFAULT and it needs to be set here.
+ * This is just an optimization to avoid multiple calls to the lookup
+ * function.
+ */
+# ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name);
+# endif
+# endif
- /* TODO: this code is very close to the unknown handling in pngpread.c,
- * maybe it can be put into a common utility routine?
- * png_struct::unknown_chunk is just used as a temporary variable, along
- * with the data into which the chunk is read. These can be eliminated.
+ /* One of the following methods will read the chunk or skip it (at least one
+ * of these is always defined because this is the only way to switch on
+ * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED)
+ */
+# ifdef PNG_READ_USER_CHUNKS_SUPPORTED
+ /* The user callback takes precedence over the chunk keep value, but the
+ * keep value is still required to validate a save of a critical chunk.
*/
- PNG_CSTRING_FROM_CHUNK(png_ptr->unknown_chunk.name, png_ptr->chunk_name);
- png_ptr->unknown_chunk.size = (png_size_t)length;
+ if (png_ptr->read_user_chunk_fn != NULL)
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) != 0)
+ {
+ /* Callback to user unknown chunk handler */
+ int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr,
+ &png_ptr->unknown_chunk);
+
+ /* ret is:
+ * negative: An error occurred; png_chunk_error will be called.
+ * zero: The chunk was not handled, the chunk will be discarded
+ * unless png_set_keep_unknown_chunks has been used to set
+ * a 'keep' behavior for this particular chunk, in which
+ * case that will be used. A critical chunk will cause an
+ * error at this point unless it is to be saved.
+ * positive: The chunk was handled, libpng will ignore/discard it.
+ */
+ if (ret < 0)
+ png_chunk_error(png_ptr, "error in user chunk");
- if (length == 0)
- png_ptr->unknown_chunk.data = NULL;
+ else if (ret == 0)
+ {
+ /* If the keep value is 'default' or 'never' override it, but
+ * still error out on critical chunks unless the keep value is
+ * 'always' While this is weird it is the behavior in 1.4.12.
+ * A possible improvement would be to obey the value set for the
+ * chunk, but this would be an API change that would probably
+ * damage some applications.
+ *
+ * The png_app_warning below catches the case that matters, where
+ * the application has not set specific save or ignore for this
+ * chunk or global save or ignore.
+ */
+ if (keep < PNG_HANDLE_CHUNK_IF_SAFE)
+ {
+# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE)
+ {
+ png_chunk_warning(png_ptr, "Saving unknown chunk:");
+ png_app_warning(png_ptr,
+ "forcing save of an unhandled chunk;"
+ " please call png_set_keep_unknown_chunks");
+ /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */
+ }
+# endif
+ keep = PNG_HANDLE_CHUNK_IF_SAFE;
+ }
+ }
+
+ else /* chunk was handled */
+ {
+ handled = 1;
+ /* Critical chunks can be safely discarded at this point. */
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
+ }
+
+ else
+ keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */
+ }
else
+ /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */
+# endif /* READ_USER_CHUNKS */
+
+# ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED
{
- png_ptr->unknown_chunk.data = (png_bytep)png_malloc(png_ptr, length);
- png_crc_read(png_ptr, png_ptr->unknown_chunk.data, length);
+ /* keep is currently just the per-chunk setting, if there was no
+ * setting change it to the global default now (not that this may
+ * still be AS_DEFAULT) then obtain the cache of the chunk if required,
+ * if not simply skip the chunk.
+ */
+ if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT)
+ keep = png_ptr->unknown_default;
+
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+ if (png_cache_unknown_chunk(png_ptr, length) == 0)
+ keep = PNG_HANDLE_CHUNK_NEVER;
+ }
+
+ else
+ png_crc_finish(png_ptr, length);
}
+# else
+# ifndef PNG_READ_USER_CHUNKS_SUPPORTED
+# error no method to support READ_UNKNOWN_CHUNKS
+# endif
-#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
- if (png_ptr->read_user_chunk_fn != NULL)
{
- /* Callback to user unknown chunk handler */
- int ret;
-
- ret = (*(png_ptr->read_user_chunk_fn))
- (png_ptr, &png_ptr->unknown_chunk);
+ /* If here there is no read callback pointer set and no support is
+ * compiled in to just save the unknown chunks, so simply skip this
+ * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then
+ * the app has erroneously asked for unknown chunk saving when there
+ * is no support.
+ */
+ if (keep > PNG_HANDLE_CHUNK_NEVER)
+ png_app_error(png_ptr, "no unknown chunk support available");
- if (ret < 0)
- png_chunk_error(png_ptr, "error in user chunk");
+ png_crc_finish(png_ptr, length);
+ }
+# endif
- if (ret == 0)
+# ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ /* Now store the chunk in the chunk list if appropriate, and if the limits
+ * permit it.
+ */
+ if (keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_IF_SAFE &&
+ PNG_CHUNK_ANCILLARY(png_ptr->chunk_name)))
+ {
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ switch (png_ptr->user_chunk_cache_max)
{
- if (PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
- {
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name) !=
- PNG_HANDLE_CHUNK_ALWAYS)
-#endif
- png_chunk_error(png_ptr, "unknown critical chunk");
- }
+ case 2:
+ png_ptr->user_chunk_cache_max = 1;
+ png_chunk_benign_error(png_ptr, "no space in chunk cache");
+ /* FALL THROUGH */
+ case 1:
+ /* NOTE: prior to 1.6.0 this case resulted in an unknown critical
+ * chunk being skipped, now there will be a hard error below.
+ */
+ break;
- png_set_unknown_chunks(png_ptr, info_ptr,
- &png_ptr->unknown_chunk, 1);
+ default: /* not at limit */
+ --(png_ptr->user_chunk_cache_max);
+ /* FALL THROUGH */
+ case 0: /* no limit */
+# endif /* USER_LIMITS */
+ /* Here when the limit isn't reached or when limits are compiled
+ * out; store the chunk.
+ */
+ png_set_unknown_chunks(png_ptr, info_ptr,
+ &png_ptr->unknown_chunk, 1);
+ handled = 1;
+# ifdef PNG_USER_LIMITS_SUPPORTED
+ break;
}
+# endif
}
+# else /* no store support: the chunk must be handled by the user callback */
+ PNG_UNUSED(info_ptr)
+# endif
- else
-#endif
- png_set_unknown_chunks(png_ptr, info_ptr, &png_ptr->unknown_chunk, 1);
-
+ /* Regardless of the error handling below the cached data (if any) can be
+ * freed now. Notice that the data is not freed if there is a png_error, but
+ * it will be freed by destroy_read_struct.
+ */
+ if (png_ptr->unknown_chunk.data != NULL)
png_free(png_ptr, png_ptr->unknown_chunk.data);
- png_ptr->unknown_chunk.data = NULL;
- }
-
- else
-#endif
- skip = length;
+ png_ptr->unknown_chunk.data = NULL;
- png_crc_finish(png_ptr, skip);
+#else /* !PNG_READ_UNKNOWN_CHUNKS_SUPPORTED */
+ /* There is no support to read an unknown chunk, so just skip it. */
+ png_crc_finish(png_ptr, length);
+ PNG_UNUSED(info_ptr)
+ PNG_UNUSED(keep)
+#endif /* !READ_UNKNOWN_CHUNKS */
-#ifndef PNG_READ_USER_CHUNKS_SUPPORTED
- PNG_UNUSED(info_ptr) /* Quiet compiler warnings about unused info_ptr */
-#endif
+ /* Check for unhandled critical chunks */
+ if (handled == 0 && PNG_CHUNK_CRITICAL(png_ptr->chunk_name))
+ png_chunk_error(png_ptr, "unhandled critical chunk");
}
/* This function is called to verify that a chunk name is valid.
@@ -2757,7 +2976,7 @@ png_handle_unknown(png_structp png_ptr, png_infop info_ptr, png_uint_32 length)
*/
void /* PRIVATE */
-png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
+png_check_chunk_name(png_structrp png_ptr, png_uint_32 chunk_name)
{
int i;
@@ -2782,11 +3001,11 @@ png_check_chunk_name(png_structp png_ptr, png_uint_32 chunk_name)
* 'display' is false only those pixels present in the pass are filled in.
*/
void /* PRIVATE */
-png_combine_row(png_structp png_ptr, png_bytep dp, int display)
+png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display)
{
unsigned int pixel_depth = png_ptr->transformed_pixel_depth;
png_const_bytep sp = png_ptr->row_buf + 1;
- png_uint_32 row_width = png_ptr->width;
+ png_alloc_size_t row_width = png_ptr->width;
unsigned int pass = png_ptr->pass;
png_bytep end_ptr = 0;
png_byte end_byte = 0;
@@ -2823,7 +3042,8 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1;
end_byte = *end_ptr;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP) /* little-endian byte */
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ /* little-endian byte */
end_mask = 0xff << end_mask;
else /* big-endian byte */
@@ -2832,17 +3052,18 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* end_mask is now the bits to *keep* from the destination row */
}
- /* For non-interlaced images this reduces to a png_memcpy(). A png_memcpy()
+ /* For non-interlaced images this reduces to a memcpy(). A memcpy()
* will also happen if interlacing isn't supported or if the application
* does not call png_set_interlace_handling(). In the latter cases the
* caller just gets a sequence of the unexpanded rows from each interlace
* pass.
*/
#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE) &&
- pass < 6 && (display == 0 ||
- /* The following copies everything for 'display' on passes 0, 2 and 4. */
- (display == 1 && (pass & 1) != 0)))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0 &&
+ pass < 6 && (display == 0 ||
+ /* The following copies everything for 'display' on passes 0, 2 and 4. */
+ (display == 1 && (pass & 1) != 0)))
{
/* Narrow images may have no bits in a pass; the caller should handle
* this, but this test is cheap:
@@ -2938,7 +3159,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
# define S_MASKS(d,s) { S_MASK(0,d,s), S_MASK(1,d,s), S_MASK(2,d,s),\
S_MASK(3,d,s), S_MASK(4,d,s), S_MASK(5,d,s) }
-# define B_MASKS(d,s) { B_MASK(1,d,s), S_MASK(3,d,s), S_MASK(5,d,s) }
+# define B_MASKS(d,s) { B_MASK(1,d,s), B_MASK(3,d,s), B_MASK(5,d,s) }
# define DEPTH_INDEX(d) ((d)==1?0:((d)==2?1:2))
@@ -2974,10 +3195,10 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
*/
# define MASK(pass,depth,display,png)\
((display)?B_MASK(pass,depth,png):S_MASK(pass,depth,png))
-#endif /* !PNG_USE_COMPILE_TIME_MASKS */
+#endif /* !USE_COMPILE_TIME_MASKS */
/* Use the appropriate mask to copy the required bits. In some cases
- * the byte mask will be 0 or 0xff, optimize these cases. row_width is
+ * the byte mask will be 0 or 0xff; optimize these cases. row_width is
* the number of pixels, but the code copies bytes, so it is necessary
* to special case the end.
*/
@@ -2985,7 +3206,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
png_uint_32 mask;
# ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
mask = MASK(pass, pixel_depth, display, 0);
else
@@ -3049,7 +3270,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
}
/* Work out the bytes to copy. */
- if (display)
+ if (display != 0)
{
/* When doing the 'block' algorithm the pixel in the pass gets
* replicated to adjacent pixels. This is why the even (0,2,4,6)
@@ -3059,7 +3280,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* But don't allow this number to exceed the actual row width. */
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
else /* normal row; Adam7 only ever gives us one pixel to copy. */
@@ -3116,7 +3337,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* This can only be the RGB case, so each copy is exactly one
* pixel and it is not necessary to check for a partial copy.
*/
- for(;;)
+ for (;;)
{
dp[0] = sp[0], dp[1] = sp[1], dp[2] = sp[2];
@@ -3133,26 +3354,27 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* Check for double byte alignment and, if possible, use a
* 16-bit copy. Don't attempt this for narrow images - ones that
* are less than an interlace panel wide. Don't attempt it for
- * wide bytes_to_copy either - use the png_memcpy there.
+ * wide bytes_to_copy either - use the memcpy there.
*/
- if (bytes_to_copy < 16 /*else use png_memcpy*/ &&
- png_isaligned(dp, png_uint_16) &&
- png_isaligned(sp, png_uint_16) &&
- bytes_to_copy % sizeof (png_uint_16) == 0 &&
- bytes_to_jump % sizeof (png_uint_16) == 0)
+ if (bytes_to_copy < 16 /*else use memcpy*/ &&
+ png_isaligned(dp, png_uint_16) &&
+ png_isaligned(sp, png_uint_16) &&
+ bytes_to_copy % (sizeof (png_uint_16)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_16)) == 0)
{
/* Everything is aligned for png_uint_16 copies, but try for
* png_uint_32 first.
*/
- if (png_isaligned(dp, png_uint_32) &&
- png_isaligned(sp, png_uint_32) &&
- bytes_to_copy % sizeof (png_uint_32) == 0 &&
- bytes_to_jump % sizeof (png_uint_32) == 0)
+ if (png_isaligned(dp, png_uint_32) != 0 &&
+ png_isaligned(sp, png_uint_32) != 0 &&
+ bytes_to_copy % (sizeof (png_uint_32)) == 0 &&
+ bytes_to_jump % (sizeof (png_uint_32)) == 0)
{
- png_uint_32p dp32 = (png_uint_32p)dp;
- png_const_uint_32p sp32 = (png_const_uint_32p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
- sizeof (png_uint_32);
+ png_uint_32p dp32 = png_aligncast(png_uint_32p,dp);
+ png_const_uint_32p sp32 = png_aligncastconst(
+ png_const_uint_32p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_32));
do
{
@@ -3160,7 +3382,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
do
{
*dp32++ = *sp32++;
- c -= sizeof (png_uint_32);
+ c -= (sizeof (png_uint_32));
}
while (c > 0);
@@ -3190,10 +3412,11 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
*/
else
{
- png_uint_16p dp16 = (png_uint_16p)dp;
- png_const_uint_16p sp16 = (png_const_uint_16p)sp;
- unsigned int skip = (bytes_to_jump-bytes_to_copy) /
- sizeof (png_uint_16);
+ png_uint_16p dp16 = png_aligncast(png_uint_16p, dp);
+ png_const_uint_16p sp16 = png_aligncastconst(
+ png_const_uint_16p, sp);
+ size_t skip = (bytes_to_jump-bytes_to_copy) /
+ (sizeof (png_uint_16));
do
{
@@ -3201,7 +3424,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
do
{
*dp16++ = *sp16++;
- c -= sizeof (png_uint_16);
+ c -= (sizeof (png_uint_16));
}
while (c > 0);
@@ -3223,12 +3446,12 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
return;
}
}
-#endif /* PNG_ALIGN_ code */
+#endif /* ALIGN_TYPE code */
- /* The true default - use a png_memcpy: */
+ /* The true default - use a memcpy: */
for (;;)
{
- png_memcpy(dp, sp, bytes_to_copy);
+ memcpy(dp, sp, bytes_to_copy);
if (row_width <= bytes_to_jump)
return;
@@ -3237,7 +3460,7 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
dp += bytes_to_jump;
row_width -= bytes_to_jump;
if (bytes_to_copy > row_width)
- bytes_to_copy = row_width;
+ bytes_to_copy = (unsigned int)/*SAFE*/row_width;
}
}
@@ -3247,13 +3470,13 @@ png_combine_row(png_structp png_ptr, png_bytep dp, int display)
/* Here if pixel_depth < 8 to check 'end_ptr' below. */
}
else
-#endif
+#endif /* READ_INTERLACING */
- /* If here then the switch above wasn't used so just png_memcpy the whole row
+ /* If here then the switch above wasn't used so just memcpy the whole row
* from the temporary row buffer (notice that this overwrites the end of the
* destination row if it is a partial byte.)
*/
- png_memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
+ memcpy(dp, sp, PNG_ROWBYTES(pixel_depth, row_width));
/* Restore the overwritten bits from the last byte if necessary. */
if (end_ptr != NULL)
@@ -3290,7 +3513,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
int j;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)((row_info->width + 7) & 0x07);
dshift = (int)((final_width + 7) & 0x07);
@@ -3314,8 +3537,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
v = (png_byte)((*sp >> sshift) & 0x01);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x7f7f >> (7 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x7f7f >> (7 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3349,7 +3573,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
png_uint_32 i;
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 3) & 0x03) << 1);
dshift = (int)(((final_width + 3) & 0x03) << 1);
@@ -3376,8 +3600,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
v = (png_byte)((*sp >> sshift) & 0x03);
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0x3f3f >> (6 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0x3f3f >> (6 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3411,7 +3636,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
int jstop = png_pass_inc[pass];
#ifdef PNG_READ_PACKSWAP_SUPPORTED
- if (transformations & PNG_PACKSWAP)
+ if ((transformations & PNG_PACKSWAP) != 0)
{
sshift = (int)(((row_info->width + 1) & 0x01) << 2);
dshift = (int)(((final_width + 1) & 0x01) << 2);
@@ -3437,8 +3662,9 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
for (j = 0; j < jstop; j++)
{
- *dp &= (png_byte)((0xf0f >> (4 - dshift)) & 0xff);
- *dp |= (png_byte)(v << dshift);
+ unsigned int tmp = *dp & (0xf0f >> (4 - dshift));
+ tmp |= v << dshift;
+ *dp = (png_byte)(tmp & 0xff);
if (dshift == s_end)
{
@@ -3476,14 +3702,14 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
for (i = 0; i < row_info->width; i++)
{
- png_byte v[8];
+ png_byte v[8]; /* SAFE; pixel_depth does not exceed 64 */
int j;
- png_memcpy(v, sp, pixel_bytes);
+ memcpy(v, sp, pixel_bytes);
for (j = 0; j < jstop; j++)
{
- png_memcpy(dp, v, pixel_bytes);
+ memcpy(dp, v, pixel_bytes);
dp -= pixel_bytes;
}
@@ -3500,7 +3726,7 @@ png_do_read_interlace(png_row_infop row_info, png_bytep row, int pass,
PNG_UNUSED(transformations) /* Silence compiler warning */
#endif
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
+#endif /* READ_INTERLACING */
static void
png_read_filter_row_sub(png_row_infop row_info, png_bytep row,
@@ -3654,74 +3880,22 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row,
if (pb < pa) pa = pb, a = b;
if (pc < pa) a = c;
- c = b;
a += *row;
*row++ = (png_byte)a;
}
}
-#ifdef PNG_ARM_NEON
-
-#ifdef __linux__
-#include <stdio.h>
-#include <elf.h>
-#include <asm/hwcap.h>
-
-static int png_have_hwcap(unsigned cap)
-{
- FILE *f = fopen("/proc/self/auxv", "r");
- Elf32_auxv_t aux;
- int have_cap = 0;
-
- if (!f)
- return 0;
-
- while (fread(&aux, sizeof(aux), 1, f) > 0)
- {
- if (aux.a_type == AT_HWCAP &&
- aux.a_un.a_val & cap)
- {
- have_cap = 1;
- break;
- }
- }
-
- fclose(f);
-
- return have_cap;
-}
-#endif /* __linux__ */
-
static void
-png_init_filter_functions_neon(png_structp pp, unsigned int bpp)
-{
-#ifdef __linux__
- if (!png_have_hwcap(HWCAP_NEON))
- return;
-#endif
-
- pp->read_filter[PNG_FILTER_VALUE_UP-1] = png_read_filter_row_up_neon;
-
- if (bpp == 3)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub3_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg3_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth3_neon;
- }
-
- else if (bpp == 4)
- {
- pp->read_filter[PNG_FILTER_VALUE_SUB-1] = png_read_filter_row_sub4_neon;
- pp->read_filter[PNG_FILTER_VALUE_AVG-1] = png_read_filter_row_avg4_neon;
- pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
- png_read_filter_row_paeth4_neon;
- }
-}
-#endif /* PNG_ARM_NEON */
-
-static void
-png_init_filter_functions(png_structp pp)
+png_init_filter_functions(png_structrp pp)
+ /* This function is called once for every PNG image (except for PNG images
+ * that only use PNG_FILTER_VALUE_NONE for all rows) to set the
+ * implementations required to reverse the filtering of PNG rows. Reversing
+ * the filter is the first transformation performed on the row data. It is
+ * performed in place, therefore an implementation can be selected based on
+ * the image pixel format. If the implementation depends on image width then
+ * take care to ensure that it works correctly if the image is interlaced -
+ * interlacing causes the actual row width to vary.
+ */
{
unsigned int bpp = (pp->pixel_depth + 7) >> 3;
@@ -3735,26 +3909,217 @@ png_init_filter_functions(png_structp pp)
pp->read_filter[PNG_FILTER_VALUE_PAETH-1] =
png_read_filter_row_paeth_multibyte_pixel;
-#ifdef PNG_ARM_NEON
- png_init_filter_functions_neon(pp, bpp);
+#ifdef PNG_FILTER_OPTIMIZATIONS
+ /* To use this define PNG_FILTER_OPTIMIZATIONS as the name of a function to
+ * call to install hardware optimizations for the above functions; simply
+ * replace whatever elements of the pp->read_filter[] array with a hardware
+ * specific (or, for that matter, generic) optimization.
+ *
+ * To see an example of this examine what configure.ac does when
+ * --enable-arm-neon is specified on the command line.
+ */
+ PNG_FILTER_OPTIMIZATIONS(pp, bpp);
#endif
}
void /* PRIVATE */
-png_read_filter_row(png_structp pp, png_row_infop row_info, png_bytep row,
+png_read_filter_row(png_structrp pp, png_row_infop row_info, png_bytep row,
png_const_bytep prev_row, int filter)
{
- if (pp->read_filter[0] == NULL)
- png_init_filter_functions(pp);
+ /* OPTIMIZATION: DO NOT MODIFY THIS FUNCTION, instead #define
+ * PNG_FILTER_OPTIMIZATIONS to a function that overrides the generic
+ * implementations. See png_init_filter_functions above.
+ */
if (filter > PNG_FILTER_VALUE_NONE && filter < PNG_FILTER_VALUE_LAST)
+ {
+ if (pp->read_filter[0] == NULL)
+ png_init_filter_functions(pp);
+
pp->read_filter[filter-1](row_info, row, prev_row);
+ }
}
#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
void /* PRIVATE */
-png_read_finish_row(png_structp png_ptr)
+png_read_IDAT_data(png_structrp png_ptr, png_bytep output,
+ png_alloc_size_t avail_out)
+{
+ /* Loop reading IDATs and decompressing the result into output[avail_out] */
+ png_ptr->zstream.next_out = output;
+ png_ptr->zstream.avail_out = 0; /* safety: set below */
+
+ if (output == NULL)
+ avail_out = 0;
+
+ do
+ {
+ int ret;
+ png_byte tmpbuf[PNG_INFLATE_BUF_SIZE];
+
+ if (png_ptr->zstream.avail_in == 0)
+ {
+ uInt avail_in;
+ png_bytep buffer;
+
+ while (png_ptr->idat_size == 0)
+ {
+ png_crc_finish(png_ptr, 0);
+
+ png_ptr->idat_size = png_read_chunk_header(png_ptr);
+ /* This is an error even in the 'check' case because the code just
+ * consumed a non-IDAT header.
+ */
+ if (png_ptr->chunk_name != png_IDAT)
+ png_error(png_ptr, "Not enough image data");
+ }
+
+ avail_in = png_ptr->IDAT_read_size;
+
+ if (avail_in > png_ptr->idat_size)
+ avail_in = (uInt)png_ptr->idat_size;
+
+ /* A PNG with a gradually increasing IDAT size will defeat this attempt
+ * to minimize memory usage by causing lots of re-allocs, but
+ * realistically doing IDAT_read_size re-allocs is not likely to be a
+ * big problem.
+ */
+ buffer = png_read_buffer(png_ptr, avail_in, 0/*error*/);
+
+ png_crc_read(png_ptr, buffer, avail_in);
+ png_ptr->idat_size -= avail_in;
+
+ png_ptr->zstream.next_in = buffer;
+ png_ptr->zstream.avail_in = avail_in;
+ }
+
+ /* And set up the output side. */
+ if (output != NULL) /* standard read */
+ {
+ uInt out = ZLIB_IO_MAX;
+
+ if (out > avail_out)
+ out = (uInt)avail_out;
+
+ avail_out -= out;
+ png_ptr->zstream.avail_out = out;
+ }
+
+ else /* after last row, checking for end */
+ {
+ png_ptr->zstream.next_out = tmpbuf;
+ png_ptr->zstream.avail_out = (sizeof tmpbuf);
+ }
+
+ /* Use NO_FLUSH; this gives zlib the maximum opportunity to optimize the
+ * process. If the LZ stream is truncated the sequential reader will
+ * terminally damage the stream, above, by reading the chunk header of the
+ * following chunk (it then exits with png_error).
+ *
+ * TODO: deal more elegantly with truncated IDAT lists.
+ */
+ ret = inflate(&png_ptr->zstream, Z_NO_FLUSH);
+
+ /* Take the unconsumed output back. */
+ if (output != NULL)
+ avail_out += png_ptr->zstream.avail_out;
+
+ else /* avail_out counts the extra bytes */
+ avail_out += (sizeof tmpbuf) - png_ptr->zstream.avail_out;
+
+ png_ptr->zstream.avail_out = 0;
+
+ if (ret == Z_STREAM_END)
+ {
+ /* Do this for safety; we won't read any more into this row. */
+ png_ptr->zstream.next_out = NULL;
+
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+
+ if (png_ptr->zstream.avail_in > 0 || png_ptr->idat_size > 0)
+ png_chunk_benign_error(png_ptr, "Extra compressed data");
+ break;
+ }
+
+ if (ret != Z_OK)
+ {
+ png_zstream_error(png_ptr, ret);
+
+ if (output != NULL)
+ png_chunk_error(png_ptr, png_ptr->zstream.msg);
+
+ else /* checking */
+ {
+ png_chunk_benign_error(png_ptr, png_ptr->zstream.msg);
+ return;
+ }
+ }
+ } while (avail_out > 0);
+
+ if (avail_out > 0)
+ {
+ /* The stream ended before the image; this is the same as too few IDATs so
+ * should be handled the same way.
+ */
+ if (output != NULL)
+ png_error(png_ptr, "Not enough image data");
+
+ else /* the deflate stream contained extra data */
+ png_chunk_benign_error(png_ptr, "Too much image data");
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_IDAT(png_structrp png_ptr)
+{
+ /* We don't need any more data and the stream should have ended, however the
+ * LZ end code may actually not have been processed. In this case we must
+ * read it otherwise stray unread IDAT data or, more likely, an IDAT chunk
+ * may still remain to be consumed.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ /* The NULL causes png_read_IDAT_data to swallow any remaining bytes in
+ * the compressed stream, but the stream may be damaged too, so even after
+ * this call we may need to terminate the zstream ownership.
+ */
+ png_read_IDAT_data(png_ptr, NULL, 0);
+ png_ptr->zstream.next_out = NULL; /* safety */
+
+ /* Now clear everything out for safety; the following may not have been
+ * done.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_ENDED) == 0)
+ {
+ png_ptr->mode |= PNG_AFTER_IDAT;
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_ENDED;
+ }
+ }
+
+ /* If the zstream has not been released do it now *and* terminate the reading
+ * of the final IDAT chunk.
+ */
+ if (png_ptr->zowner == png_IDAT)
+ {
+ /* Always do this; the pointers otherwise point into the read buffer. */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+
+ /* Now we no longer own the zstream. */
+ png_ptr->zowner = 0;
+
+ /* The slightly weird semantics of the sequential IDAT reading is that we
+ * are always in or at the end of an IDAT chunk, so we always need to do a
+ * crc_finish here. If idat_size is non-zero we also need to read the
+ * spurious bytes at the end of the chunk now.
+ */
+ (void)png_crc_finish(png_ptr, png_ptr->idat_size);
+ }
+}
+
+void /* PRIVATE */
+png_read_finish_row(png_structrp png_ptr)
{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
@@ -3768,22 +4133,20 @@ png_read_finish_row(png_structp png_ptr)
/* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
png_debug(1, "in png_read_finish_row");
png_ptr->row_number++;
if (png_ptr->row_number < png_ptr->num_rows)
return;
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
/* TO DO: don't do this if prev_row isn't needed (requires
* read-ahead of the next row's filter byte.
*/
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
do
{
@@ -3797,7 +4160,7 @@ png_read_finish_row(png_structp png_ptr)
png_pass_start[png_ptr->pass]) /
png_pass_inc[png_ptr->pass];
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height +
png_pass_yinc[png_ptr->pass] - 1 -
@@ -3813,80 +4176,15 @@ png_read_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
return;
}
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_FINISHED))
- {
- char extra;
- int ret;
-
- png_ptr->zstream.next_out = (Byte *)&extra;
- png_ptr->zstream.avail_out = (uInt)1;
-
- for (;;)
- {
- if (!(png_ptr->zstream.avail_in))
- {
- while (!png_ptr->idat_size)
- {
- png_crc_finish(png_ptr, 0);
- png_ptr->idat_size = png_read_chunk_header(png_ptr);
- if (png_ptr->chunk_name != png_IDAT)
- png_error(png_ptr, "Not enough image data");
- }
-
- png_ptr->zstream.avail_in = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_in = png_ptr->zbuf;
-
- if (png_ptr->zbuf_size > png_ptr->idat_size)
- png_ptr->zstream.avail_in = (uInt)png_ptr->idat_size;
-
- png_crc_read(png_ptr, png_ptr->zbuf, png_ptr->zstream.avail_in);
- png_ptr->idat_size -= png_ptr->zstream.avail_in;
- }
-
- ret = inflate(&png_ptr->zstream, Z_PARTIAL_FLUSH);
-
- if (ret == Z_STREAM_END)
- {
- if (!(png_ptr->zstream.avail_out) || png_ptr->zstream.avail_in ||
- png_ptr->idat_size)
- png_warning(png_ptr, "Extra compressed data");
-
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- if (ret != Z_OK)
- png_error(png_ptr, png_ptr->zstream.msg ? png_ptr->zstream.msg :
- "Decompression Error");
-
- if (!(png_ptr->zstream.avail_out))
- {
- png_warning(png_ptr, "Extra compressed data");
- png_ptr->mode |= PNG_AFTER_IDAT;
- png_ptr->flags |= PNG_FLAG_ZLIB_FINISHED;
- break;
- }
-
- }
- png_ptr->zstream.avail_out = 0;
- }
-
- if (png_ptr->idat_size || png_ptr->zstream.avail_in)
- png_warning(png_ptr, "Extra compression data");
- inflateReset(&png_ptr->zstream);
-
- png_ptr->mode |= PNG_AFTER_IDAT;
+ /* Here after at the end of the last row of the last pass. */
+ png_read_finish_IDAT(png_ptr);
}
-#endif /* PNG_SEQUENTIAL_READ_SUPPORTED */
+#endif /* SEQUENTIAL_READ */
void /* PRIVATE */
-png_read_start_row(png_structp png_ptr)
+png_read_start_row(png_structrp png_ptr)
{
-#ifdef PNG_READ_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
/* Start of interlace block */
@@ -3900,20 +4198,18 @@ png_read_start_row(png_structp png_ptr)
/* Offset to next interlace block in the y direction */
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
-#endif
int max_pixel_depth;
png_size_t row_bytes;
png_debug(1, "in png_read_start_row");
- png_ptr->zstream.avail_in = 0;
+
#ifdef PNG_READ_TRANSFORMS_SUPPORTED
png_init_read_transformations(png_ptr);
#endif
-#ifdef PNG_READ_INTERLACING_SUPPORTED
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -3927,7 +4223,6 @@ png_read_start_row(png_structp png_ptr)
}
else
-#endif /* PNG_READ_INTERLACING_SUPPORTED */
{
png_ptr->num_rows = png_ptr->height;
png_ptr->iwidth = png_ptr->width;
@@ -3935,7 +4230,7 @@ png_read_start_row(png_structp png_ptr)
max_pixel_depth = png_ptr->pixel_depth;
- /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpliar set of
+ /* WARNING: * png_read_transform_info (pngrtran.c) performs a simpler set of
* calculations to calculate the final pixel depth, then
* png_do_read_transforms actually does the transforms. This means that the
* code which effectively calculates this value is actually repeated in three
@@ -3946,16 +4241,16 @@ png_read_start_row(png_structp png_ptr)
* TODO: fix this.
*/
#ifdef PNG_READ_PACK_SUPPORTED
- if ((png_ptr->transformations & PNG_PACK) && png_ptr->bit_depth < 8)
+ if ((png_ptr->transformations & PNG_PACK) != 0 && png_ptr->bit_depth < 8)
max_pixel_depth = 8;
#endif
#ifdef PNG_READ_EXPAND_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth = 32;
else
@@ -3967,13 +4262,13 @@ png_read_start_row(png_structp png_ptr)
if (max_pixel_depth < 8)
max_pixel_depth = 8;
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
max_pixel_depth *= 2;
}
else if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
{
- if (png_ptr->num_trans)
+ if (png_ptr->num_trans != 0)
{
max_pixel_depth *= 4;
max_pixel_depth /= 3;
@@ -3983,13 +4278,13 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_EXPAND_16_SUPPORTED
- if (png_ptr->transformations & PNG_EXPAND_16)
+ if ((png_ptr->transformations & PNG_EXPAND_16) != 0)
{
# ifdef PNG_READ_EXPAND_SUPPORTED
/* In fact it is an error if it isn't supported, but checking is
* the safe way.
*/
- if (png_ptr->transformations & PNG_EXPAND)
+ if ((png_ptr->transformations & PNG_EXPAND) != 0)
{
if (png_ptr->bit_depth < 16)
max_pixel_depth *= 2;
@@ -4001,7 +4296,7 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- if (png_ptr->transformations & (PNG_FILLER))
+ if ((png_ptr->transformations & (PNG_FILLER)) != 0)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY)
{
@@ -4025,14 +4320,15 @@ png_read_start_row(png_structp png_ptr)
#endif
#ifdef PNG_READ_GRAY_TO_RGB_SUPPORTED
- if (png_ptr->transformations & PNG_GRAY_TO_RGB)
+ if ((png_ptr->transformations & PNG_GRAY_TO_RGB) != 0)
{
if (
#ifdef PNG_READ_EXPAND_SUPPORTED
- (png_ptr->num_trans && (png_ptr->transformations & PNG_EXPAND)) ||
+ (png_ptr->num_trans != 0 &&
+ (png_ptr->transformations & PNG_EXPAND) != 0) ||
#endif
#ifdef PNG_READ_FILLER_SUPPORTED
- (png_ptr->transformations & (PNG_FILLER)) ||
+ (png_ptr->transformations & (PNG_FILLER)) != 0 ||
#endif
png_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
{
@@ -4065,7 +4361,7 @@ png_read_start_row(png_structp png_ptr)
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) && \
defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
{
int user_pixel_depth = png_ptr->user_transform_depth *
png_ptr->user_transform_channels;
@@ -4101,7 +4397,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_free(png_ptr, png_ptr->big_row_buf);
png_free(png_ptr, png_ptr->big_prev_row);
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
png_ptr->big_row_buf = (png_bytep)png_calloc(png_ptr,
row_bytes + 48);
@@ -4144,7 +4440,7 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
if (png_ptr->rowbytes > (PNG_SIZE_MAX - 1))
png_error(png_ptr, "Row has too many bytes to allocate in memory");
- png_memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
+ memset(png_ptr->prev_row, 0, png_ptr->rowbytes + 1);
png_debug1(3, "width = %u,", png_ptr->width);
png_debug1(3, "height = %u,", png_ptr->height);
@@ -4154,6 +4450,27 @@ defined(PNG_USER_TRANSFORM_PTR_SUPPORTED)
png_debug1(3, "irowbytes = %lu",
(unsigned long)PNG_ROWBYTES(png_ptr->pixel_depth, png_ptr->iwidth) + 1);
+ /* The sequential reader needs a buffer for IDAT, but the progressive reader
+ * does not, so free the read buffer now regardless; the sequential reader
+ * reallocates it on demand.
+ */
+ if (png_ptr->read_buffer != 0)
+ {
+ png_bytep buffer = png_ptr->read_buffer;
+
+ png_ptr->read_buffer_size = 0;
+ png_ptr->read_buffer = NULL;
+ png_free(png_ptr, buffer);
+ }
+
+ /* Finally claim the zstream for the inflate of the IDAT data, use the bits
+ * value from the stream (note that this will result in a fatal error if the
+ * IDAT stream has a bogus deflate header window_bits value, but this should
+ * not be happening any longer!)
+ */
+ if (png_inflate_claim(png_ptr, png_IDAT) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
png_ptr->flags |= PNG_FLAG_ROW_INIT;
}
-#endif /* PNG_READ_SUPPORTED */
+#endif /* READ */
diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c
index e0118fa8c2..fce3039168 100644
--- a/src/3rdparty/libpng/pngset.c
+++ b/src/3rdparty/libpng/pngset.c
@@ -1,8 +1,8 @@
/* pngset.c - storage of image information into info struct
*
- * Last changed in libpng 1.5.10 [(PENDING RELEASE)]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -22,50 +22,51 @@
#ifdef PNG_bKGD_SUPPORTED
void PNGAPI
-png_set_bKGD(png_structp png_ptr, png_infop info_ptr,
+png_set_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_16p background)
{
png_debug1(1, "in %s storage function", "bKGD");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || background == NULL)
return;
- png_memcpy(&(info_ptr->background), background, png_sizeof(png_color_16));
+ info_ptr->background = *background;
info_ptr->valid |= PNG_INFO_bKGD;
}
#endif
#ifdef PNG_cHRM_SUPPORTED
void PNGFAPI
-png_set_cHRM_fixed(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
png_fixed_point white_x, png_fixed_point white_y, png_fixed_point red_x,
png_fixed_point red_y, png_fixed_point green_x, png_fixed_point green_y,
png_fixed_point blue_x, png_fixed_point blue_y)
{
+ png_xy xy;
+
png_debug1(1, "in %s storage function", "cHRM fixed");
if (png_ptr == NULL || info_ptr == NULL)
return;
-# ifdef PNG_CHECK_cHRM_SUPPORTED
- if (png_check_cHRM_fixed(png_ptr,
- white_x, white_y, red_x, red_y, green_x, green_y, blue_x, blue_y))
-# endif
- {
- info_ptr->x_white = white_x;
- info_ptr->y_white = white_y;
- info_ptr->x_red = red_x;
- info_ptr->y_red = red_y;
- info_ptr->x_green = green_x;
- info_ptr->y_green = green_y;
- info_ptr->x_blue = blue_x;
- info_ptr->y_blue = blue_y;
- info_ptr->valid |= PNG_INFO_cHRM;
- }
+ xy.redx = red_x;
+ xy.redy = red_y;
+ xy.greenx = green_x;
+ xy.greeny = green_y;
+ xy.bluex = blue_x;
+ xy.bluey = blue_y;
+ xy.whitex = white_x;
+ xy.whitey = white_y;
+
+ if (png_colorspace_set_chromaticities(png_ptr, &info_ptr->colorspace, &xy,
+ 2/* override with app values*/) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
void PNGFAPI
-png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
png_fixed_point int_red_X, png_fixed_point int_red_Y,
png_fixed_point int_red_Z, png_fixed_point int_green_X,
png_fixed_point int_green_Y, png_fixed_point int_green_Z,
@@ -73,33 +74,32 @@ png_set_cHRM_XYZ_fixed(png_structp png_ptr, png_infop info_ptr,
png_fixed_point int_blue_Z)
{
png_XYZ XYZ;
- png_xy xy;
png_debug1(1, "in %s storage function", "cHRM XYZ fixed");
if (png_ptr == NULL || info_ptr == NULL)
return;
- XYZ.redX = int_red_X;
- XYZ.redY = int_red_Y;
- XYZ.redZ = int_red_Z;
- XYZ.greenX = int_green_X;
- XYZ.greenY = int_green_Y;
- XYZ.greenZ = int_green_Z;
- XYZ.blueX = int_blue_X;
- XYZ.blueY = int_blue_Y;
- XYZ.blueZ = int_blue_Z;
-
- if (png_xy_from_XYZ(&xy, XYZ))
- png_error(png_ptr, "XYZ values out of representable range");
-
- png_set_cHRM_fixed(png_ptr, info_ptr, xy.whitex, xy.whitey, xy.redx, xy.redy,
- xy.greenx, xy.greeny, xy.bluex, xy.bluey);
+ XYZ.red_X = int_red_X;
+ XYZ.red_Y = int_red_Y;
+ XYZ.red_Z = int_red_Z;
+ XYZ.green_X = int_green_X;
+ XYZ.green_Y = int_green_Y;
+ XYZ.green_Z = int_green_Z;
+ XYZ.blue_X = int_blue_X;
+ XYZ.blue_Y = int_blue_Y;
+ XYZ.blue_Z = int_blue_Z;
+
+ if (png_colorspace_set_endpoints(png_ptr, &info_ptr->colorspace,
+ &XYZ, 2) != 0)
+ info_ptr->colorspace.flags |= PNG_COLORSPACE_FROM_cHRM;
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
double white_x, double white_y, double red_x, double red_y,
double green_x, double green_y, double blue_x, double blue_y)
{
@@ -115,7 +115,7 @@ png_set_cHRM(png_structp png_ptr, png_infop info_ptr,
}
void PNGAPI
-png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
+png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X,
double red_Y, double red_Z, double green_X, double green_Y, double green_Z,
double blue_X, double blue_Y, double blue_Z)
{
@@ -130,41 +130,27 @@ png_set_cHRM_XYZ(png_structp png_ptr, png_infop info_ptr, double red_X,
png_fixed(png_ptr, blue_Y, "cHRM Red Y"),
png_fixed(png_ptr, blue_Z, "cHRM Red Z"));
}
-# endif /* PNG_FLOATING_POINT_SUPPORTED */
+# endif /* FLOATING_POINT */
-#endif /* PNG_cHRM_SUPPORTED */
+#endif /* cHRM */
#ifdef PNG_gAMA_SUPPORTED
void PNGFAPI
-png_set_gAMA_fixed(png_structp png_ptr, png_infop info_ptr, png_fixed_point
- file_gamma)
+png_set_gAMA_fixed(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_fixed_point file_gamma)
{
png_debug1(1, "in %s storage function", "gAMA");
if (png_ptr == NULL || info_ptr == NULL)
return;
- /* Changed in libpng-1.5.4 to limit the values to ensure overflow can't
- * occur. Since the fixed point representation is assymetrical it is
- * possible for 1/gamma to overflow the limit of 21474 and this means the
- * gamma value must be at least 5/100000 and hence at most 20000.0. For
- * safety the limits here are a little narrower. The values are 0.00016 to
- * 6250.0, which are truly ridiculous gammma values (and will produce
- * displays that are all black or all white.)
- */
- if (file_gamma < 16 || file_gamma > 625000000)
- png_warning(png_ptr, "Out of range gamma value ignored");
-
- else
- {
- info_ptr->gamma = file_gamma;
- info_ptr->valid |= PNG_INFO_gAMA;
- }
+ png_colorspace_set_gamma(png_ptr, &info_ptr->colorspace, file_gamma);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
+png_set_gAMA(png_const_structrp png_ptr, png_inforp info_ptr, double file_gamma)
{
png_set_gAMA_fixed(png_ptr, info_ptr, png_fixed(png_ptr, file_gamma,
"png_set_gAMA"));
@@ -174,7 +160,8 @@ png_set_gAMA(png_structp png_ptr, png_infop info_ptr, double file_gamma)
#ifdef PNG_hIST_SUPPORTED
void PNGAPI
-png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
+png_set_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_uint_16p hist)
{
int i;
@@ -197,26 +184,27 @@ png_set_hIST(png_structp png_ptr, png_infop info_ptr, png_const_uint_16p hist)
/* Changed from info->num_palette to PNG_MAX_PALETTE_LENGTH in
* version 1.2.1
*/
- png_ptr->hist = (png_uint_16p)png_malloc_warn(png_ptr,
- PNG_MAX_PALETTE_LENGTH * png_sizeof(png_uint_16));
+ info_ptr->hist = png_voidcast(png_uint_16p, png_malloc_warn(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_uint_16))));
- if (png_ptr->hist == NULL)
+ if (info_ptr->hist == NULL)
{
png_warning(png_ptr, "Insufficient memory for hIST chunk data");
+
return;
}
+ info_ptr->free_me |= PNG_FREE_HIST;
+
for (i = 0; i < info_ptr->num_palette; i++)
- png_ptr->hist[i] = hist[i];
+ info_ptr->hist[i] = hist[i];
- info_ptr->hist = png_ptr->hist;
info_ptr->valid |= PNG_INFO_hIST;
- info_ptr->free_me |= PNG_FREE_HIST;
}
#endif
void PNGAPI
-png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
+png_set_IHDR(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 width, png_uint_32 height, int bit_depth,
int color_type, int interlace_type, int compression_type,
int filter_type)
@@ -241,32 +229,23 @@ png_set_IHDR(png_structp png_ptr, png_infop info_ptr,
if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
info_ptr->channels = 1;
- else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR)
+ else if ((info_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0)
info_ptr->channels = 3;
else
info_ptr->channels = 1;
- if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((info_ptr->color_type & PNG_COLOR_MASK_ALPHA) != 0)
info_ptr->channels++;
info_ptr->pixel_depth = (png_byte)(info_ptr->channels * info_ptr->bit_depth);
- /* Check for potential overflow */
- if (width >
- (PNG_UINT_32_MAX >> 3) /* 8-byte RRGGBBAA pixels */
- - 48 /* bigrowbuf hack */
- - 1 /* filter byte */
- - 7*8 /* rounding of width to multiple of 8 pixels */
- - 8) /* extra max_pixel_depth pad */
- info_ptr->rowbytes = 0;
- else
- info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
+ info_ptr->rowbytes = PNG_ROWBYTES(info_ptr->pixel_depth, width);
}
#ifdef PNG_oFFs_SUPPORTED
void PNGAPI
-png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
+png_set_oFFs(png_const_structrp png_ptr, png_inforp info_ptr,
png_int_32 offset_x, png_int_32 offset_y, int unit_type)
{
png_debug1(1, "in %s storage function", "oFFs");
@@ -283,7 +262,7 @@ png_set_oFFs(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_pCAL_SUPPORTED
void PNGAPI
-png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
+png_set_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp purpose, png_int_32 X0, png_int_32 X1, int type,
int nparams, png_const_charp units, png_charpp params)
{
@@ -292,10 +271,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
png_debug1(1, "in %s storage function", "pCAL");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || purpose == NULL || units == NULL
+ || (nparams > 0 && params == NULL))
return;
- length = png_strlen(purpose) + 1;
+ length = strlen(purpose) + 1;
png_debug1(3, "allocating purpose for info (%lu bytes)",
(unsigned long)length);
@@ -305,20 +285,28 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (type < 0 || type > 3)
png_error(png_ptr, "Invalid pCAL equation type");
+ if (nparams < 0 || nparams > 255)
+ png_error(png_ptr, "Invalid pCAL parameter count");
+
/* Validate params[nparams] */
for (i=0; i<nparams; ++i)
- if (!png_check_fp_string(params[i], png_strlen(params[i])))
+ {
+ if (params[i] == NULL ||
+ !png_check_fp_string(params[i], strlen(params[i])))
png_error(png_ptr, "Invalid format for pCAL parameter");
+ }
- info_ptr->pcal_purpose = (png_charp)png_malloc_warn(png_ptr, length);
+ info_ptr->pcal_purpose = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_purpose == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL purpose");
+
return;
}
- png_memcpy(info_ptr->pcal_purpose, purpose, length);
+ memcpy(info_ptr->pcal_purpose, purpose, length);
png_debug(3, "storing X0, X1, type, and nparams in info");
info_ptr->pcal_X0 = X0;
@@ -326,34 +314,37 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
info_ptr->pcal_type = (png_byte)type;
info_ptr->pcal_nparams = (png_byte)nparams;
- length = png_strlen(units) + 1;
+ length = strlen(units) + 1;
png_debug1(3, "allocating units for info (%lu bytes)",
(unsigned long)length);
- info_ptr->pcal_units = (png_charp)png_malloc_warn(png_ptr, length);
+ info_ptr->pcal_units = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, length));
if (info_ptr->pcal_units == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL units");
+
return;
}
- png_memcpy(info_ptr->pcal_units, units, length);
+ memcpy(info_ptr->pcal_units, units, length);
- info_ptr->pcal_params = (png_charpp)png_malloc_warn(png_ptr,
- (png_size_t)((nparams + 1) * png_sizeof(png_charp)));
+ info_ptr->pcal_params = png_voidcast(png_charpp, png_malloc_warn(png_ptr,
+ (png_size_t)((nparams + 1) * (sizeof (png_charp)))));
if (info_ptr->pcal_params == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL params");
+
return;
}
- png_memset(info_ptr->pcal_params, 0, (nparams + 1) * png_sizeof(png_charp));
+ memset(info_ptr->pcal_params, 0, (nparams + 1) * (sizeof (png_charp)));
for (i = 0; i < nparams; i++)
{
- length = png_strlen(params[i]) + 1;
+ length = strlen(params[i]) + 1;
png_debug2(3, "allocating parameter %d for info (%lu bytes)", i,
(unsigned long)length);
@@ -362,10 +353,11 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
if (info_ptr->pcal_params[i] == NULL)
{
png_warning(png_ptr, "Insufficient memory for pCAL parameter");
+
return;
}
- png_memcpy(info_ptr->pcal_params[i], params[i], length);
+ memcpy(info_ptr->pcal_params[i], params[i], length);
}
info_ptr->valid |= PNG_INFO_pCAL;
@@ -375,7 +367,7 @@ png_set_pCAL(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sCAL_SUPPORTED
void PNGAPI
-png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
+png_set_sCAL_s(png_const_structrp png_ptr, png_inforp info_ptr,
int unit, png_const_charp swidth, png_const_charp sheight)
{
png_size_t lengthw = 0, lengthh = 0;
@@ -391,11 +383,11 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
if (unit != 1 && unit != 2)
png_error(png_ptr, "Invalid sCAL unit");
- if (swidth == NULL || (lengthw = png_strlen(swidth)) == 0 ||
+ if (swidth == NULL || (lengthw = strlen(swidth)) == 0 ||
swidth[0] == 45 /* '-' */ || !png_check_fp_string(swidth, lengthw))
png_error(png_ptr, "Invalid sCAL width");
- if (sheight == NULL || (lengthh = png_strlen(sheight)) == 0 ||
+ if (sheight == NULL || (lengthh = strlen(sheight)) == 0 ||
sheight[0] == 45 /* '-' */ || !png_check_fp_string(sheight, lengthh))
png_error(png_ptr, "Invalid sCAL height");
@@ -405,21 +397,24 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthw);
- info_ptr->scal_s_width = (png_charp)png_malloc_warn(png_ptr, lengthw);
+ info_ptr->scal_s_width = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthw));
if (info_ptr->scal_s_width == NULL)
{
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
- png_memcpy(info_ptr->scal_s_width, swidth, lengthw);
+ memcpy(info_ptr->scal_s_width, swidth, lengthw);
++lengthh;
png_debug1(3, "allocating unit for info (%u bytes)", (unsigned int)lengthh);
- info_ptr->scal_s_height = (png_charp)png_malloc_warn(png_ptr, lengthh);
+ info_ptr->scal_s_height = png_voidcast(png_charp,
+ png_malloc_warn(png_ptr, lengthh));
if (info_ptr->scal_s_height == NULL)
{
@@ -427,10 +422,11 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
info_ptr->scal_s_width = NULL;
png_warning(png_ptr, "Memory allocation failed while processing sCAL");
+
return;
}
- png_memcpy(info_ptr->scal_s_height, sheight, lengthh);
+ memcpy(info_ptr->scal_s_height, sheight, lengthh);
info_ptr->valid |= PNG_INFO_sCAL;
info_ptr->free_me |= PNG_FREE_SCAL;
@@ -438,8 +434,8 @@ png_set_sCAL_s(png_structp png_ptr, png_infop info_ptr,
# ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
- double height)
+png_set_sCAL(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
+ double width, double height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -456,9 +452,9 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
char swidth[PNG_sCAL_MAX_DIGITS+1];
char sheight[PNG_sCAL_MAX_DIGITS+1];
- png_ascii_from_fp(png_ptr, swidth, sizeof swidth, width,
+ png_ascii_from_fp(png_ptr, swidth, (sizeof swidth), width,
PNG_sCAL_PRECISION);
- png_ascii_from_fp(png_ptr, sheight, sizeof sheight, height,
+ png_ascii_from_fp(png_ptr, sheight, (sizeof sheight), height,
PNG_sCAL_PRECISION);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
@@ -468,7 +464,7 @@ png_set_sCAL(png_structp png_ptr, png_infop info_ptr, int unit, double width,
# ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
+png_set_sCAL_fixed(png_const_structrp png_ptr, png_inforp info_ptr, int unit,
png_fixed_point width, png_fixed_point height)
{
png_debug1(1, "in %s storage function", "sCAL");
@@ -486,8 +482,8 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
char swidth[PNG_sCAL_MAX_DIGITS+1];
char sheight[PNG_sCAL_MAX_DIGITS+1];
- png_ascii_from_fixed(png_ptr, swidth, sizeof swidth, width);
- png_ascii_from_fixed(png_ptr, sheight, sizeof sheight, height);
+ png_ascii_from_fixed(png_ptr, swidth, (sizeof swidth), width);
+ png_ascii_from_fixed(png_ptr, sheight, (sizeof sheight), height);
png_set_sCAL_s(png_ptr, info_ptr, unit, swidth, sheight);
}
@@ -497,7 +493,7 @@ png_set_sCAL_fixed(png_structp png_ptr, png_infop info_ptr, int unit,
#ifdef PNG_pHYs_SUPPORTED
void PNGAPI
-png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
+png_set_pHYs(png_const_structrp png_ptr, png_inforp info_ptr,
png_uint_32 res_x, png_uint_32 res_y, int unit_type)
{
png_debug1(1, "in %s storage function", "pHYs");
@@ -513,7 +509,7 @@ png_set_pHYs(png_structp png_ptr, png_infop info_ptr,
#endif
void PNGAPI
-png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
+png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr,
png_const_colorp palette, int num_palette)
{
@@ -530,13 +526,27 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
else
{
png_warning(png_ptr, "Invalid palette length");
+
return;
}
}
+ if ((num_palette > 0 && palette == NULL) ||
+ (num_palette == 0
+# ifdef PNG_MNG_FEATURES_SUPPORTED
+ && (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0
+# endif
+ ))
+ {
+ png_error(png_ptr, "Invalid palette");
+ }
+
/* It may not actually be necessary to set png_ptr->palette here;
* we do it for backward compatibility with the way the png_handle_tRNS
* function used to do the allocation.
+ *
+ * 1.6.0: the above statement appears to be incorrect; something has to set
+ * the palette inside png_struct on read.
*/
png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0);
@@ -544,10 +554,11 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
* of num_palette entries, in case of an invalid PNG file that has
* too-large sample values.
*/
- png_ptr->palette = (png_colorp)png_calloc(png_ptr,
- PNG_MAX_PALETTE_LENGTH * png_sizeof(png_color));
+ png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr,
+ PNG_MAX_PALETTE_LENGTH * (sizeof (png_color))));
- png_memcpy(png_ptr->palette, palette, num_palette * png_sizeof(png_color));
+ if (num_palette > 0)
+ memcpy(png_ptr->palette, palette, num_palette * (sizeof (png_color)));
info_ptr->palette = png_ptr->palette;
info_ptr->num_palette = png_ptr->num_palette = (png_uint_16)num_palette;
@@ -558,34 +569,34 @@ png_set_PLTE(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sBIT_SUPPORTED
void PNGAPI
-png_set_sBIT(png_structp png_ptr, png_infop info_ptr,
+png_set_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_color_8p sig_bit)
{
png_debug1(1, "in %s storage function", "sBIT");
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || sig_bit == NULL)
return;
- png_memcpy(&(info_ptr->sig_bit), sig_bit, png_sizeof(png_color_8));
+ info_ptr->sig_bit = *sig_bit;
info_ptr->valid |= PNG_INFO_sBIT;
}
#endif
#ifdef PNG_sRGB_SUPPORTED
void PNGAPI
-png_set_sRGB(png_structp png_ptr, png_infop info_ptr, int srgb_intent)
+png_set_sRGB(png_const_structrp png_ptr, png_inforp info_ptr, int srgb_intent)
{
png_debug1(1, "in %s storage function", "sRGB");
if (png_ptr == NULL || info_ptr == NULL)
return;
- info_ptr->srgb_intent = (png_byte)srgb_intent;
- info_ptr->valid |= PNG_INFO_sRGB;
+ (void)png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace, srgb_intent);
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
void PNGAPI
-png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
+png_set_sRGB_gAMA_and_cHRM(png_const_structrp png_ptr, png_inforp info_ptr,
int srgb_intent)
{
png_debug1(1, "in %s storage function", "sRGB_gAMA_and_cHRM");
@@ -593,28 +604,22 @@ png_set_sRGB_gAMA_and_cHRM(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL)
return;
- png_set_sRGB(png_ptr, info_ptr, srgb_intent);
-
-# ifdef PNG_gAMA_SUPPORTED
- png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
-# endif
+ if (png_colorspace_set_sRGB(png_ptr, &info_ptr->colorspace,
+ srgb_intent) != 0)
+ {
+ /* This causes the gAMA and cHRM to be written too */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
-# ifdef PNG_cHRM_SUPPORTED
- png_set_cHRM_fixed(png_ptr, info_ptr,
- /* color x y */
- /* white */ 31270, 32900,
- /* red */ 64000, 33000,
- /* green */ 30000, 60000,
- /* blue */ 15000, 6000
- );
-# endif /* cHRM */
+ png_colorspace_sync_info(png_ptr, info_ptr);
}
#endif /* sRGB */
#ifdef PNG_iCCP_SUPPORTED
void PNGAPI
-png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
+png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_charp name, int compression_type,
png_const_bytep profile, png_uint_32 proflen)
{
@@ -627,37 +632,61 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
if (png_ptr == NULL || info_ptr == NULL || name == NULL || profile == NULL)
return;
- length = png_strlen(name)+1;
- new_iccp_name = (png_charp)png_malloc_warn(png_ptr, length);
+ if (compression_type != PNG_COMPRESSION_TYPE_BASE)
+ png_app_error(png_ptr, "Invalid iCCP compression method");
+
+ /* Set the colorspace first because this validates the profile; do not
+ * override previously set app cHRM or gAMA here (because likely as not the
+ * application knows better than libpng what the correct values are.) Pass
+ * the info_ptr color_type field to png_colorspace_set_ICC because in the
+ * write case it has not yet been stored in png_ptr.
+ */
+ {
+ int result = png_colorspace_set_ICC(png_ptr, &info_ptr->colorspace, name,
+ proflen, profile, info_ptr->color_type);
+
+ png_colorspace_sync_info(png_ptr, info_ptr);
+
+ /* Don't do any of the copying if the profile was bad, or inconsistent. */
+ if (result == 0)
+ return;
+
+ /* But do write the gAMA and cHRM chunks from the profile. */
+ info_ptr->colorspace.flags |=
+ PNG_COLORSPACE_FROM_gAMA|PNG_COLORSPACE_FROM_cHRM;
+ }
+
+ length = strlen(name)+1;
+ new_iccp_name = png_voidcast(png_charp, png_malloc_warn(png_ptr, length));
if (new_iccp_name == NULL)
{
- png_warning(png_ptr, "Insufficient memory to process iCCP chunk");
+ png_benign_error(png_ptr, "Insufficient memory to process iCCP chunk");
+
return;
}
- png_memcpy(new_iccp_name, name, length);
- new_iccp_profile = (png_bytep)png_malloc_warn(png_ptr, proflen);
+ memcpy(new_iccp_name, name, length);
+ new_iccp_profile = png_voidcast(png_bytep,
+ png_malloc_warn(png_ptr, proflen));
if (new_iccp_profile == NULL)
{
- png_free (png_ptr, new_iccp_name);
- png_warning(png_ptr,
+ png_free(png_ptr, new_iccp_name);
+ new_iccp_name = NULL;
+ png_benign_error(png_ptr,
"Insufficient memory to process iCCP profile");
+
return;
}
- png_memcpy(new_iccp_profile, profile, (png_size_t)proflen);
+ memcpy(new_iccp_profile, profile, proflen);
png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, 0);
info_ptr->iccp_proflen = proflen;
info_ptr->iccp_name = new_iccp_name;
info_ptr->iccp_profile = new_iccp_profile;
- /* Compression is always zero but is here so the API and info structure
- * does not have to change if we introduce multiple compression types
- */
- info_ptr->iccp_compression = (png_byte)compression_type;
info_ptr->free_me |= PNG_FREE_ICCP;
info_ptr->valid |= PNG_INFO_iCCP;
}
@@ -665,18 +694,18 @@ png_set_iCCP(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_TEXT_SUPPORTED
void PNGAPI
-png_set_text(png_structp png_ptr, png_infop info_ptr, png_const_textp text_ptr,
- int num_text)
+png_set_text(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_textp text_ptr, int num_text)
{
int ret;
ret = png_set_text_2(png_ptr, info_ptr, text_ptr, num_text);
- if (ret)
+ if (ret != 0)
png_error(png_ptr, "Insufficient memory to store text");
}
int /* PRIVATE */
-png_set_text_2(png_structp png_ptr, png_infop info_ptr,
+png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
png_const_textp text_ptr, int num_text)
{
int i;
@@ -684,63 +713,63 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" :
(unsigned long)png_ptr->chunk_name);
- if (png_ptr == NULL || info_ptr == NULL || num_text == 0)
+ if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
return(0);
/* Make sure we have enough space in the "text" array in info_struct
- * to hold all of the incoming text_ptr objects.
+ * to hold all of the incoming text_ptr objects. This compare can't overflow
+ * because max_text >= num_text (anyway, subtract of two positive integers
+ * can't overflow in any case.)
*/
- if (info_ptr->num_text + num_text > info_ptr->max_text)
+ if (num_text > info_ptr->max_text - info_ptr->num_text)
{
- int old_max_text = info_ptr->max_text;
int old_num_text = info_ptr->num_text;
+ int max_text;
+ png_textp new_text = NULL;
- if (info_ptr->text != NULL)
+ /* Calculate an appropriate max_text, checking for overflow. */
+ max_text = old_num_text;
+ if (num_text <= INT_MAX - max_text)
{
- png_textp old_text;
-
- info_ptr->max_text = info_ptr->num_text + num_text + 8;
- old_text = info_ptr->text;
+ max_text += num_text;
- info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
+ /* Round up to a multiple of 8 */
+ if (max_text < INT_MAX-8)
+ max_text = (max_text + 8) & ~0x7;
- if (info_ptr->text == NULL)
- {
- /* Restore to previous condition */
- info_ptr->max_text = old_max_text;
- info_ptr->text = old_text;
- return(1);
- }
-
- png_memcpy(info_ptr->text, old_text, (png_size_t)(old_max_text *
- png_sizeof(png_text)));
- png_free(png_ptr, old_text);
+ else
+ max_text = INT_MAX;
+
+ /* Now allocate a new array and copy the old members in; this does all
+ * the overflow checks.
+ */
+ new_text = png_voidcast(png_textp,png_realloc_array(png_ptr,
+ info_ptr->text, old_num_text, max_text-old_num_text,
+ sizeof *new_text));
}
- else
+ if (new_text == NULL)
{
- info_ptr->max_text = num_text + 8;
- info_ptr->num_text = 0;
- info_ptr->text = (png_textp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->max_text * png_sizeof(png_text)));
- if (info_ptr->text == NULL)
- {
- /* Restore to previous condition */
- info_ptr->num_text = old_num_text;
- info_ptr->max_text = old_max_text;
- return(1);
- }
- info_ptr->free_me |= PNG_FREE_TEXT;
+ png_chunk_report(png_ptr, "too many text chunks",
+ PNG_CHUNK_WRITE_ERROR);
+
+ return 1;
}
- png_debug1(3, "allocated %d entries for info_ptr->text",
- info_ptr->max_text);
+ png_free(png_ptr, info_ptr->text);
+
+ info_ptr->text = new_text;
+ info_ptr->free_me |= PNG_FREE_TEXT;
+ info_ptr->max_text = max_text;
+ /* num_text is adjusted below as the entries are copied in */
+
+ png_debug1(3, "allocated %d entries for info_ptr->text", max_text);
}
+
for (i = 0; i < num_text; i++)
{
- png_size_t text_length, key_len;
- png_size_t lang_len, lang_key_len;
+ size_t text_length, key_len;
+ size_t lang_len, lang_key_len;
png_textp textp = &(info_ptr->text[info_ptr->num_text]);
if (text_ptr[i].key == NULL)
@@ -749,11 +778,12 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
if (text_ptr[i].compression < PNG_TEXT_COMPRESSION_NONE ||
text_ptr[i].compression >= PNG_TEXT_COMPRESSION_LAST)
{
- png_warning(png_ptr, "text compression mode is out of range");
+ png_chunk_report(png_ptr, "text compression mode is out of range",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
- key_len = png_strlen(text_ptr[i].key);
+ key_len = strlen(text_ptr[i].key);
if (text_ptr[i].compression <= 0)
{
@@ -767,20 +797,21 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
/* Set iTXt data */
if (text_ptr[i].lang != NULL)
- lang_len = png_strlen(text_ptr[i].lang);
+ lang_len = strlen(text_ptr[i].lang);
else
lang_len = 0;
if (text_ptr[i].lang_key != NULL)
- lang_key_len = png_strlen(text_ptr[i].lang_key);
+ lang_key_len = strlen(text_ptr[i].lang_key);
else
lang_key_len = 0;
}
-# else /* PNG_iTXt_SUPPORTED */
+# else /* iTXt */
{
- png_warning(png_ptr, "iTXt chunk not supported");
+ png_chunk_report(png_ptr, "iTXt chunk not supported",
+ PNG_CHUNK_WRITE_ERROR);
continue;
}
# endif
@@ -799,32 +830,36 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
else
{
- text_length = png_strlen(text_ptr[i].text);
+ text_length = strlen(text_ptr[i].text);
textp->compression = text_ptr[i].compression;
}
- textp->key = (png_charp)png_malloc_warn(png_ptr,
- (png_size_t)
- (key_len + text_length + lang_len + lang_key_len + 4));
+ textp->key = png_voidcast(png_charp,png_malloc_base(png_ptr,
+ key_len + text_length + lang_len + lang_key_len + 4));
if (textp->key == NULL)
- return(1);
+ {
+ png_chunk_report(png_ptr, "text chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+
+ return 1;
+ }
png_debug2(2, "Allocated %lu bytes at %p in png_set_text",
(unsigned long)(png_uint_32)
(key_len + lang_len + lang_key_len + text_length + 4),
textp->key);
- png_memcpy(textp->key, text_ptr[i].key,(png_size_t)(key_len));
+ memcpy(textp->key, text_ptr[i].key, key_len);
*(textp->key + key_len) = '\0';
if (text_ptr[i].compression > 0)
{
textp->lang = textp->key + key_len + 1;
- png_memcpy(textp->lang, text_ptr[i].lang, lang_len);
+ memcpy(textp->lang, text_ptr[i].lang, lang_len);
*(textp->lang + lang_len) = '\0';
textp->lang_key = textp->lang + lang_len + 1;
- png_memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
+ memcpy(textp->lang_key, text_ptr[i].lang_key, lang_key_len);
*(textp->lang_key + lang_key_len) = '\0';
textp->text = textp->lang_key + lang_key_len + 1;
}
@@ -836,9 +871,8 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
textp->text = textp->key + key_len + 1;
}
- if (text_length)
- png_memcpy(textp->text, text_ptr[i].text,
- (png_size_t)(text_length));
+ if (text_length != 0)
+ memcpy(textp->text, text_ptr[i].text, text_length);
*(textp->text + text_length) = '\0';
@@ -859,18 +893,20 @@ png_set_text_2(png_structp png_ptr, png_infop info_ptr,
info_ptr->num_text++;
png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
}
+
return(0);
}
#endif
#ifdef PNG_tIME_SUPPORTED
void PNGAPI
-png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
+png_set_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_const_timep mod_time)
{
png_debug1(1, "in %s storage function", "tIME");
- if (png_ptr == NULL || info_ptr == NULL ||
- (png_ptr->mode & PNG_WROTE_tIME))
+ if (png_ptr == NULL || info_ptr == NULL || mod_time == NULL ||
+ (png_ptr->mode & PNG_WROTE_tIME) != 0)
return;
if (mod_time->month == 0 || mod_time->month > 12 ||
@@ -879,22 +915,24 @@ png_set_tIME(png_structp png_ptr, png_infop info_ptr, png_const_timep mod_time)
mod_time->second > 60)
{
png_warning(png_ptr, "Ignoring invalid time value");
+
return;
}
- png_memcpy(&(info_ptr->mod_time), mod_time, png_sizeof(png_time));
+ info_ptr->mod_time = *mod_time;
info_ptr->valid |= PNG_INFO_tIME;
}
#endif
#ifdef PNG_tRNS_SUPPORTED
void PNGAPI
-png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
+png_set_tRNS(png_structrp png_ptr, png_inforp info_ptr,
png_const_bytep trans_alpha, int num_trans, png_const_color_16p trans_color)
{
png_debug1(1, "in %s storage function", "tRNS");
if (png_ptr == NULL || info_ptr == NULL)
+
return;
if (trans_alpha != NULL)
@@ -902,33 +940,41 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
/* It may not actually be necessary to set png_ptr->trans_alpha here;
* we do it for backward compatibility with the way the png_handle_tRNS
* function used to do the allocation.
+ *
+ * 1.6.0: The above statement is incorrect; png_handle_tRNS effectively
+ * relies on png_set_tRNS storing the information in png_struct
+ * (otherwise it won't be there for the code in pngrtran.c).
*/
png_free_data(png_ptr, info_ptr, PNG_FREE_TRNS, 0);
/* Changed from num_trans to PNG_MAX_PALETTE_LENGTH in version 1.2.1 */
- png_ptr->trans_alpha = info_ptr->trans_alpha =
- (png_bytep)png_malloc(png_ptr, (png_size_t)PNG_MAX_PALETTE_LENGTH);
+ png_ptr->trans_alpha = info_ptr->trans_alpha = png_voidcast(png_bytep,
+ png_malloc(png_ptr, PNG_MAX_PALETTE_LENGTH));
if (num_trans > 0 && num_trans <= PNG_MAX_PALETTE_LENGTH)
- png_memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
+ memcpy(info_ptr->trans_alpha, trans_alpha, (png_size_t)num_trans);
}
if (trans_color != NULL)
{
- int sample_max = (1 << info_ptr->bit_depth);
-
- if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
- (int)trans_color->gray > sample_max) ||
- (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
- ((int)trans_color->red > sample_max ||
- (int)trans_color->green > sample_max ||
- (int)trans_color->blue > sample_max)))
- png_warning(png_ptr,
- "tRNS chunk has out-of-range samples for bit_depth");
+#ifdef PNG_WARNINGS_SUPPORTED
+ if (info_ptr->bit_depth < 16)
+ {
+ int sample_max = (1 << info_ptr->bit_depth) - 1;
+
+ if ((info_ptr->color_type == PNG_COLOR_TYPE_GRAY &&
+ trans_color->gray > sample_max) ||
+ (info_ptr->color_type == PNG_COLOR_TYPE_RGB &&
+ (trans_color->red > sample_max ||
+ trans_color->green > sample_max ||
+ trans_color->blue > sample_max)))
+ png_warning(png_ptr,
+ "tRNS chunk has out-of-range samples for bit_depth");
+ }
+#endif
- png_memcpy(&(info_ptr->trans_color), trans_color,
- png_sizeof(png_color_16));
+ info_ptr->trans_color = *trans_color;
if (num_trans == 0)
num_trans = 1;
@@ -946,8 +992,8 @@ png_set_tRNS(png_structp png_ptr, png_infop info_ptr,
#ifdef PNG_sPLT_SUPPORTED
void PNGAPI
-png_set_sPLT(png_structp png_ptr,
- png_infop info_ptr, png_const_sPLT_tp entries, int nentries)
+png_set_sPLT(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_sPLT_tp entries, int nentries)
/*
* entries - array of png_sPLT_t structures
* to be added to the list of palettes
@@ -958,220 +1004,462 @@ png_set_sPLT(png_structp png_ptr,
*/
{
png_sPLT_tp np;
- int i;
- if (png_ptr == NULL || info_ptr == NULL)
+ if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
return;
- np = (png_sPLT_tp)png_malloc_warn(png_ptr,
- (info_ptr->splt_palettes_num + nentries) *
- (png_size_t)png_sizeof(png_sPLT_t));
+ /* Use the internal realloc function, which checks for all the possible
+ * overflows. Notice that the parameters are (int) and (size_t)
+ */
+ np = png_voidcast(png_sPLT_tp,png_realloc_array(png_ptr,
+ info_ptr->splt_palettes, info_ptr->splt_palettes_num, nentries,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr, "No memory for sPLT palettes");
+ /* Out of memory or too many chunks */
+ png_chunk_report(png_ptr, "too many sPLT chunks", PNG_CHUNK_WRITE_ERROR);
+
return;
}
- png_memcpy(np, info_ptr->splt_palettes,
- info_ptr->splt_palettes_num * png_sizeof(png_sPLT_t));
-
png_free(png_ptr, info_ptr->splt_palettes);
- info_ptr->splt_palettes=NULL;
+ info_ptr->splt_palettes = np;
+ info_ptr->free_me |= PNG_FREE_SPLT;
- for (i = 0; i < nentries; i++)
+ np += info_ptr->splt_palettes_num;
+
+ do
{
- png_sPLT_tp to = np + info_ptr->splt_palettes_num + i;
- png_const_sPLT_tp from = entries + i;
png_size_t length;
- length = png_strlen(from->name) + 1;
- to->name = (png_charp)png_malloc_warn(png_ptr, length);
-
- if (to->name == NULL)
+ /* Skip invalid input entries */
+ if (entries->name == NULL || entries->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
+ /* png_handle_sPLT doesn't do this, so this is an app error */
+ png_app_error(png_ptr, "png_set_sPLT: invalid sPLT");
+ /* Just skip the invalid entry */
continue;
}
- png_memcpy(to->name, from->name, length);
- to->entries = (png_sPLT_entryp)png_malloc_warn(png_ptr,
- from->nentries * png_sizeof(png_sPLT_entry));
+ np->depth = entries->depth;
+
+ /* In the event of out-of-memory just return - there's no point keeping
+ * on trying to add sPLT chunks.
+ */
+ length = strlen(entries->name) + 1;
+ np->name = png_voidcast(png_charp, png_malloc_base(png_ptr, length));
+
+ if (np->name == NULL)
+ break;
+
+ memcpy(np->name, entries->name, length);
- if (to->entries == NULL)
+ /* IMPORTANT: we have memory now that won't get freed if something else
+ * goes wrong; this code must free it. png_malloc_array produces no
+ * warnings; use a png_chunk_report (below) if there is an error.
+ */
+ np->entries = png_voidcast(png_sPLT_entryp, png_malloc_array(png_ptr,
+ entries->nentries, sizeof (png_sPLT_entry)));
+
+ if (np->entries == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing sPLT chunk");
- png_free(png_ptr, to->name);
- to->name = NULL;
- continue;
+ png_free(png_ptr, np->name);
+ np->name = NULL;
+ break;
}
- png_memcpy(to->entries, from->entries,
- from->nentries * png_sizeof(png_sPLT_entry));
+ np->nentries = entries->nentries;
+ /* This multiply can't overflow because png_malloc_array has already
+ * checked it when doing the allocation.
+ */
+ memcpy(np->entries, entries->entries,
+ entries->nentries * sizeof (png_sPLT_entry));
+
+ /* Note that 'continue' skips the advance of the out pointer and out
+ * count, so an invalid entry is not added.
+ */
+ info_ptr->valid |= PNG_INFO_sPLT;
+ ++(info_ptr->splt_palettes_num);
+ ++np;
+ }
+ while (++entries, --nentries);
+
+ if (nentries > 0)
+ png_chunk_report(png_ptr, "sPLT out of memory", PNG_CHUNK_WRITE_ERROR);
+}
+#endif /* sPLT */
+
+#ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+static png_byte
+check_location(png_const_structrp png_ptr, int location)
+{
+ location &= (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT);
- to->nentries = from->nentries;
- to->depth = from->depth;
+ /* New in 1.6.0; copy the location and check it. This is an API
+ * change; previously the app had to use the
+ * png_set_unknown_chunk_location API below for each chunk.
+ */
+ if (location == 0 && (png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ /* Write struct, so unknown chunks come from the app */
+ png_app_warning(png_ptr,
+ "png_set_unknown_chunks now expects a valid location");
+ /* Use the old behavior */
+ location = (png_byte)(png_ptr->mode &
+ (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT));
}
- info_ptr->splt_palettes = np;
- info_ptr->splt_palettes_num += nentries;
- info_ptr->valid |= PNG_INFO_sPLT;
- info_ptr->free_me |= PNG_FREE_SPLT;
+ /* This need not be an internal error - if the app calls
+ * png_set_unknown_chunks on a read pointer it must get the location right.
+ */
+ if (location == 0)
+ png_error(png_ptr, "invalid location in png_set_unknown_chunks");
+
+ /* Now reduce the location to the top-most set bit by removing each least
+ * significant bit in turn.
+ */
+ while (location != (location & -location))
+ location &= ~(location & -location);
+
+ /* The cast is safe because 'location' is a bit mask and only the low four
+ * bits are significant.
+ */
+ return (png_byte)location;
}
-#endif /* PNG_sPLT_SUPPORTED */
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
void PNGAPI
-png_set_unknown_chunks(png_structp png_ptr,
- png_infop info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
+png_set_unknown_chunks(png_const_structrp png_ptr,
+ png_inforp info_ptr, png_const_unknown_chunkp unknowns, int num_unknowns)
{
png_unknown_chunkp np;
- int i;
- if (png_ptr == NULL || info_ptr == NULL || num_unknowns == 0)
+ if (png_ptr == NULL || info_ptr == NULL || num_unknowns <= 0 ||
+ unknowns == NULL)
return;
- np = (png_unknown_chunkp)png_malloc_warn(png_ptr,
- (png_size_t)(info_ptr->unknown_chunks_num + num_unknowns) *
- png_sizeof(png_unknown_chunk));
+ /* Check for the failure cases where support has been disabled at compile
+ * time. This code is hardly ever compiled - it's here because
+ * STORE_UNKNOWN_CHUNKS is set by both read and write code (compiling in this
+ * code) but may be meaningless if the read or write handling of unknown
+ * chunks is not compiled in.
+ */
+# if !defined(PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_READ_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on read");
+
+ return;
+ }
+# endif
+# if !defined(PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED) && \
+ defined(PNG_WRITE_SUPPORTED)
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ png_app_error(png_ptr, "no unknown chunk support on write");
+
+ return;
+ }
+# endif
+
+ /* Prior to 1.6.0 this code used png_malloc_warn; however, this meant that
+ * unknown critical chunks could be lost with just a warning resulting in
+ * undefined behavior. Now png_chunk_report is used to provide behavior
+ * appropriate to read or write.
+ */
+ np = png_voidcast(png_unknown_chunkp, png_realloc_array(png_ptr,
+ info_ptr->unknown_chunks, info_ptr->unknown_chunks_num, num_unknowns,
+ sizeof *np));
if (np == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
+ png_chunk_report(png_ptr, "too many unknown chunks",
+ PNG_CHUNK_WRITE_ERROR);
+
return;
}
- png_memcpy(np, info_ptr->unknown_chunks,
- (png_size_t)info_ptr->unknown_chunks_num *
- png_sizeof(png_unknown_chunk));
-
png_free(png_ptr, info_ptr->unknown_chunks);
- info_ptr->unknown_chunks = NULL;
-
- for (i = 0; i < num_unknowns; i++)
- {
- png_unknown_chunkp to = np + info_ptr->unknown_chunks_num + i;
- png_const_unknown_chunkp from = unknowns + i;
+ info_ptr->unknown_chunks = np; /* safe because it is initialized */
+ info_ptr->free_me |= PNG_FREE_UNKN;
- png_memcpy(to->name, from->name, png_sizeof(from->name));
- to->name[png_sizeof(to->name)-1] = '\0';
- to->size = from->size;
+ np += info_ptr->unknown_chunks_num;
- /* Note our location in the read or write sequence */
- to->location = (png_byte)(png_ptr->mode & 0xff);
+ /* Increment unknown_chunks_num each time round the loop to protect the
+ * just-allocated chunk data.
+ */
+ for (; num_unknowns > 0; --num_unknowns, ++unknowns)
+ {
+ memcpy(np->name, unknowns->name, (sizeof np->name));
+ np->name[(sizeof np->name)-1] = '\0';
+ np->location = check_location(png_ptr, unknowns->location);
- if (from->size == 0)
- to->data=NULL;
+ if (unknowns->size == 0)
+ {
+ np->data = NULL;
+ np->size = 0;
+ }
else
{
- to->data = (png_bytep)png_malloc_warn(png_ptr,
- (png_size_t)from->size);
+ np->data = png_voidcast(png_bytep,
+ png_malloc_base(png_ptr, unknowns->size));
- if (to->data == NULL)
+ if (np->data == NULL)
{
- png_warning(png_ptr,
- "Out of memory while processing unknown chunk");
- to->size = 0;
+ png_chunk_report(png_ptr, "unknown chunk: out of memory",
+ PNG_CHUNK_WRITE_ERROR);
+ /* But just skip storing the unknown chunk */
+ continue;
}
- else
- png_memcpy(to->data, from->data, from->size);
+ memcpy(np->data, unknowns->data, unknowns->size);
+ np->size = unknowns->size;
}
- }
- info_ptr->unknown_chunks = np;
- info_ptr->unknown_chunks_num += num_unknowns;
- info_ptr->free_me |= PNG_FREE_UNKN;
+ /* These increments are skipped on out-of-memory for the data - the
+ * unknown chunk entry gets overwritten if the png_chunk_report returns.
+ * This is correct in the read case (the chunk is just dropped.)
+ */
+ ++np;
+ ++(info_ptr->unknown_chunks_num);
+ }
}
void PNGAPI
-png_set_unknown_chunk_location(png_structp png_ptr, png_infop info_ptr,
+png_set_unknown_chunk_location(png_const_structrp png_ptr, png_inforp info_ptr,
int chunk, int location)
{
- if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 && chunk <
- info_ptr->unknown_chunks_num)
- info_ptr->unknown_chunks[chunk].location = (png_byte)location;
-}
-#endif
+ /* This API is pretty pointless in 1.6.0 because the location can be set
+ * before the call to png_set_unknown_chunks.
+ *
+ * TODO: add a png_app_warning in 1.7
+ */
+ if (png_ptr != NULL && info_ptr != NULL && chunk >= 0 &&
+ chunk < info_ptr->unknown_chunks_num)
+ {
+ if ((location & (PNG_HAVE_IHDR|PNG_HAVE_PLTE|PNG_AFTER_IDAT)) == 0)
+ {
+ png_app_error(png_ptr, "invalid unknown chunk location");
+ /* Fake out the pre 1.6.0 behavior: */
+ if ((location & PNG_HAVE_IDAT) != 0) /* undocumented! */
+ location = PNG_AFTER_IDAT;
+
+ else
+ location = PNG_HAVE_IHDR; /* also undocumented */
+ }
+ info_ptr->unknown_chunks[chunk].location =
+ check_location(png_ptr, location);
+ }
+}
+#endif /* STORE_UNKNOWN_CHUNKS */
#ifdef PNG_MNG_FEATURES_SUPPORTED
png_uint_32 PNGAPI
-png_permit_mng_features (png_structp png_ptr, png_uint_32 mng_features)
+png_permit_mng_features (png_structrp png_ptr, png_uint_32 mng_features)
{
png_debug(1, "in png_permit_mng_features");
if (png_ptr == NULL)
- return (png_uint_32)0;
+ return 0;
- png_ptr->mng_features_permitted =
- (png_byte)(mng_features & PNG_ALL_MNG_FEATURES);
+ png_ptr->mng_features_permitted = mng_features & PNG_ALL_MNG_FEATURES;
- return (png_uint_32)png_ptr->mng_features_permitted;
+ return png_ptr->mng_features_permitted;
}
#endif
#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
+static unsigned int
+add_one_chunk(png_bytep list, unsigned int count, png_const_bytep add, int keep)
+{
+ unsigned int i;
+
+ /* Utility function: update the 'keep' state of a chunk if it is already in
+ * the list, otherwise add it to the list.
+ */
+ for (i=0; i<count; ++i, list += 5)
+ {
+ if (memcmp(list, add, 4) == 0)
+ {
+ list[4] = (png_byte)keep;
+
+ return count;
+ }
+ }
+
+ if (keep != PNG_HANDLE_CHUNK_AS_DEFAULT)
+ {
+ ++count;
+ memcpy(list, add, 4);
+ list[4] = (png_byte)keep;
+ }
+
+ return count;
+}
+
void PNGAPI
-png_set_keep_unknown_chunks(png_structp png_ptr, int keep, png_const_bytep
- chunk_list, int num_chunks)
+png_set_keep_unknown_chunks(png_structrp png_ptr, int keep,
+ png_const_bytep chunk_list, int num_chunks_in)
{
- png_bytep new_list, p;
- int i, old_num_chunks;
+ png_bytep new_list;
+ unsigned int num_chunks, old_num_chunks;
+
if (png_ptr == NULL)
return;
- if (num_chunks == 0)
+ if (keep < 0 || keep >= PNG_HANDLE_CHUNK_LAST)
{
- if (keep == PNG_HANDLE_CHUNK_ALWAYS || keep == PNG_HANDLE_CHUNK_IF_SAFE)
- png_ptr->flags |= PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: invalid keep");
- else
- png_ptr->flags &= ~PNG_FLAG_KEEP_UNKNOWN_CHUNKS;
+ return;
+ }
- if (keep == PNG_HANDLE_CHUNK_ALWAYS)
- png_ptr->flags |= PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ if (num_chunks_in <= 0)
+ {
+ png_ptr->unknown_default = keep;
- else
- png_ptr->flags &= ~PNG_FLAG_KEEP_UNSAFE_CHUNKS;
+ /* '0' means just set the flags, so stop here */
+ if (num_chunks_in == 0)
+ return;
+ }
- return;
+ if (num_chunks_in < 0)
+ {
+ /* Ignore all unknown chunks and all chunks recognized by
+ * libpng except for IHDR, PLTE, tRNS, IDAT, and IEND
+ */
+ static PNG_CONST png_byte chunks_to_ignore[] = {
+ 98, 75, 71, 68, '\0', /* bKGD */
+ 99, 72, 82, 77, '\0', /* cHRM */
+ 103, 65, 77, 65, '\0', /* gAMA */
+ 104, 73, 83, 84, '\0', /* hIST */
+ 105, 67, 67, 80, '\0', /* iCCP */
+ 105, 84, 88, 116, '\0', /* iTXt */
+ 111, 70, 70, 115, '\0', /* oFFs */
+ 112, 67, 65, 76, '\0', /* pCAL */
+ 112, 72, 89, 115, '\0', /* pHYs */
+ 115, 66, 73, 84, '\0', /* sBIT */
+ 115, 67, 65, 76, '\0', /* sCAL */
+ 115, 80, 76, 84, '\0', /* sPLT */
+ 115, 84, 69, 82, '\0', /* sTER */
+ 115, 82, 71, 66, '\0', /* sRGB */
+ 116, 69, 88, 116, '\0', /* tEXt */
+ 116, 73, 77, 69, '\0', /* tIME */
+ 122, 84, 88, 116, '\0' /* zTXt */
+ };
+
+ chunk_list = chunks_to_ignore;
+ num_chunks = (unsigned int)/*SAFE*/(sizeof chunks_to_ignore)/5U;
}
- if (chunk_list == NULL)
- return;
+ else /* num_chunks_in > 0 */
+ {
+ if (chunk_list == NULL)
+ {
+ /* Prior to 1.6.0 this was silently ignored, now it is an app_error
+ * which can be switched off.
+ */
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: no chunk list");
+
+ return;
+ }
+
+ num_chunks = num_chunks_in;
+ }
old_num_chunks = png_ptr->num_chunk_list;
- new_list=(png_bytep)png_malloc(png_ptr,
- (png_size_t)(5*(num_chunks + old_num_chunks)));
+ if (png_ptr->chunk_list == NULL)
+ old_num_chunks = 0;
+
+ /* Since num_chunks is always restricted to UINT_MAX/5 this can't overflow.
+ */
+ if (num_chunks + old_num_chunks > UINT_MAX/5)
+ {
+ png_app_error(png_ptr, "png_set_keep_unknown_chunks: too many chunks");
+
+ return;
+ }
- if (png_ptr->chunk_list != NULL)
+ /* If these chunks are being reset to the default then no more memory is
+ * required because add_one_chunk above doesn't extend the list if the 'keep'
+ * parameter is the default.
+ */
+ if (keep != 0)
{
- png_memcpy(new_list, png_ptr->chunk_list,
- (png_size_t)(5*old_num_chunks));
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->chunk_list=NULL;
+ new_list = png_voidcast(png_bytep, png_malloc(png_ptr,
+ 5 * (num_chunks + old_num_chunks)));
+
+ if (old_num_chunks > 0)
+ memcpy(new_list, png_ptr->chunk_list, 5*old_num_chunks);
}
- png_memcpy(new_list + 5*old_num_chunks, chunk_list,
- (png_size_t)(5*num_chunks));
+ else if (old_num_chunks > 0)
+ new_list = png_ptr->chunk_list;
+
+ else
+ new_list = NULL;
+
+ /* Add the new chunks together with each one's handling code. If the chunk
+ * already exists the code is updated, otherwise the chunk is added to the
+ * end. (In libpng 1.6.0 order no longer matters because this code enforces
+ * the earlier convention that the last setting is the one that is used.)
+ */
+ if (new_list != NULL)
+ {
+ png_const_bytep inlist;
+ png_bytep outlist;
+ unsigned int i;
+
+ for (i=0; i<num_chunks; ++i)
+ {
+ old_num_chunks = add_one_chunk(new_list, old_num_chunks,
+ chunk_list+5*i, keep);
+ }
- for (p = new_list + 5*old_num_chunks + 4, i = 0; i<num_chunks; i++, p += 5)
- *p=(png_byte)keep;
+ /* Now remove any spurious 'default' entries. */
+ num_chunks = 0;
+ for (i=0, inlist=outlist=new_list; i<old_num_chunks; ++i, inlist += 5)
+ {
+ if (inlist[4])
+ {
+ if (outlist != inlist)
+ memcpy(outlist, inlist, 5);
+ outlist += 5;
+ ++num_chunks;
+ }
+ }
+
+ /* This means the application has removed all the specialized handling. */
+ if (num_chunks == 0)
+ {
+ if (png_ptr->chunk_list != new_list)
+ png_free(png_ptr, new_list);
+
+ new_list = NULL;
+ }
+ }
+
+ else
+ num_chunks = 0;
+
+ png_ptr->num_chunk_list = num_chunks;
+
+ if (png_ptr->chunk_list != new_list)
+ {
+ if (png_ptr->chunk_list != NULL)
+ png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->num_chunk_list = old_num_chunks + num_chunks;
- png_ptr->chunk_list = new_list;
- png_ptr->free_me |= PNG_FREE_LIST;
+ png_ptr->chunk_list = new_list;
+ }
}
#endif
#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
void PNGAPI
-png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
+png_set_read_user_chunk_fn(png_structrp png_ptr, png_voidp user_chunk_ptr,
png_user_chunk_ptr read_user_chunk_fn)
{
png_debug(1, "in png_set_read_user_chunk_fn");
@@ -1186,64 +1474,94 @@ png_set_read_user_chunk_fn(png_structp png_ptr, png_voidp user_chunk_ptr,
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_set_rows(png_structp png_ptr, png_infop info_ptr, png_bytepp row_pointers)
+png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
+ png_bytepp row_pointers)
{
png_debug1(1, "in %s storage function", "rows");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (info_ptr->row_pointers && (info_ptr->row_pointers != row_pointers))
+ if (info_ptr->row_pointers != NULL &&
+ (info_ptr->row_pointers != row_pointers))
png_free_data(png_ptr, info_ptr, PNG_FREE_ROWS, 0);
info_ptr->row_pointers = row_pointers;
- if (row_pointers)
+ if (row_pointers != NULL)
info_ptr->valid |= PNG_INFO_IDAT;
}
#endif
void PNGAPI
-png_set_compression_buffer_size(png_structp png_ptr, png_size_t size)
+png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size)
{
if (png_ptr == NULL)
return;
- png_free(png_ptr, png_ptr->zbuf);
+ if (size == 0 || size > PNG_UINT_31_MAX)
+ png_error(png_ptr, "invalid compression buffer size");
- if (size > ZLIB_IO_MAX)
- {
- png_warning(png_ptr, "Attempt to set buffer size beyond max ignored");
- png_ptr->zbuf_size = ZLIB_IO_MAX;
- size = ZLIB_IO_MAX; /* must fit */
- }
+# ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+ png_ptr->IDAT_read_size = (png_uint_32)size; /* checked above */
+ return;
+ }
+# endif
- else
- png_ptr->zbuf_size = (uInt)size;
+# ifdef PNG_WRITE_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) == 0)
+ {
+ if (png_ptr->zowner != 0)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size cannot be changed because it is in use");
- png_ptr->zbuf = (png_bytep)png_malloc(png_ptr, size);
+ return;
+ }
- /* The following ensures a relatively safe failure if this gets called while
- * the buffer is actually in use.
- */
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = 0;
- png_ptr->zstream.avail_in = 0;
+#ifndef __COVERITY__
+ if (size > ZLIB_IO_MAX)
+ {
+ png_warning(png_ptr,
+ "Compression buffer size limited to system maximum");
+ size = ZLIB_IO_MAX; /* must fit */
+ }
+#endif
+
+ if (size < 6)
+ {
+ /* Deflate will potentially go into an infinite loop on a SYNC_FLUSH
+ * if this is permitted.
+ */
+ png_warning(png_ptr,
+ "Compression buffer size cannot be reduced below 6");
+
+ return;
+ }
+
+ if (png_ptr->zbuffer_size != size)
+ {
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
+ png_ptr->zbuffer_size = (uInt)size;
+ }
+ }
+# endif
}
void PNGAPI
-png_set_invalid(png_structp png_ptr, png_infop info_ptr, int mask)
+png_set_invalid(png_const_structrp png_ptr, png_inforp info_ptr, int mask)
{
- if (png_ptr && info_ptr)
+ if (png_ptr != NULL && info_ptr != NULL)
info_ptr->valid &= ~mask;
}
-
#ifdef PNG_SET_USER_LIMITS_SUPPORTED
/* This function was added to libpng 1.2.6 */
void PNGAPI
-png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
+png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max,
png_uint_32 user_height_max)
{
/* Images with dimensions larger than these limits will be
@@ -1259,51 +1577,64 @@ png_set_user_limits (png_structp png_ptr, png_uint_32 user_width_max,
/* This function was added to libpng 1.4.0 */
void PNGAPI
-png_set_chunk_cache_max (png_structp png_ptr,
- png_uint_32 user_chunk_cache_max)
+png_set_chunk_cache_max (png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
{
- if (png_ptr)
- png_ptr->user_chunk_cache_max = user_chunk_cache_max;
+ if (png_ptr != NULL)
+ png_ptr->user_chunk_cache_max = user_chunk_cache_max;
}
/* This function was added to libpng 1.4.1 */
void PNGAPI
-png_set_chunk_malloc_max (png_structp png_ptr,
+png_set_chunk_malloc_max (png_structrp png_ptr,
png_alloc_size_t user_chunk_malloc_max)
{
- if (png_ptr)
+ if (png_ptr != NULL)
png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
}
-#endif /* ?PNG_SET_USER_LIMITS_SUPPORTED */
+#endif /* ?SET_USER_LIMITS */
#ifdef PNG_BENIGN_ERRORS_SUPPORTED
void PNGAPI
-png_set_benign_errors(png_structp png_ptr, int allowed)
+png_set_benign_errors(png_structrp png_ptr, int allowed)
{
png_debug(1, "in png_set_benign_errors");
- if (allowed)
- png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
+ /* If allowed is 1, png_benign_error() is treated as a warning.
+ *
+ * If allowed is 0, png_benign_error() is treated as an error (which
+ * is the default behavior if png_set_benign_errors() is not called).
+ */
+
+ if (allowed != 0)
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN;
else
- png_ptr->flags &= ~PNG_FLAG_BENIGN_ERRORS_WARN;
+ png_ptr->flags &= ~(PNG_FLAG_BENIGN_ERRORS_WARN |
+ PNG_FLAG_APP_WARNINGS_WARN | PNG_FLAG_APP_ERRORS_WARN);
}
-#endif /* PNG_BENIGN_ERRORS_SUPPORTED */
-
-#ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
- /* Do not report invalid palette index; added at libng-1.5.10 */
+#endif /* BENIGN_ERRORS */
+
+#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ /* Whether to report invalid palette index; added at libng-1.5.10.
+ * It is possible for an indexed (color-type==3) PNG file to contain
+ * pixels with invalid (out-of-range) indexes if the PLTE chunk has
+ * fewer entries than the image's bit-depth would allow. We recover
+ * from this gracefully by filling any incomplete palette with zeros
+ * (opaque black). By default, when this occurs libpng will issue
+ * a benign error. This API can be used to override that behavior.
+ */
void PNGAPI
-png_set_check_for_invalid_index(png_structp png_ptr, int allowed)
+png_set_check_for_invalid_index(png_structrp png_ptr, int allowed)
{
png_debug(1, "in png_set_check_for_invalid_index");
- if (allowed)
+ if (allowed > 0)
png_ptr->num_palette_max = 0;
else
png_ptr->num_palette_max = -1;
}
#endif
-
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h
index 43a45cdec6..8420d09972 100644
--- a/src/3rdparty/libpng/pngstruct.h
+++ b/src/3rdparty/libpng/pngstruct.h
@@ -1,12 +1,11 @@
/* pngstruct.h - header file for PNG reference library
*
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.1 [March 28, 2013]
+ * Copyright (c) 1998-2013 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
- * Last changed in libpng 1.5.9 [March 29, 2012]
- *
* This code is released under the libpng license.
* For conditions of distribution and use, see the disclaimer
* and license in png.h
@@ -24,13 +23,130 @@
* in this structure and is required for decompressing the LZ compressed
* data in PNG files.
*/
+#ifndef ZLIB_CONST
+ /* We must ensure that zlib uses 'const' in declarations. */
+# define ZLIB_CONST
+#endif
#include "zlib.h"
+#ifdef const
+ /* zlib.h sometimes #defines const to nothing, undo this. */
+# undef const
+#endif
+
+/* zlib.h has mediocre z_const use before 1.2.6, this stuff is for compatibility
+ * with older builds.
+ */
+#if ZLIB_VERNUM < 0x1260
+# define PNGZ_MSG_CAST(s) png_constcast(char*,s)
+# define PNGZ_INPUT_CAST(b) png_constcast(png_bytep,b)
+#else
+# define PNGZ_MSG_CAST(s) (s)
+# define PNGZ_INPUT_CAST(b) (b)
+#endif
+
+/* zlib.h declares a magic type 'uInt' that limits the amount of data that zlib
+ * can handle at once. This type need be no larger than 16 bits (so maximum of
+ * 65535), this define allows us to discover how big it is, but limited by the
+ * maximuum for png_size_t. The value can be overriden in a library build
+ * (pngusr.h, or set it in CPPFLAGS) and it works to set it to a considerably
+ * lower value (e.g. 255 works). A lower value may help memory usage (slightly)
+ * and may even improve performance on some systems (and degrade it on others.)
+ */
+#ifndef ZLIB_IO_MAX
+# define ZLIB_IO_MAX ((uInt)-1)
+#endif
+
+#ifdef PNG_WRITE_SUPPORTED
+/* The type of a compression buffer list used by the write code. */
+typedef struct png_compression_buffer
+{
+ struct png_compression_buffer *next;
+ png_byte output[1]; /* actually zbuf_size */
+} png_compression_buffer, *png_compression_bufferp;
+
+#define PNG_COMPRESSION_BUFFER_SIZE(pp)\
+ (offsetof(png_compression_buffer, output) + (pp)->zbuffer_size)
+#endif
+
+/* Colorspace support; structures used in png_struct, png_info and in internal
+ * functions to hold and communicate information about the color space.
+ *
+ * PNG_COLORSPACE_SUPPORTED is only required if the application will perform
+ * colorspace corrections, otherwise all the colorspace information can be
+ * skipped and the size of libpng can be reduced (significantly) by compiling
+ * out the colorspace support.
+ */
+#ifdef PNG_COLORSPACE_SUPPORTED
+/* The chromaticities of the red, green and blue colorants and the chromaticity
+ * of the corresponding white point (i.e. of rgb(1.0,1.0,1.0)).
+ */
+typedef struct png_xy
+{
+ png_fixed_point redx, redy;
+ png_fixed_point greenx, greeny;
+ png_fixed_point bluex, bluey;
+ png_fixed_point whitex, whitey;
+} png_xy;
+
+/* The same data as above but encoded as CIE XYZ values. When this data comes
+ * from chromaticities the sum of the Y values is assumed to be 1.0
+ */
+typedef struct png_XYZ
+{
+ png_fixed_point red_X, red_Y, red_Z;
+ png_fixed_point green_X, green_Y, green_Z;
+ png_fixed_point blue_X, blue_Y, blue_Z;
+} png_XYZ;
+#endif /* COLORSPACE */
+
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+/* A colorspace is all the above plus, potentially, profile information;
+ * however at present libpng does not use the profile internally so it is only
+ * stored in the png_info struct (if iCCP is supported.) The rendering intent
+ * is retained here and is checked.
+ *
+ * The file gamma encoding information is also stored here and gamma correction
+ * is done by libpng, whereas color correction must currently be done by the
+ * application.
+ */
+typedef struct png_colorspace
+{
+#ifdef PNG_GAMMA_SUPPORTED
+ png_fixed_point gamma; /* File gamma */
+#endif
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+ png_xy end_points_xy; /* End points as chromaticities */
+ png_XYZ end_points_XYZ; /* End points as CIE XYZ colorant values */
+ png_uint_16 rendering_intent; /* Rendering intent of a profile */
+#endif
+
+ /* Flags are always defined to simplify the code. */
+ png_uint_16 flags; /* As defined below */
+} png_colorspace, * PNG_RESTRICT png_colorspacerp;
+
+typedef const png_colorspace * PNG_RESTRICT png_const_colorspacerp;
+
+/* General flags for the 'flags' field */
+#define PNG_COLORSPACE_HAVE_GAMMA 0x0001
+#define PNG_COLORSPACE_HAVE_ENDPOINTS 0x0002
+#define PNG_COLORSPACE_HAVE_INTENT 0x0004
+#define PNG_COLORSPACE_FROM_gAMA 0x0008
+#define PNG_COLORSPACE_FROM_cHRM 0x0010
+#define PNG_COLORSPACE_FROM_sRGB 0x0020
+#define PNG_COLORSPACE_ENDPOINTS_MATCH_sRGB 0x0040
+#define PNG_COLORSPACE_MATCHES_sRGB 0x0080 /* exact match on profile */
+#define PNG_COLORSPACE_INVALID 0x8000
+#define PNG_COLORSPACE_CANCEL(flags) (0xffff ^ (flags))
+#endif /* COLORSPACE || GAMMA */
struct png_struct_def
{
#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf longjmp_buffer; /* used in png_error */
+ jmp_buf jmp_buf_local; /* New name in 1.6.0 for jmp_buf in png_struct */
png_longjmp_ptr longjmp_fn;/* setjmp non-local goto function. */
+ jmp_buf *jmp_buf_ptr; /* passed to longjmp_fn */
+ size_t jmp_buf_size; /* size of the above, if allocated */
#endif
png_error_ptr error_fn; /* function for printing errors and aborting */
#ifdef PNG_WARNINGS_SUPPORTED
@@ -63,22 +179,12 @@ struct png_struct_def
png_uint_32 flags; /* flags indicating various things to libpng */
png_uint_32 transformations; /* which transformations to perform */
- z_stream zstream; /* pointer to decompression structure (below) */
- png_bytep zbuf; /* buffer for zlib */
- uInt zbuf_size; /* size of zbuf (typically 65536) */
-#ifdef PNG_WRITE_SUPPORTED
+ png_uint_32 zowner; /* ID (chunk type) of zstream owner, 0 if none */
+ z_stream zstream; /* decompression structure */
-/* Added in 1.5.4: state to keep track of whether the zstream has been
- * initialized and if so whether it is for IDAT or some other chunk.
- */
-#define PNG_ZLIB_UNINITIALIZED 0
-#define PNG_ZLIB_FOR_IDAT 1
-#define PNG_ZLIB_FOR_TEXT 2 /* anything other than IDAT */
-#define PNG_ZLIB_USE_MASK 3 /* bottom two bits */
-#define PNG_ZLIB_IN_USE 4 /* a flag value */
-
- png_uint_32 zlib_state; /* State of zlib initialization */
-/* End of material added at libpng 1.5.4 */
+#ifdef PNG_WRITE_SUPPORTED
+ png_compression_bufferp zbuffer_list; /* Created on demand during write */
+ uInt zbuffer_size; /* size of the actual buffer */
int zlib_level; /* holds zlib compression level */
int zlib_method; /* holds zlib compression method */
@@ -87,8 +193,7 @@ struct png_struct_def
int zlib_strategy; /* holds zlib compression strategy */
#endif
/* Added at libpng 1.5.4 */
-#if defined(PNG_WRITE_COMPRESSED_TEXT_SUPPORTED) || \
- defined(PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED)
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
int zlib_text_level; /* holds zlib compression level */
int zlib_text_method; /* holds zlib compression method */
int zlib_text_window_bits; /* holds zlib compression window bits */
@@ -96,6 +201,14 @@ struct png_struct_def
int zlib_text_strategy; /* holds zlib compression strategy */
#endif
/* End of material added at libpng 1.5.4 */
+/* Added at libpng 1.6.0 */
+#ifdef PNG_WRITE_SUPPORTED
+ int zlib_set_level; /* Actual values set into the zstream on write */
+ int zlib_set_method;
+ int zlib_set_window_bits;
+ int zlib_set_mem_level;
+ int zlib_set_strategy;
+#endif
png_uint_32 width; /* width of image in pixels */
png_uint_32 height; /* height of image in pixels */
@@ -111,10 +224,12 @@ struct png_struct_def
png_bytep row_buf; /* buffer to save current (unfiltered) row.
* This is a pointer into big_row_buf
*/
+#ifdef PNG_WRITE_SUPPORTED
png_bytep sub_row; /* buffer to save "sub" row when filtering */
png_bytep up_row; /* buffer to save "up" row when filtering */
png_bytep avg_row; /* buffer to save "avg" row when filtering */
png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */
+#endif
png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */
png_uint_32 idat_size; /* current IDAT size for read */
@@ -138,15 +253,14 @@ struct png_struct_def
png_byte usr_bit_depth; /* bit depth of users row: write only */
png_byte pixel_depth; /* number of bits per pixel */
png_byte channels; /* number of channels in file */
+#ifdef PNG_WRITE_SUPPORTED
png_byte usr_channels; /* channels at start of write: write only */
+#endif
png_byte sig_bytes; /* magic bytes read/written from start of file */
png_byte maximum_pixel_depth;
/* pixel depth used for the row buffers */
png_byte transformed_pixel_depth;
/* pixel depth after read/write transforms */
- png_byte io_chunk_string[5];
- /* string name of chunk */
-
#if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED)
png_uint_16 filler; /* filler bytes for pixel expansion */
#endif
@@ -159,7 +273,7 @@ struct png_struct_def
#ifdef PNG_READ_GAMMA_SUPPORTED
png_color_16 background_1; /* background normalized to gamma 1.0 */
#endif
-#endif /* PNG_bKGD_SUPPORTED */
+#endif /* bKGD */
#ifdef PNG_WRITE_FLUSH_SUPPORTED
png_flush_ptr output_flush_fn; /* Function for flushing output */
@@ -169,7 +283,6 @@ struct png_struct_def
#ifdef PNG_READ_GAMMA_SUPPORTED
int gamma_shift; /* number of "insignificant" bits in 16-bit gamma */
- png_fixed_point gamma; /* file gamma value */
png_fixed_point screen_gamma; /* screen gamma value (display_exponent) */
png_bytep gamma_table; /* gamma table for 8-bit depth files */
@@ -217,7 +330,7 @@ struct png_struct_def
int process_mode; /* what push library is currently doing */
int cur_palette; /* current push library palette index */
-#endif /* PNG_PROGRESSIVE_READ_SUPPORTED */
+#endif /* PROGRESSIVE_READ */
#if defined(__TURBOC__) && !defined(_Windows) && !defined(__FLAT__)
/* For the Borland special 64K segment handler */
@@ -233,10 +346,6 @@ struct png_struct_def
png_bytep quantize_index; /* index translation for palette files */
#endif
-#if defined(PNG_READ_QUANTIZE_SUPPORTED) || defined(PNG_hIST_SUPPORTED)
- png_uint_16p hist; /* histogram */
-#endif
-
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
png_byte heuristic_method; /* heuristic for row filter selection */
png_byte num_prev_filters; /* number of weights for previous rows */
@@ -247,9 +356,17 @@ struct png_struct_def
png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */
#endif
+ /* Options */
+#ifdef PNG_SET_OPTION_SUPPORTED
+ png_byte options; /* On/off state (up to 4 options) */
+#endif
+
+#if PNG_LIBPNG_VER < 10700
+/* To do: remove this from libpng-1.7 */
#ifdef PNG_TIME_RFC1123_SUPPORTED
char time_buffer[29]; /* String to hold RFC 1123 time text */
#endif
+#endif
/* New members added in libpng-1.0.6 */
@@ -257,17 +374,16 @@ struct png_struct_def
#ifdef PNG_USER_CHUNKS_SUPPORTED
png_voidp user_chunk_ptr;
+#ifdef PNG_READ_USER_CHUNKS_SUPPORTED
png_user_chunk_ptr read_user_chunk_fn; /* user read chunk handler */
#endif
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- int num_chunk_list;
- png_bytep chunk_list;
#endif
-#ifdef PNG_READ_sRGB_SUPPORTED
- /* Added in 1.5.5 to record an sRGB chunk in the png. */
- png_byte is_sRGB;
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int unknown_default; /* As PNG_HANDLE_* */
+ unsigned int num_chunk_list; /* Number of entries in the list */
+ png_bytep chunk_list; /* List of png_byte[5]; the textual chunk name
+ * followed by a PNG_HANDLE_* byte */
#endif
/* New members added in libpng-1.0.3 */
@@ -332,16 +448,24 @@ struct png_struct_def
#endif
/* New member added in libpng-1.0.25 and 1.2.17 */
-#ifdef PNG_UNKNOWN_CHUNKS_SUPPORTED
- /* Storage for unknown chunk that the library doesn't recognize. */
+#ifdef PNG_READ_UNKNOWN_CHUNKS_SUPPORTED
+ /* Temporary storage for unknown chunk that the library doesn't recognize,
+ * used while reading the chunk.
+ */
png_unknown_chunk unknown_chunk;
#endif
/* New member added in libpng-1.2.26 */
png_size_t old_big_row_buf_size;
+#ifdef PNG_READ_SUPPORTED
/* New member added in libpng-1.2.30 */
- png_charp chunkdata; /* buffer for reading chunk data */
+ png_bytep read_buffer; /* buffer for reading chunk data */
+ png_alloc_size_t read_buffer_size; /* current size of the buffer */
+#endif
+#ifdef PNG_SEQUENTIAL_READ_SUPPORTED
+ uInt IDAT_read_size; /* limit on read buffer size for IDAT */
+#endif
#ifdef PNG_IO_STATE_SUPPORTED
/* New member added in libpng-1.4.0 */
@@ -351,7 +475,14 @@ struct png_struct_def
/* New member added in libpng-1.5.6 */
png_bytep big_prev_row;
+/* New member added in libpng-1.5.7 */
void (*read_filter[PNG_FILTER_VALUE_LAST-1])(png_row_infop row_info,
png_bytep row, png_const_bytep prev_row);
+
+#ifdef PNG_READ_SUPPORTED
+#if defined(PNG_COLORSPACE_SUPPORTED) || defined(PNG_GAMMA_SUPPORTED)
+ png_colorspace colorspace;
+#endif
+#endif
};
#endif /* PNGSTRUCT_H */
diff --git a/src/3rdparty/libpng/pngtrans.c b/src/3rdparty/libpng/pngtrans.c
index fef12f1851..cd3a79b6fa 100644
--- a/src/3rdparty/libpng/pngtrans.c
+++ b/src/3rdparty/libpng/pngtrans.c
@@ -1,8 +1,8 @@
/* pngtrans.c - transforms the data in a row (used by both readers and writers)
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -18,7 +18,7 @@
#if defined(PNG_READ_BGR_SUPPORTED) || defined(PNG_WRITE_BGR_SUPPORTED)
/* Turn on BGR-to-RGB mapping */
void PNGAPI
-png_set_bgr(png_structp png_ptr)
+png_set_bgr(png_structrp png_ptr)
{
png_debug(1, "in png_set_bgr");
@@ -32,7 +32,7 @@ png_set_bgr(png_structp png_ptr)
#if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED)
/* Turn on 16 bit byte swapping */
void PNGAPI
-png_set_swap(png_structp png_ptr)
+png_set_swap(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap");
@@ -47,7 +47,7 @@ png_set_swap(png_structp png_ptr)
#if defined(PNG_READ_PACK_SUPPORTED) || defined(PNG_WRITE_PACK_SUPPORTED)
/* Turn on pixel packing */
void PNGAPI
-png_set_packing(png_structp png_ptr)
+png_set_packing(png_structrp png_ptr)
{
png_debug(1, "in png_set_packing");
@@ -57,7 +57,9 @@ png_set_packing(png_structp png_ptr)
if (png_ptr->bit_depth < 8)
{
png_ptr->transformations |= PNG_PACK;
- png_ptr->usr_bit_depth = 8;
+# ifdef PNG_WRITE_SUPPORTED
+ png_ptr->usr_bit_depth = 8;
+# endif
}
}
#endif
@@ -65,7 +67,7 @@ png_set_packing(png_structp png_ptr)
#if defined(PNG_READ_PACKSWAP_SUPPORTED)||defined(PNG_WRITE_PACKSWAP_SUPPORTED)
/* Turn on packed pixel swapping */
void PNGAPI
-png_set_packswap(png_structp png_ptr)
+png_set_packswap(png_structrp png_ptr)
{
png_debug(1, "in png_set_packswap");
@@ -79,7 +81,7 @@ png_set_packswap(png_structp png_ptr)
#if defined(PNG_READ_SHIFT_SUPPORTED) || defined(PNG_WRITE_SHIFT_SUPPORTED)
void PNGAPI
-png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
+png_set_shift(png_structrp png_ptr, png_const_color_8p true_bits)
{
png_debug(1, "in png_set_shift");
@@ -94,11 +96,11 @@ png_set_shift(png_structp png_ptr, png_const_color_8p true_bits)
#if defined(PNG_READ_INTERLACING_SUPPORTED) || \
defined(PNG_WRITE_INTERLACING_SUPPORTED)
int PNGAPI
-png_set_interlace_handling(png_structp png_ptr)
+png_set_interlace_handling(png_structrp png_ptr)
{
png_debug(1, "in png_set_interlace handling");
- if (png_ptr && png_ptr->interlaced)
+ if (png_ptr != 0 && png_ptr->interlaced != 0)
{
png_ptr->transformations |= PNG_INTERLACE;
return (7);
@@ -115,44 +117,91 @@ png_set_interlace_handling(png_structp png_ptr)
* that don't like bytes as parameters.
*/
void PNGAPI
-png_set_filler(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+png_set_filler(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_filler");
if (png_ptr == NULL)
return;
+ /* In libpng 1.6 it is possible to determine whether this is a read or write
+ * operation and therefore to do more checking here for a valid call.
+ */
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0)
+ {
+# ifdef PNG_READ_FILLER_SUPPORTED
+ /* On read png_set_filler is always valid, regardless of the base PNG
+ * format, because other transformations can give a format where the
+ * filler code can execute (basically an 8 or 16-bit component RGB or G
+ * format.)
+ *
+ * NOTE: usr_channels is not used by the read code! (This has led to
+ * confusion in the past.) The filler is only used in the read code.
+ */
+ png_ptr->filler = (png_uint_16)filler;
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on read");
+ PNG_UNUSED(filler) /* not used in the write case */
+ return;
+# endif
+ }
+
+ else /* write */
+ {
+# ifdef PNG_WRITE_FILLER_SUPPORTED
+ /* On write the usr_channels parameter must be set correctly at the
+ * start to record the number of channels in the app-supplied data.
+ */
+ switch (png_ptr->color_type)
+ {
+ case PNG_COLOR_TYPE_RGB:
+ png_ptr->usr_channels = 4;
+ break;
+
+ case PNG_COLOR_TYPE_GRAY:
+ if (png_ptr->bit_depth >= 8)
+ {
+ png_ptr->usr_channels = 2;
+ break;
+ }
+
+ else
+ {
+ /* There simply isn't any code in libpng to strip out bits
+ * from bytes when the components are less than a byte in
+ * size!
+ */
+ png_app_error(png_ptr,
+ "png_set_filler is invalid for low bit depth gray output");
+ return;
+ }
+
+ default:
+ png_app_error(png_ptr,
+ "png_set_filler: inappropriate color type");
+ return;
+ }
+# else
+ png_app_error(png_ptr, "png_set_filler not supported on write");
+ return;
+# endif
+ }
+
+ /* Here on success - libpng supports the operation, set the transformation
+ * and the flag to say where the filler channel is.
+ */
png_ptr->transformations |= PNG_FILLER;
- png_ptr->filler = (png_uint_16)filler;
if (filler_loc == PNG_FILLER_AFTER)
png_ptr->flags |= PNG_FLAG_FILLER_AFTER;
else
png_ptr->flags &= ~PNG_FLAG_FILLER_AFTER;
-
- /* This should probably go in the "do_read_filler" routine.
- * I attempted to do that in libpng-1.0.1a but that caused problems
- * so I restored it in libpng-1.0.2a
- */
-
- if (png_ptr->color_type == PNG_COLOR_TYPE_RGB)
- {
- png_ptr->usr_channels = 4;
- }
-
- /* Also I added this in libpng-1.0.2a (what happens when we expand
- * a less-than-8-bit grayscale to GA?) */
-
- if (png_ptr->color_type == PNG_COLOR_TYPE_GRAY && png_ptr->bit_depth >= 8)
- {
- png_ptr->usr_channels = 2;
- }
}
/* Added to libpng-1.2.7 */
void PNGAPI
-png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
+png_set_add_alpha(png_structrp png_ptr, png_uint_32 filler, int filler_loc)
{
png_debug(1, "in png_set_add_alpha");
@@ -160,7 +209,9 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
return;
png_set_filler(png_ptr, filler, filler_loc);
- png_ptr->transformations |= PNG_ADD_ALPHA;
+ /* The above may fail to do anything. */
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_ptr->transformations |= PNG_ADD_ALPHA;
}
#endif
@@ -168,7 +219,7 @@ png_set_add_alpha(png_structp png_ptr, png_uint_32 filler, int filler_loc)
#if defined(PNG_READ_SWAP_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_SWAP_ALPHA_SUPPORTED)
void PNGAPI
-png_set_swap_alpha(png_structp png_ptr)
+png_set_swap_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_swap_alpha");
@@ -182,7 +233,7 @@ png_set_swap_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_ALPHA_SUPPORTED) || \
defined(PNG_WRITE_INVERT_ALPHA_SUPPORTED)
void PNGAPI
-png_set_invert_alpha(png_structp png_ptr)
+png_set_invert_alpha(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_alpha");
@@ -195,7 +246,7 @@ png_set_invert_alpha(png_structp png_ptr)
#if defined(PNG_READ_INVERT_SUPPORTED) || defined(PNG_WRITE_INVERT_SUPPORTED)
void PNGAPI
-png_set_invert_mono(png_structp png_ptr)
+png_set_invert_mono(png_structrp png_ptr)
{
png_debug(1, "in png_set_invert_mono");
@@ -276,9 +327,16 @@ png_do_swap(png_row_infop row_info, png_bytep row)
for (i = 0; i < istop; i++, rp += 2)
{
+#ifdef PNG_BUILTIN_BSWAP16_SUPPORTED
+ /* Feature added to libpng-1.6.11 for testing purposes, not
+ * enabled by default.
+ */
+ *(png_uint_16*)rp = __builtin_bswap16(*(png_uint_16*)rp);
+#else
png_byte t = *rp;
*rp = *(rp + 1);
*(rp + 1) = t;
+#endif
}
}
}
@@ -420,7 +478,7 @@ png_do_packswap(png_row_infop row_info, png_bytep row)
*rp = table[*rp];
}
}
-#endif /* PNG_READ_PACKSWAP_SUPPORTED or PNG_WRITE_PACKSWAP_SUPPORTED */
+#endif /* PACKSWAP || WRITE_PACKSWAP */
#if defined(PNG_WRITE_FILLER_SUPPORTED) || \
defined(PNG_READ_STRIP_ALPHA_SUPPORTED)
@@ -452,7 +510,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channel and, for sp, the filler */
sp += 2, ++dp;
@@ -466,7 +524,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channel and, for sp, the filler */
sp += 4, dp += 2;
@@ -492,7 +550,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
{
if (row_info->bit_depth == 8)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
++sp;
else /* Skip initial channels and, for sp, the filler */
sp += 4, dp += 3;
@@ -506,7 +564,7 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
else if (row_info->bit_depth == 16)
{
- if (at_start) /* Skip initial filler */
+ if (at_start != 0) /* Skip initial filler */
sp += 2;
else /* Skip initial channels and, for sp, the filler */
sp += 8, dp += 6;
@@ -547,7 +605,7 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_bgr");
- if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_uint_32 row_width = row_info->width;
if (row_info->bit_depth == 8)
@@ -617,16 +675,16 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
#endif
}
}
-#endif /* PNG_READ_BGR_SUPPORTED or PNG_WRITE_BGR_SUPPORTED */
+#endif /* READ_BGR || WRITE_BGR */
#if defined(PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED) || \
defined(PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED)
/* Added at libpng-1.5.10 */
void /* PRIVATE */
-png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
+png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
{
if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
- png_ptr->num_palette_max >= 0)
+ png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
{
/* Calculations moved outside switch in an attempt to stop different
* compiler warnings. 'padding' is in *bits* within the last byte, it is
@@ -708,7 +766,7 @@ png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
{
for (; rp > png_ptr->row_buf; rp--)
{
- if (*rp >= png_ptr->num_palette_max)
+ if (*rp > png_ptr->num_palette_max)
png_ptr->num_palette_max = (int) *rp;
}
@@ -720,19 +778,30 @@ png_do_check_palette_indexes(png_structp png_ptr, png_row_infop row_info)
}
}
}
-#endif /* PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED */
+#endif /* CHECK_FOR_INVALID_INDEX */
#if defined(PNG_READ_USER_TRANSFORM_SUPPORTED) || \
defined(PNG_WRITE_USER_TRANSFORM_SUPPORTED)
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
void PNGAPI
-png_set_user_transform_info(png_structp png_ptr, png_voidp
+png_set_user_transform_info(png_structrp png_ptr, png_voidp
user_transform_ptr, int user_transform_depth, int user_transform_channels)
{
png_debug(1, "in png_set_user_transform_info");
if (png_ptr == NULL)
return;
+
+#ifdef PNG_READ_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 &&
+ (png_ptr->flags & PNG_FLAG_ROW_INIT) != 0)
+ {
+ png_app_error(png_ptr,
+ "info change after png_start_read_image or png_read_update_info");
+ return;
+ }
+#endif
+
png_ptr->user_transform_ptr = user_transform_ptr;
png_ptr->user_transform_depth = (png_byte)user_transform_depth;
png_ptr->user_transform_channels = (png_byte)user_transform_channels;
@@ -746,20 +815,20 @@ png_set_user_transform_info(png_structp png_ptr, png_voidp
*/
#ifdef PNG_USER_TRANSFORM_PTR_SUPPORTED
png_voidp PNGAPI
-png_get_user_transform_ptr(png_const_structp png_ptr)
+png_get_user_transform_ptr(png_const_structrp png_ptr)
{
if (png_ptr == NULL)
return (NULL);
- return ((png_voidp)png_ptr->user_transform_ptr);
+ return png_ptr->user_transform_ptr;
}
#endif
#ifdef PNG_USER_TRANSFORM_INFO_SUPPORTED
png_uint_32 PNGAPI
-png_get_current_row_number(png_const_structp png_ptr)
+png_get_current_row_number(png_const_structrp png_ptr)
{
- /* See the comments in png.h - this is the sub-image row when reading and
+ /* See the comments in png.h - this is the sub-image row when reading an
* interlaced image.
*/
if (png_ptr != NULL)
@@ -769,13 +838,12 @@ png_get_current_row_number(png_const_structp png_ptr)
}
png_byte PNGAPI
-png_get_current_pass_number(png_const_structp png_ptr)
+png_get_current_pass_number(png_const_structrp png_ptr)
{
if (png_ptr != NULL)
return png_ptr->pass;
return 8; /* invalid */
}
-#endif /* PNG_USER_TRANSFORM_INFO_SUPPORTED */
-#endif /* PNG_READ_USER_TRANSFORM_SUPPORTED ||
- PNG_WRITE_USER_TRANSFORM_SUPPORTED */
-#endif /* PNG_READ_SUPPORTED || PNG_WRITE_SUPPORTED */
+#endif /* USER_TRANSFORM_INFO */
+#endif /* READ_USER_TRANSFORM || WRITE_USER_TRANSFORM */
+#endif /* READ || WRITE */
diff --git a/src/3rdparty/libpng/pngwio.c b/src/3rdparty/libpng/pngwio.c
index 95ffb3429f..0a40948aab 100644
--- a/src/3rdparty/libpng/pngwio.c
+++ b/src/3rdparty/libpng/pngwio.c
@@ -1,8 +1,8 @@
/* pngwio.c - functions for data output
*
- * Last changed in libpng 1.5.0 [January 6, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.15 [November 20, 2014]
+ * Copyright (c) 1998-2014 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -30,11 +30,12 @@
*/
void /* PRIVATE */
-png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
+png_write_data(png_structrp png_ptr, png_const_bytep data, png_size_t length)
{
/* NOTE: write_data_fn must not change the buffer! */
if (png_ptr->write_data_fn != NULL )
- (*(png_ptr->write_data_fn))(png_ptr, (png_bytep)data, length);
+ (*(png_ptr->write_data_fn))(png_ptr, png_constcast(png_bytep,data),
+ length);
else
png_error(png_ptr, "Call to NULL write function");
@@ -46,7 +47,6 @@ png_write_data(png_structp png_ptr, png_const_bytep data, png_size_t length)
* write_data function and use it at run time with png_set_write_fn(), rather
* than changing the library.
*/
-#ifndef USE_FAR_KEYWORD
void PNGCBAPI
png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
{
@@ -60,64 +60,6 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
if (check != length)
png_error(png_ptr, "Write Error");
}
-#else
-/* This is the model-independent version. Since the standard I/O library
- * can't handle far buffers in the medium and small models, we have to copy
- * the data.
- */
-
-#define NEAR_BUF_SIZE 1024
-#define MIN(a,b) (a <= b ? a : b)
-
-void PNGCBAPI
-png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
-{
- png_uint_32 check;
- png_byte *near_data; /* Needs to be "png_byte *" instead of "png_bytep" */
- png_FILE_p io_ptr;
-
- if (png_ptr == NULL)
- return;
-
- /* Check if data really is near. If so, use usual code. */
- near_data = (png_byte *)CVT_PTR_NOCHECK(data);
- io_ptr = (png_FILE_p)CVT_PTR(png_ptr->io_ptr);
-
- if ((png_bytep)near_data == data)
- {
- check = fwrite(near_data, 1, length, io_ptr);
- }
-
- else
- {
- png_byte buf[NEAR_BUF_SIZE];
- png_size_t written, remaining, err;
- check = 0;
- remaining = length;
-
- do
- {
- written = MIN(NEAR_BUF_SIZE, remaining);
- png_memcpy(buf, data, written); /* Copy far buffer to near buffer */
- err = fwrite(buf, 1, written, io_ptr);
-
- if (err != written)
- break;
-
- else
- check += err;
-
- data += written;
- remaining -= written;
- }
- while (remaining != 0);
- }
-
- if (check != length)
- png_error(png_ptr, "Write Error");
-}
-
-#endif
#endif
/* This function is called to output any data pending writing (normally
@@ -126,7 +68,7 @@ png_default_write_data(png_structp png_ptr, png_bytep data, png_size_t length)
*/
#ifdef PNG_WRITE_FLUSH_SUPPORTED
void /* PRIVATE */
-png_flush(png_structp png_ptr)
+png_flush(png_structrp png_ptr)
{
if (png_ptr->output_flush_fn != NULL)
(*(png_ptr->output_flush_fn))(png_ptr);
@@ -141,7 +83,7 @@ png_default_flush(png_structp png_ptr)
if (png_ptr == NULL)
return;
- io_ptr = (png_FILE_p)CVT_PTR((png_ptr->io_ptr));
+ io_ptr = png_voidcast(png_FILE_p, (png_ptr->io_ptr));
fflush(io_ptr);
}
# endif
@@ -177,7 +119,7 @@ png_default_flush(png_structp png_ptr)
* *FILE structure.
*/
void PNGAPI
-png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
+png_set_write_fn(png_structrp png_ptr, png_voidp io_ptr,
png_rw_ptr write_data_fn, png_flush_ptr output_flush_fn)
{
if (png_ptr == NULL)
@@ -207,8 +149,11 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
# else
png_ptr->output_flush_fn = output_flush_fn;
# endif
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
+#else
+ PNG_UNUSED(output_flush_fn)
+#endif /* WRITE_FLUSH */
+#ifdef PNG_READ_SUPPORTED
/* It is an error to read while writing a png file */
if (png_ptr->read_data_fn != NULL)
{
@@ -218,37 +163,6 @@ png_set_write_fn(png_structp png_ptr, png_voidp io_ptr,
"Can't set both read_data_fn and write_data_fn in the"
" same structure");
}
-}
-
-#ifdef USE_FAR_KEYWORD
-# ifdef _MSC_VER
-void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
-{
- void *near_ptr;
- void FAR *far_ptr;
- FP_OFF(near_ptr) = FP_OFF(ptr);
- far_ptr = (void FAR *)near_ptr;
-
- if (check != 0)
- if (FP_SEG(ptr) != FP_SEG(far_ptr))
- png_error(png_ptr, "segment lost in conversion");
-
- return(near_ptr);
-}
-# else
-void *png_far_to_near(png_structp png_ptr, png_voidp ptr, int check)
-{
- void *near_ptr;
- void FAR *far_ptr;
- near_ptr = (void FAR *)ptr;
- far_ptr = (void FAR *)near_ptr;
-
- if (check != 0)
- if (far_ptr != ptr)
- png_error(png_ptr, "segment lost in conversion");
-
- return(near_ptr);
-}
-# endif
#endif
-#endif /* PNG_WRITE_SUPPORTED */
+}
+#endif /* WRITE */
diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c
index b587f1b999..e3c203496e 100644
--- a/src/3rdparty/libpng/pngwrite.c
+++ b/src/3rdparty/libpng/pngwrite.c
@@ -1,8 +1,8 @@
/* pngwrite.c - general routines to write a PNG file
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -12,9 +12,65 @@
*/
#include "pngpriv.h"
+#if defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) && defined(PNG_STDIO_SUPPORTED)
+# include <errno.h>
+#endif
#ifdef PNG_WRITE_SUPPORTED
+#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
+/* Write out all the unknown chunks for the current given location */
+static void
+write_unknown_chunks(png_structrp png_ptr, png_const_inforp info_ptr,
+ unsigned int where)
+{
+ if (info_ptr->unknown_chunks_num != 0)
+ {
+ png_const_unknown_chunkp up;
+
+ png_debug(5, "writing extra chunks");
+
+ for (up = info_ptr->unknown_chunks;
+ up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
+ ++up)
+ if ((up->location & where) != 0)
+ {
+ /* If per-chunk unknown chunk handling is enabled use it, otherwise
+ * just write the chunks the application has set.
+ */
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ int keep = png_handle_as_unknown(png_ptr, up->name);
+
+ /* NOTE: this code is radically different from the read side in the
+ * matter of handling an ancillary unknown chunk. In the read side
+ * the default behavior is to discard it, in the code below the default
+ * behavior is to write it. Critical chunks are, however, only
+ * written if explicitly listed or if the default is set to write all
+ * unknown chunks.
+ *
+ * The default handling is also slightly weird - it is not possible to
+ * stop the writing of all unsafe-to-copy chunks!
+ *
+ * TODO: REVIEW: this would seem to be a bug.
+ */
+ if (keep != PNG_HANDLE_CHUNK_NEVER &&
+ ((up->name[3] & 0x20) /* safe-to-copy overrides everything */ ||
+ keep == PNG_HANDLE_CHUNK_ALWAYS ||
+ (keep == PNG_HANDLE_CHUNK_AS_DEFAULT &&
+ png_ptr->unknown_default == PNG_HANDLE_CHUNK_ALWAYS)))
+#endif
+ {
+ /* TODO: review, what is wrong with a zero length unknown chunk? */
+ if (up->size == 0)
+ png_warning(png_ptr, "Writing zero-length unknown chunk");
+
+ png_write_chunk(png_ptr, up->name, up->data, up->size);
+ }
+ }
+ }
+}
+#endif /* WRITE_UNKNOWN_CHUNKS */
+
/* Writes all the PNG information. This is the suggested way to use the
* library. If you have a new chunk to add, make a function to write it,
* and put it in the correct location here. If you want the chunk written
@@ -25,21 +81,21 @@
* them in png_write_end(), and compressing them.
*/
void PNGAPI
-png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
+png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr)
{
png_debug(1, "in png_write_info_before_PLTE");
if (png_ptr == NULL || info_ptr == NULL)
return;
- if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
{
/* Write PNG signature */
png_write_sig(png_ptr);
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) && \
- (png_ptr->mng_features_permitted))
+ if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \
+ png_ptr->mng_features_permitted != 0)
{
png_warning(png_ptr, "MNG features are not allowed in a PNG datastream");
png_ptr->mng_features_permitted = 0;
@@ -51,75 +107,88 @@ png_write_info_before_PLTE(png_structp png_ptr, png_infop info_ptr)
info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type,
info_ptr->filter_type,
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
- info_ptr->interlace_type);
+ info_ptr->interlace_type
#else
- 0);
+ 0
#endif
+ );
+
/* The rest of these check to see if the valid field has the appropriate
* flag set, and if it does, writes the chunk.
+ *
+ * 1.6.0: COLORSPACE support controls the writing of these chunks too, and
+ * the chunks will be written if the WRITE routine is there and information
+ * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c
+ * for where the valid flags get set.)
+ *
+ * Under certain circumstances the colorspace can be invalidated without
+ * syncing the info_struct 'valid' flags; this happens if libpng detects and
+ * error and calls png_error while the color space is being set, yet the
+ * application continues writing the PNG. So check the 'invalid' flag here
+ * too.
*/
-#ifdef PNG_WRITE_gAMA_SUPPORTED
- if (info_ptr->valid & PNG_INFO_gAMA)
- png_write_gAMA_fixed(png_ptr, info_ptr->gamma);
-#endif
-#ifdef PNG_WRITE_sRGB_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sRGB)
- png_write_sRGB(png_ptr, (int)info_ptr->srgb_intent);
+#ifdef PNG_GAMMA_SUPPORTED
+# ifdef PNG_WRITE_gAMA_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_gAMA) != 0 &&
+ (info_ptr->valid & PNG_INFO_gAMA) != 0)
+ png_write_gAMA_fixed(png_ptr, info_ptr->colorspace.gamma);
+# endif
#endif
-#ifdef PNG_WRITE_iCCP_SUPPORTED
- if (info_ptr->valid & PNG_INFO_iCCP)
- png_write_iCCP(png_ptr, info_ptr->iccp_name, PNG_COMPRESSION_TYPE_BASE,
- (png_charp)info_ptr->iccp_profile, (int)info_ptr->iccp_proflen);
-#endif
+#ifdef PNG_COLORSPACE_SUPPORTED
+ /* Write only one of sRGB or an ICC profile. If a profile was supplied
+ * and it matches one of the known sRGB ones issue a warning.
+ */
+# ifdef PNG_WRITE_iCCP_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_iCCP) != 0)
+ {
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_app_warning(png_ptr,
+ "profile matches sRGB but writing iCCP instead");
+# endif
+
+ png_write_iCCP(png_ptr, info_ptr->iccp_name,
+ info_ptr->iccp_profile);
+ }
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ else
+# endif
+# endif
+
+# ifdef PNG_WRITE_sRGB_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->valid & PNG_INFO_sRGB) != 0)
+ png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent);
+# endif /* WRITE_sRGB */
+#endif /* COLORSPACE */
+
#ifdef PNG_WRITE_sBIT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sBIT)
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type);
#endif
-#ifdef PNG_WRITE_cHRM_SUPPORTED
- if (info_ptr->valid & PNG_INFO_cHRM)
- png_write_cHRM_fixed(png_ptr,
- info_ptr->x_white, info_ptr->y_white,
- info_ptr->x_red, info_ptr->y_red,
- info_ptr->x_green, info_ptr->y_green,
- info_ptr->x_blue, info_ptr->y_blue);
+
+#ifdef PNG_COLORSPACE_SUPPORTED
+# ifdef PNG_WRITE_cHRM_SUPPORTED
+ if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 &&
+ (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 &&
+ (info_ptr->valid & PNG_INFO_cHRM) != 0)
+ png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy);
+# endif
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
-
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- !(up->location & PNG_HAVE_PLTE) &&
- !(up->location & PNG_HAVE_IDAT) &&
- !(up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- if (up->size == 0)
- png_warning(png_ptr, "Writing zero-length unknown chunk");
-
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR);
#endif
+
png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE;
}
}
void PNGAPI
-png_write_info(png_structp png_ptr, png_infop info_ptr)
+png_write_info(png_structrp png_ptr, png_const_inforp info_ptr)
{
#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
int i;
@@ -132,19 +201,19 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
png_write_info_before_PLTE(png_ptr, info_ptr);
- if (info_ptr->valid & PNG_INFO_PLTE)
+ if ((info_ptr->valid & PNG_INFO_PLTE) != 0)
png_write_PLTE(png_ptr, info_ptr->palette,
(png_uint_32)info_ptr->num_palette);
- else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
+ else if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) !=0)
png_error(png_ptr, "Valid palette required for paletted images");
#ifdef PNG_WRITE_tRNS_SUPPORTED
- if (info_ptr->valid & PNG_INFO_tRNS)
+ if ((info_ptr->valid & PNG_INFO_tRNS) !=0)
{
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel (in tRNS) */
- if ((png_ptr->transformations & PNG_INVERT_ALPHA) &&
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 &&
info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
{
int j;
@@ -158,42 +227,42 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
}
#endif
#ifdef PNG_WRITE_bKGD_SUPPORTED
- if (info_ptr->valid & PNG_INFO_bKGD)
+ if ((info_ptr->valid & PNG_INFO_bKGD) != 0)
png_write_bKGD(png_ptr, &(info_ptr->background), info_ptr->color_type);
#endif
#ifdef PNG_WRITE_hIST_SUPPORTED
- if (info_ptr->valid & PNG_INFO_hIST)
+ if ((info_ptr->valid & PNG_INFO_hIST) != 0)
png_write_hIST(png_ptr, info_ptr->hist, info_ptr->num_palette);
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
- if (info_ptr->valid & PNG_INFO_oFFs)
+ if ((info_ptr->valid & PNG_INFO_oFFs) != 0)
png_write_oFFs(png_ptr, info_ptr->x_offset, info_ptr->y_offset,
info_ptr->offset_unit_type);
#endif
#ifdef PNG_WRITE_pCAL_SUPPORTED
- if (info_ptr->valid & PNG_INFO_pCAL)
+ if ((info_ptr->valid & PNG_INFO_pCAL) != 0)
png_write_pCAL(png_ptr, info_ptr->pcal_purpose, info_ptr->pcal_X0,
info_ptr->pcal_X1, info_ptr->pcal_type, info_ptr->pcal_nparams,
info_ptr->pcal_units, info_ptr->pcal_params);
#endif
#ifdef PNG_WRITE_sCAL_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sCAL)
+ if ((info_ptr->valid & PNG_INFO_sCAL) != 0)
png_write_sCAL_s(png_ptr, (int)info_ptr->scal_unit,
info_ptr->scal_s_width, info_ptr->scal_s_height);
#endif /* sCAL */
#ifdef PNG_WRITE_pHYs_SUPPORTED
- if (info_ptr->valid & PNG_INFO_pHYs)
+ if ((info_ptr->valid & PNG_INFO_pHYs) != 0)
png_write_pHYs(png_ptr, info_ptr->x_pixels_per_unit,
info_ptr->y_pixels_per_unit, info_ptr->phys_unit_type);
#endif /* pHYs */
#ifdef PNG_WRITE_tIME_SUPPORTED
- if (info_ptr->valid & PNG_INFO_tIME)
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0)
{
png_write_tIME(png_ptr, &(info_ptr->mod_time));
png_ptr->mode |= PNG_WROTE_tIME;
@@ -201,7 +270,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif /* tIME */
#ifdef PNG_WRITE_sPLT_SUPPORTED
- if (info_ptr->valid & PNG_INFO_sPLT)
+ if ((info_ptr->valid & PNG_INFO_sPLT) != 0)
for (i = 0; i < (int)info_ptr->splt_palettes_num; i++)
png_write_sPLT(png_ptr, info_ptr->splt_palettes + i);
#endif /* sPLT */
@@ -223,11 +292,14 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
- png_warning(png_ptr, "Unable to write international text");
+ png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
/* If we want a compressed text chunk */
@@ -236,13 +308,12 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
- info_ptr->text[i].text, 0,
- info_ptr->text[i].compression);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -263,29 +334,7 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
#endif /* tEXt */
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- (up->location & PNG_HAVE_PLTE) &&
- !(up->location & PNG_HAVE_IDAT) &&
- !(up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_PLTE);
#endif
}
@@ -295,14 +344,14 @@ png_write_info(png_structp png_ptr, png_infop info_ptr)
* comments, I suggest writing them here, and compressing them.
*/
void PNGAPI
-png_write_end(png_structp png_ptr, png_infop info_ptr)
+png_write_end(png_structrp png_ptr, png_inforp info_ptr)
{
png_debug(1, "in png_write_end");
if (png_ptr == NULL)
return;
- if (!(png_ptr->mode & PNG_HAVE_IDAT))
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0)
png_error(png_ptr, "No IDATs written into file");
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
@@ -318,8 +367,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#endif
#ifdef PNG_WRITE_tIME_SUPPORTED
/* Check to see if user has supplied a time chunk */
- if ((info_ptr->valid & PNG_INFO_tIME) &&
- !(png_ptr->mode & PNG_WROTE_tIME))
+ if ((info_ptr->valid & PNG_INFO_tIME) != 0 &&
+ (png_ptr->mode & PNG_WROTE_tIME) == 0)
png_write_tIME(png_ptr, &(info_ptr->mod_time));
#endif
@@ -340,11 +389,14 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
info_ptr->text[i].lang,
info_ptr->text[i].lang_key,
info_ptr->text[i].text);
+ /* Mark this chunk as written */
+ if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
+ else
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write international text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
else if (info_ptr->text[i].compression >= PNG_TEXT_COMPRESSION_zTXt)
@@ -352,13 +404,12 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write compressed chunk */
png_write_zTXt(png_ptr, info_ptr->text[i].key,
- info_ptr->text[i].text, 0,
- info_ptr->text[i].compression);
+ info_ptr->text[i].text, info_ptr->text[i].compression);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
#else
png_warning(png_ptr, "Unable to write compressed text");
#endif
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_zTXt_WR;
}
else if (info_ptr->text[i].compression == PNG_TEXT_COMPRESSION_NONE)
@@ -367,37 +418,16 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* Write uncompressed chunk */
png_write_tEXt(png_ptr, info_ptr->text[i].key,
info_ptr->text[i].text, 0);
+ /* Mark this chunk as written */
+ info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
#else
png_warning(png_ptr, "Unable to write uncompressed text");
#endif
-
- /* Mark this chunk as written */
- info_ptr->text[i].compression = PNG_TEXT_COMPRESSION_NONE_WR;
}
}
#endif
#ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED
- if (info_ptr->unknown_chunks_num)
- {
- png_unknown_chunk *up;
-
- png_debug(5, "writing extra chunks");
-
- for (up = info_ptr->unknown_chunks;
- up < info_ptr->unknown_chunks + info_ptr->unknown_chunks_num;
- up++)
- {
- int keep = png_handle_as_unknown(png_ptr, up->name);
- if (keep != PNG_HANDLE_CHUNK_NEVER &&
- up->location &&
- (up->location & PNG_AFTER_IDAT) &&
- ((up->name[3] & 0x20) || keep == PNG_HANDLE_CHUNK_ALWAYS ||
- (png_ptr->flags & PNG_FLAG_KEEP_UNSAFE_CHUNKS)))
- {
- png_write_chunk(png_ptr, up->name, up->data, up->size);
- }
- }
- }
+ write_unknown_chunks(png_ptr, info_ptr, PNG_AFTER_IDAT);
#endif
}
@@ -405,6 +435,7 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
/* Write end of PNG file */
png_write_IEND(png_ptr);
+
/* This flush, added in libpng-1.0.8, removed from libpng-1.0.9beta03,
* and restored again in libpng-1.2.30, may cause some applications that
* do not set png_ptr->output_flush_fn to crash. If your application
@@ -420,9 +451,8 @@ png_write_end(png_structp png_ptr, png_infop info_ptr)
}
#ifdef PNG_CONVERT_tIME_SUPPORTED
-/* "tm" structure is not supported on WindowsCE */
void PNGAPI
-png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm FAR * ttime)
+png_convert_from_struct_tm(png_timep ptime, PNG_CONST struct tm * ttime)
{
png_debug(1, "in png_convert_from_struct_tm");
@@ -451,104 +481,75 @@ PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn),PNG_ALLOCATED)
{
-#ifdef PNG_USER_MEM_SUPPORTED
- return (png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
- warn_fn, NULL, NULL, NULL));
+#ifndef PNG_USER_MEM_SUPPORTED
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, NULL, NULL, NULL);
+#else
+ return png_create_write_struct_2(user_png_ver, error_ptr, error_fn,
+ warn_fn, NULL, NULL, NULL);
}
/* Alternate initialize png_ptr structure, and allocate any memory needed */
-static void png_reset_filter_heuristics(png_structp png_ptr); /* forward decl */
-
PNG_FUNCTION(png_structp,PNGAPI
png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
png_error_ptr error_fn, png_error_ptr warn_fn, png_voidp mem_ptr,
png_malloc_ptr malloc_fn, png_free_ptr free_fn),PNG_ALLOCATED)
{
-#endif /* PNG_USER_MEM_SUPPORTED */
- volatile int png_cleanup_needed = 0;
-#ifdef PNG_SETJMP_SUPPORTED
- volatile
-#endif
- png_structp png_ptr;
-#ifdef PNG_SETJMP_SUPPORTED
-#ifdef USE_FAR_KEYWORD
- jmp_buf tmp_jmpbuf;
-#endif
-#endif
-
- png_debug(1, "in png_create_write_struct");
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr = (png_structp)png_create_struct_2(PNG_STRUCT_PNG,
- (png_malloc_ptr)malloc_fn, (png_voidp)mem_ptr);
-#else
- png_ptr = (png_structp)png_create_struct(PNG_STRUCT_PNG);
-#endif /* PNG_USER_MEM_SUPPORTED */
- if (png_ptr == NULL)
- return (NULL);
+ png_structrp png_ptr = png_create_png_struct(user_png_ver, error_ptr,
+ error_fn, warn_fn, mem_ptr, malloc_fn, free_fn);
+#endif /* USER_MEM */
+ if (png_ptr != NULL)
+ {
+ /* Set the zlib control values to defaults; they can be overridden by the
+ * application after the struct has been created.
+ */
+ png_ptr->zbuffer_size = PNG_ZBUF_SIZE;
- /* Added at libpng-1.2.6 */
-#ifdef PNG_SET_USER_LIMITS_SUPPORTED
- png_ptr->user_width_max = PNG_USER_WIDTH_MAX;
- png_ptr->user_height_max = PNG_USER_HEIGHT_MAX;
+ /* The 'zlib_strategy' setting is irrelevant because png_default_claim in
+ * pngwutil.c defaults it according to whether or not filters will be
+ * used, and ignores this setting.
+ */
+ png_ptr->zlib_strategy = PNG_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_level = PNG_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_mem_level = 8;
+ png_ptr->zlib_window_bits = 15;
+ png_ptr->zlib_method = 8;
+
+#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
+ png_ptr->zlib_text_strategy = PNG_TEXT_Z_DEFAULT_STRATEGY;
+ png_ptr->zlib_text_level = PNG_TEXT_Z_DEFAULT_COMPRESSION;
+ png_ptr->zlib_text_mem_level = 8;
+ png_ptr->zlib_text_window_bits = 15;
+ png_ptr->zlib_text_method = 8;
+#endif /* WRITE_COMPRESSED_TEXT */
+
+ /* This is a highly dubious configuration option; by default it is off,
+ * but it may be appropriate for private builds that are testing
+ * extensions not conformant to the current specification, or of
+ * applications that must not fail to write at all costs!
+ */
+#ifdef PNG_BENIGN_WRITE_ERRORS_SUPPORTED
+ /* In stable builds only warn if an application error can be completely
+ * handled.
+ */
+ png_ptr->flags |= PNG_FLAG_BENIGN_ERRORS_WARN;
#endif
-#ifdef PNG_SETJMP_SUPPORTED
-/* Applications that neglect to set up their own setjmp() and then
- * encounter a png_error() will longjmp here. Since the jmpbuf is
- * then meaningless we abort instead of returning.
- */
-#ifdef USE_FAR_KEYWORD
- if (setjmp(tmp_jmpbuf))
-#else
- if (setjmp(png_jmpbuf(png_ptr))) /* sets longjmp to match setjmp */
-#endif
-#ifdef USE_FAR_KEYWORD
- png_memcpy(png_jmpbuf(png_ptr), tmp_jmpbuf, png_sizeof(jmp_buf));
-#endif
- PNG_ABORT();
+ /* App warnings are warnings in release (or release candidate) builds but
+ * are errors during development.
+ */
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN;
#endif
-#ifdef PNG_USER_MEM_SUPPORTED
- png_set_mem_fn(png_ptr, mem_ptr, malloc_fn, free_fn);
-#endif /* PNG_USER_MEM_SUPPORTED */
- png_set_error_fn(png_ptr, error_ptr, error_fn, warn_fn);
-
- if (!png_user_version_check(png_ptr, user_png_ver))
- png_cleanup_needed = 1;
-
- /* Initialize zbuf - compression buffer */
- png_ptr->zbuf_size = PNG_ZBUF_SIZE;
-
- if (!png_cleanup_needed)
- {
- png_ptr->zbuf = (png_bytep)png_malloc_warn(png_ptr,
- png_ptr->zbuf_size);
- if (png_ptr->zbuf == NULL)
- png_cleanup_needed = 1;
- }
-
- if (png_cleanup_needed)
- {
- /* Clean up PNG structure and deallocate any memory. */
- png_free(png_ptr, png_ptr->zbuf);
- png_ptr->zbuf = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr,
- (png_free_ptr)free_fn, (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
-#endif
- return (NULL);
+ /* TODO: delay this, it can be done in png_init_io() (if the app doesn't
+ * do it itself) avoiding setting the default function if it is not
+ * required.
+ */
+ png_set_write_fn(png_ptr, NULL, NULL, NULL);
}
- png_set_write_fn(png_ptr, NULL, NULL, NULL);
-
-#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
- png_reset_filter_heuristics(png_ptr);
-#endif
-
- return (png_ptr);
+ return png_ptr;
}
@@ -558,7 +559,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr,
* "write" the image seven times.
*/
void PNGAPI
-png_write_rows(png_structp png_ptr, png_bytepp row,
+png_write_rows(png_structrp png_ptr, png_bytepp row,
png_uint_32 num_rows)
{
png_uint_32 i; /* row counter */
@@ -580,7 +581,7 @@ png_write_rows(png_structp png_ptr, png_bytepp row,
* if you are writing an interlaced image.
*/
void PNGAPI
-png_write_image(png_structp png_ptr, png_bytepp image)
+png_write_image(png_structrp png_ptr, png_bytepp image)
{
png_uint_32 i; /* row index */
int pass, num_pass; /* pass variables */
@@ -610,9 +611,74 @@ png_write_image(png_structp png_ptr, png_bytepp image)
}
}
+#ifdef PNG_MNG_FEATURES_SUPPORTED
+/* Performs intrapixel differencing */
+static void
+png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+{
+ png_debug(1, "in png_do_write_intrapixel");
+
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
+ {
+ int bytes_per_pixel;
+ png_uint_32 row_width = row_info->width;
+ if (row_info->bit_depth == 8)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 3;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 4;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ *(rp) = (png_byte)(*rp - *(rp + 1));
+ *(rp + 2) = (png_byte)(*(rp + 2) - *(rp + 1));
+ }
+ }
+
+#ifdef PNG_WRITE_16BIT_SUPPORTED
+ else if (row_info->bit_depth == 16)
+ {
+ png_bytep rp;
+ png_uint_32 i;
+
+ if (row_info->color_type == PNG_COLOR_TYPE_RGB)
+ bytes_per_pixel = 6;
+
+ else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
+ bytes_per_pixel = 8;
+
+ else
+ return;
+
+ for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
+ {
+ png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
+ png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
+ png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
+ png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
+ png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
+ *(rp ) = (png_byte)(red >> 8);
+ *(rp + 1) = (png_byte)red;
+ *(rp + 4) = (png_byte)(blue >> 8);
+ *(rp + 5) = (png_byte)blue;
+ }
+ }
+#endif /* WRITE_16BIT */
+ }
+}
+#endif /* MNG_FEATURES */
+
/* Called by user to write a row of image data */
void PNGAPI
-png_write_row(png_structp png_ptr, png_const_bytep row)
+png_write_row(png_structrp png_ptr, png_const_bytep row)
{
/* 1.5.6: moved from png_struct to be a local structure: */
png_row_info row_info;
@@ -627,44 +693,44 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
if (png_ptr->row_number == 0 && png_ptr->pass == 0)
{
/* Make sure we wrote the header info */
- if (!(png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE))
+ if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0)
png_error(png_ptr,
"png_write_info was never called before png_write_row");
/* Check for transforms that have been set but were defined out */
#if !defined(PNG_WRITE_INVERT_SUPPORTED) && defined(PNG_READ_INVERT_SUPPORTED)
- if (png_ptr->transformations & PNG_INVERT_MONO)
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
png_warning(png_ptr, "PNG_WRITE_INVERT_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_FILLER_SUPPORTED) && defined(PNG_READ_FILLER_SUPPORTED)
- if (png_ptr->transformations & PNG_FILLER)
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
png_warning(png_ptr, "PNG_WRITE_FILLER_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_PACKSWAP_SUPPORTED) && \
defined(PNG_READ_PACKSWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_PACKSWAP)
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
png_warning(png_ptr,
"PNG_WRITE_PACKSWAP_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_PACK_SUPPORTED) && defined(PNG_READ_PACK_SUPPORTED)
- if (png_ptr->transformations & PNG_PACK)
+ if ((png_ptr->transformations & PNG_PACK) != 0)
png_warning(png_ptr, "PNG_WRITE_PACK_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_SHIFT_SUPPORTED) && defined(PNG_READ_SHIFT_SUPPORTED)
- if (png_ptr->transformations & PNG_SHIFT)
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
png_warning(png_ptr, "PNG_WRITE_SHIFT_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_BGR_SUPPORTED) && defined(PNG_READ_BGR_SUPPORTED)
- if (png_ptr->transformations & PNG_BGR)
+ if ((png_ptr->transformations & PNG_BGR) != 0)
png_warning(png_ptr, "PNG_WRITE_BGR_SUPPORTED is not defined");
#endif
#if !defined(PNG_WRITE_SWAP_SUPPORTED) && defined(PNG_READ_SWAP_SUPPORTED)
- if (png_ptr->transformations & PNG_SWAP_BYTES)
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
png_warning(png_ptr, "PNG_WRITE_SWAP_SUPPORTED is not defined");
#endif
@@ -673,12 +739,13 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced and not interested in row, return */
- if (png_ptr->interlaced && (png_ptr->transformations & PNG_INTERLACE))
+ if (png_ptr->interlaced != 0 &&
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
switch (png_ptr->pass)
{
case 0:
- if (png_ptr->row_number & 0x07)
+ if ((png_ptr->row_number & 0x07) != 0)
{
png_write_finish_row(png_ptr);
return;
@@ -686,7 +753,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 1:
- if ((png_ptr->row_number & 0x07) || png_ptr->width < 5)
+ if ((png_ptr->row_number & 0x07) != 0 || png_ptr->width < 5)
{
png_write_finish_row(png_ptr);
return;
@@ -702,7 +769,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 3:
- if ((png_ptr->row_number & 0x03) || png_ptr->width < 3)
+ if ((png_ptr->row_number & 0x03) != 0 || png_ptr->width < 3)
{
png_write_finish_row(png_ptr);
return;
@@ -718,7 +785,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 5:
- if ((png_ptr->row_number & 0x01) || png_ptr->width < 2)
+ if ((png_ptr->row_number & 0x01) != 0 || png_ptr->width < 2)
{
png_write_finish_row(png_ptr);
return;
@@ -726,7 +793,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
break;
case 6:
- if (!(png_ptr->row_number & 0x01))
+ if ((png_ptr->row_number & 0x01) == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -755,16 +822,16 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
png_debug1(3, "row_info->rowbytes = %lu", (unsigned long)row_info.rowbytes);
/* Copy user's row into buffer, leaving room for filter byte. */
- png_memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
+ memcpy(png_ptr->row_buf + 1, row, row_info.rowbytes);
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Handle interlacing */
if (png_ptr->interlaced && png_ptr->pass < 6 &&
- (png_ptr->transformations & PNG_INTERLACE))
+ (png_ptr->transformations & PNG_INTERLACE) != 0)
{
png_do_write_interlace(&row_info, png_ptr->row_buf + 1, png_ptr->pass);
/* This should always get caught above, but still ... */
- if (!(row_info.width))
+ if (row_info.width == 0)
{
png_write_finish_row(png_ptr);
return;
@@ -774,7 +841,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
/* Handle other transformations */
- if (png_ptr->transformations)
+ if (png_ptr->transformations != 0)
png_do_write_transformations(png_ptr, &row_info);
#endif
@@ -795,7 +862,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
* 4. The filter_method is 64 and
* 5. The color_type is RGB or RGBA
*/
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(png_ptr->filter_type == PNG_INTRAPIXEL_DIFFERENCING))
{
/* Intrapixel differencing */
@@ -806,7 +873,8 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
/* Added at libpng-1.5.10 */
#ifdef PNG_WRITE_CHECK_FOR_INVALID_INDEX_SUPPORTED
/* Check for out-of-range palette index */
- if(row_info.color_type == PNG_COLOR_TYPE_PALETTE)
+ if (row_info.color_type == PNG_COLOR_TYPE_PALETTE &&
+ png_ptr->num_palette_max >= 0)
png_do_check_palette_indexes(png_ptr, &row_info);
#endif
@@ -820,7 +888,7 @@ png_write_row(png_structp png_ptr, png_const_bytep row)
#ifdef PNG_WRITE_FLUSH_SUPPORTED
/* Set the automatic flush interval or 0 to turn flushing off */
void PNGAPI
-png_set_flush(png_structp png_ptr, int nrows)
+png_set_flush(png_structrp png_ptr, int nrows)
{
png_debug(1, "in png_set_flush");
@@ -832,10 +900,8 @@ png_set_flush(png_structp png_ptr, int nrows)
/* Flush the current output buffers now */
void PNGAPI
-png_write_flush(png_structp png_ptr)
+png_write_flush(png_structrp png_ptr)
{
- int wrote_IDAT;
-
png_debug(1, "in png_write_flush");
if (png_ptr == NULL)
@@ -845,140 +911,41 @@ png_write_flush(png_structp png_ptr)
if (png_ptr->row_number >= png_ptr->num_rows)
return;
- do
- {
- int ret;
-
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_SYNC_FLUSH);
- wrote_IDAT = 0;
-
- /* Check for compression errors */
- if (ret != Z_OK)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
-
- if (!(png_ptr->zstream.avail_out))
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- wrote_IDAT = 1;
- }
- } while (wrote_IDAT == 1);
-
- /* If there is any data left to be output, write it into a new IDAT */
- if (png_ptr->zbuf_size != png_ptr->zstream.avail_out)
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf,
- png_ptr->zbuf_size - png_ptr->zstream.avail_out);
- }
+ png_compress_IDAT(png_ptr, NULL, 0, Z_SYNC_FLUSH);
png_ptr->flush_rows = 0;
png_flush(png_ptr);
}
-#endif /* PNG_WRITE_FLUSH_SUPPORTED */
-
-/* Free all memory used by the write */
-void PNGAPI
-png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
-{
- png_structp png_ptr = NULL;
- png_infop info_ptr = NULL;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn = NULL;
- png_voidp mem_ptr = NULL;
-#endif
-
- png_debug(1, "in png_destroy_write_struct");
-
- if (png_ptr_ptr != NULL)
- png_ptr = *png_ptr_ptr;
+#endif /* WRITE_FLUSH */
-#ifdef PNG_USER_MEM_SUPPORTED
- if (png_ptr != NULL)
- {
- free_fn = png_ptr->free_fn;
- mem_ptr = png_ptr->mem_ptr;
- }
-#endif
-
- if (info_ptr_ptr != NULL)
- info_ptr = *info_ptr_ptr;
-
- if (info_ptr != NULL)
- {
- if (png_ptr != NULL)
- {
- png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1);
-
-#ifdef PNG_HANDLE_AS_UNKNOWN_SUPPORTED
- if (png_ptr->num_chunk_list)
- {
- png_free(png_ptr, png_ptr->chunk_list);
- png_ptr->num_chunk_list = 0;
- }
-#endif
- }
-
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)info_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)info_ptr);
-#endif
- *info_ptr_ptr = NULL;
- }
-
- if (png_ptr != NULL)
- {
- png_write_destroy(png_ptr);
-#ifdef PNG_USER_MEM_SUPPORTED
- png_destroy_struct_2((png_voidp)png_ptr, (png_free_ptr)free_fn,
- (png_voidp)mem_ptr);
-#else
- png_destroy_struct((png_voidp)png_ptr);
+#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
+static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */
#endif
- *png_ptr_ptr = NULL;
- }
-}
-
-/* Free any memory used in png_ptr struct (old method) */
-void /* PRIVATE */
-png_write_destroy(png_structp png_ptr)
+/* Free any memory used in png_ptr struct without freeing the struct itself. */
+static void
+png_write_destroy(png_structrp png_ptr)
{
-#ifdef PNG_SETJMP_SUPPORTED
- jmp_buf tmp_jmp; /* Save jump buffer */
-#endif
- png_error_ptr error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_error_ptr warning_fn;
-#endif
- png_voidp error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_free_ptr free_fn;
-#endif
-
png_debug(1, "in png_write_destroy");
/* Free any memory zlib uses */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
deflateEnd(&png_ptr->zstream);
/* Free our memory. png_free checks NULL for us. */
- png_free(png_ptr, png_ptr->zbuf);
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list);
png_free(png_ptr, png_ptr->row_buf);
+ png_ptr->row_buf = NULL;
#ifdef PNG_WRITE_FILTER_SUPPORTED
png_free(png_ptr, png_ptr->prev_row);
png_free(png_ptr, png_ptr->sub_row);
png_free(png_ptr, png_ptr->up_row);
png_free(png_ptr, png_ptr->avg_row);
png_free(png_ptr, png_ptr->paeth_row);
+ png_ptr->prev_row = NULL;
+ png_ptr->sub_row = NULL;
+ png_ptr->up_row = NULL;
+ png_ptr->avg_row = NULL;
+ png_ptr->paeth_row = NULL;
#endif
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED
@@ -986,41 +953,51 @@ png_write_destroy(png_structp png_ptr)
png_reset_filter_heuristics(png_ptr);
png_free(png_ptr, png_ptr->filter_costs);
png_free(png_ptr, png_ptr->inv_filter_costs);
+ png_ptr->filter_costs = NULL;
+ png_ptr->inv_filter_costs = NULL;
#endif
-#ifdef PNG_SETJMP_SUPPORTED
- /* Reset structure */
- png_memcpy(tmp_jmp, png_ptr->longjmp_buffer, png_sizeof(jmp_buf));
+#ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ png_free(png_ptr, png_ptr->chunk_list);
+ png_ptr->chunk_list = NULL;
#endif
- error_fn = png_ptr->error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- warning_fn = png_ptr->warning_fn;
-#endif
- error_ptr = png_ptr->error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- free_fn = png_ptr->free_fn;
-#endif
+ /* The error handling and memory handling information is left intact at this
+ * point: the jmp_buf may still have to be freed. See png_destroy_png_struct
+ * for how this happens.
+ */
+}
- png_memset(png_ptr, 0, png_sizeof(png_struct));
+/* Free all memory used by the write.
+ * In libpng 1.6.0 this API changed quietly to no longer accept a NULL value for
+ * *png_ptr_ptr. Prior to 1.6.0 it would accept such a value and it would free
+ * the passed in info_structs but it would quietly fail to free any of the data
+ * inside them. In 1.6.0 it quietly does nothing (it has to be quiet because it
+ * has no png_ptr.)
+ */
+void PNGAPI
+png_destroy_write_struct(png_structpp png_ptr_ptr, png_infopp info_ptr_ptr)
+{
+ png_debug(1, "in png_destroy_write_struct");
- png_ptr->error_fn = error_fn;
-#ifdef PNG_WARNINGS_SUPPORTED
- png_ptr->warning_fn = warning_fn;
-#endif
- png_ptr->error_ptr = error_ptr;
-#ifdef PNG_USER_MEM_SUPPORTED
- png_ptr->free_fn = free_fn;
-#endif
+ if (png_ptr_ptr != NULL)
+ {
+ png_structrp png_ptr = *png_ptr_ptr;
-#ifdef PNG_SETJMP_SUPPORTED
- png_memcpy(png_ptr->longjmp_buffer, tmp_jmp, png_sizeof(jmp_buf));
-#endif
+ if (png_ptr != NULL) /* added in libpng 1.6.0 */
+ {
+ png_destroy_info_struct(png_ptr, info_ptr_ptr);
+
+ *png_ptr_ptr = NULL;
+ png_write_destroy(png_ptr);
+ png_destroy_png_struct(png_ptr);
+ }
+ }
}
/* Allow the application to select one or more row filters to use. */
void PNGAPI
-png_set_filter(png_structp png_ptr, int method, int filters)
+png_set_filter(png_structrp png_ptr, int method, int filters)
{
png_debug(1, "in png_set_filter");
@@ -1028,7 +1005,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
return;
#ifdef PNG_MNG_FEATURES_SUPPORTED
- if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
+ if ((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
(method == PNG_INTRAPIXEL_DIFFERENCING))
method = PNG_FILTER_TYPE_BASE;
@@ -1040,8 +1017,9 @@ png_set_filter(png_structp png_ptr, int method, int filters)
#ifdef PNG_WRITE_FILTER_SUPPORTED
case 5:
case 6:
- case 7: png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ case 7: png_app_error(png_ptr, "Unknown row filter for method 0");
+ /* FALL THROUGH */
+#endif /* WRITE_FILTER */
case PNG_FILTER_VALUE_NONE:
png_ptr->do_filter = PNG_FILTER_NONE; break;
@@ -1062,8 +1040,8 @@ png_set_filter(png_structp png_ptr, int method, int filters)
png_ptr->do_filter = (png_byte)filters; break;
#else
default:
- png_warning(png_ptr, "Unknown row filter for method 0");
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+ png_app_error(png_ptr, "Unknown row filter for method 0");
+#endif /* WRITE_FILTER */
}
/* If we have allocated the row_buf, this means we have already started
@@ -1072,20 +1050,22 @@ png_set_filter(png_structp png_ptr, int method, int filters)
* it is too late to start using the filters that need it, since we
* will be missing the data in the previous row. If an application
* wants to start and stop using particular filters during compression,
- * it should start out with all of the filters, and then add and
- * remove them after the start of compression.
+ * it should start out with all of the filters, and then remove them
+ * or add them back after the start of compression.
*/
if (png_ptr->row_buf != NULL)
{
#ifdef PNG_WRITE_FILTER_SUPPORTED
- if ((png_ptr->do_filter & PNG_FILTER_SUB) && png_ptr->sub_row == NULL)
+ if ((png_ptr->do_filter & PNG_FILTER_SUB) != 0 &&
+ png_ptr->sub_row == NULL)
{
png_ptr->sub_row = (png_bytep)png_malloc(png_ptr,
(png_ptr->rowbytes + 1));
png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB;
}
- if ((png_ptr->do_filter & PNG_FILTER_UP) && png_ptr->up_row == NULL)
+ if ((png_ptr->do_filter & PNG_FILTER_UP) != 0 &&
+ png_ptr->up_row == NULL)
{
if (png_ptr->prev_row == NULL)
{
@@ -1102,7 +1082,8 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
}
- if ((png_ptr->do_filter & PNG_FILTER_AVG) && png_ptr->avg_row == NULL)
+ if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0 &&
+ png_ptr->avg_row == NULL)
{
if (png_ptr->prev_row == NULL)
{
@@ -1119,7 +1100,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
}
- if ((png_ptr->do_filter & PNG_FILTER_PAETH) &&
+ if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0 &&
png_ptr->paeth_row == NULL)
{
if (png_ptr->prev_row == NULL)
@@ -1137,7 +1118,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
}
if (png_ptr->do_filter == PNG_NO_FILTERS)
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
png_ptr->do_filter = PNG_FILTER_NONE;
}
}
@@ -1155,7 +1136,7 @@ png_set_filter(png_structp png_ptr, int method, int filters)
#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */
/* Convenience reset API. */
static void
-png_reset_filter_heuristics(png_structp png_ptr)
+png_reset_filter_heuristics(png_structrp png_ptr)
{
/* Clear out any old values in the 'weights' - this must be done because if
* the app calls set_filter_heuristics multiple times with different
@@ -1188,7 +1169,7 @@ png_reset_filter_heuristics(png_structp png_ptr)
}
static int
-png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
+png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int num_weights)
{
if (png_ptr == NULL)
@@ -1208,7 +1189,7 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
if (num_weights > 0)
{
png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_byte) * num_weights));
+ (png_uint_32)((sizeof (png_byte)) * num_weights));
/* To make sure that the weighting starts out fairly */
for (i = 0; i < num_weights; i++)
@@ -1217,10 +1198,10 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
}
png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ (png_uint_32)((sizeof (png_uint_16)) * num_weights));
png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * num_weights));
+ (png_uint_32)((sizeof (png_uint_16)) * num_weights));
for (i = 0; i < num_weights; i++)
{
@@ -1238,10 +1219,10 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
if (png_ptr->filter_costs == NULL)
{
png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+ (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr,
- (png_uint_32)(png_sizeof(png_uint_16) * PNG_FILTER_VALUE_LAST));
+ (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST));
}
for (i = 0; i < PNG_FILTER_VALUE_LAST; i++)
@@ -1271,7 +1252,7 @@ png_init_filter_heuristics(png_structp png_ptr, int heuristic_method,
/* Provide floating and fixed point APIs */
#ifdef PNG_FLOATING_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_doublep filter_weights,
png_const_doublep filter_costs)
{
@@ -1280,7 +1261,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
/* The internal API allocates all the arrays and ensures that the elements of
* those arrays are set to the default value.
*/
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
+ if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0)
return;
/* If using the weighted method copy in the weights. */
@@ -1326,7 +1307,7 @@ png_set_filter_heuristics(png_structp png_ptr, int heuristic_method,
#ifdef PNG_FIXED_POINT_SUPPORTED
void PNGAPI
-png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
+png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method,
int num_weights, png_const_fixed_point_p filter_weights,
png_const_fixed_point_p filter_costs)
{
@@ -1335,7 +1316,7 @@ png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
/* The internal API allocates all the arrays and ensures that the elements of
* those arrays are set to the default value.
*/
- if (!png_init_filter_heuristics(png_ptr, heuristic_method, num_weights))
+ if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0)
return;
/* If using the weighted method copy in the weights. */
@@ -1389,40 +1370,41 @@ png_set_filter_heuristics_fixed(png_structp png_ptr, int heuristic_method,
}
}
#endif /* FIXED_POINT */
-#endif /* PNG_WRITE_WEIGHTED_FILTER_SUPPORTED */
+#endif /* WRITE_WEIGHTED_FILTER */
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
void PNGAPI
-png_set_compression_level(png_structp png_ptr, int level)
+png_set_compression_level(png_structrp png_ptr, int level)
{
png_debug(1, "in png_set_compression_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_LEVEL;
png_ptr->zlib_level = level;
}
void PNGAPI
-png_set_compression_mem_level(png_structp png_ptr, int mem_level)
+png_set_compression_mem_level(png_structrp png_ptr, int mem_level)
{
png_debug(1, "in png_set_compression_mem_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL;
png_ptr->zlib_mem_level = mem_level;
}
void PNGAPI
-png_set_compression_strategy(png_structp png_ptr, int strategy)
+png_set_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_compression_strategy");
if (png_ptr == NULL)
return;
+ /* The flag setting here prevents the libpng dynamic selection of strategy.
+ */
png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_STRATEGY;
png_ptr->zlib_strategy = strategy;
}
@@ -1431,80 +1413,82 @@ png_set_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_compression_window_bits(png_structrp png_ptr, int window_bits)
{
if (png_ptr == NULL)
return;
+ /* Prior to 1.6.0 this would warn but then set the window_bits value. This
+ * meant that negative window bits values could be selected that would cause
+ * libpng to write a non-standard PNG file with raw deflate or gzip
+ * compressed IDAT or ancillary chunks. Such files can be read and there is
+ * no warning on read, so this seems like a very bad idea.
+ */
if (window_bits > 15)
+ {
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#ifndef WBITS_8_OK
- /* Avoid libpng bug with 256-byte windows */
- if (window_bits == 8)
- {
- png_warning(png_ptr, "Compression window is being reset to 512");
- window_bits = 9;
- }
-
-#endif
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS;
png_ptr->zlib_window_bits = window_bits;
}
void PNGAPI
-png_set_compression_method(png_structp png_ptr, int method)
+png_set_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_compression_method");
if (png_ptr == NULL)
return;
+ /* This would produce an invalid PNG file if it worked, but it doesn't and
+ * deflate will fault it, so it is harmless to just warn here.
+ */
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
- png_ptr->flags |= PNG_FLAG_ZLIB_CUSTOM_METHOD;
png_ptr->zlib_method = method;
}
+#endif /* WRITE_CUSTOMIZE_COMPRESSION */
/* The following were added to libpng-1.5.4 */
#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
void PNGAPI
-png_set_text_compression_level(png_structp png_ptr, int level)
+png_set_text_compression_level(png_structrp png_ptr, int level)
{
png_debug(1, "in png_set_text_compression_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_LEVEL;
png_ptr->zlib_text_level = level;
}
void PNGAPI
-png_set_text_compression_mem_level(png_structp png_ptr, int mem_level)
+png_set_text_compression_mem_level(png_structrp png_ptr, int mem_level)
{
png_debug(1, "in png_set_text_compression_mem_level");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL;
png_ptr->zlib_text_mem_level = mem_level;
}
void PNGAPI
-png_set_text_compression_strategy(png_structp png_ptr, int strategy)
+png_set_text_compression_strategy(png_structrp png_ptr, int strategy)
{
png_debug(1, "in png_set_text_compression_strategy");
if (png_ptr == NULL)
return;
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_STRATEGY;
png_ptr->zlib_text_strategy = strategy;
}
@@ -1512,32 +1496,28 @@ png_set_text_compression_strategy(png_structp png_ptr, int strategy)
* smaller value of window_bits if it can do so safely.
*/
void PNGAPI
-png_set_text_compression_window_bits(png_structp png_ptr, int window_bits)
+png_set_text_compression_window_bits(png_structrp png_ptr, int window_bits)
{
if (png_ptr == NULL)
return;
if (window_bits > 15)
+ {
png_warning(png_ptr, "Only compression windows <= 32k supported by PNG");
+ window_bits = 15;
+ }
else if (window_bits < 8)
+ {
png_warning(png_ptr, "Only compression windows >= 256 supported by PNG");
+ window_bits = 8;
+ }
-#ifndef WBITS_8_OK
- /* Avoid libpng bug with 256-byte windows */
- if (window_bits == 8)
- {
- png_warning(png_ptr, "Text compression window is being reset to 512");
- window_bits = 9;
- }
-
-#endif
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS;
png_ptr->zlib_text_window_bits = window_bits;
}
void PNGAPI
-png_set_text_compression_method(png_structp png_ptr, int method)
+png_set_text_compression_method(png_structrp png_ptr, int method)
{
png_debug(1, "in png_set_text_compression_method");
@@ -1547,14 +1527,13 @@ png_set_text_compression_method(png_structp png_ptr, int method)
if (method != 8)
png_warning(png_ptr, "Only compression method 8 is supported by PNG");
- png_ptr->flags |= PNG_FLAG_ZTXT_CUSTOM_METHOD;
png_ptr->zlib_text_method = method;
}
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
+#endif /* WRITE_CUSTOMIZE_ZTXT_COMPRESSION */
/* end of API added to libpng-1.5.4 */
void PNGAPI
-png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
+png_set_write_status_fn(png_structrp png_ptr, png_write_status_ptr write_row_fn)
{
if (png_ptr == NULL)
return;
@@ -1564,7 +1543,7 @@ png_set_write_status_fn(png_structp png_ptr, png_write_status_ptr write_row_fn)
#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
void PNGAPI
-png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
+png_set_write_user_transform_fn(png_structrp png_ptr, png_user_transform_ptr
write_user_transform_fn)
{
png_debug(1, "in png_set_write_user_transform_fn");
@@ -1580,88 +1559,901 @@ png_set_write_user_transform_fn(png_structp png_ptr, png_user_transform_ptr
#ifdef PNG_INFO_IMAGE_SUPPORTED
void PNGAPI
-png_write_png(png_structp png_ptr, png_infop info_ptr,
+png_write_png(png_structrp png_ptr, png_inforp info_ptr,
int transforms, voidp params)
{
if (png_ptr == NULL || info_ptr == NULL)
return;
+ if ((info_ptr->valid & PNG_INFO_IDAT) == 0)
+ {
+ png_app_error(png_ptr, "no rows for png_write_image to write");
+ return;
+ }
+
/* Write the file header information. */
png_write_info(png_ptr, info_ptr);
/* ------ these transformations don't touch the info structure ------- */
-#ifdef PNG_WRITE_INVERT_SUPPORTED
/* Invert monochrome pixels */
- if (transforms & PNG_TRANSFORM_INVERT_MONO)
+ if ((transforms & PNG_TRANSFORM_INVERT_MONO) != 0)
+#ifdef PNG_WRITE_INVERT_SUPPORTED
png_set_invert_mono(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_MONO not supported");
#endif
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
/* Shift the pixels up to a legal bit depth and fill in
* as appropriate to correctly scale the image.
*/
- if ((transforms & PNG_TRANSFORM_SHIFT)
- && (info_ptr->valid & PNG_INFO_sBIT))
- png_set_shift(png_ptr, &info_ptr->sig_bit);
+ if ((transforms & PNG_TRANSFORM_SHIFT) != 0)
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((info_ptr->valid & PNG_INFO_sBIT) != 0)
+ png_set_shift(png_ptr, &info_ptr->sig_bit);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SHIFT not supported");
#endif
-#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes */
- if (transforms & PNG_TRANSFORM_PACKING)
- png_set_packing(png_ptr);
+ if ((transforms & PNG_TRANSFORM_PACKING) != 0)
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ png_set_packing(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKING not supported");
#endif
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
/* Swap location of alpha bytes from ARGB to RGBA */
- if (transforms & PNG_TRANSFORM_SWAP_ALPHA)
+ if ((transforms & PNG_TRANSFORM_SWAP_ALPHA) != 0)
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
png_set_swap_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ALPHA not supported");
#endif
+ /* Remove a filler (X) from XRGB/RGBX/AG/GA into to convert it into
+ * RGB, note that the code expects the input color type to be G or RGB; no
+ * alpha channel.
+ */
+ if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER|
+ PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0)
+ {
#ifdef PNG_WRITE_FILLER_SUPPORTED
- /* Pack XRGB/RGBX/ARGB/RGBA into RGB (4 channels -> 3 channels) */
- if (transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER)
- png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0)
+ {
+ if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_app_error(png_ptr,
+ "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported");
+
+ /* Continue if ignored - this is the pre-1.6.10 behavior */
+ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER);
+ }
- else if (transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE)
- png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+ else if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0)
+ png_set_filler(png_ptr, 0, PNG_FILLER_BEFORE);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_STRIP_FILLER not supported");
#endif
+ }
-#ifdef PNG_WRITE_BGR_SUPPORTED
/* Flip BGR pixels to RGB */
- if (transforms & PNG_TRANSFORM_BGR)
+ if ((transforms & PNG_TRANSFORM_BGR) != 0)
+#ifdef PNG_WRITE_BGR_SUPPORTED
png_set_bgr(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_BGR not supported");
#endif
-#ifdef PNG_WRITE_SWAP_SUPPORTED
/* Swap bytes of 16-bit files to most significant byte first */
- if (transforms & PNG_TRANSFORM_SWAP_ENDIAN)
+ if ((transforms & PNG_TRANSFORM_SWAP_ENDIAN) != 0)
+#ifdef PNG_WRITE_SWAP_SUPPORTED
png_set_swap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported");
#endif
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
/* Swap bits of 1, 2, 4 bit packed pixel formats */
- if (transforms & PNG_TRANSFORM_PACKSWAP)
+ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0)
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
png_set_packswap(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_PACKSWAP not supported");
#endif
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
/* Invert the alpha channel from opacity to transparency */
- if (transforms & PNG_TRANSFORM_INVERT_ALPHA)
+ if ((transforms & PNG_TRANSFORM_INVERT_ALPHA) != 0)
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
png_set_invert_alpha(png_ptr);
+#else
+ png_app_error(png_ptr, "PNG_TRANSFORM_INVERT_ALPHA not supported");
#endif
/* ----------------------- end of transformations ------------------- */
/* Write the bits */
- if (info_ptr->valid & PNG_INFO_IDAT)
- png_write_image(png_ptr, info_ptr->row_pointers);
+ png_write_image(png_ptr, info_ptr->row_pointers);
/* It is REQUIRED to call this to finish writing the rest of the file */
png_write_end(png_ptr, info_ptr);
- PNG_UNUSED(transforms) /* Quiet compiler warnings */
PNG_UNUSED(params)
}
#endif
-#endif /* PNG_WRITE_SUPPORTED */
+
+
+#ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED
+#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */
+/* Initialize the write structure - general purpose utility. */
+static int
+png_image_write_init(png_imagep image)
+{
+ png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image,
+ png_safe_error, png_safe_warning);
+
+ if (png_ptr != NULL)
+ {
+ png_infop info_ptr = png_create_info_struct(png_ptr);
+
+ if (info_ptr != NULL)
+ {
+ png_controlp control = png_voidcast(png_controlp,
+ png_malloc_warn(png_ptr, (sizeof *control)));
+
+ if (control != NULL)
+ {
+ memset(control, 0, (sizeof *control));
+
+ control->png_ptr = png_ptr;
+ control->info_ptr = info_ptr;
+ control->for_write = 1;
+
+ image->opaque = control;
+ return 1;
+ }
+
+ /* Error clean up */
+ png_destroy_info_struct(png_ptr, &info_ptr);
+ }
+
+ png_destroy_write_struct(&png_ptr, NULL);
+ }
+
+ return png_image_error(image, "png_image_write_: out of memory");
+}
+
+/* Arguments to png_image_write_main: */
+typedef struct
+{
+ /* Arguments: */
+ png_imagep image;
+ png_const_voidp buffer;
+ png_int_32 row_stride;
+ png_const_voidp colormap;
+ int convert_to_8bit;
+ /* Local variables: */
+ png_const_voidp first_row;
+ ptrdiff_t row_bytes;
+ png_voidp local_row;
+} png_image_write_control;
+
+/* Write png_uint_16 input to a 16-bit PNG; the png_ptr has already been set to
+ * do any necessary byte swapping. The component order is defined by the
+ * png_image format value.
+ */
+static int
+png_write_image_16bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row);
+ png_uint_16p row_end;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+ int aindex = 0;
+ png_uint_32 y = image->height;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+
+ else
+# endif
+ aindex = channels;
+ }
+
+ else
+ png_error(png_ptr, "png_write_image: internal call error");
+
+ /* Work out the output row end and count over this, note that the increment
+ * above to 'row' means that row_end can actually be beyond the end of the
+ * row; this is correct.
+ */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_uint_16p out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ const png_uint_16 alpha = in_ptr[aindex];
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ out_ptr[aindex] = alpha;
+
+ /* Calculate a reciprocal. The correct calculation is simply
+ * component/alpha*65535 << 15. (I.e. 15 bits of precision); this
+ * allows correct rounding by adding .5 before the shift. 'reciprocal'
+ * is only initialized when required.
+ */
+ if (alpha > 0 && alpha < 65535)
+ reciprocal = ((0xffff<<15)+(alpha>>1))/alpha;
+
+ c = channels;
+ do /* always at least one channel */
+ {
+ png_uint_16 component = *in_ptr++;
+
+ /* The following gives 65535 for an alpha of 0, which is fine,
+ * otherwise if 0/0 is represented as some other value there is more
+ * likely to be a discontinuity which will probably damage
+ * compression when moving from a fully transparent area to a
+ * nearly transparent one. (The assumption here is that opaque
+ * areas tend not to be 0 intensity.)
+ */
+ if (component >= alpha)
+ component = 65535;
+
+ /* component<alpha, so component/alpha is less than one and
+ * component*reciprocal is less than 2^31.
+ */
+ else if (component > 0 && alpha < 65535)
+ {
+ png_uint_32 calc = component * reciprocal;
+ calc += 16384; /* round to nearest */
+ component = (png_uint_16)(calc >> 15);
+ }
+
+ *out_ptr++ = component;
+ }
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ }
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep, display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+
+ return 1;
+}
+
+/* Given 16-bit input (1 to 4 channels) write 8-bit output. If an alpha channel
+ * is present it must be removed from the components, the components are then
+ * written in sRGB encoding. No components are added or removed.
+ *
+ * Calculate an alpha reciprocal to reverse pre-multiplication. As above the
+ * calculation can be done to 15 bits of accuracy; however, the output needs to
+ * be scaled in the range 0..255*65535, so include that scaling here.
+ */
+#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha)
+
+static png_byte
+png_unpremultiply(png_uint_32 component, png_uint_32 alpha,
+ png_uint_32 reciprocal/*from the above macro*/)
+{
+ /* The following gives 1.0 for an alpha of 0, which is fine, otherwise if 0/0
+ * is represented as some other value there is more likely to be a
+ * discontinuity which will probably damage compression when moving from a
+ * fully transparent area to a nearly transparent one. (The assumption here
+ * is that opaque areas tend not to be 0 intensity.)
+ *
+ * There is a rounding problem here; if alpha is less than 128 it will end up
+ * as 0 when scaled to 8 bits. To avoid introducing spurious colors into the
+ * output change for this too.
+ */
+ if (component >= alpha || alpha < 128)
+ return 255;
+
+ /* component<alpha, so component/alpha is less than one and
+ * component*reciprocal is less than 2^31.
+ */
+ else if (component > 0)
+ {
+ /* The test is that alpha/257 (rounded) is less than 255, the first value
+ * that becomes 255 is 65407.
+ * NOTE: this must agree with the PNG_DIV257 macro (which must, therefore,
+ * be exact!) [Could also test reciprocal != 0]
+ */
+ if (alpha < 65407)
+ {
+ component *= reciprocal;
+ component += 64; /* round to nearest */
+ component >>= 7;
+ }
+
+ else
+ component *= 255;
+
+ /* Convert the component to sRGB. */
+ return (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ else
+ return 0;
+}
+
+static int
+png_write_image_8bit(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+
+ png_const_uint_16p input_row = png_voidcast(png_const_uint_16p,
+ display->first_row);
+ png_bytep output_row = png_voidcast(png_bytep, display->local_row);
+ png_uint_32 y = image->height;
+ const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1;
+
+ if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ {
+ png_bytep row_end;
+ int aindex;
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ aindex = -1;
+ ++input_row; /* To point to the first component */
+ ++output_row;
+ }
+
+ else
+# endif
+ aindex = channels;
+
+ /* Use row_end in place of a loop counter: */
+ row_end = output_row + image->width * (channels+1);
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_16 alpha = in_ptr[aindex];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+ int c;
+
+ /* Scale and write the alpha channel. */
+ out_ptr[aindex] = alphabyte;
+
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = UNP_RECIPROCAL(alpha);
+
+ c = channels;
+ do /* always at least one channel */
+ *out_ptr++ = png_unpremultiply(*in_ptr++, alpha, reciprocal);
+ while (--c > 0);
+
+ /* Skip to next component (skip the intervening alpha channel) */
+ ++in_ptr;
+ ++out_ptr;
+ } /* while out_ptr < row_end */
+
+ png_write_row(png_ptr, png_voidcast(png_const_bytep,
+ display->local_row));
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ } /* while y */
+ }
+
+ else
+ {
+ /* No alpha channel, so the row_end really is the end of the row and it
+ * is sufficient to loop over the components one by one.
+ */
+ png_bytep row_end = output_row + image->width * channels;
+
+ while (y-- > 0)
+ {
+ png_const_uint_16p in_ptr = input_row;
+ png_bytep out_ptr = output_row;
+
+ while (out_ptr < row_end)
+ {
+ png_uint_32 component = *in_ptr++;
+
+ component *= 255;
+ *out_ptr++ = (png_byte)PNG_sRGB_FROM_LINEAR(component);
+ }
+
+ png_write_row(png_ptr, output_row);
+ input_row += display->row_bytes/(sizeof (png_uint_16));
+ }
+ }
+
+ return 1;
+}
+
+static void
+png_image_set_PLTE(png_image_write_control *display)
+{
+ const png_imagep image = display->image;
+ const void *cmap = display->colormap;
+ const int entries = image->colormap_entries > 256 ? 256 :
+ (int)image->colormap_entries;
+
+ /* NOTE: the caller must check for cmap != NULL and entries != 0 */
+ const png_uint_32 format = image->format;
+ const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format);
+
+# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\
+ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED)
+ const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 &&
+ (format & PNG_FORMAT_FLAG_ALPHA) != 0;
+# else
+# define afirst 0
+# endif
+
+# ifdef PNG_FORMAT_BGR_SUPPORTED
+ const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0;
+# else
+# define bgr 0
+# endif
+
+ int i, num_trans;
+ png_color palette[256];
+ png_byte tRNS[256];
+
+ memset(tRNS, 255, (sizeof tRNS));
+ memset(palette, 0, (sizeof palette));
+
+ for (i=num_trans=0; i<entries; ++i)
+ {
+ /* This gets automatically converted to sRGB with reversal of the
+ * pre-multiplication if the color-map has an alpha channel.
+ */
+ if ((format & PNG_FORMAT_FLAG_LINEAR) != 0)
+ {
+ png_const_uint_16p entry = png_voidcast(png_const_uint_16p, cmap);
+
+ entry += i * channels;
+
+ if ((channels & 1) != 0) /* no alpha */
+ {
+ if (channels >= 3) /* RGB */
+ {
+ palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[(2 ^ bgr)]);
+ palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[1]);
+ palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 *
+ entry[bgr]);
+ }
+
+ else /* Gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ (png_byte)PNG_sRGB_FROM_LINEAR(255 * *entry);
+ }
+
+ else /* alpha */
+ {
+ png_uint_16 alpha = entry[afirst ? 0 : channels-1];
+ png_byte alphabyte = (png_byte)PNG_DIV257(alpha);
+ png_uint_32 reciprocal = 0;
+
+ /* Calculate a reciprocal, as in the png_write_image_8bit code above
+ * this is designed to produce a value scaled to 255*65535 when
+ * divided by 128 (i.e. asr 7).
+ */
+ if (alphabyte > 0 && alphabyte < 255)
+ reciprocal = (((0xffff*0xff)<<7)+(alpha>>1))/alpha;
+
+ tRNS[i] = alphabyte;
+ if (alphabyte < 255)
+ num_trans = i+1;
+
+ if (channels >= 3) /* RGB */
+ {
+ palette[i].blue = png_unpremultiply(entry[afirst + (2 ^ bgr)],
+ alpha, reciprocal);
+ palette[i].green = png_unpremultiply(entry[afirst + 1], alpha,
+ reciprocal);
+ palette[i].red = png_unpremultiply(entry[afirst + bgr], alpha,
+ reciprocal);
+ }
+
+ else /* gray */
+ palette[i].blue = palette[i].red = palette[i].green =
+ png_unpremultiply(entry[afirst], alpha, reciprocal);
+ }
+ }
+
+ else /* Color-map has sRGB values */
+ {
+ png_const_bytep entry = png_voidcast(png_const_bytep, cmap);
+
+ entry += i * channels;
+
+ switch (channels)
+ {
+ case 4:
+ tRNS[i] = entry[afirst ? 0 : 3];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 3:
+ palette[i].blue = entry[afirst + (2 ^ bgr)];
+ palette[i].green = entry[afirst + 1];
+ palette[i].red = entry[afirst + bgr];
+ break;
+
+ case 2:
+ tRNS[i] = entry[1 ^ afirst];
+ if (tRNS[i] < 255)
+ num_trans = i+1;
+ /* FALL THROUGH */
+ case 1:
+ palette[i].blue = palette[i].red = palette[i].green =
+ entry[afirst];
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+# ifdef afirst
+# undef afirst
+# endif
+# ifdef bgr
+# undef bgr
+# endif
+
+ png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette,
+ entries);
+
+ if (num_trans > 0)
+ png_set_tRNS(image->opaque->png_ptr, image->opaque->info_ptr, tRNS,
+ num_trans, NULL);
+
+ image->colormap_entries = entries;
+}
+
+static int
+png_image_write_main(png_voidp argument)
+{
+ png_image_write_control *display = png_voidcast(png_image_write_control*,
+ argument);
+ png_imagep image = display->image;
+ png_structrp png_ptr = image->opaque->png_ptr;
+ png_inforp info_ptr = image->opaque->info_ptr;
+ png_uint_32 format = image->format;
+
+ /* The following four ints are actually booleans */
+ int colormap = (format & PNG_FORMAT_FLAG_COLORMAP);
+ int linear = !colormap && (format & PNG_FORMAT_FLAG_LINEAR); /* input */
+ int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA);
+ int write_16bit = linear && !colormap && (display->convert_to_8bit == 0);
+
+# ifdef PNG_BENIGN_ERRORS_SUPPORTED
+ /* Make sure we error out on any bad situation */
+ png_set_benign_errors(png_ptr, 0/*error*/);
+# endif
+
+ /* Default the 'row_stride' parameter if required. */
+ if (display->row_stride == 0)
+ display->row_stride = PNG_IMAGE_ROW_STRIDE(*image);
+
+ /* Set the required transforms then write the rows in the correct order. */
+ if ((format & PNG_FORMAT_FLAG_COLORMAP) != 0)
+ {
+ if (display->colormap != NULL && image->colormap_entries > 0)
+ {
+ png_uint_32 entries = image->colormap_entries;
+
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ entries > 16 ? 8 : (entries > 4 ? 4 : (entries > 2 ? 2 : 1)),
+ PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ png_image_set_PLTE(display);
+ }
+
+ else
+ png_error(image->opaque->png_ptr,
+ "no color-map for color-mapped image");
+ }
+
+ else
+ png_set_IHDR(png_ptr, info_ptr, image->width, image->height,
+ write_16bit ? 16 : 8,
+ ((format & PNG_FORMAT_FLAG_COLOR) ? PNG_COLOR_MASK_COLOR : 0) +
+ ((format & PNG_FORMAT_FLAG_ALPHA) ? PNG_COLOR_MASK_ALPHA : 0),
+ PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+
+ /* Counter-intuitively the data transformations must be called *after*
+ * png_write_info, not before as in the read code, but the 'set' functions
+ * must still be called before. Just set the color space information, never
+ * write an interlaced image.
+ */
+
+ if (write_16bit != 0)
+ {
+ /* The gamma here is 1.0 (linear) and the cHRM chunk matches sRGB. */
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_LINEAR);
+
+ if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_cHRM_fixed(png_ptr, info_ptr,
+ /* color x y */
+ /* white */ 31270, 32900,
+ /* red */ 64000, 33000,
+ /* green */ 30000, 60000,
+ /* blue */ 15000, 6000
+ );
+ }
+
+ else if ((image->flags & PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB) == 0)
+ png_set_sRGB(png_ptr, info_ptr, PNG_sRGB_INTENT_PERCEPTUAL);
+
+ /* Else writing an 8-bit file and the *colors* aren't sRGB, but the 8-bit
+ * space must still be gamma encoded.
+ */
+ else
+ png_set_gAMA_fixed(png_ptr, info_ptr, PNG_GAMMA_sRGB_INVERSE);
+
+ /* Write the file header. */
+ png_write_info(png_ptr, info_ptr);
+
+ /* Now set up the data transformations (*after* the header is written),
+ * remove the handled transformations from the 'format' flags for checking.
+ *
+ * First check for a little endian system if writing 16 bit files.
+ */
+ if (write_16bit != 0)
+ {
+ PNG_CONST png_uint_16 le = 0x0001;
+
+ if ((*(png_const_bytep) & le) != 0)
+ png_set_swap(png_ptr);
+ }
+
+# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_BGR) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0)
+ png_set_bgr(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_BGR;
+ }
+# endif
+
+# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ if ((format & PNG_FORMAT_FLAG_AFIRST) != 0)
+ {
+ if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0)
+ png_set_swap_alpha(png_ptr);
+ format &= ~PNG_FORMAT_FLAG_AFIRST;
+ }
+# endif
+
+ /* If there are 16 or fewer color-map entries we wrote a lower bit depth
+ * above, but the application data is still byte packed.
+ */
+ if (colormap != 0 && image->colormap_entries <= 16)
+ png_set_packing(png_ptr);
+
+ /* That should have handled all (both) the transforms. */
+ if ((format & ~(png_uint_32)(PNG_FORMAT_FLAG_COLOR | PNG_FORMAT_FLAG_LINEAR |
+ PNG_FORMAT_FLAG_ALPHA | PNG_FORMAT_FLAG_COLORMAP)) != 0)
+ png_error(png_ptr, "png_write_image: unsupported transformation");
+
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->buffer);
+ ptrdiff_t row_bytes = display->row_stride;
+
+ if (linear != 0)
+ row_bytes *= (sizeof (png_uint_16));
+
+ if (row_bytes < 0)
+ row += (image->height-1) * (-row_bytes);
+
+ display->first_row = row;
+ display->row_bytes = row_bytes;
+ }
+
+ /* Apply 'fast' options if the flag is set. */
+ if ((image->flags & PNG_IMAGE_FLAG_FAST) != 0)
+ {
+ png_set_filter(png_ptr, PNG_FILTER_TYPE_BASE, PNG_NO_FILTERS);
+ /* NOTE: determined by experiment using pngstest, this reflects some
+ * balance between the time to write the image once and the time to read
+ * it about 50 times. The speed-up in pngstest was about 10-20% of the
+ * total (user) time on a heavily loaded system.
+ */
+#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED
+ png_set_compression_level(png_ptr, 3);
+#endif
+ }
+
+ /* Check for the cases that currently require a pre-transform on the row
+ * before it is written. This only applies when the input is 16-bit and
+ * either there is an alpha channel or it is converted to 8-bit.
+ */
+ if ((linear != 0 && alpha != 0 ) ||
+ (colormap == 0 && display->convert_to_8bit != 0))
+ {
+ png_bytep row = png_voidcast(png_bytep, png_malloc(png_ptr,
+ png_get_rowbytes(png_ptr, info_ptr)));
+ int result;
+
+ display->local_row = row;
+ if (write_16bit != 0)
+ result = png_safe_execute(image, png_write_image_16bit, display);
+ else
+ result = png_safe_execute(image, png_write_image_8bit, display);
+ display->local_row = NULL;
+
+ png_free(png_ptr, row);
+
+ /* Skip the 'write_end' on error: */
+ if (result == 0)
+ return 0;
+ }
+
+ /* Otherwise this is the case where the input is in a format currently
+ * supported by the rest of the libpng write code; call it directly.
+ */
+ else
+ {
+ png_const_bytep row = png_voidcast(png_const_bytep, display->first_row);
+ ptrdiff_t row_bytes = display->row_bytes;
+ png_uint_32 y = image->height;
+
+ while (y-- > 0)
+ {
+ png_write_row(png_ptr, row);
+ row += row_bytes;
+ }
+ }
+
+ png_write_end(png_ptr, info_ptr);
+ return 1;
+}
+
+int PNGAPI
+png_image_write_to_stdio(png_imagep image, FILE *file, int convert_to_8bit,
+ const void *buffer, png_int_32 row_stride, const void *colormap)
+{
+ /* Write the image to the given (FILE*). */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file != NULL)
+ {
+ if (png_image_write_init(image) != 0)
+ {
+ png_image_write_control display;
+ int result;
+
+ /* This is slightly evil, but png_init_io doesn't do anything other
+ * than this and we haven't changed the standard IO functions so
+ * this saves a 'safe' function.
+ */
+ image->opaque->png_ptr->io_ptr = file;
+
+ memset(&display, 0, (sizeof display));
+ display.image = image;
+ display.buffer = buffer;
+ display.row_stride = row_stride;
+ display.colormap = colormap;
+ display.convert_to_8bit = convert_to_8bit;
+
+ result = png_safe_execute(image, png_image_write_main, &display);
+ png_image_free(image);
+ return result;
+ }
+
+ else
+ return 0;
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_stdio: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_stdio: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+
+int PNGAPI
+png_image_write_to_file(png_imagep image, const char *file_name,
+ int convert_to_8bit, const void *buffer, png_int_32 row_stride,
+ const void *colormap)
+{
+ /* Write the image to the named file. */
+ if (image != NULL && image->version == PNG_IMAGE_VERSION)
+ {
+ if (file_name != NULL)
+ {
+ FILE *fp = fopen(file_name, "wb");
+
+ if (fp != NULL)
+ {
+ if (png_image_write_to_stdio(image, fp, convert_to_8bit, buffer,
+ row_stride, colormap) != 0)
+ {
+ int error; /* from fflush/fclose */
+
+ /* Make sure the file is flushed correctly. */
+ if (fflush(fp) == 0 && ferror(fp) == 0)
+ {
+ if (fclose(fp) == 0)
+ return 1;
+
+ error = errno; /* from fclose */
+ }
+
+ else
+ {
+ error = errno; /* from fflush or ferror */
+ (void)fclose(fp);
+ }
+
+ (void)remove(file_name);
+ /* The image has already been cleaned up; this is just used to
+ * set the error (because the original write succeeded).
+ */
+ return png_image_error(image, strerror(error));
+ }
+
+ else
+ {
+ /* Clean up: just the opened file. */
+ (void)fclose(fp);
+ (void)remove(file_name);
+ return 0;
+ }
+ }
+
+ else
+ return png_image_error(image, strerror(errno));
+ }
+
+ else
+ return png_image_error(image,
+ "png_image_write_to_file: invalid argument");
+ }
+
+ else if (image != NULL)
+ return png_image_error(image,
+ "png_image_write_to_file: incorrect PNG_IMAGE_VERSION");
+
+ else
+ return 0;
+}
+#endif /* STDIO */
+#endif /* SIMPLIFIED_WRITE */
+#endif /* WRITE */
diff --git a/src/3rdparty/libpng/pngwtran.c b/src/3rdparty/libpng/pngwtran.c
index 96608efcb4..db82e27bce 100644
--- a/src/3rdparty/libpng/pngwtran.c
+++ b/src/3rdparty/libpng/pngwtran.c
@@ -1,8 +1,8 @@
/* pngwtran.c - transforms the data in a row for PNG writers
*
- * Last changed in libpng 1.5.6 [November 3, 2011]
- * Copyright (c) 1998-2011 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -14,90 +14,14 @@
#include "pngpriv.h"
#ifdef PNG_WRITE_SUPPORTED
-
#ifdef PNG_WRITE_TRANSFORMS_SUPPORTED
-/* Transform the data according to the user's wishes. The order of
- * transformations is significant.
- */
-void /* PRIVATE */
-png_do_write_transformations(png_structp png_ptr, png_row_infop row_info)
-{
- png_debug(1, "in png_do_write_transformations");
-
- if (png_ptr == NULL)
- return;
-
-#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
- if (png_ptr->transformations & PNG_USER_TRANSFORM)
- if (png_ptr->write_user_transform_fn != NULL)
- (*(png_ptr->write_user_transform_fn)) /* User write transform
- function */
- (png_ptr, /* png_ptr */
- row_info, /* row_info: */
- /* png_uint_32 width; width of row */
- /* png_size_t rowbytes; number of bytes in row */
- /* png_byte color_type; color type of pixels */
- /* png_byte bit_depth; bit depth of samples */
- /* png_byte channels; number of channels (1-4) */
- /* png_byte pixel_depth; bits per pixel (depth*channels) */
- png_ptr->row_buf + 1); /* start of pixel data for row */
-#endif
-
-#ifdef PNG_WRITE_FILLER_SUPPORTED
- if (png_ptr->transformations & PNG_FILLER)
- png_do_strip_channel(row_info, png_ptr->row_buf + 1,
- !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
-#endif
-
-#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
- if (png_ptr->transformations & PNG_PACKSWAP)
- png_do_packswap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_PACK_SUPPORTED
- if (png_ptr->transformations & PNG_PACK)
- png_do_pack(row_info, png_ptr->row_buf + 1,
- (png_uint_32)png_ptr->bit_depth);
-#endif
-
-#ifdef PNG_WRITE_SWAP_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_BYTES)
- png_do_swap(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_SHIFT_SUPPORTED
- if (png_ptr->transformations & PNG_SHIFT)
- png_do_shift(row_info, png_ptr->row_buf + 1,
- &(png_ptr->shift));
-#endif
-
-#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_SWAP_ALPHA)
- png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_ALPHA)
- png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_BGR_SUPPORTED
- if (png_ptr->transformations & PNG_BGR)
- png_do_bgr(row_info, png_ptr->row_buf + 1);
-#endif
-
-#ifdef PNG_WRITE_INVERT_SUPPORTED
- if (png_ptr->transformations & PNG_INVERT_MONO)
- png_do_invert(row_info, png_ptr->row_buf + 1);
-#endif
-}
#ifdef PNG_WRITE_PACK_SUPPORTED
/* Pack pixels into bytes. Pass the true bit depth in bit_depth. The
* row_info bit depth should be 8 (one pixel per byte). The channels
* should be 1 (this only happens on grayscale and paletted images).
*/
-void /* PRIVATE */
+static void
png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
{
png_debug(1, "in png_do_pack");
@@ -242,7 +166,7 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth)
* would pass 3 as bit_depth, and this routine would translate the
* data to 0 to 15.
*/
-void /* PRIVATE */
+static void
png_do_shift(png_row_infop row_info, png_bytep row,
png_const_color_8p bit_depth)
{
@@ -253,7 +177,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
int shift_start[4], shift_dec[4];
int channels = 0;
- if (row_info->color_type & PNG_COLOR_MASK_COLOR)
+ if ((row_info->color_type & PNG_COLOR_MASK_COLOR) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->red;
shift_dec[channels] = bit_depth->red;
@@ -275,7 +199,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
channels++;
}
- if (row_info->color_type & PNG_COLOR_MASK_ALPHA)
+ if ((row_info->color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
shift_start[channels] = row_info->bit_depth - bit_depth->alpha;
shift_dec[channels] = bit_depth->alpha;
@@ -287,7 +211,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
{
png_bytep bp = row;
png_size_t i;
- png_byte mask;
+ unsigned int mask;
png_size_t row_bytes = row_info->rowbytes;
if (bit_depth->gray == 1 && row_info->bit_depth == 2)
@@ -301,20 +225,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < row_bytes; i++, bp++)
{
- png_uint_16 v;
int j;
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[0]; j > -shift_dec[0]; j -= shift_dec[0])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & mask);
+ out |= (v >> (-j)) & mask;
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -327,21 +253,23 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (i = 0; i < istop; i++, bp++)
{
- png_uint_16 v;
+ const unsigned int c = i%channels;
int j;
- int c = (int)(i%channels);
+ unsigned int v, out;
v = *bp;
- *bp = 0;
+ out = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
- *bp |= (png_byte)((v << j) & 0xff);
+ out |= v << j;
else
- *bp |= (png_byte)((v >> (-j)) & 0xff);
+ out |= v >> (-j);
}
+
+ *bp = (png_byte)(out & 0xff);
}
}
@@ -353,22 +281,22 @@ png_do_shift(png_row_infop row_info, png_bytep row,
for (bp = row, i = 0; i < istop; i++)
{
- int c = (int)(i%channels);
- png_uint_16 value, v;
+ const unsigned int c = i%channels;
int j;
+ unsigned int value, v;
- v = (png_uint_16)(((png_uint_16)(*bp) << 8) + *(bp + 1));
+ v = png_get_uint_16(bp);
value = 0;
for (j = shift_start[c]; j > -shift_dec[c]; j -= shift_dec[c])
{
if (j > 0)
- value |= (png_uint_16)((v << j) & (png_uint_16)0xffff);
+ value |= v << j;
else
- value |= (png_uint_16)((v >> (-j)) & (png_uint_16)0xffff);
+ value |= v >> (-j);
}
- *bp++ = (png_byte)(value >> 8);
+ *bp++ = (png_byte)((value >> 8) & 0xff);
*bp++ = (png_byte)(value & 0xff);
}
}
@@ -377,7 +305,7 @@ png_do_shift(png_row_infop row_info, png_bytep row,
#endif
#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_swap_alpha");
@@ -425,7 +353,7 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -464,14 +392,14 @@ png_do_write_swap_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = save[1];
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
-void /* PRIVATE */
+static void
png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
{
png_debug(1, "in png_do_write_invert_alpha");
@@ -521,7 +449,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
else if (row_info->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
@@ -559,75 +487,88 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row)
*(dp++) = (png_byte)(255 - *(sp++));
}
}
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
+#endif /* WRITE_16BIT */
}
}
}
#endif
-#endif /* PNG_WRITE_TRANSFORMS_SUPPORTED */
-#ifdef PNG_MNG_FEATURES_SUPPORTED
-/* Undoes intrapixel differencing */
+/* Transform the data according to the user's wishes. The order of
+ * transformations is significant.
+ */
void /* PRIVATE */
-png_do_write_intrapixel(png_row_infop row_info, png_bytep row)
+png_do_write_transformations(png_structrp png_ptr, png_row_infop row_info)
{
- png_debug(1, "in png_do_write_intrapixel");
+ png_debug(1, "in png_do_write_transformations");
- if ((row_info->color_type & PNG_COLOR_MASK_COLOR))
- {
- int bytes_per_pixel;
- png_uint_32 row_width = row_info->width;
- if (row_info->bit_depth == 8)
- {
- png_bytep rp;
- png_uint_32 i;
+ if (png_ptr == NULL)
+ return;
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 3;
+#ifdef PNG_WRITE_USER_TRANSFORM_SUPPORTED
+ if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0)
+ if (png_ptr->write_user_transform_fn != NULL)
+ (*(png_ptr->write_user_transform_fn)) /* User write transform
+ function */
+ (png_ptr, /* png_ptr */
+ row_info, /* row_info: */
+ /* png_uint_32 width; width of row */
+ /* png_size_t rowbytes; number of bytes in row */
+ /* png_byte color_type; color type of pixels */
+ /* png_byte bit_depth; bit depth of samples */
+ /* png_byte channels; number of channels (1-4) */
+ /* png_byte pixel_depth; bits per pixel (depth*channels) */
+ png_ptr->row_buf + 1); /* start of pixel data for row */
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 4;
+#ifdef PNG_WRITE_FILLER_SUPPORTED
+ if ((png_ptr->transformations & PNG_FILLER) != 0)
+ png_do_strip_channel(row_info, png_ptr->row_buf + 1,
+ !(png_ptr->flags & PNG_FLAG_FILLER_AFTER));
+#endif
- else
- return;
+#ifdef PNG_WRITE_PACKSWAP_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACKSWAP) != 0)
+ png_do_packswap(row_info, png_ptr->row_buf + 1);
+#endif
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- *(rp) = (png_byte)((*rp - *(rp + 1)) & 0xff);
- *(rp + 2) = (png_byte)((*(rp + 2) - *(rp + 1)) & 0xff);
- }
- }
+#ifdef PNG_WRITE_PACK_SUPPORTED
+ if ((png_ptr->transformations & PNG_PACK) != 0)
+ png_do_pack(row_info, png_ptr->row_buf + 1,
+ (png_uint_32)png_ptr->bit_depth);
+#endif
-#ifdef PNG_WRITE_16BIT_SUPPORTED
- else if (row_info->bit_depth == 16)
- {
- png_bytep rp;
- png_uint_32 i;
+#ifdef PNG_WRITE_SWAP_SUPPORTED
+# ifdef PNG_16BIT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_BYTES) != 0)
+ png_do_swap(row_info, png_ptr->row_buf + 1);
+# endif
+#endif
+
+#ifdef PNG_WRITE_SHIFT_SUPPORTED
+ if ((png_ptr->transformations & PNG_SHIFT) != 0)
+ png_do_shift(row_info, png_ptr->row_buf + 1,
+ &(png_ptr->shift));
+#endif
- if (row_info->color_type == PNG_COLOR_TYPE_RGB)
- bytes_per_pixel = 6;
+#ifdef PNG_WRITE_SWAP_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_SWAP_ALPHA) != 0)
+ png_do_write_swap_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- else if (row_info->color_type == PNG_COLOR_TYPE_RGB_ALPHA)
- bytes_per_pixel = 8;
+#ifdef PNG_WRITE_INVERT_ALPHA_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0)
+ png_do_write_invert_alpha(row_info, png_ptr->row_buf + 1);
+#endif
- else
- return;
+#ifdef PNG_WRITE_BGR_SUPPORTED
+ if ((png_ptr->transformations & PNG_BGR) != 0)
+ png_do_bgr(row_info, png_ptr->row_buf + 1);
+#endif
- for (i = 0, rp = row; i < row_width; i++, rp += bytes_per_pixel)
- {
- png_uint_32 s0 = (*(rp ) << 8) | *(rp + 1);
- png_uint_32 s1 = (*(rp + 2) << 8) | *(rp + 3);
- png_uint_32 s2 = (*(rp + 4) << 8) | *(rp + 5);
- png_uint_32 red = (png_uint_32)((s0 - s1) & 0xffffL);
- png_uint_32 blue = (png_uint_32)((s2 - s1) & 0xffffL);
- *(rp ) = (png_byte)((red >> 8) & 0xff);
- *(rp + 1) = (png_byte)(red & 0xff);
- *(rp + 4) = (png_byte)((blue >> 8) & 0xff);
- *(rp + 5) = (png_byte)(blue & 0xff);
- }
- }
-#endif /* PNG_WRITE_16BIT_SUPPORTED */
- }
+#ifdef PNG_WRITE_INVERT_SUPPORTED
+ if ((png_ptr->transformations & PNG_INVERT_MONO) != 0)
+ png_do_invert(row_info, png_ptr->row_buf + 1);
+#endif
}
-#endif /* PNG_MNG_FEATURES_SUPPORTED */
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE_TRANSFORMS */
+#endif /* WRITE */
diff --git a/src/3rdparty/libpng/pngwutil.c b/src/3rdparty/libpng/pngwutil.c
index b49704f1a5..b289671d12 100644
--- a/src/3rdparty/libpng/pngwutil.c
+++ b/src/3rdparty/libpng/pngwutil.c
@@ -1,8 +1,8 @@
/* pngwutil.c - utilities to write a PNG file
*
- * Last changed in libpng 1.5.10 [March 8, 2012]
- * Copyright (c) 1998-2012 Glenn Randers-Pehrson
+ * Last changed in libpng 1.6.17 [March 26, 2015]
+ * Copyright (c) 1998-2015 Glenn Randers-Pehrson
* (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger)
* (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.)
*
@@ -23,29 +23,12 @@
void PNGAPI
png_save_uint_32(png_bytep buf, png_uint_32 i)
{
- buf[0] = (png_byte)((i >> 24) & 0xff);
- buf[1] = (png_byte)((i >> 16) & 0xff);
- buf[2] = (png_byte)((i >> 8) & 0xff);
- buf[3] = (png_byte)(i & 0xff);
+ buf[0] = (png_byte)(i >> 24);
+ buf[1] = (png_byte)(i >> 16);
+ buf[2] = (png_byte)(i >> 8);
+ buf[3] = (png_byte)(i );
}
-#ifdef PNG_SAVE_INT_32_SUPPORTED
-/* The png_save_int_32 function assumes integers are stored in two's
- * complement format. If this isn't the case, then this routine needs to
- * be modified to write data in two's complement format. Note that,
- * the following works correctly even if png_int_32 has more than 32 bits
- * (compare the more complex code required on read for sign extention.)
- */
-void PNGAPI
-png_save_int_32(png_bytep buf, png_int_32 i)
-{
- buf[0] = (png_byte)((i >> 24) & 0xff);
- buf[1] = (png_byte)((i >> 16) & 0xff);
- buf[2] = (png_byte)((i >> 8) & 0xff);
- buf[3] = (png_byte)(i & 0xff);
-}
-#endif
-
/* Place a 16-bit number into a buffer in PNG byte order.
* The parameter is declared unsigned int, not png_uint_16,
* just to avoid potential problems on pre-ANSI C compilers.
@@ -53,8 +36,8 @@ png_save_int_32(png_bytep buf, png_int_32 i)
void PNGAPI
png_save_uint_16(png_bytep buf, unsigned int i)
{
- buf[0] = (png_byte)((i >> 8) & 0xff);
- buf[1] = (png_byte)(i & 0xff);
+ buf[0] = (png_byte)(i >> 8);
+ buf[1] = (png_byte)(i );
}
#endif
@@ -65,7 +48,7 @@ png_save_uint_16(png_bytep buf, unsigned int i)
* bytes have already been written.
*/
void PNGAPI
-png_write_sig(png_structp png_ptr)
+png_write_sig(png_structrp png_ptr)
{
png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
@@ -87,7 +70,7 @@ png_write_sig(png_structp png_ptr)
* passing in png_write_chunk_data().
*/
static void
-png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
+png_write_chunk_header(png_structrp png_ptr, png_uint_32 chunk_name,
png_uint_32 length)
{
png_byte buf[8];
@@ -129,7 +112,7 @@ png_write_chunk_header(png_structp png_ptr, png_uint_32 chunk_name,
}
void PNGAPI
-png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
+png_write_chunk_start(png_structrp png_ptr, png_const_bytep chunk_string,
png_uint_32 length)
{
png_write_chunk_header(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), length);
@@ -141,7 +124,7 @@ png_write_chunk_start(png_structp png_ptr, png_const_bytep chunk_string,
* given to png_write_chunk_header().
*/
void PNGAPI
-png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
+png_write_chunk_data(png_structrp png_ptr, png_const_bytep data,
png_size_t length)
{
/* Write the data, and run the CRC over it */
@@ -153,7 +136,7 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
png_write_data(png_ptr, data, length);
/* Update the CRC after writing the data,
- * in case that the user I/O routine alters it.
+ * in case the user I/O routine alters it.
*/
png_calculate_crc(png_ptr, data, length);
}
@@ -161,7 +144,7 @@ png_write_chunk_data(png_structp png_ptr, png_const_bytep data,
/* Finish a chunk started with png_write_chunk_header(). */
void PNGAPI
-png_write_chunk_end(png_structp png_ptr)
+png_write_chunk_end(png_structrp png_ptr)
{
png_byte buf[4];
@@ -190,15 +173,15 @@ png_write_chunk_end(png_structp png_ptr)
* functions instead.
*/
static void
-png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
+png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name,
png_const_bytep data, png_size_t length)
{
if (png_ptr == NULL)
return;
/* On 64 bit architectures 'length' may not fit in a png_uint_32. */
- if (length > PNG_UINT_32_MAX)
- png_error(png_ptr, "length exceeds PNG maxima");
+ if (length > PNG_UINT_31_MAX)
+ png_error(png_ptr, "length exceeds PNG maximum");
png_write_chunk_header(png_ptr, chunk_name, (png_uint_32)length);
png_write_chunk_data(png_ptr, data, length);
@@ -207,474 +190,571 @@ png_write_complete_chunk(png_structp png_ptr, png_uint_32 chunk_name,
/* This is the API that calls the internal function above. */
void PNGAPI
-png_write_chunk(png_structp png_ptr, png_const_bytep chunk_string,
+png_write_chunk(png_structrp png_ptr, png_const_bytep chunk_string,
png_const_bytep data, png_size_t length)
{
png_write_complete_chunk(png_ptr, PNG_CHUNK_FROM_STRING(chunk_string), data,
length);
}
-/* Initialize the compressor for the appropriate type of compression. */
-static void
-png_zlib_claim(png_structp png_ptr, png_uint_32 state)
+/* This is used below to find the size of an image to pass to png_deflate_claim,
+ * so it only needs to be accurate if the size is less than 16384 bytes (the
+ * point at which a lower LZ window size can be used.)
+ */
+static png_alloc_size_t
+png_image_size(png_structrp png_ptr)
{
- if (!(png_ptr->zlib_state & PNG_ZLIB_IN_USE))
+ /* Only return sizes up to the maximum of a png_uint_32; do this by limiting
+ * the width and height used to 15 bits.
+ */
+ png_uint_32 h = png_ptr->height;
+
+ if (png_ptr->rowbytes < 32768 && h < 32768)
{
- /* If already initialized for 'state' do not re-init. */
- if (png_ptr->zlib_state != state)
+ if (png_ptr->interlaced != 0)
{
- int ret = Z_OK;
- png_const_charp who = "-";
+ /* Interlacing makes the image larger because of the replication of
+ * both the filter byte and the padding to a byte boundary.
+ */
+ png_uint_32 w = png_ptr->width;
+ unsigned int pd = png_ptr->pixel_depth;
+ png_alloc_size_t cb_base;
+ int pass;
- /* If actually initialized for another state do a deflateEnd. */
- if (png_ptr->zlib_state != PNG_ZLIB_UNINITIALIZED)
+ for (cb_base=0, pass=0; pass<=6; ++pass)
{
- ret = deflateEnd(&png_ptr->zstream);
- who = "end";
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
+ png_uint_32 pw = PNG_PASS_COLS(w, pass);
+
+ if (pw > 0)
+ cb_base += (PNG_ROWBYTES(pd, pw)+1) * PNG_PASS_ROWS(h, pass);
}
- /* zlib itself detects an incomplete state on deflateEnd */
- if (ret == Z_OK) switch (state)
+ return cb_base;
+ }
+
+ else
+ return (png_ptr->rowbytes+1) * h;
+ }
+
+ else
+ return 0xffffffffU;
+}
+
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* This is the code to hack the first two bytes of the deflate stream (the
+ * deflate header) to correct the windowBits value to match the actual data
+ * size. Note that the second argument is the *uncompressed* size but the
+ * first argument is the *compressed* data (and it must be deflate
+ * compressed.)
+ */
+static void
+optimize_cmf(png_bytep data, png_alloc_size_t data_size)
+{
+ /* Optimize the CMF field in the zlib stream. The resultant zlib stream is
+ * still compliant to the stream specification.
+ */
+ if (data_size <= 16384) /* else windowBits must be 15 */
+ {
+ unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+
+ if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ {
+ unsigned int z_cinfo;
+ unsigned int half_z_window_size;
+
+ z_cinfo = z_cmf >> 4;
+ half_z_window_size = 1U << (z_cinfo + 7);
+
+ if (data_size <= half_z_window_size) /* else no change */
{
-# ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
- case PNG_ZLIB_FOR_TEXT:
- ret = deflateInit2(&png_ptr->zstream,
- png_ptr->zlib_text_level, png_ptr->zlib_text_method,
- png_ptr->zlib_text_window_bits,
- png_ptr->zlib_text_mem_level, png_ptr->zlib_text_strategy);
- who = "text";
- break;
-# endif
+ unsigned int tmp;
- case PNG_ZLIB_FOR_IDAT:
- ret = deflateInit2(&png_ptr->zstream, png_ptr->zlib_level,
- png_ptr->zlib_method, png_ptr->zlib_window_bits,
- png_ptr->zlib_mem_level, png_ptr->zlib_strategy);
- who = "IDAT";
- break;
+ do
+ {
+ half_z_window_size >>= 1;
+ --z_cinfo;
+ }
+ while (z_cinfo > 0 && data_size <= half_z_window_size);
- default:
- png_error(png_ptr, "invalid zlib state");
+ z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+
+ data[0] = (png_byte)z_cmf;
+ tmp = data[1] & 0xe0;
+ tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
+ data[1] = (png_byte)tmp;
}
+ }
+ }
+}
+#endif /* WRITE_OPTIMIZE_CMF */
- if (ret == Z_OK)
- png_ptr->zlib_state = state;
+/* Initialize the compressor for the appropriate type of compression. */
+static int
+png_deflate_claim(png_structrp png_ptr, png_uint_32 owner,
+ png_alloc_size_t data_size)
+{
+ if (png_ptr->zowner != 0)
+ {
+#if defined(PNG_WARNINGS_SUPPORTED) || defined(PNG_ERROR_TEXT_SUPPORTED)
+ char msg[64];
+
+ PNG_STRING_FROM_CHUNK(msg, owner);
+ msg[4] = ':';
+ msg[5] = ' ';
+ PNG_STRING_FROM_CHUNK(msg+6, png_ptr->zowner);
+ /* So the message that results is "<chunk> using zstream"; this is an
+ * internal error, but is very useful for debugging. i18n requirements
+ * are minimal.
+ */
+ (void)png_safecat(msg, (sizeof msg), 10, " using zstream");
+#endif
+#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC
+ png_warning(png_ptr, msg);
- else /* an error in deflateEnd or deflateInit2 */
+ /* Attempt sane error recovery */
+ if (png_ptr->zowner == png_IDAT) /* don't steal from IDAT */
{
- size_t pos = 0;
- char msg[64];
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("in use by IDAT");
+ return Z_STREAM_ERROR;
+ }
- pos = png_safecat(msg, sizeof msg, pos,
- "zlib failed to initialize compressor (");
- pos = png_safecat(msg, sizeof msg, pos, who);
+ png_ptr->zowner = 0;
+#else
+ png_error(png_ptr, msg);
+#endif
+ }
- switch (ret)
- {
- case Z_VERSION_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") version error");
- break;
+ {
+ int level = png_ptr->zlib_level;
+ int method = png_ptr->zlib_method;
+ int windowBits = png_ptr->zlib_window_bits;
+ int memLevel = png_ptr->zlib_mem_level;
+ int strategy; /* set below */
+ int ret; /* zlib return code */
- case Z_STREAM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") stream error");
- break;
+ if (owner == png_IDAT)
+ {
+ if ((png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY) != 0)
+ strategy = png_ptr->zlib_strategy;
- case Z_MEM_ERROR:
- pos = png_safecat(msg, sizeof msg, pos, ") memory error");
- break;
+ else if (png_ptr->do_filter != PNG_FILTER_NONE)
+ strategy = PNG_Z_DEFAULT_STRATEGY;
- default:
- pos = png_safecat(msg, sizeof msg, pos, ") unknown error");
- break;
- }
+ else
+ strategy = PNG_Z_DEFAULT_NOFILTER_STRATEGY;
+ }
+
+ else
+ {
+#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
+ level = png_ptr->zlib_text_level;
+ method = png_ptr->zlib_text_method;
+ windowBits = png_ptr->zlib_text_window_bits;
+ memLevel = png_ptr->zlib_text_mem_level;
+ strategy = png_ptr->zlib_text_strategy;
+#else
+ /* If customization is not supported the values all come from the
+ * IDAT values except for the strategy, which is fixed to the
+ * default. (This is the pre-1.6.0 behavior too, although it was
+ * implemented in a very different way.)
+ */
+ strategy = Z_DEFAULT_STRATEGY;
+#endif
+ }
- png_error(png_ptr, msg);
+ /* Adjust 'windowBits' down if larger than 'data_size'; to stop this
+ * happening just pass 32768 as the data_size parameter. Notice that zlib
+ * requires an extra 262 bytes in the window in addition to the data to be
+ * able to see the whole of the data, so if data_size+262 takes us to the
+ * next windowBits size we need to fix up the value later. (Because even
+ * though deflate needs the extra window, inflate does not!)
+ */
+ if (data_size <= 16384)
+ {
+ /* IMPLEMENTATION NOTE: this 'half_window_size' stuff is only here to
+ * work round a Microsoft Visual C misbehavior which, contrary to C-90,
+ * widens the result of the following shift to 64-bits if (and,
+ * apparently, only if) it is used in a test.
+ */
+ unsigned int half_window_size = 1U << (windowBits-1);
+
+ while (data_size + 262 <= half_window_size)
+ {
+ half_window_size >>= 1;
+ --windowBits;
}
}
- /* Here on success, claim the zstream: */
- png_ptr->zlib_state |= PNG_ZLIB_IN_USE;
- }
+ /* Check against the previous initialized values, if any. */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0 &&
+ (png_ptr->zlib_set_level != level ||
+ png_ptr->zlib_set_method != method ||
+ png_ptr->zlib_set_window_bits != windowBits ||
+ png_ptr->zlib_set_mem_level != memLevel ||
+ png_ptr->zlib_set_strategy != strategy))
+ {
+ if (deflateEnd(&png_ptr->zstream) != Z_OK)
+ png_warning(png_ptr, "deflateEnd failed (ignored)");
- else
- png_error(png_ptr, "zstream already in use (internal error)");
-}
+ png_ptr->flags &= ~PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
-/* The opposite: release the stream. It is also reset, this API will warn on
- * error but will not fail.
- */
-static void
-png_zlib_release(png_structp png_ptr)
-{
- if (png_ptr->zlib_state & PNG_ZLIB_IN_USE)
- {
- int ret = deflateReset(&png_ptr->zstream);
+ /* For safety clear out the input and output pointers (currently zlib
+ * doesn't use them on Init, but it might in the future).
+ */
+ png_ptr->zstream.next_in = NULL;
+ png_ptr->zstream.avail_in = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->zstream.avail_out = 0;
- png_ptr->zlib_state &= ~PNG_ZLIB_IN_USE;
+ /* Now initialize if required, setting the new parameters, otherwise just
+ * to a simple reset to the previous parameters.
+ */
+ if ((png_ptr->flags & PNG_FLAG_ZSTREAM_INITIALIZED) != 0)
+ ret = deflateReset(&png_ptr->zstream);
- if (ret != Z_OK)
+ else
{
- png_const_charp err;
- PNG_WARNING_PARAMETERS(p)
+ ret = deflateInit2(&png_ptr->zstream, level, method, windowBits,
+ memLevel, strategy);
- switch (ret)
- {
- case Z_VERSION_ERROR:
- err = "version";
- break;
+ if (ret == Z_OK)
+ png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
+ }
- case Z_STREAM_ERROR:
- err = "stream";
- break;
+ /* The return code is from either deflateReset or deflateInit2; they have
+ * pretty much the same set of error codes.
+ */
+ if (ret == Z_OK)
+ png_ptr->zowner = owner;
- case Z_MEM_ERROR:
- err = "memory";
- break;
+ else
+ png_zstream_error(png_ptr, ret);
- default:
- err = "unknown";
- break;
- }
+ return ret;
+ }
+}
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d, ret);
- png_warning_parameter(p, 2, err);
+/* Clean up (or trim) a linked list of compression buffers. */
+void /* PRIVATE */
+png_free_buffer_list(png_structrp png_ptr, png_compression_bufferp *listp)
+{
+ png_compression_bufferp list = *listp;
- if (png_ptr->zstream.msg)
- err = png_ptr->zstream.msg;
- else
- err = "[no zlib message]";
+ if (list != NULL)
+ {
+ *listp = NULL;
- png_warning_parameter(p, 3, err);
+ do
+ {
+ png_compression_bufferp next = list->next;
- png_formatted_warning(png_ptr, p,
- "zlib failed to reset compressor: @1(@2): @3");
+ png_free(png_ptr, list);
+ list = next;
}
+ while (list != NULL);
}
-
- else
- png_warning(png_ptr, "zstream not in use (internal error)");
}
#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
/* This pair of functions encapsulates the operation of (a) compressing a
* text string, and (b) issuing it later as a series of chunk data writes.
* The compression_state structure is shared context for these functions
- * set up by the caller in order to make the whole mess thread-safe.
+ * set up by the caller to allow access to the relevant local variables.
+ *
+ * compression_buffer (new in 1.6.0) is just a linked list of zbuffer_size
+ * temporary buffers. From 1.6.0 it is retained in png_struct so that it will
+ * be correctly freed in the event of a write error (previous implementations
+ * just leaked memory.)
*/
-
typedef struct
{
- png_const_bytep input; /* The uncompressed input data */
- png_size_t input_len; /* Its length */
- int num_output_ptr; /* Number of output pointers used */
- int max_output_ptr; /* Size of output_ptr */
- png_bytep *output_ptr; /* Array of pointers to output */
+ png_const_bytep input; /* The uncompressed input data */
+ png_alloc_size_t input_len; /* Its length */
+ png_uint_32 output_len; /* Final compressed length */
+ png_byte output[1024]; /* First block of output */
} compression_state;
-/* Compress given text into storage in the png_ptr structure */
-static int /* PRIVATE */
-png_text_compress(png_structp png_ptr,
- png_const_charp text, png_size_t text_len, int compression,
- compression_state *comp)
+static void
+png_text_compress_init(compression_state *comp, png_const_bytep input,
+ png_alloc_size_t input_len)
{
- int ret;
-
- comp->num_output_ptr = 0;
- comp->max_output_ptr = 0;
- comp->output_ptr = NULL;
- comp->input = NULL;
- comp->input_len = text_len;
-
- /* We may just want to pass the text right through */
- if (compression == PNG_TEXT_COMPRESSION_NONE)
- {
- comp->input = (png_const_bytep)text;
- return((int)text_len);
- }
-
- if (compression >= PNG_TEXT_COMPRESSION_LAST)
- {
- PNG_WARNING_PARAMETERS(p)
+ comp->input = input;
+ comp->input_len = input_len;
+ comp->output_len = 0;
+}
- png_warning_parameter_signed(p, 1, PNG_NUMBER_FORMAT_d,
- compression);
- png_formatted_warning(png_ptr, p, "Unknown compression type @1");
- }
+/* Compress the data in the compression state input */
+static int
+png_text_compress(png_structrp png_ptr, png_uint_32 chunk_name,
+ compression_state *comp, png_uint_32 prefix_len)
+{
+ int ret;
- /* We can't write the chunk until we find out how much data we have,
- * which means we need to run the compressor first and save the
- * output. This shouldn't be a problem, as the vast majority of
- * comments should be reasonable, but we will set up an array of
- * malloc'd pointers to be sure.
+ /* To find the length of the output it is necessary to first compress the
+ * input. The result is buffered rather than using the two-pass algorithm
+ * that is used on the inflate side; deflate is assumed to be slower and a
+ * PNG writer is assumed to have more memory available than a PNG reader.
*
- * If we knew the application was well behaved, we could simplify this
- * greatly by assuming we can always malloc an output buffer large
- * enough to hold the compressed text ((1001 * text_len / 1000) + 12)
- * and malloc this directly. The only time this would be a bad idea is
- * if we can't malloc more than 64K and we have 64K of random input
- * data, or if the input string is incredibly large (although this
- * wouldn't cause a failure, just a slowdown due to swapping).
+ * IMPLEMENTATION NOTE: the zlib API deflateBound() can be used to find an
+ * upper limit on the output size, but it is always bigger than the input
+ * size so it is likely to be more efficient to use this linked-list
+ * approach.
*/
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_TEXT);
+ ret = png_deflate_claim(png_ptr, chunk_name, comp->input_len);
- /* Set up the compression buffers */
- /* TODO: the following cast hides a potential overflow problem. */
- png_ptr->zstream.avail_in = (uInt)text_len;
+ if (ret != Z_OK)
+ return ret;
- /* NOTE: assume zlib doesn't overwrite the input */
- png_ptr->zstream.next_in = (Bytef *)text;
- png_ptr->zstream.avail_out = png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
-
- /* This is the same compression loop as in png_write_row() */
- do
+ /* Set up the compression buffers, we need a loop here to avoid overflowing a
+ * uInt. Use ZLIB_IO_MAX to limit the input. The output is always limited
+ * by the output buffer size, so there is no need to check that. Since this
+ * is ANSI-C we know that an 'int', hence a uInt, is always at least 16 bits
+ * in size.
+ */
{
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
+ png_compression_bufferp *end = &png_ptr->zbuffer_list;
+ png_alloc_size_t input_len = comp->input_len; /* may be zero! */
+ png_uint_32 output_len;
- if (ret != Z_OK)
- {
- /* Error */
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
+ /* zlib updates these for us: */
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(comp->input);
+ png_ptr->zstream.avail_in = 0; /* Set below */
+ png_ptr->zstream.next_out = comp->output;
+ png_ptr->zstream.avail_out = (sizeof comp->output);
- else
- png_error(png_ptr, "zlib error");
- }
+ output_len = png_ptr->zstream.avail_out;
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
+ do
{
- /* Make sure the output array has room */
- if (comp->num_output_ptr >= comp->max_output_ptr)
- {
- int old_max;
+ uInt avail_in = ZLIB_IO_MAX;
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
- {
- png_bytepp old_ptr;
+ if (avail_in > input_len)
+ avail_in = (uInt)input_len;
- old_ptr = comp->output_ptr;
+ input_len -= avail_in;
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charpp)));
+ png_ptr->zstream.avail_in = avail_in;
- png_memcpy(comp->output_ptr, old_ptr, old_max
- * png_sizeof(png_charp));
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ png_compression_buffer *next;
- png_free(png_ptr, old_ptr);
+ /* Chunk data is limited to 2^31 bytes in length, so the prefix
+ * length must be counted here.
+ */
+ if (output_len + prefix_len > PNG_UINT_31_MAX)
+ {
+ ret = Z_MEM_ERROR;
+ break;
}
- else
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)
- (comp->max_output_ptr * png_sizeof(png_charp)));
- }
-
- /* Save the data */
- comp->output_ptr[comp->num_output_ptr] =
- (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)png_ptr->zbuf_size);
-
- png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
- png_ptr->zbuf_size);
- comp->num_output_ptr++;
-
- /* and reset the buffer */
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
- }
- /* Continue until we don't have any more to compress */
- } while (png_ptr->zstream.avail_in);
-
- /* Finish the compression */
- do
- {
- /* Tell zlib we are finished */
- ret = deflate(&png_ptr->zstream, Z_FINISH);
-
- if (ret == Z_OK)
- {
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
- {
- /* Check to make sure our output array has room */
- if (comp->num_output_ptr >= comp->max_output_ptr)
+ /* Need a new (malloc'ed) buffer, but there may be one present
+ * already.
+ */
+ next = *end;
+ if (next == NULL)
{
- int old_max;
+ next = png_voidcast(png_compression_bufferp, png_malloc_base
+ (png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
- old_max = comp->max_output_ptr;
- comp->max_output_ptr = comp->num_output_ptr + 4;
- if (comp->output_ptr != NULL)
+ if (next == NULL)
{
- png_bytepp old_ptr;
-
- old_ptr = comp->output_ptr;
-
- /* This could be optimized to realloc() */
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)(comp->max_output_ptr *
- png_sizeof(png_charp)));
-
- png_memcpy(comp->output_ptr, old_ptr,
- old_max * png_sizeof(png_charp));
-
- png_free(png_ptr, old_ptr);
+ ret = Z_MEM_ERROR;
+ break;
}
- else
- comp->output_ptr = (png_bytepp)png_malloc(png_ptr,
- (png_alloc_size_t)(comp->max_output_ptr *
- png_sizeof(png_charp)));
+ /* Link in this buffer (so that it will be freed later) */
+ next->next = NULL;
+ *end = next;
}
- /* Save the data */
- comp->output_ptr[comp->num_output_ptr] =
- (png_bytep)png_malloc(png_ptr,
- (png_alloc_size_t)png_ptr->zbuf_size);
+ png_ptr->zstream.next_out = next->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
+ output_len += png_ptr->zstream.avail_out;
- png_memcpy(comp->output_ptr[comp->num_output_ptr], png_ptr->zbuf,
- png_ptr->zbuf_size);
+ /* Move 'end' to the next buffer pointer. */
+ end = &next->next;
+ }
- comp->num_output_ptr++;
+ /* Compress the data */
+ ret = deflate(&png_ptr->zstream,
+ input_len > 0 ? Z_NO_FLUSH : Z_FINISH);
- /* and reset the buffer pointers */
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
- }
+ /* Claw back input data that was not consumed (because avail_in is
+ * reset above every time round the loop).
+ */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0; /* safety */
}
- else if (ret != Z_STREAM_END)
- {
- /* We got an error */
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
+ while (ret == Z_OK);
- else
- png_error(png_ptr, "zlib error");
+ /* There may be some space left in the last output buffer. This needs to
+ * be subtracted from output_len.
+ */
+ output_len -= png_ptr->zstream.avail_out;
+ png_ptr->zstream.avail_out = 0; /* safety */
+ comp->output_len = output_len;
+
+ /* Now double check the output length, put in a custom message if it is
+ * too long. Otherwise ensure the z_stream::msg pointer is set to
+ * something.
+ */
+ if (output_len + prefix_len >= PNG_UINT_31_MAX)
+ {
+ png_ptr->zstream.msg = PNGZ_MSG_CAST("compressed data too long");
+ ret = Z_MEM_ERROR;
}
- } while (ret != Z_STREAM_END);
- /* Text length is number of buffers plus last buffer */
- text_len = png_ptr->zbuf_size * comp->num_output_ptr;
+ else
+ png_zstream_error(png_ptr, ret);
+
+ /* Reset zlib for another zTXt/iTXt or image data */
+ png_ptr->zowner = 0;
- if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
- text_len += png_ptr->zbuf_size - (png_size_t)png_ptr->zstream.avail_out;
+ /* The only success case is Z_STREAM_END, input_len must be 0; if not this
+ * is an internal error.
+ */
+ if (ret == Z_STREAM_END && input_len == 0)
+ {
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ /* Fix up the deflate header, if required */
+ optimize_cmf(comp->output, comp->input_len);
+#endif
+ /* But Z_OK is returned, not Z_STREAM_END; this allows the claim
+ * function above to return Z_STREAM_END on an error (though it never
+ * does in the current versions of zlib.)
+ */
+ return Z_OK;
+ }
- return((int)text_len);
+ else
+ return ret;
+ }
}
/* Ship the compressed text out via chunk writes */
-static void /* PRIVATE */
-png_write_compressed_data_out(png_structp png_ptr, compression_state *comp,
- png_size_t data_len)
+static void
+png_write_compressed_data_out(png_structrp png_ptr, compression_state *comp)
{
- int i;
+ png_uint_32 output_len = comp->output_len;
+ png_const_bytep output = comp->output;
+ png_uint_32 avail = (sizeof comp->output);
+ png_compression_buffer *next = png_ptr->zbuffer_list;
- /* Handle the no-compression case */
- if (comp->input)
+ for (;;)
{
- png_write_chunk_data(png_ptr, comp->input, data_len);
+ if (avail > output_len)
+ avail = output_len;
- return;
- }
+ png_write_chunk_data(png_ptr, output, avail);
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- /* The zbuf_size test is because the code below doesn't work if zbuf_size is
- * '1'; simply skip it to avoid memory overwrite.
- */
- if (data_len >= 2 && comp->input_len < 16384 && png_ptr->zbuf_size > 1)
- {
- unsigned int z_cmf; /* zlib compression method and flags */
+ output_len -= avail;
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
- */
+ if (output_len == 0 || next == NULL)
+ break;
- if (comp->num_output_ptr)
- z_cmf = comp->output_ptr[0][0];
- else
- z_cmf = png_ptr->zbuf[0];
+ avail = png_ptr->zbuffer_size;
+ output = next->output;
+ next = next->next;
+ }
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
- {
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_size_t uncompressed_text_size = comp->input_len;
+ /* This is an internal error; 'next' must have been NULL! */
+ if (output_len > 0)
+ png_error(png_ptr, "error writing ancillary chunked compressed data");
+}
+#endif /* WRITE_COMPRESSED_TEXT */
- z_cinfo = z_cmf >> 4;
- half_z_window_size = 1 << (z_cinfo + 7);
+#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
+ defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
+/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
+ * and if invalid, correct the keyword rather than discarding the entire
+ * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
+ * length, forbids leading or trailing whitespace, multiple internal spaces,
+ * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
+ *
+ * The 'new_key' buffer must be 80 characters in size (for the keyword plus a
+ * trailing '\0'). If this routine returns 0 then there was no keyword, or a
+ * valid one could not be generated, and the caller must png_error.
+ */
+static png_uint_32
+png_check_keyword(png_structrp png_ptr, png_const_charp key, png_bytep new_key)
+{
+ png_const_charp orig_key = key;
+ png_uint_32 key_len = 0;
+ int bad_character = 0;
+ int space = 1;
- while (uncompressed_text_size <= half_z_window_size &&
- half_z_window_size >= 256)
- {
- z_cinfo--;
- half_z_window_size >>= 1;
- }
+ png_debug(1, "in png_check_keyword");
- z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ if (key == NULL)
+ {
+ *new_key = 0;
+ return 0;
+ }
- if (comp->num_output_ptr)
- {
+ while (*key && key_len < 79)
+ {
+ png_byte ch = (png_byte)*key++;
- if (comp->output_ptr[0][0] != z_cmf)
- {
- int tmp;
+ if ((ch > 32 && ch <= 126) || (ch >= 161 /*&& ch <= 255*/))
+ *new_key++ = ch, ++key_len, space = 0;
- comp->output_ptr[0][0] = (png_byte)z_cmf;
- tmp = comp->output_ptr[0][1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- comp->output_ptr[0][1] = (png_byte)tmp;
- }
- }
- else
- {
- int tmp;
+ else if (space == 0)
+ {
+ /* A space or an invalid character when one wasn't seen immediately
+ * before; output just a space.
+ */
+ *new_key++ = 32, ++key_len, space = 1;
- png_ptr->zbuf[0] = (png_byte)z_cmf;
- tmp = png_ptr->zbuf[1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- png_ptr->zbuf[1] = (png_byte)tmp;
- }
+ /* If the character was not a space then it is invalid. */
+ if (ch != 32)
+ bad_character = ch;
}
- else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in non-IDAT chunk");
+ else if (bad_character == 0)
+ bad_character = ch; /* just skip it, record the first error */
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
- /* Write saved output buffers, if any */
- for (i = 0; i < comp->num_output_ptr; i++)
+ if (key_len > 0 && space != 0) /* trailing space */
{
- png_write_chunk_data(png_ptr, comp->output_ptr[i],
- (png_size_t)png_ptr->zbuf_size);
-
- png_free(png_ptr, comp->output_ptr[i]);
+ --key_len, --new_key;
+ if (bad_character == 0)
+ bad_character = 32;
}
- if (comp->max_output_ptr != 0)
- png_free(png_ptr, comp->output_ptr);
+ /* Terminate the keyword */
+ *new_key = 0;
+
+ if (key_len == 0)
+ return 0;
- /* Write anything left in zbuf */
- if (png_ptr->zstream.avail_out < (png_uint_32)png_ptr->zbuf_size)
- png_write_chunk_data(png_ptr, png_ptr->zbuf,
- (png_size_t)(png_ptr->zbuf_size - png_ptr->zstream.avail_out));
+#ifdef PNG_WARNINGS_SUPPORTED
+ /* Try to only output one warning per keyword: */
+ if (*key != 0) /* keyword too long */
+ png_warning(png_ptr, "keyword truncated");
- /* Reset zlib for another zTXt/iTXt or image data */
- png_zlib_release(png_ptr);
+ else if (bad_character != 0)
+ {
+ PNG_WARNING_PARAMETERS(p)
+
+ png_warning_parameter(p, 1, orig_key);
+ png_warning_parameter_signed(p, 2, PNG_NUMBER_FORMAT_02x, bad_character);
+
+ png_formatted_warning(png_ptr, p, "keyword \"@1\": bad character '0x@2'");
+ }
+#endif /* WARNINGS */
+
+ return key_len;
}
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
+#endif /* WRITE_TEXT || WRITE_pCAL || WRITE_iCCP || WRITE_sPLT */
/* Write the IHDR chunk, and update the png_struct with the necessary
* information. Note that the rest of this code depends upon this
* information being correct.
*/
void /* PRIVATE */
-png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
+png_write_IHDR(png_structrp png_ptr, png_uint_32 width, png_uint_32 height,
int bit_depth, int color_type, int compression_type, int filter_type,
int interlace_type)
{
@@ -768,8 +848,8 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
*/
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) &&
- ((png_ptr->mode&PNG_HAVE_PNG_SIGNATURE) == 0) &&
+ !((png_ptr->mng_features_permitted & PNG_FLAG_MNG_FILTER_64) != 0 &&
+ ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) == 0) &&
(color_type == PNG_COLOR_TYPE_RGB ||
color_type == PNG_COLOR_TYPE_RGB_ALPHA) &&
(filter_type == PNG_INTRAPIXEL_DIFFERENCING)) &&
@@ -791,7 +871,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
interlace_type=PNG_INTERLACE_NONE;
#endif
- /* Save the relevent information */
+ /* Save the relevant information */
png_ptr->bit_depth = (png_byte)bit_depth;
png_ptr->color_type = (png_byte)color_type;
png_ptr->interlaced = (png_byte)interlace_type;
@@ -821,12 +901,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
/* Write the chunk */
png_write_complete_chunk(png_ptr, png_IHDR, buf, (png_size_t)13);
- /* Initialize zlib with PNG info */
- png_ptr->zstream.zalloc = png_zalloc;
- png_ptr->zstream.zfree = png_zfree;
- png_ptr->zstream.opaque = (voidpf)png_ptr;
-
- if (!(png_ptr->do_filter))
+ if ((png_ptr->do_filter) == PNG_NO_FILTERS)
{
if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE ||
png_ptr->bit_depth < 8)
@@ -836,55 +911,6 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
png_ptr->do_filter = PNG_ALL_FILTERS;
}
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_STRATEGY))
- {
- if (png_ptr->do_filter != PNG_FILTER_NONE)
- png_ptr->zlib_strategy = Z_FILTERED;
-
- else
- png_ptr->zlib_strategy = Z_DEFAULT_STRATEGY;
- }
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_LEVEL))
- png_ptr->zlib_level = Z_DEFAULT_COMPRESSION;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_MEM_LEVEL))
- png_ptr->zlib_mem_level = 8;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_WINDOW_BITS))
- png_ptr->zlib_window_bits = 15;
-
- if (!(png_ptr->flags & PNG_FLAG_ZLIB_CUSTOM_METHOD))
- png_ptr->zlib_method = 8;
-
-#ifdef PNG_WRITE_COMPRESSED_TEXT_SUPPORTED
-#ifdef PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_STRATEGY))
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_LEVEL))
- png_ptr->zlib_text_level = png_ptr->zlib_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_MEM_LEVEL))
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_WINDOW_BITS))
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
-
- if (!(png_ptr->flags & PNG_FLAG_ZTXT_CUSTOM_METHOD))
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#else
- png_ptr->zlib_text_strategy = Z_DEFAULT_STRATEGY;
- png_ptr->zlib_text_level = png_ptr->zlib_level;
- png_ptr->zlib_text_mem_level = png_ptr->zlib_mem_level;
- png_ptr->zlib_text_window_bits = png_ptr->zlib_window_bits;
- png_ptr->zlib_text_method = png_ptr->zlib_method;
-#endif /* PNG_WRITE_CUSTOMIZE_ZTXT_COMPRESSION_SUPPORTED */
-#endif /* PNG_WRITE_COMPRESSED_TEXT_SUPPORTED */
-
- /* Record that the compressor has not yet been initialized. */
- png_ptr->zlib_state = PNG_ZLIB_UNINITIALIZED;
-
png_ptr->mode = PNG_HAVE_IHDR; /* not READY_FOR_ZTXT */
}
@@ -893,7 +919,7 @@ png_write_IHDR(png_structp png_ptr, png_uint_32 width, png_uint_32 height,
* structure.
*/
void /* PRIVATE */
-png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
+png_write_PLTE(png_structrp png_ptr, png_const_colorp palette,
png_uint_32 num_pal)
{
png_uint_32 i;
@@ -904,7 +930,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
if ((
#ifdef PNG_MNG_FEATURES_SUPPORTED
- !(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) &&
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 &&
#endif
num_pal == 0) || num_pal > 256)
{
@@ -920,7 +946,7 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
}
}
- if (!(png_ptr->color_type&PNG_COLOR_MASK_COLOR))
+ if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) == 0)
{
png_warning(png_ptr,
"Ignoring request to write a PLTE chunk in grayscale PNG");
@@ -961,94 +987,165 @@ png_write_PLTE(png_structp png_ptr, png_const_colorp palette,
png_ptr->mode |= PNG_HAVE_PLTE;
}
-/* Write an IDAT chunk */
+/* This is similar to png_text_compress, above, except that it does not require
+ * all of the data at once and, instead of buffering the compressed result,
+ * writes it as IDAT chunks. Unlike png_text_compress it *can* png_error out
+ * because it calls the write interface. As a result it does its own error
+ * reporting and does not return an error code. In the event of error it will
+ * just call png_error. The input data length may exceed 32-bits. The 'flush'
+ * parameter is exactly the same as that to deflate, with the following
+ * meanings:
+ *
+ * Z_NO_FLUSH: normal incremental output of compressed data
+ * Z_SYNC_FLUSH: do a SYNC_FLUSH, used by png_write_flush
+ * Z_FINISH: this is the end of the input, do a Z_FINISH and clean up
+ *
+ * The routine manages the acquire and release of the png_ptr->zstream by
+ * checking and (at the end) clearing png_ptr->zowner; it does some sanity
+ * checks on the 'mode' flags while doing this.
+ */
void /* PRIVATE */
-png_write_IDAT(png_structp png_ptr, png_bytep data, png_size_t length)
+png_compress_IDAT(png_structrp png_ptr, png_const_bytep input,
+ png_alloc_size_t input_len, int flush)
{
- png_debug(1, "in png_write_IDAT");
+ if (png_ptr->zowner != png_IDAT)
+ {
+ /* First time. Ensure we have a temporary buffer for compression and
+ * trim the buffer list if it has more than one entry to free memory.
+ * If 'WRITE_COMPRESSED_TEXT' is not set the list will never have been
+ * created at this point, but the check here is quick and safe.
+ */
+ if (png_ptr->zbuffer_list == NULL)
+ {
+ png_ptr->zbuffer_list = png_voidcast(png_compression_bufferp,
+ png_malloc(png_ptr, PNG_COMPRESSION_BUFFER_SIZE(png_ptr)));
+ png_ptr->zbuffer_list->next = NULL;
+ }
-#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
- if (!(png_ptr->mode & PNG_HAVE_IDAT) &&
- png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ else
+ png_free_buffer_list(png_ptr, &png_ptr->zbuffer_list->next);
+
+ /* It is a terminal error if we can't claim the zstream. */
+ if (png_deflate_claim(png_ptr, png_IDAT, png_image_size(png_ptr)) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+
+ /* The output state is maintained in png_ptr->zstream, so it must be
+ * initialized here after the claim.
+ */
+ png_ptr->zstream.next_out = png_ptr->zbuffer_list->output;
+ png_ptr->zstream.avail_out = png_ptr->zbuffer_size;
+ }
+
+ /* Now loop reading and writing until all the input is consumed or an error
+ * terminates the operation. The _out values are maintained across calls to
+ * this function, but the input must be reset each time.
+ */
+ png_ptr->zstream.next_in = PNGZ_INPUT_CAST(input);
+ png_ptr->zstream.avail_in = 0; /* set below */
+ for (;;)
{
- /* Optimize the CMF field in the zlib stream. This hack of the zlib
- * stream is compliant to the stream specification.
+ int ret;
+
+ /* INPUT: from the row data */
+ uInt avail = ZLIB_IO_MAX;
+
+ if (avail > input_len)
+ avail = (uInt)input_len; /* safe because of the check */
+
+ png_ptr->zstream.avail_in = avail;
+ input_len -= avail;
+
+ ret = deflate(&png_ptr->zstream, input_len > 0 ? Z_NO_FLUSH : flush);
+
+ /* Include as-yet unconsumed input */
+ input_len += png_ptr->zstream.avail_in;
+ png_ptr->zstream.avail_in = 0;
+
+ /* OUTPUT: write complete IDAT chunks when avail_out drops to zero. Note
+ * that these two zstream fields are preserved across the calls, therefore
+ * there is no need to set these up on entry to the loop.
*/
- unsigned int z_cmf = data[0]; /* zlib compression method and flags */
+ if (png_ptr->zstream.avail_out == 0)
+ {
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size;
- if ((z_cmf & 0x0f) == 8 && (z_cmf & 0xf0) <= 0x70)
+ /* Write an IDAT containing the data then reset the buffer. The
+ * first IDAT may need deflate header optimization.
+ */
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
+
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->mode |= PNG_HAVE_IDAT;
+
+ png_ptr->zstream.next_out = data;
+ png_ptr->zstream.avail_out = size;
+
+ /* For SYNC_FLUSH or FINISH it is essential to keep calling zlib with
+ * the same flush parameter until it has finished output, for NO_FLUSH
+ * it doesn't matter.
+ */
+ if (ret == Z_OK && flush != Z_NO_FLUSH)
+ continue;
+ }
+
+ /* The order of these checks doesn't matter much; it just affects which
+ * possible error might be detected if multiple things go wrong at once.
+ */
+ if (ret == Z_OK) /* most likely return code! */
{
- /* Avoid memory underflows and multiplication overflows.
- *
- * The conditions below are practically always satisfied;
- * however, they still must be checked.
+ /* If all the input has been consumed then just return. If Z_FINISH
+ * was used as the flush parameter something has gone wrong if we get
+ * here.
*/
- if (length >= 2 &&
- png_ptr->height < 16384 && png_ptr->width < 16384)
+ if (input_len == 0)
{
- /* Compute the maximum possible length of the datastream */
+ if (flush == Z_FINISH)
+ png_error(png_ptr, "Z_OK on Z_FINISH with output space");
- /* Number of pixels, plus for each row a filter byte
- * and possibly a padding byte, so increase the maximum
- * size to account for these.
- */
- unsigned int z_cinfo;
- unsigned int half_z_window_size;
- png_uint_32 uncompressed_idat_size = png_ptr->height *
- ((png_ptr->width *
- png_ptr->channels * png_ptr->bit_depth + 15) >> 3);
-
- /* If it's interlaced, each block of 8 rows is sent as up to
- * 14 rows, i.e., 6 additional rows, each with a filter byte
- * and possibly a padding byte
- */
- if (png_ptr->interlaced)
- uncompressed_idat_size += ((png_ptr->height + 7)/8) *
- (png_ptr->bit_depth < 8 ? 12 : 6);
+ return;
+ }
+ }
- z_cinfo = z_cmf >> 4;
- half_z_window_size = 1 << (z_cinfo + 7);
+ else if (ret == Z_STREAM_END && flush == Z_FINISH)
+ {
+ /* This is the end of the IDAT data; any pending output must be
+ * flushed. For small PNG files we may still be at the beginning.
+ */
+ png_bytep data = png_ptr->zbuffer_list->output;
+ uInt size = png_ptr->zbuffer_size - png_ptr->zstream.avail_out;
- while (uncompressed_idat_size <= half_z_window_size &&
- half_z_window_size >= 256)
- {
- z_cinfo--;
- half_z_window_size >>= 1;
- }
+#ifdef PNG_WRITE_OPTIMIZE_CMF_SUPPORTED
+ if ((png_ptr->mode & PNG_HAVE_IDAT) == 0 &&
+ png_ptr->compression_type == PNG_COMPRESSION_TYPE_BASE)
+ optimize_cmf(data, png_image_size(png_ptr));
+#endif
- z_cmf = (z_cmf & 0x0f) | (z_cinfo << 4);
+ png_write_complete_chunk(png_ptr, png_IDAT, data, size);
+ png_ptr->zstream.avail_out = 0;
+ png_ptr->zstream.next_out = NULL;
+ png_ptr->mode |= PNG_HAVE_IDAT | PNG_AFTER_IDAT;
- if (data[0] != z_cmf)
- {
- int tmp;
- data[0] = (png_byte)z_cmf;
- tmp = data[1] & 0xe0;
- tmp += 0x1f - ((z_cmf << 8) + tmp) % 0x1f;
- data[1] = (png_byte)tmp;
- }
- }
+ png_ptr->zowner = 0; /* Release the stream */
+ return;
}
else
- png_error(png_ptr,
- "Invalid zlib compression method or flags in IDAT");
+ {
+ /* This is an error condition. */
+ png_zstream_error(png_ptr, ret);
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
}
-#endif /* PNG_WRITE_OPTIMIZE_CMF_SUPPORTED */
-
- png_write_complete_chunk(png_ptr, png_IDAT, data, length);
- png_ptr->mode |= PNG_HAVE_IDAT;
-
- /* Prior to 1.5.4 this code was replicated in every caller (except at the
- * end, where it isn't technically necessary). Since this function has
- * flushed the data we can safely reset the zlib output buffer here.
- */
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
}
/* Write an IEND chunk */
void /* PRIVATE */
-png_write_IEND(png_structp png_ptr)
+png_write_IEND(png_structrp png_ptr)
{
png_debug(1, "in png_write_IEND");
@@ -1059,7 +1156,7 @@ png_write_IEND(png_structp png_ptr)
#ifdef PNG_WRITE_gAMA_SUPPORTED
/* Write a gAMA chunk */
void /* PRIVATE */
-png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
+png_write_gAMA_fixed(png_structrp png_ptr, png_fixed_point file_gamma)
{
png_byte buf[4];
@@ -1074,7 +1171,7 @@ png_write_gAMA_fixed(png_structp png_ptr, png_fixed_point file_gamma)
#ifdef PNG_WRITE_sRGB_SUPPORTED
/* Write a sRGB chunk */
void /* PRIVATE */
-png_write_sRGB(png_structp png_ptr, int srgb_intent)
+png_write_sRGB(png_structrp png_ptr, int srgb_intent)
{
png_byte buf[1];
@@ -1092,94 +1189,72 @@ png_write_sRGB(png_structp png_ptr, int srgb_intent)
#ifdef PNG_WRITE_iCCP_SUPPORTED
/* Write an iCCP chunk */
void /* PRIVATE */
-png_write_iCCP(png_structp png_ptr, png_const_charp name, int compression_type,
- png_const_charp profile, int profile_len)
+png_write_iCCP(png_structrp png_ptr, png_const_charp name,
+ png_const_bytep profile)
{
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_uint_32 profile_len;
+ png_byte new_name[81]; /* 1 byte for the compression byte */
compression_state comp;
- int embedded_profile_len = 0;
+ png_uint_32 temp;
png_debug(1, "in png_write_iCCP");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
- comp.input_len = 0;
-
- if ((name_len = png_check_keyword(png_ptr, name, &new_name)) == 0)
- return;
-
- if (compression_type != PNG_COMPRESSION_TYPE_BASE)
- png_warning(png_ptr, "Unknown compression type in iCCP chunk");
-
+ /* These are all internal problems: the profile should have been checked
+ * before when it was stored.
+ */
if (profile == NULL)
- profile_len = 0;
+ png_error(png_ptr, "No profile for iCCP chunk"); /* internal error */
- if (profile_len > 3)
- embedded_profile_len =
- ((*( (png_const_bytep)profile ))<<24) |
- ((*( (png_const_bytep)profile + 1))<<16) |
- ((*( (png_const_bytep)profile + 2))<< 8) |
- ((*( (png_const_bytep)profile + 3)) );
+ profile_len = png_get_uint_32(profile);
- if (embedded_profile_len < 0)
- {
- png_warning(png_ptr,
- "Embedded profile length in iCCP chunk is negative");
+ if (profile_len < 132)
+ png_error(png_ptr, "ICC profile too short");
- png_free(png_ptr, new_name);
- return;
- }
+ temp = (png_uint_32) (*(profile+8));
+ if (temp > 3 && (profile_len & 0x03))
+ png_error(png_ptr, "ICC profile length invalid (not a multiple of 4)");
- if (profile_len < embedded_profile_len)
{
- png_warning(png_ptr,
- "Embedded profile length too large in iCCP chunk");
+ png_uint_32 embedded_profile_len = png_get_uint_32(profile);
- png_free(png_ptr, new_name);
- return;
+ if (profile_len != embedded_profile_len)
+ png_error(png_ptr, "Profile length does not match profile");
}
- if (profile_len > embedded_profile_len)
- {
- png_warning(png_ptr,
- "Truncating profile to actual length in iCCP chunk");
+ name_len = png_check_keyword(png_ptr, name, new_name);
- profile_len = embedded_profile_len;
- }
+ if (name_len == 0)
+ png_error(png_ptr, "iCCP: invalid keyword");
- if (profile_len)
- profile_len = png_text_compress(png_ptr, profile,
- (png_size_t)profile_len, PNG_COMPRESSION_TYPE_BASE, &comp);
+ new_name[++name_len] = PNG_COMPRESSION_TYPE_BASE;
/* Make sure we include the NULL after the name and the compression type */
- png_write_chunk_header(png_ptr, png_iCCP,
- (png_uint_32)(name_len + profile_len + 2));
+ ++name_len;
- new_name[name_len + 1] = 0x00;
+ png_text_compress_init(&comp, profile, profile_len);
- png_write_chunk_data(png_ptr, (png_bytep)new_name,
- (png_size_t)(name_len + 2));
+ /* Allow for keyword terminator and compression byte */
+ if (png_text_compress(png_ptr, png_iCCP, &comp, name_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
- if (profile_len)
- {
- png_write_compressed_data_out(png_ptr, &comp, profile_len);
- }
+ png_write_chunk_header(png_ptr, png_iCCP, name_len + comp.output_len);
+
+ png_write_chunk_data(png_ptr, new_name, name_len);
+
+ png_write_compressed_data_out(png_ptr, &comp);
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
#ifdef PNG_WRITE_sPLT_SUPPORTED
/* Write a sPLT chunk */
void /* PRIVATE */
-png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
+png_write_sPLT(png_structrp png_ptr, png_const_sPLT_tp spalette)
{
- png_size_t name_len;
- png_charp new_name;
+ png_uint_32 name_len;
+ png_byte new_name[80];
png_byte entrybuf[10];
png_size_t entry_size = (spalette->depth == 8 ? 6 : 10);
png_size_t palette_size = entry_size * spalette->nentries;
@@ -1190,8 +1265,10 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_debug(1, "in png_write_sPLT");
- if ((name_len = png_check_keyword(png_ptr,spalette->name, &new_name))==0)
- return;
+ name_len = png_check_keyword(png_ptr, spalette->name, new_name);
+
+ if (name_len == 0)
+ png_error(png_ptr, "sPLT: invalid keyword");
/* Make sure we include the NULL after the name */
png_write_chunk_header(png_ptr, png_sPLT,
@@ -1224,7 +1301,7 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep->frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, entry_size);
}
#else
ep=spalette->entries;
@@ -1248,19 +1325,18 @@ png_write_sPLT(png_structp png_ptr, png_const_sPLT_tp spalette)
png_save_uint_16(entrybuf + 8, ep[i].frequency);
}
- png_write_chunk_data(png_ptr, entrybuf, (png_size_t)entry_size);
+ png_write_chunk_data(png_ptr, entrybuf, entry_size);
}
#endif
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_name);
}
#endif
#ifdef PNG_WRITE_sBIT_SUPPORTED
/* Write the sBIT chunk */
void /* PRIVATE */
-png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
+png_write_sBIT(png_structrp png_ptr, png_const_color_8p sbit, int color_type)
{
png_byte buf[4];
png_size_t size;
@@ -1268,7 +1344,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
png_debug(1, "in png_write_sBIT");
/* Make sure we don't depend upon the order of PNG_COLOR_8 */
- if (color_type & PNG_COLOR_MASK_COLOR)
+ if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_byte maxbits;
@@ -1301,7 +1377,7 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
size = 1;
}
- if (color_type & PNG_COLOR_MASK_ALPHA)
+ if ((color_type & PNG_COLOR_MASK_ALPHA) != 0)
{
if (sbit->alpha == 0 || sbit->alpha > png_ptr->usr_bit_depth)
{
@@ -1319,42 +1395,33 @@ png_write_sBIT(png_structp png_ptr, png_const_color_8p sbit, int color_type)
#ifdef PNG_WRITE_cHRM_SUPPORTED
/* Write the cHRM chunk */
void /* PRIVATE */
-png_write_cHRM_fixed(png_structp png_ptr, png_fixed_point white_x,
- png_fixed_point white_y, png_fixed_point red_x, png_fixed_point red_y,
- png_fixed_point green_x, png_fixed_point green_y, png_fixed_point blue_x,
- png_fixed_point blue_y)
+png_write_cHRM_fixed(png_structrp png_ptr, const png_xy *xy)
{
png_byte buf[32];
png_debug(1, "in png_write_cHRM");
/* Each value is saved in 1/100,000ths */
-#ifdef PNG_CHECK_cHRM_SUPPORTED
- if (png_check_cHRM_fixed(png_ptr, white_x, white_y, red_x, red_y,
- green_x, green_y, blue_x, blue_y))
-#endif
- {
- png_save_uint_32(buf, (png_uint_32)white_x);
- png_save_uint_32(buf + 4, (png_uint_32)white_y);
+ png_save_int_32(buf, xy->whitex);
+ png_save_int_32(buf + 4, xy->whitey);
- png_save_uint_32(buf + 8, (png_uint_32)red_x);
- png_save_uint_32(buf + 12, (png_uint_32)red_y);
+ png_save_int_32(buf + 8, xy->redx);
+ png_save_int_32(buf + 12, xy->redy);
- png_save_uint_32(buf + 16, (png_uint_32)green_x);
- png_save_uint_32(buf + 20, (png_uint_32)green_y);
+ png_save_int_32(buf + 16, xy->greenx);
+ png_save_int_32(buf + 20, xy->greeny);
- png_save_uint_32(buf + 24, (png_uint_32)blue_x);
- png_save_uint_32(buf + 28, (png_uint_32)blue_y);
+ png_save_int_32(buf + 24, xy->bluex);
+ png_save_int_32(buf + 28, xy->bluey);
- png_write_complete_chunk(png_ptr, png_cHRM, buf, (png_size_t)32);
- }
+ png_write_complete_chunk(png_ptr, png_cHRM, buf, 32);
}
#endif
#ifdef PNG_WRITE_tRNS_SUPPORTED
/* Write the tRNS chunk */
void /* PRIVATE */
-png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
+png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha,
png_const_color_16p tran, int num_trans, int color_type)
{
png_byte buf[6];
@@ -1365,12 +1432,14 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
{
if (num_trans <= 0 || num_trans > (int)png_ptr->num_palette)
{
- png_warning(png_ptr, "Invalid number of transparent colors specified");
+ png_app_warning(png_ptr,
+ "Invalid number of transparent colors specified");
return;
}
/* Write the chunk out as it is */
- png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha, (png_size_t)num_trans);
+ png_write_complete_chunk(png_ptr, png_tRNS, trans_alpha,
+ (png_size_t)num_trans);
}
else if (color_type == PNG_COLOR_TYPE_GRAY)
@@ -1378,7 +1447,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
/* One 16 bit value */
if (tran->gray >= (1 << png_ptr->bit_depth))
{
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"Ignoring attempt to write tRNS chunk out-of-range for bit_depth");
return;
@@ -1395,12 +1464,12 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
png_save_uint_16(buf + 2, tran->green);
png_save_uint_16(buf + 4, tran->blue);
#ifdef PNG_WRITE_16BIT_SUPPORTED
- if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
- png_warning(png_ptr,
+ png_app_warning(png_ptr,
"Ignoring attempt to write 16-bit tRNS chunk when bit_depth is 8");
return;
}
@@ -1410,7 +1479,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
else
{
- png_warning(png_ptr, "Can't write tRNS with an alpha channel");
+ png_app_warning(png_ptr, "Can't write tRNS with an alpha channel");
}
}
#endif
@@ -1418,7 +1487,7 @@ png_write_tRNS(png_structp png_ptr, png_const_bytep trans_alpha,
#ifdef PNG_WRITE_bKGD_SUPPORTED
/* Write the background chunk */
void /* PRIVATE */
-png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
+png_write_bKGD(png_structrp png_ptr, png_const_color_16p back, int color_type)
{
png_byte buf[6];
@@ -1428,8 +1497,8 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
{
if (
#ifdef PNG_MNG_FEATURES_SUPPORTED
- (png_ptr->num_palette ||
- (!(png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE))) &&
+ (png_ptr->num_palette != 0 ||
+ (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0) &&
#endif
back->index >= png_ptr->num_palette)
{
@@ -1441,15 +1510,15 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
png_write_complete_chunk(png_ptr, png_bKGD, buf, (png_size_t)1);
}
- else if (color_type & PNG_COLOR_MASK_COLOR)
+ else if ((color_type & PNG_COLOR_MASK_COLOR) != 0)
{
png_save_uint_16(buf, back->red);
png_save_uint_16(buf + 2, back->green);
png_save_uint_16(buf + 4, back->blue);
#ifdef PNG_WRITE_16BIT_SUPPORTED
- if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]))
+ if (png_ptr->bit_depth == 8 && (buf[0] | buf[2] | buf[4]) != 0)
#else
- if (buf[0] | buf[2] | buf[4])
+ if ((buf[0] | buf[2] | buf[4]) != 0)
#endif
{
png_warning(png_ptr,
@@ -1480,7 +1549,7 @@ png_write_bKGD(png_structp png_ptr, png_const_color_16p back, int color_type)
#ifdef PNG_WRITE_hIST_SUPPORTED
/* Write the histogram */
void /* PRIVATE */
-png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
+png_write_hIST(png_structrp png_ptr, png_const_uint_16p hist, int num_hist)
{
int i;
png_byte buf[3];
@@ -1508,234 +1577,94 @@ png_write_hIST(png_structp png_ptr, png_const_uint_16p hist, int num_hist)
}
#endif
-#if defined(PNG_WRITE_TEXT_SUPPORTED) || defined(PNG_WRITE_pCAL_SUPPORTED) || \
- defined(PNG_WRITE_iCCP_SUPPORTED) || defined(PNG_WRITE_sPLT_SUPPORTED)
-/* Check that the tEXt or zTXt keyword is valid per PNG 1.0 specification,
- * and if invalid, correct the keyword rather than discarding the entire
- * chunk. The PNG 1.0 specification requires keywords 1-79 characters in
- * length, forbids leading or trailing whitespace, multiple internal spaces,
- * and the non-break space (0x80) from ISO 8859-1. Returns keyword length.
- *
- * The new_key is allocated to hold the corrected keyword and must be freed
- * by the calling routine. This avoids problems with trying to write to
- * static keywords without having to have duplicate copies of the strings.
- */
-png_size_t /* PRIVATE */
-png_check_keyword(png_structp png_ptr, png_const_charp key, png_charpp new_key)
-{
- png_size_t key_len;
- png_const_charp ikp;
- png_charp kp, dp;
- int kflag;
- int kwarn=0;
-
- png_debug(1, "in png_check_keyword");
-
- *new_key = NULL;
-
- if (key == NULL || (key_len = png_strlen(key)) == 0)
- {
- png_warning(png_ptr, "zero length keyword");
- return ((png_size_t)0);
- }
-
- png_debug1(2, "Keyword to be checked is '%s'", key);
-
- *new_key = (png_charp)png_malloc_warn(png_ptr, (png_uint_32)(key_len + 2));
-
- if (*new_key == NULL)
- {
- png_warning(png_ptr, "Out of memory while procesing keyword");
- return ((png_size_t)0);
- }
-
- /* Replace non-printing characters with a blank and print a warning */
- for (ikp = key, dp = *new_key; *ikp != '\0'; ikp++, dp++)
- {
- if ((png_byte)*ikp < 0x20 ||
- ((png_byte)*ikp > 0x7E && (png_byte)*ikp < 0xA1))
- {
- PNG_WARNING_PARAMETERS(p)
-
- png_warning_parameter_unsigned(p, 1, PNG_NUMBER_FORMAT_02x,
- (png_byte)*ikp);
- png_formatted_warning(png_ptr, p, "invalid keyword character 0x@1");
- *dp = ' ';
- }
-
- else
- {
- *dp = *ikp;
- }
- }
- *dp = '\0';
-
- /* Remove any trailing white space. */
- kp = *new_key + key_len - 1;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "trailing spaces removed from keyword");
-
- while (*kp == ' ')
- {
- *(kp--) = '\0';
- key_len--;
- }
- }
-
- /* Remove any leading white space. */
- kp = *new_key;
- if (*kp == ' ')
- {
- png_warning(png_ptr, "leading spaces removed from keyword");
-
- while (*kp == ' ')
- {
- kp++;
- key_len--;
- }
- }
-
- png_debug1(2, "Checking for multiple internal spaces in '%s'", kp);
-
- /* Remove multiple internal spaces. */
- for (kflag = 0, dp = *new_key; *kp != '\0'; kp++)
- {
- if (*kp == ' ' && kflag == 0)
- {
- *(dp++) = *kp;
- kflag = 1;
- }
-
- else if (*kp == ' ')
- {
- key_len--;
- kwarn = 1;
- }
-
- else
- {
- *(dp++) = *kp;
- kflag = 0;
- }
- }
- *dp = '\0';
- if (kwarn)
- png_warning(png_ptr, "extra interior spaces removed from keyword");
-
- if (key_len == 0)
- {
- png_free(png_ptr, *new_key);
- png_warning(png_ptr, "Zero length keyword");
- }
-
- if (key_len > 79)
- {
- png_warning(png_ptr, "keyword length must be 1 - 79 characters");
- (*new_key)[79] = '\0';
- key_len = 79;
- }
-
- return (key_len);
-}
-#endif
-
#ifdef PNG_WRITE_tEXt_SUPPORTED
/* Write a tEXt chunk */
void /* PRIVATE */
-png_write_tEXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
+png_write_tEXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
png_size_t text_len)
{
- png_size_t key_len;
- png_charp new_key;
+ png_uint_32 key_len;
+ png_byte new_key[80];
png_debug(1, "in png_write_tEXt");
- if ((key_len = png_check_keyword(png_ptr, key, &new_key))==0)
- return;
+ key_len = png_check_keyword(png_ptr, key, new_key);
+
+ if (key_len == 0)
+ png_error(png_ptr, "tEXt: invalid keyword");
if (text == NULL || *text == '\0')
text_len = 0;
else
- text_len = png_strlen(text);
+ text_len = strlen(text);
+
+ if (text_len > PNG_UINT_31_MAX - (key_len+1))
+ png_error(png_ptr, "tEXt: text too long");
/* Make sure we include the 0 after the key */
png_write_chunk_header(png_ptr, png_tEXt,
- (png_uint_32)(key_len + text_len + 1));
+ (png_uint_32)/*checked above*/(key_len + text_len + 1));
/*
* We leave it to the application to meet PNG-1.0 requirements on the
* contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
* any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
* The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
*/
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
- (png_size_t)(key_len + 1));
+ png_write_chunk_data(png_ptr, new_key, key_len + 1);
- if (text_len)
- png_write_chunk_data(png_ptr, (png_const_bytep)text,
- (png_size_t)text_len);
+ if (text_len != 0)
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, text_len);
png_write_chunk_end(png_ptr);
- png_free(png_ptr, new_key);
}
#endif
#ifdef PNG_WRITE_zTXt_SUPPORTED
/* Write a compressed text chunk */
void /* PRIVATE */
-png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
- png_size_t text_len, int compression)
+png_write_zTXt(png_structrp png_ptr, png_const_charp key, png_const_charp text,
+ int compression)
{
- png_size_t key_len;
- png_byte buf;
- png_charp new_key;
+ png_uint_32 key_len;
+ png_byte new_key[81];
compression_state comp;
png_debug(1, "in png_write_zTXt");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
- comp.input_len = 0;
-
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
+ if (compression == PNG_TEXT_COMPRESSION_NONE)
{
- png_free(png_ptr, new_key);
+ png_write_tEXt(png_ptr, key, text, 0);
return;
}
- if (text == NULL || *text == '\0' || compression==PNG_TEXT_COMPRESSION_NONE)
- {
- png_write_tEXt(png_ptr, new_key, text, (png_size_t)0);
- png_free(png_ptr, new_key);
- return;
- }
+ if (compression != PNG_TEXT_COMPRESSION_zTXt)
+ png_error(png_ptr, "zTXt: invalid compression type");
- text_len = png_strlen(text);
+ key_len = png_check_keyword(png_ptr, key, new_key);
- /* Compute the compressed data; do it now for the length */
- text_len = png_text_compress(png_ptr, text, text_len, compression,
- &comp);
+ if (key_len == 0)
+ png_error(png_ptr, "zTXt: invalid keyword");
- /* Write start of chunk */
- png_write_chunk_header(png_ptr, png_zTXt,
- (png_uint_32)(key_len+text_len + 2));
+ /* Add the compression method and 1 for the keyword separator. */
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len;
- /* Write key */
- png_write_chunk_data(png_ptr, (png_bytep)new_key,
- (png_size_t)(key_len + 1));
+ /* Compute the compressed data; do it now for the length */
+ png_text_compress_init(&comp, (png_const_bytep)text,
+ text == NULL ? 0 : strlen(text));
- png_free(png_ptr, new_key);
+ if (png_text_compress(png_ptr, png_zTXt, &comp, key_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
- buf = (png_byte)compression;
+ /* Write start of chunk */
+ png_write_chunk_header(png_ptr, png_zTXt, key_len + comp.output_len);
- /* Write compression */
- png_write_chunk_data(png_ptr, &buf, (png_size_t)1);
+ /* Write key */
+ png_write_chunk_data(png_ptr, new_key, key_len);
/* Write the compressed data */
- png_write_compressed_data_out(png_ptr, &comp, text_len);
+ png_write_compressed_data_out(png_ptr, &comp);
/* Close the chunk */
png_write_chunk_end(png_ptr);
@@ -1745,100 +1674,107 @@ png_write_zTXt(png_structp png_ptr, png_const_charp key, png_const_charp text,
#ifdef PNG_WRITE_iTXt_SUPPORTED
/* Write an iTXt chunk */
void /* PRIVATE */
-png_write_iTXt(png_structp png_ptr, int compression, png_const_charp key,
+png_write_iTXt(png_structrp png_ptr, int compression, png_const_charp key,
png_const_charp lang, png_const_charp lang_key, png_const_charp text)
{
- png_size_t lang_len, key_len, lang_key_len, text_len;
- png_charp new_lang;
- png_charp new_key = NULL;
- png_byte cbuf[2];
+ png_uint_32 key_len, prefix_len;
+ png_size_t lang_len, lang_key_len;
+ png_byte new_key[82];
compression_state comp;
png_debug(1, "in png_write_iTXt");
- comp.num_output_ptr = 0;
- comp.max_output_ptr = 0;
- comp.output_ptr = NULL;
- comp.input = NULL;
+ key_len = png_check_keyword(png_ptr, key, new_key);
- if ((key_len = png_check_keyword(png_ptr, key, &new_key)) == 0)
- return;
+ if (key_len == 0)
+ png_error(png_ptr, "iTXt: invalid keyword");
- if ((lang_len = png_check_keyword(png_ptr, lang, &new_lang)) == 0)
+ /* Set the compression flag */
+ switch (compression)
{
- png_warning(png_ptr, "Empty language field in iTXt chunk");
- new_lang = NULL;
- lang_len = 0;
- }
+ case PNG_ITXT_COMPRESSION_NONE:
+ case PNG_TEXT_COMPRESSION_NONE:
+ compression = new_key[++key_len] = 0; /* no compression */
+ break;
- if (lang_key == NULL)
- lang_key_len = 0;
+ case PNG_TEXT_COMPRESSION_zTXt:
+ case PNG_ITXT_COMPRESSION_zTXt:
+ compression = new_key[++key_len] = 1; /* compressed */
+ break;
- else
- lang_key_len = png_strlen(lang_key);
+ default:
+ png_error(png_ptr, "iTXt: invalid compression");
+ }
- if (text == NULL)
- text_len = 0;
+ new_key[++key_len] = PNG_COMPRESSION_TYPE_BASE;
+ ++key_len; /* for the keywod separator */
+ /* We leave it to the application to meet PNG-1.0 requirements on the
+ * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
+ * any non-Latin-1 characters except for NEWLINE. ISO PNG, however,
+ * specifies that the text is UTF-8 and this really doesn't require any
+ * checking.
+ *
+ * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
+ *
+ * TODO: validate the language tag correctly (see the spec.)
+ */
+ if (lang == NULL) lang = ""; /* empty language is valid */
+ lang_len = strlen(lang)+1;
+ if (lang_key == NULL) lang_key = ""; /* may be empty */
+ lang_key_len = strlen(lang_key)+1;
+ if (text == NULL) text = ""; /* may be empty */
+
+ prefix_len = key_len;
+ if (lang_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
else
- text_len = png_strlen(text);
-
- /* Compute the compressed data; do it now for the length */
- text_len = png_text_compress(png_ptr, text, text_len, compression - 2,
- &comp);
+ prefix_len = (png_uint_32)(prefix_len + lang_len);
+ if (lang_key_len > PNG_UINT_31_MAX-prefix_len)
+ prefix_len = PNG_UINT_31_MAX;
+ else
+ prefix_len = (png_uint_32)(prefix_len + lang_key_len);
- /* Make sure we include the compression flag, the compression byte,
- * and the NULs after the key, lang, and lang_key parts
- */
+ png_text_compress_init(&comp, (png_const_bytep)text, strlen(text));
- png_write_chunk_header(png_ptr, png_iTXt, (png_uint_32)(
- 5 /* comp byte, comp flag, terminators for key, lang and lang_key */
- + key_len
- + lang_len
- + lang_key_len
- + text_len));
+ if (compression != 0)
+ {
+ if (png_text_compress(png_ptr, png_iTXt, &comp, prefix_len) != Z_OK)
+ png_error(png_ptr, png_ptr->zstream.msg);
+ }
- /* We leave it to the application to meet PNG-1.0 requirements on the
- * contents of the text. PNG-1.0 through PNG-1.2 discourage the use of
- * any non-Latin-1 characters except for NEWLINE. ISO PNG will forbid them.
- * The NUL character is forbidden by PNG-1.0 through PNG-1.2 and ISO PNG.
- */
- png_write_chunk_data(png_ptr, (png_bytep)new_key, (png_size_t)(key_len + 1));
+ else
+ {
+ if (comp.input_len > PNG_UINT_31_MAX-prefix_len)
+ png_error(png_ptr, "iTXt: uncompressed text too long");
- /* Set the compression flag */
- if (compression == PNG_ITXT_COMPRESSION_NONE ||
- compression == PNG_TEXT_COMPRESSION_NONE)
- cbuf[0] = 0;
+ /* So the string will fit in a chunk: */
+ comp.output_len = (png_uint_32)/*SAFE*/comp.input_len;
+ }
- else /* compression == PNG_ITXT_COMPRESSION_zTXt */
- cbuf[0] = 1;
+ png_write_chunk_header(png_ptr, png_iTXt, comp.output_len + prefix_len);
- /* Set the compression method */
- cbuf[1] = 0;
+ png_write_chunk_data(png_ptr, new_key, key_len);
- png_write_chunk_data(png_ptr, cbuf, (png_size_t)2);
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang, lang_len);
- cbuf[0] = 0;
- png_write_chunk_data(png_ptr, (new_lang ? (png_const_bytep)new_lang : cbuf),
- (png_size_t)(lang_len + 1));
+ png_write_chunk_data(png_ptr, (png_const_bytep)lang_key, lang_key_len);
- png_write_chunk_data(png_ptr, (lang_key ? (png_const_bytep)lang_key : cbuf),
- (png_size_t)(lang_key_len + 1));
+ if (compression != 0)
+ png_write_compressed_data_out(png_ptr, &comp);
- png_write_compressed_data_out(png_ptr, &comp, text_len);
+ else
+ png_write_chunk_data(png_ptr, (png_const_bytep)text, comp.output_len);
png_write_chunk_end(png_ptr);
-
- png_free(png_ptr, new_key);
- png_free(png_ptr, new_lang);
}
#endif
#ifdef PNG_WRITE_oFFs_SUPPORTED
/* Write the oFFs chunk */
void /* PRIVATE */
-png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
+png_write_oFFs(png_structrp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
int unit_type)
{
png_byte buf[9];
@@ -1858,36 +1794,43 @@ png_write_oFFs(png_structp png_ptr, png_int_32 x_offset, png_int_32 y_offset,
#ifdef PNG_WRITE_pCAL_SUPPORTED
/* Write the pCAL chunk (described in the PNG extensions document) */
void /* PRIVATE */
-png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
+png_write_pCAL(png_structrp png_ptr, png_charp purpose, png_int_32 X0,
png_int_32 X1, int type, int nparams, png_const_charp units,
png_charpp params)
{
- png_size_t purpose_len, units_len, total_len;
+ png_uint_32 purpose_len;
+ png_size_t units_len, total_len;
png_size_tp params_len;
png_byte buf[10];
- png_charp new_purpose;
+ png_byte new_purpose[80];
int i;
png_debug1(1, "in png_write_pCAL (%d parameters)", nparams);
if (type >= PNG_EQUATION_LAST)
- png_warning(png_ptr, "Unrecognized equation type for pCAL chunk");
+ png_error(png_ptr, "Unrecognized equation type for pCAL chunk");
+
+ purpose_len = png_check_keyword(png_ptr, purpose, new_purpose);
+
+ if (purpose_len == 0)
+ png_error(png_ptr, "pCAL: invalid keyword");
+
+ ++purpose_len; /* terminator */
- purpose_len = png_check_keyword(png_ptr, purpose, &new_purpose) + 1;
png_debug1(3, "pCAL purpose length = %d", (int)purpose_len);
- units_len = png_strlen(units) + (nparams == 0 ? 0 : 1);
+ units_len = strlen(units) + (nparams == 0 ? 0 : 1);
png_debug1(3, "pCAL units length = %d", (int)units_len);
total_len = purpose_len + units_len + 10;
params_len = (png_size_tp)png_malloc(png_ptr,
- (png_alloc_size_t)(nparams * png_sizeof(png_size_t)));
+ (png_alloc_size_t)(nparams * (sizeof (png_size_t))));
/* Find the length of each parameter, making sure we don't count the
* null terminator for the last parameter.
*/
for (i = 0; i < nparams; i++)
{
- params_len[i] = png_strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
+ params_len[i] = strlen(params[i]) + (i == nparams - 1 ? 0 : 1);
png_debug2(3, "pCAL parameter %d length = %lu", i,
(unsigned long)params_len[i]);
total_len += params_len[i];
@@ -1895,7 +1838,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_debug1(3, "pCAL total length = %d", (int)total_len);
png_write_chunk_header(png_ptr, png_pCAL, (png_uint_32)total_len);
- png_write_chunk_data(png_ptr, (png_const_bytep)new_purpose, purpose_len);
+ png_write_chunk_data(png_ptr, new_purpose, purpose_len);
png_save_int_32(buf, X0);
png_save_int_32(buf + 4, X1);
buf[8] = (png_byte)type;
@@ -1903,8 +1846,6 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
png_write_chunk_data(png_ptr, buf, (png_size_t)10);
png_write_chunk_data(png_ptr, (png_const_bytep)units, (png_size_t)units_len);
- png_free(png_ptr, new_purpose);
-
for (i = 0; i < nparams; i++)
{
png_write_chunk_data(png_ptr, (png_const_bytep)params[i], params_len[i]);
@@ -1918,7 +1859,7 @@ png_write_pCAL(png_structp png_ptr, png_charp purpose, png_int_32 X0,
#ifdef PNG_WRITE_sCAL_SUPPORTED
/* Write the sCAL chunk */
void /* PRIVATE */
-png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
+png_write_sCAL_s(png_structrp png_ptr, int unit, png_const_charp width,
png_const_charp height)
{
png_byte buf[64];
@@ -1926,8 +1867,8 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
png_debug(1, "in png_write_sCAL_s");
- wlen = png_strlen(width);
- hlen = png_strlen(height);
+ wlen = strlen(width);
+ hlen = strlen(height);
total_len = wlen + hlen + 2;
if (total_len > 64)
@@ -1937,8 +1878,8 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
}
buf[0] = (png_byte)unit;
- png_memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
- png_memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
+ memcpy(buf + 1, width, wlen + 1); /* Append the '\0' here */
+ memcpy(buf + wlen + 2, height, hlen); /* Do NOT append the '\0' here */
png_debug1(3, "sCAL total length = %u", (unsigned int)total_len);
png_write_complete_chunk(png_ptr, png_sCAL, buf, total_len);
@@ -1948,7 +1889,7 @@ png_write_sCAL_s(png_structp png_ptr, int unit, png_const_charp width,
#ifdef PNG_WRITE_pHYs_SUPPORTED
/* Write the pHYs chunk */
void /* PRIVATE */
-png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
+png_write_pHYs(png_structrp png_ptr, png_uint_32 x_pixels_per_unit,
png_uint_32 y_pixels_per_unit,
int unit_type)
{
@@ -1972,7 +1913,7 @@ png_write_pHYs(png_structp png_ptr, png_uint_32 x_pixels_per_unit,
* or png_convert_from_time_t(), or fill in the structure yourself.
*/
void /* PRIVATE */
-png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
+png_write_tIME(png_structrp png_ptr, png_const_timep mod_time)
{
png_byte buf[7];
@@ -1999,7 +1940,7 @@ png_write_tIME(png_structp png_ptr, png_const_timep mod_time)
/* Initializes the row writing capability of libpng */
void /* PRIVATE */
-png_write_start_row(png_structp png_ptr)
+png_write_start_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@@ -2044,12 +1985,13 @@ png_write_start_row(png_structp png_ptr)
}
/* We only need to keep the previous row if we are using one of these. */
- if (png_ptr->do_filter & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH))
+ if ((png_ptr->do_filter &
+ (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0)
{
/* Set up previous row buffer */
png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size);
- if (png_ptr->do_filter & PNG_FILTER_UP)
+ if ((png_ptr->do_filter & PNG_FILTER_UP) != 0)
{
png_ptr->up_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2057,7 +1999,7 @@ png_write_start_row(png_structp png_ptr)
png_ptr->up_row[0] = PNG_FILTER_VALUE_UP;
}
- if (png_ptr->do_filter & PNG_FILTER_AVG)
+ if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0)
{
png_ptr->avg_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2065,7 +2007,7 @@ png_write_start_row(png_structp png_ptr)
png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG;
}
- if (png_ptr->do_filter & PNG_FILTER_PAETH)
+ if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0)
{
png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr,
png_ptr->rowbytes + 1);
@@ -2073,13 +2015,13 @@ png_write_start_row(png_structp png_ptr)
png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH;
}
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, we need to set up width and height of pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
- if (!(png_ptr->transformations & PNG_INTERLACE))
+ if ((png_ptr->transformations & PNG_INTERLACE) == 0)
{
png_ptr->num_rows = (png_ptr->height + png_pass_yinc[0] - 1 -
png_pass_ystart[0]) / png_pass_yinc[0];
@@ -2101,15 +2043,11 @@ png_write_start_row(png_structp png_ptr)
png_ptr->num_rows = png_ptr->height;
png_ptr->usr_width = png_ptr->width;
}
-
- png_zlib_claim(png_ptr, PNG_ZLIB_FOR_IDAT);
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- png_ptr->zstream.next_out = png_ptr->zbuf;
}
/* Internal use only. Called when finished processing a row of data. */
void /* PRIVATE */
-png_write_finish_row(png_structp png_ptr)
+png_write_finish_row(png_structrp png_ptr)
{
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* Arrays to facilitate easy interlacing - use pass (0 - 6) as index */
@@ -2127,8 +2065,6 @@ png_write_finish_row(png_structp png_ptr)
static PNG_CONST png_byte png_pass_yinc[7] = {8, 8, 8, 4, 4, 2, 2};
#endif
- int ret;
-
png_debug(1, "in png_write_finish_row");
/* Next row */
@@ -2140,10 +2076,10 @@ png_write_finish_row(png_structp png_ptr)
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
/* If interlaced, go to next pass */
- if (png_ptr->interlaced)
+ if (png_ptr->interlaced != 0)
{
png_ptr->row_number = 0;
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
{
png_ptr->pass++;
}
@@ -2168,7 +2104,7 @@ png_write_finish_row(png_structp png_ptr)
png_pass_ystart[png_ptr->pass]) /
png_pass_yinc[png_ptr->pass];
- if (png_ptr->transformations & PNG_INTERLACE)
+ if ((png_ptr->transformations & PNG_INTERLACE) != 0)
break;
} while (png_ptr->usr_width == 0 || png_ptr->num_rows == 0);
@@ -2179,7 +2115,7 @@ png_write_finish_row(png_structp png_ptr)
if (png_ptr->pass < 7)
{
if (png_ptr->prev_row != NULL)
- png_memset(png_ptr->prev_row, 0,
+ memset(png_ptr->prev_row, 0,
(png_size_t)(PNG_ROWBYTES(png_ptr->usr_channels*
png_ptr->usr_bit_depth, png_ptr->width)) + 1);
@@ -2190,42 +2126,7 @@ png_write_finish_row(png_structp png_ptr)
/* If we get here, we've just written the last row, so we need
to flush the compressor */
- do
- {
- /* Tell the compressor we are done */
- ret = deflate(&png_ptr->zstream, Z_FINISH);
-
- /* Check for an error */
- if (ret == Z_OK)
- {
- /* Check to see if we need more room */
- if (!(png_ptr->zstream.avail_out))
- {
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- png_ptr->zstream.next_out = png_ptr->zbuf;
- png_ptr->zstream.avail_out = (uInt)png_ptr->zbuf_size;
- }
- }
-
- else if (ret != Z_STREAM_END)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
- } while (ret != Z_STREAM_END);
-
- /* Write any extra space */
- if (png_ptr->zstream.avail_out < png_ptr->zbuf_size)
- {
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size -
- png_ptr->zstream.avail_out);
- }
-
- png_zlib_release(png_ptr);
- png_ptr->zstream.data_type = Z_BINARY;
+ png_compress_IDAT(png_ptr, NULL, 0, Z_FINISH);
}
#ifdef PNG_WRITE_INTERLACING_SUPPORTED
@@ -2389,7 +2290,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
/* Move the pixel */
if (dp != sp)
- png_memcpy(dp, sp, pixel_bytes);
+ memcpy(dp, sp, pixel_bytes);
/* Next pixel */
dp += pixel_bytes;
@@ -2413,7 +2314,8 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass)
* been specified by the application, and then writes the row out with the
* chosen filter.
*/
-static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
+static void /* PRIVATE */
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
png_size_t row_bytes);
#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1)
@@ -2421,7 +2323,7 @@ static void png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
#define PNG_LOMASK ((png_uint_32)0xffffL)
#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT))
void /* PRIVATE */
-png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
+png_write_find_filter(png_structrp png_ptr, png_row_infop row_info)
{
png_bytep best_row;
#ifdef PNG_WRITE_FILTER_SUPPORTED
@@ -2481,7 +2383,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
/* We don't need to test the 'no filter' case if this is the only filter
* that has been chosen, as it doesn't actually do anything to the data.
*/
- if ((filter_to_do & PNG_FILTER_NONE) && filter_to_do != PNG_FILTER_NONE)
+ if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE)
{
png_bytep rp;
png_uint_32 sum = 0;
@@ -2551,13 +2453,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (lp = row_buf + 1; i < row_bytes;
i++, rp++, lp++, dp++)
{
- *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+ *dp = (png_byte)((int)*rp - (int)*lp);
}
best_row = png_ptr->sub_row;
}
- else if (filter_to_do & PNG_FILTER_SUB)
+ else if ((filter_to_do & PNG_FILTER_SUB) != 0)
{
png_bytep rp, dp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -2613,7 +2515,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (lp = row_buf + 1; i < row_bytes;
i++, rp++, lp++, dp++)
{
- v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff);
+ v = *dp = (png_byte)((int)*rp - (int)*lp);
sum += (v < 128) ? v : 256 - v;
@@ -2672,13 +2574,13 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
pp = prev_row + 1; i < row_bytes;
i++, rp++, pp++, dp++)
{
- *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff);
+ *dp = (png_byte)((int)*rp - (int)*pp);
}
best_row = png_ptr->up_row;
}
- else if (filter_to_do & PNG_FILTER_UP)
+ else if ((filter_to_do & PNG_FILTER_UP) != 0)
{
png_bytep rp, dp, pp;
png_uint_32 sum = 0, lmins = mins;
@@ -2723,7 +2625,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1,
pp = prev_row + 1; i < row_bytes; i++)
{
- v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+ v = *dp++ = (png_byte)((int)*rp++ - (int)*pp++);
sum += (v < 128) ? v : 256 - v;
@@ -2781,18 +2683,18 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
- *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+ *dp++ = (png_byte)((int)*rp++ - ((int)*pp++ / 2));
}
for (lp = row_buf + 1; i < row_bytes; i++)
{
- *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2))
- & 0xff);
+ *dp++ =
+ (png_byte)((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2));
}
best_row = png_ptr->avg_row;
}
- else if (filter_to_do & PNG_FILTER_AVG)
+ else if ((filter_to_do & PNG_FILTER_AVG) != 0)
{
png_bytep rp, dp, pp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -2836,7 +2738,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
- v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff);
+ v = *dp++ = (png_byte)((int)*rp++ - ((int)*pp++ / 2));
sum += (v < 128) ? v : 256 - v;
}
@@ -2844,7 +2746,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (lp = row_buf + 1; i < row_bytes; i++)
{
v = *dp++ =
- (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) & 0xff);
+ (png_byte)(((int)*rp++ - ((int)*pp++ + (int)*lp++) / 2));
sum += (v < 128) ? v : 256 - v;
@@ -2894,7 +2796,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
}
/* Paeth filter */
- if (filter_to_do == PNG_FILTER_PAETH)
+ if ((filter_to_do == PNG_FILTER_PAETH) != 0)
{
png_bytep rp, dp, pp, cp, lp;
png_size_t i;
@@ -2902,7 +2804,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
- *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+ *dp++ = (png_byte)((int)*rp++ - (int)*pp++);
}
for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++)
@@ -2928,12 +2830,12 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
- *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+ *dp++ = (png_byte)((int)*rp++ - p);
}
best_row = png_ptr->paeth_row;
}
- else if (filter_to_do & PNG_FILTER_PAETH)
+ else if ((filter_to_do & PNG_FILTER_PAETH) != 0)
{
png_bytep rp, dp, pp, cp, lp;
png_uint_32 sum = 0, lmins = mins;
@@ -2977,7 +2879,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1,
pp = prev_row + 1; i < bpp; i++)
{
- v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff);
+ v = *dp++ = (png_byte)((int)*rp++ - (int)*pp++);
sum += (v < 128) ? v : 256 - v;
}
@@ -3003,7 +2905,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
pc = (p + pc) < 0 ? -(p + pc) : p + pc;
#endif
p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c;
-#else /* PNG_SLOW_PAETH */
+#else /* SLOW_PAETH */
p = a + b - c;
pa = abs(p - a);
pb = abs(p - b);
@@ -3017,9 +2919,9 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
else
p = c;
-#endif /* PNG_SLOW_PAETH */
+#endif /* SLOW_PAETH */
- v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff);
+ v = *dp++ = (png_byte)((int)*rp++ - p);
sum += (v < 128) ? v : 256 - v;
@@ -3066,7 +2968,7 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
best_row = png_ptr->paeth_row;
}
}
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
/* Do the actual writing of the filtered row data from the chosen filter. */
png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1);
@@ -3086,73 +2988,22 @@ png_write_find_filter(png_structp png_ptr, png_row_infop row_info)
png_ptr->prev_filters[j] = best_row[0];
}
#endif
-#endif /* PNG_WRITE_FILTER_SUPPORTED */
+#endif /* WRITE_FILTER */
}
/* Do the actual writing of a previously filtered row. */
static void
-png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
- png_size_t avail/*includes filter byte*/)
+png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row,
+ png_size_t full_row_length/*includes filter byte*/)
{
png_debug(1, "in png_write_filtered_row");
png_debug1(2, "filter = %d", filtered_row[0]);
- /* Set up the zlib input buffer */
-
- png_ptr->zstream.next_in = filtered_row;
- png_ptr->zstream.avail_in = 0;
- /* Repeat until we have compressed all the data */
- do
- {
- int ret; /* Return of zlib */
-
- /* Record the number of bytes available - zlib supports at least 65535
- * bytes at one step, depending on the size of the zlib type 'uInt', the
- * maximum size zlib can write at once is ZLIB_IO_MAX (from pngpriv.h).
- * Use this because on 16 bit systems 'rowbytes' can be up to 65536 (i.e.
- * one more than 16 bits) and, in this case 'rowbytes+1' can overflow a
- * uInt. ZLIB_IO_MAX can be safely reduced to cause zlib to be called
- * with smaller chunks of data.
- */
- if (png_ptr->zstream.avail_in == 0)
- {
- if (avail > ZLIB_IO_MAX)
- {
- png_ptr->zstream.avail_in = ZLIB_IO_MAX;
- avail -= ZLIB_IO_MAX;
- }
- else
- {
- /* So this will fit in the available uInt space: */
- png_ptr->zstream.avail_in = (uInt)avail;
- avail = 0;
- }
- }
-
- /* Compress the data */
- ret = deflate(&png_ptr->zstream, Z_NO_FLUSH);
-
- /* Check for compression errors */
- if (ret != Z_OK)
- {
- if (png_ptr->zstream.msg != NULL)
- png_error(png_ptr, png_ptr->zstream.msg);
-
- else
- png_error(png_ptr, "zlib error");
- }
-
- /* See if it is time to write another IDAT */
- if (!(png_ptr->zstream.avail_out))
- {
- /* Write the IDAT and reset the zlib output buffer */
- png_write_IDAT(png_ptr, png_ptr->zbuf, png_ptr->zbuf_size);
- }
- /* Repeat until all data has been compressed */
- } while (avail > 0 || png_ptr->zstream.avail_in > 0);
+ png_compress_IDAT(png_ptr, filtered_row, full_row_length, Z_NO_FLUSH);
+#ifdef PNG_WRITE_FILTER_SUPPORTED
/* Swap the current and previous rows */
if (png_ptr->prev_row != NULL)
{
@@ -3162,6 +3013,7 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
png_ptr->prev_row = png_ptr->row_buf;
png_ptr->row_buf = tptr;
}
+#endif /* WRITE_FILTER */
/* Finish row - updates counters and flushes zlib if last row */
png_write_finish_row(png_ptr);
@@ -3174,6 +3026,6 @@ png_write_filtered_row(png_structp png_ptr, png_bytep filtered_row,
{
png_write_flush(png_ptr);
}
-#endif
+#endif /* WRITE_FLUSH */
}
-#endif /* PNG_WRITE_SUPPORTED */
+#endif /* WRITE */
diff --git a/src/3rdparty/libpng/qtpatches.diff b/src/3rdparty/libpng/qtpatches.diff
new file mode 100644
index 0000000000..1fb9b3f0c0
--- /dev/null
+++ b/src/3rdparty/libpng/qtpatches.diff
@@ -0,0 +1,77 @@
+diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h
+index b4ec3c3..f0fdcf8 100644
+--- a/src/3rdparty/libpng/pnglibconf.h
++++ b/src/3rdparty/libpng/pnglibconf.h
+@@ -27,7 +27,9 @@
+ #define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
+ #define PNG_COLORSPACE_SUPPORTED
+ #define PNG_CONSOLE_IO_SUPPORTED
++#ifndef _WIN32_WCE
+ #define PNG_CONVERT_tIME_SUPPORTED
++#endif
+ #define PNG_EASY_ACCESS_SUPPORTED
+ /*#undef PNG_ERROR_NUMBERS_SUPPORTED*/
+ #define PNG_ERROR_TEXT_SUPPORTED
+@@ -106,12 +108,14 @@
+ #define PNG_SET_OPTION_SUPPORTED
+ #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED
+ #define PNG_SET_USER_LIMITS_SUPPORTED
++#ifndef _WIN32_WCE
+ #define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED
+ #define PNG_SIMPLIFIED_READ_BGR_SUPPORTED
+ #define PNG_SIMPLIFIED_READ_SUPPORTED
+ #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED
+ #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED
+ #define PNG_SIMPLIFIED_WRITE_SUPPORTED
++#endif
+ #define PNG_STDIO_SUPPORTED
+ #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED
+ #define PNG_TEXT_SUPPORTED
+diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h
+index 5980a3f..7185444 100644
+--- a/src/3rdparty/libpng/pngpriv.h
++++ b/src/3rdparty/libpng/pngpriv.h
+@@ -23,6 +23,12 @@
+ #ifndef PNGPRIV_H
+ #define PNGPRIV_H
+
++#ifdef _MSC_VER
++# ifndef _CRT_SECURE_NO_DEPRECATE
++# define _CRT_SECURE_NO_DEPRECATE
++# endif
++#endif
++
+ /* Feature Test Macros. The following are defined here to ensure that correctly
+ * implemented libraries reveal the APIs libpng needs to build and hide those
+ * that are not needed and potentially damaging to the compilation.
+@@ -215,6 +221,11 @@
+ # endif
+ #endif /* Setting PNG_BUILD_DLL if required */
+
++/* Modfied for usage in Qt: Do not export the libpng APIs */
++#ifdef PNG_BUILD_DLL
++#undef PNG_BUILD_DLL
++#endif
++
+ /* See pngconf.h for more details: the builder of the library may set this on
+ * the command line to the right thing for the specific compilation system or it
+ * may be automagically set above (at present we know of no system where it does
+@@ -426,6 +437,9 @@
+ #if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \
+ defined(_WIN32) || defined(__WIN32__)
+ # include <windows.h> /* defines _WINDOWS_ macro */
++# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY==WINAPI_FAMILY_APP || WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP)
++# define _WINRT_ /* Define a macro for Windows Runtime builds */
++# endif
+ #endif
+ #endif /* PNG_VERSION_INFO_ONLY */
+
+@@ -436,7 +450,7 @@
+
+ /* Memory model/platform independent fns */
+ #ifndef PNG_ABORT
+-# ifdef _WINDOWS_
++# if (defined(_WINDOWS_) || defined(_WIN32_WCE)) && !defined(_WINRT_)
+ # define PNG_ABORT() ExitProcess(0)
+ # else
+ # define PNG_ABORT() abort()
diff --git a/src/3rdparty/pcre/pcre_compile.c b/src/3rdparty/pcre/pcre_compile.c
index 13f738eb88..6510835c17 100644
--- a/src/3rdparty/pcre/pcre_compile.c
+++ b/src/3rdparty/pcre/pcre_compile.c
@@ -866,6 +866,14 @@ static const pcre_uint8 opcode_possessify[] = {
};
+/* Structure for mutual recursion detection. */
+
+typedef struct recurse_check {
+ struct recurse_check *prev;
+ const pcre_uchar *group;
+} recurse_check;
+
+
/*************************************************
* Find an error text *
@@ -1704,6 +1712,7 @@ Arguments:
utf TRUE in UTF-8 / UTF-16 / UTF-32 mode
atend TRUE if called when the pattern is complete
cd the "compile data" structure
+ recurses chain of recurse_check to catch mutual recursion
Returns: the fixed length,
or -1 if there is no fixed length,
@@ -1713,10 +1722,11 @@ Returns: the fixed length,
*/
static int
-find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd)
+find_fixedlength(pcre_uchar *code, BOOL utf, BOOL atend, compile_data *cd,
+ recurse_check *recurses)
{
int length = -1;
-
+recurse_check this_recurse;
register int branchlength = 0;
register pcre_uchar *cc = code + 1 + LINK_SIZE;
@@ -1741,7 +1751,8 @@ for (;;)
case OP_ONCE:
case OP_ONCE_NC:
case OP_COND:
- d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd);
+ d = find_fixedlength(cc + ((op == OP_CBRA)? IMM2_SIZE : 0), utf, atend, cd,
+ recurses);
if (d < 0) return d;
branchlength += d;
do cc += GET(cc, 1); while (*cc == OP_ALT);
@@ -1775,7 +1786,15 @@ for (;;)
cs = ce = (pcre_uchar *)cd->start_code + GET(cc, 1); /* Start subpattern */
do ce += GET(ce, 1); while (*ce == OP_ALT); /* End subpattern */
if (cc > cs && cc < ce) return -1; /* Recursion */
- d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd);
+ else /* Check for mutual recursion */
+ {
+ recurse_check *r = recurses;
+ for (r = recurses; r != NULL; r = r->prev) if (r->group == cs) break;
+ if (r != NULL) return -1; /* Mutual recursion */
+ }
+ this_recurse.prev = recurses;
+ this_recurse.group = cs;
+ d = find_fixedlength(cs + IMM2_SIZE, utf, atend, cd, &this_recurse);
if (d < 0) return d;
branchlength += d;
cc += 1 + LINK_SIZE;
@@ -2362,11 +2381,6 @@ Arguments:
Returns: TRUE if what is matched could be empty
*/
-typedef struct recurse_check {
- struct recurse_check *prev;
- const pcre_uchar *group;
-} recurse_check;
-
static BOOL
could_be_empty_branch(const pcre_uchar *code, const pcre_uchar *endcode,
BOOL utf, compile_data *cd, recurse_check *recurses)
@@ -2497,8 +2511,8 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE);
empty_branch = FALSE;
do
{
- if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd, NULL))
- empty_branch = TRUE;
+ if (!empty_branch && could_be_empty_branch(code, endcode, utf, cd,
+ recurses)) empty_branch = TRUE;
code += GET(code, 1);
}
while (*code == OP_ALT);
@@ -3093,7 +3107,7 @@ Returns: TRUE if the auto-possessification is possible
static BOOL
compare_opcodes(const pcre_uchar *code, BOOL utf, const compile_data *cd,
- const pcre_uint32 *base_list, const pcre_uchar *base_end)
+ const pcre_uint32 *base_list, const pcre_uchar *base_end, int *rec_limit)
{
pcre_uchar c;
pcre_uint32 list[8];
@@ -3110,6 +3124,9 @@ pcre_uint32 chr;
BOOL accepted, invert_bits;
BOOL entered_a_group = FALSE;
+if (*rec_limit == 0) return FALSE;
+--(*rec_limit);
+
/* Note: the base_list[1] contains whether the current opcode has greedy
(represented by a non-zero value) quantifier. This is a different from
other character type lists, which stores here that the character iterator
@@ -3180,7 +3197,8 @@ for(;;)
while (*next_code == OP_ALT)
{
- if (!compare_opcodes(code, utf, cd, base_list, base_end)) return FALSE;
+ if (!compare_opcodes(code, utf, cd, base_list, base_end, rec_limit))
+ return FALSE;
code = next_code + 1 + LINK_SIZE;
next_code += GET(next_code, 1);
}
@@ -3200,7 +3218,7 @@ for(;;)
/* The bracket content will be checked by the
OP_BRA/OP_CBRA case above. */
next_code += 1 + LINK_SIZE;
- if (!compare_opcodes(next_code, utf, cd, base_list, base_end))
+ if (!compare_opcodes(next_code, utf, cd, base_list, base_end, rec_limit))
return FALSE;
code += PRIV(OP_lengths)[c];
@@ -3633,6 +3651,7 @@ register pcre_uchar c;
const pcre_uchar *end;
pcre_uchar *repeat_opcode;
pcre_uint32 list[8];
+int rec_limit;
for (;;)
{
@@ -3653,7 +3672,8 @@ for (;;)
get_chr_property_list(code, utf, cd->fcc, list) : NULL;
list[1] = c == OP_STAR || c == OP_PLUS || c == OP_QUERY || c == OP_UPTO;
- if (end != NULL && compare_opcodes(end, utf, cd, list, end))
+ rec_limit = 1000;
+ if (end != NULL && compare_opcodes(end, utf, cd, list, end, &rec_limit))
{
switch(c)
{
@@ -3709,7 +3729,8 @@ for (;;)
list[1] = (c & 1) == 0;
- if (compare_opcodes(end, utf, cd, list, end))
+ rec_limit = 1000;
+ if (compare_opcodes(end, utf, cd, list, end, &rec_limit))
{
switch (c)
{
@@ -4002,7 +4023,7 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL)
/* See if this recursion is on the forward reference list. If so, adjust the
reference. */
- for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
+ for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm;
hc += LINK_SIZE)
{
offset = (int)GET(hc, 0);
@@ -4208,7 +4229,11 @@ if ((options & PCRE_CASELESS) != 0)
range. Otherwise, use a recursive call to add the additional range. */
else if (oc < start && od >= start - 1) start = oc; /* Extend downwards */
- else if (od > end && oc <= end + 1) end = od; /* Extend upwards */
+ else if (od > end && oc <= end + 1)
+ {
+ end = od; /* Extend upwards */
+ if (end > classbits_end) classbits_end = (end <= 0xff ? end : 0xff);
+ }
else n8 += add_to_class(classbits, uchardptr, options, cd, oc, od);
}
}
@@ -5509,6 +5534,12 @@ for (;; ptr++)
}
#endif
+ /* Even though any XCLASS list is now discarded, we must allow for
+ its memory. */
+
+ if (lengthptr != NULL)
+ *lengthptr += (int)(class_uchardata - class_uchardata_base);
+
/* If there are no characters > 255, or they are all to be included or
excluded, set the opcode to OP_CLASS or OP_NCLASS, depending on whether the
whole class was negated and whether there were negative specials such as \S
@@ -5907,6 +5938,7 @@ for (;; ptr++)
{
register int i;
int len = (int)(code - previous);
+ size_t base_hwm_offset = save_hwm_offset;
pcre_uchar *bralink = NULL;
pcre_uchar *brazeroptr = NULL;
@@ -6052,21 +6084,21 @@ for (;; ptr++)
memcpy(code, previous, IN_UCHARS(len));
while (cd->hwm > cd->start_workspace + cd->workspace_size -
- WORK_SIZE_SAFETY_MARGIN -
- (this_hwm_offset - save_hwm_offset))
+ WORK_SIZE_SAFETY_MARGIN -
+ (this_hwm_offset - base_hwm_offset))
{
*errorcodeptr = expand_workspace(cd);
if (*errorcodeptr != 0) goto FAILED;
}
- for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset;
- hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
+ for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
+ hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
hc += LINK_SIZE)
{
PUT(cd->hwm, 0, GET(hc, 0) + len);
cd->hwm += LINK_SIZE;
}
- save_hwm_offset = this_hwm_offset;
+ base_hwm_offset = this_hwm_offset;
code += len;
}
}
@@ -6133,21 +6165,21 @@ for (;; ptr++)
copying them. */
while (cd->hwm > cd->start_workspace + cd->workspace_size -
- WORK_SIZE_SAFETY_MARGIN -
- (this_hwm_offset - save_hwm_offset))
+ WORK_SIZE_SAFETY_MARGIN -
+ (this_hwm_offset - base_hwm_offset))
{
*errorcodeptr = expand_workspace(cd);
if (*errorcodeptr != 0) goto FAILED;
}
- for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset;
- hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
+ for (hc = (pcre_uchar *)cd->start_workspace + base_hwm_offset;
+ hc < (pcre_uchar *)cd->start_workspace + this_hwm_offset;
hc += LINK_SIZE)
{
PUT(cd->hwm, 0, GET(hc, 0) + len + ((i != 0)? 2+LINK_SIZE : 1));
cd->hwm += LINK_SIZE;
}
- save_hwm_offset = this_hwm_offset;
+ base_hwm_offset = this_hwm_offset;
code += len;
}
@@ -6455,15 +6487,25 @@ for (;; ptr++)
parenthesis forms. */
case CHAR_LEFT_PARENTHESIS:
- newoptions = options;
- skipbytes = 0;
- bravalue = OP_CBRA;
- save_hwm_offset = cd->hwm - cd->start_workspace;
- reset_bracount = FALSE;
+ ptr++;
- /* First deal with various "verbs" that can be introduced by '*'. */
+ /* First deal with comments. Putting this code right at the start ensures
+ that comments have no bad side effects. */
+
+ if (ptr[0] == CHAR_QUESTION_MARK && ptr[1] == CHAR_NUMBER_SIGN)
+ {
+ ptr += 2;
+ while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
+ if (*ptr == CHAR_NULL)
+ {
+ *errorcodeptr = ERR18;
+ goto FAILED;
+ }
+ continue;
+ }
+
+ /* Now deal with various "verbs" that can be introduced by '*'. */
- ptr++;
if (ptr[0] == CHAR_ASTERISK && (ptr[1] == ':'
|| (MAX_255(ptr[1]) && ((cd->ctypes[ptr[1]] & ctype_letter) != 0))))
{
@@ -6584,10 +6626,18 @@ for (;; ptr++)
goto FAILED;
}
+ /* Initialize for "real" parentheses */
+
+ newoptions = options;
+ skipbytes = 0;
+ bravalue = OP_CBRA;
+ save_hwm_offset = cd->hwm - cd->start_workspace;
+ reset_bracount = FALSE;
+
/* Deal with the extended parentheses; all are introduced by '?', and the
appearance of any of them means that this is not a capturing group. */
- else if (*ptr == CHAR_QUESTION_MARK)
+ if (*ptr == CHAR_QUESTION_MARK)
{
int i, set, unset, namelen;
int *optset;
@@ -6596,17 +6646,6 @@ for (;; ptr++)
switch (*(++ptr))
{
- case CHAR_NUMBER_SIGN: /* Comment; skip to ket */
- ptr++;
- while (*ptr != CHAR_NULL && *ptr != CHAR_RIGHT_PARENTHESIS) ptr++;
- if (*ptr == CHAR_NULL)
- {
- *errorcodeptr = ERR18;
- goto FAILED;
- }
- continue;
-
-
/* ------------------------------------------------------------ */
case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */
reset_bracount = TRUE;
@@ -6655,7 +6694,9 @@ for (;; ptr++)
if (tempptr[1] == CHAR_QUESTION_MARK &&
(tempptr[2] == CHAR_EQUALS_SIGN ||
tempptr[2] == CHAR_EXCLAMATION_MARK ||
- tempptr[2] == CHAR_LESS_THAN_SIGN))
+ (tempptr[2] == CHAR_LESS_THAN_SIGN &&
+ (tempptr[3] == CHAR_EQUALS_SIGN ||
+ tempptr[3] == CHAR_EXCLAMATION_MARK))))
{
cd->iscondassert = TRUE;
break;
@@ -8264,7 +8305,7 @@ for (;;)
int fixed_length;
*code = OP_END;
fixed_length = find_fixedlength(last_branch, (options & PCRE_UTF8) != 0,
- FALSE, cd);
+ FALSE, cd, NULL);
DPRINTF(("fixed length = %d\n", fixed_length));
if (fixed_length == -3)
{
@@ -8549,6 +8590,7 @@ do {
case OP_RREF:
case OP_DNRREF:
case OP_DEF:
+ case OP_FAIL:
return FALSE;
default: /* Assertion */
@@ -9366,7 +9408,7 @@ if (cd->check_lookbehind)
int end_op = *be;
*be = OP_END;
fixed_length = find_fixedlength(cc, (re->options & PCRE_UTF8) != 0, TRUE,
- cd);
+ cd, NULL);
*be = end_op;
DPRINTF(("fixed length = %d\n", fixed_length));
if (fixed_length < 0)
diff --git a/src/3rdparty/pcre/pcre_dfa_exec.c b/src/3rdparty/pcre/pcre_dfa_exec.c
index 87f4aef9ab..170ce6a001 100644
--- a/src/3rdparty/pcre/pcre_dfa_exec.c
+++ b/src/3rdparty/pcre/pcre_dfa_exec.c
@@ -2736,9 +2736,10 @@ for (;;)
condcode == OP_DNRREF)
return PCRE_ERROR_DFA_UCOND;
- /* The DEFINE condition is always false */
+ /* The DEFINE condition is always false, and the assertion (?!) is
+ converted to OP_FAIL. */
- if (condcode == OP_DEF)
+ if (condcode == OP_DEF || condcode == OP_FAIL)
{ ADD_ACTIVE(state_offset + codelink + LINK_SIZE + 1, 0); }
/* The only supported version of OP_RREF is for the value RREF_ANY,
diff --git a/src/3rdparty/pcre/pcre_exec.c b/src/3rdparty/pcre/pcre_exec.c
index 788cc76849..c021fe1a4c 100644
--- a/src/3rdparty/pcre/pcre_exec.c
+++ b/src/3rdparty/pcre/pcre_exec.c
@@ -1376,6 +1376,7 @@ for (;;)
break;
case OP_DEF: /* DEFINE - always false */
+ case OP_FAIL: /* From optimized (?!) condition */
break;
/* The condition is an assertion. Call match() to evaluate it - setting
@@ -3482,7 +3483,7 @@ for (;;)
if (possessive) continue; /* No backtracking */
for(;;)
{
- if (eptr == pp) goto TAIL_RECURSE;
+ if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM23);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
#ifdef SUPPORT_UCP
@@ -3903,7 +3904,7 @@ for (;;)
if (possessive) continue; /* No backtracking */
for(;;)
{
- if (eptr == pp) goto TAIL_RECURSE;
+ if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM30);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
@@ -4038,7 +4039,7 @@ for (;;)
if (possessive) continue; /* No backtracking */
for(;;)
{
- if (eptr == pp) goto TAIL_RECURSE;
+ if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM34);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
@@ -5609,7 +5610,7 @@ for (;;)
if (possessive) continue; /* No backtracking */
for(;;)
{
- if (eptr == pp) goto TAIL_RECURSE;
+ if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM44);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
@@ -5651,12 +5652,17 @@ for (;;)
if (possessive) continue; /* No backtracking */
+ /* We use <= pp rather than == pp to detect the start of the run while
+ backtracking because the use of \C in UTF mode can cause BACKCHAR to
+ move back past pp. This is just palliative; the use of \C in UTF mode
+ is fraught with danger. */
+
for(;;)
{
int lgb, rgb;
PCRE_PUCHAR fptr;
- if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
+ if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */
RMATCH(eptr, ecode, offset_top, md, eptrb, RM45);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
@@ -5674,7 +5680,7 @@ for (;;)
for (;;)
{
- if (eptr == pp) goto TAIL_RECURSE; /* At start of char run */
+ if (eptr <= pp) goto TAIL_RECURSE; /* At start of char run */
fptr = eptr - 1;
if (!utf) c = *fptr; else
{
@@ -5924,7 +5930,7 @@ for (;;)
if (possessive) continue; /* No backtracking */
for(;;)
{
- if (eptr == pp) goto TAIL_RECURSE;
+ if (eptr <= pp) goto TAIL_RECURSE;
RMATCH(eptr, ecode, offset_top, md, eptrb, RM46);
if (rrc != MATCH_NOMATCH) RRETURN(rrc);
eptr--;
diff --git a/src/3rdparty/pcre/pcre_jit_compile.c b/src/3rdparty/pcre/pcre_jit_compile.c
index 46ce0975a9..dd378e097b 100644
--- a/src/3rdparty/pcre/pcre_jit_compile.c
+++ b/src/3rdparty/pcre/pcre_jit_compile.c
@@ -2108,7 +2108,7 @@ sljit_uw *result;
if (SLJIT_UNLIKELY(sljit_get_compiler_error(compiler)))
return NULL;
-result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), common->allocator_data);
+result = (sljit_uw *)SLJIT_MALLOC(size + sizeof(sljit_uw), compiler->allocator_data);
if (SLJIT_UNLIKELY(result == NULL))
{
sljit_set_compiler_memory_error(compiler);
@@ -6997,7 +6997,7 @@ cc += GET(cc, 1);
has_alternatives = *cc == OP_ALT;
if (SLJIT_UNLIKELY(opcode == OP_COND || opcode == OP_SCOND))
- has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF) ? FALSE : TRUE;
+ has_alternatives = (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL) ? FALSE : TRUE;
if (SLJIT_UNLIKELY(opcode == OP_COND) && (*cc == OP_KETRMAX || *cc == OP_KETRMIN))
opcode = OP_SCOND;
@@ -7255,12 +7255,14 @@ if (opcode == OP_COND || opcode == OP_SCOND)
add_jump(compiler, &(BACKTRACK_AS(bracket_backtrack)->u.condfailed), JUMP(SLJIT_ZERO));
matchingpath += 1 + 2 * IMM2_SIZE;
}
- else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF)
+ else if (*matchingpath == OP_RREF || *matchingpath == OP_DNRREF || *matchingpath == OP_FAIL)
{
/* Never has other case. */
BACKTRACK_AS(bracket_backtrack)->u.condfailed = NULL;
SLJIT_ASSERT(!has_alternatives);
+ if (*matchingpath == OP_FAIL)
+ stacksize = 0;
if (*matchingpath == OP_RREF)
{
stacksize = GET2(matchingpath, 1);
diff --git a/src/3rdparty/pcre/sljit/sljitLir.c b/src/3rdparty/pcre/sljit/sljitLir.c
index 8112e8da6e..5039a7e04e 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.c
+++ b/src/3rdparty/pcre/sljit/sljitLir.c
@@ -435,6 +435,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile
SLJIT_FREE(compiler, allocator_data);
}
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler)
+{
+ if (compiler->error == SLJIT_SUCCESS)
+ compiler->error = SLJIT_ERR_ALLOC_FAILED;
+}
+
#if (defined SLJIT_CONFIG_ARM_THUMB2 && SLJIT_CONFIG_ARM_THUMB2)
SLJIT_API_FUNC_ATTRIBUTE void sljit_free_code(void* code)
{
diff --git a/src/3rdparty/pcre/sljit/sljitLir.h b/src/3rdparty/pcre/sljit/sljitLir.h
index 79f1d102c1..24c0f60399 100644
--- a/src/3rdparty/pcre/sljit/sljitLir.h
+++ b/src/3rdparty/pcre/sljit/sljitLir.h
@@ -429,11 +429,13 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_compiler(struct sljit_compiler *compile
these checks increases the performance of the compiling process. */
static SLJIT_INLINE sljit_si sljit_get_compiler_error(struct sljit_compiler *compiler) { return compiler->error; }
-/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED. After
- the error code is set, the compiler behaves as if itself detected
- an allocation failure. This can greatly simplify error management,
- since only the compiler needs to be checked after compilation. */
-static SLJIT_INLINE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler) { compiler->error = SLJIT_ERR_ALLOC_FAILED; }
+/* Sets the compiler error code to SLJIT_ERR_ALLOC_FAILED except
+ if an error was detected before. After the error code is set
+ the compiler behaves as if the allocation failure happened
+ during an sljit function call. This can greatly simplify error
+ checking, since only the compiler status needs to be checked
+ after the compilation. */
+SLJIT_API_FUNC_ATTRIBUTE void sljit_set_compiler_memory_error(struct sljit_compiler *compiler);
/*
Allocate a small amount of memory. The size must be <= 64 bytes on 32 bit,
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index c7355c1530..73140839cc 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -983,7 +983,7 @@ public class QtActivityDelegate
if (!m_backKeyPressedSent)
return true;
}
- QtNative.keyDown(keyCode, c, event.getMetaState());
+ QtNative.keyDown(keyCode, c, event.getMetaState(), event.getRepeatCount() > 0);
return true;
}
@@ -1007,7 +1007,7 @@ public class QtActivityDelegate
}
m_metaState = MetaKeyKeyListener.handleKeyUp(m_metaState, keyCode, event);
- QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState());
+ QtNative.keyUp(keyCode, event.getUnicodeChar(), event.getMetaState(), event.getRepeatCount() > 0);
return true;
}
@@ -1018,8 +1018,8 @@ public class QtActivityDelegate
&& event.getCharacters() != null
&& event.getCharacters().length() == 1
&& event.getKeyCode() == 0) {
- QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState());
- QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState());
+ QtNative.keyDown(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0);
+ QtNative.keyUp(0, event.getCharacters().charAt(0), event.getMetaState(), event.getRepeatCount() > 0);
}
try {
@@ -1195,7 +1195,6 @@ public class QtActivityDelegate
} else {
m_activity.getWindow().setBackgroundDrawable(m_activity.getResources().getDrawable(attr.resourceId));
}
-
if (m_dummyView != null) {
m_layout.removeView(m_dummyView);
m_dummyView = null;
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
index bed9d69782..b2480618f8 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtNative.java
@@ -593,8 +593,8 @@ public class QtNative
// pointer methods
// keyboard methods
- public static native void keyDown(int key, int unicode, int modifier);
- public static native void keyUp(int key, int unicode, int modifier);
+ public static native void keyDown(int key, int unicode, int modifier, boolean autoRepeat);
+ public static native void keyUp(int key, int unicode, int modifier, boolean autoRepeat);
public static native void keyboardVisibilityChanged(boolean visibility);
// keyboard methods
diff --git a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch b/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch
deleted file mode 100644
index ad3187ec7c..0000000000
--- a/src/angle/patches/0000-General-fixes-for-ANGLE-2.1.patch
+++ /dev/null
@@ -1,477 +0,0 @@
-From bd27c33a4a7c48bd14b9b6c18c8cdce1c3aae155 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Fri, 14 Nov 2014 10:53:40 +0200
-Subject: [PATCH] General fixes for ANGLE 2.1
-
-- Fix commit.h include (use hard-coded version)
-- Fix export mismatch in libEGL.cpp and libGLESv2.cpp
-- Normalize all precompiled shader names and includes
-- Remove third-party event tracing; it was hardly used in ANGLE
- and not enabled in Qt builds anyway.
-
-Change-Id: I22254aed62e89a26756ca0784bae95909189c0f9
----
- src/3rdparty/angle/src/commit.h | 6 +-
- src/3rdparty/angle/src/common/version.h | 2 +-
- .../src/common/winrt/CoreWindowNativeWindow.cpp | 2 +-
- src/3rdparty/angle/src/libEGL/libEGL.cpp | 3 +
- src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp | 4 ++
- src/3rdparty/angle/src/libGLESv2/libGLESv2.def | 3 -
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 3 -
- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 66 +++++++++++-----------
- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 12 ++--
- .../renderer/d3d/d3d11/PixelTransfer11.cpp | 10 ++--
- .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 4 +-
- .../renderer/d3d/d3d11/shaders/Clear11.hlsl | 4 ++
- .../src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp | 20 +++----
- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 12 ----
- .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps | 6 +-
- .../libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs | 4 +-
- 16 files changed, 76 insertions(+), 85 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/commit.h b/src/3rdparty/angle/src/commit.h
-index 4c89a65..08fc893 100644
---- a/src/3rdparty/angle/src/commit.h
-+++ b/src/3rdparty/angle/src/commit.h
-@@ -7,8 +7,6 @@
- // This is a default commit hash header, when git is not available.
- //
-
--#define ANGLE_COMMIT_HASH "unknown hash"
-+#define ANGLE_COMMIT_HASH "30d6c255d238"
- #define ANGLE_COMMIT_HASH_SIZE 12
--#define ANGLE_COMMIT_DATE "unknown date"
--
--#define ANGLE_DISABLE_PROGRAM_BINARY_LOAD
-+#define ANGLE_COMMIT_DATE "2014-11-13 17:37:03 +0000"
-diff --git a/src/3rdparty/angle/src/common/version.h b/src/3rdparty/angle/src/common/version.h
-index d9148d1..f01e024 100644
---- a/src/3rdparty/angle/src/common/version.h
-+++ b/src/3rdparty/angle/src/common/version.h
-@@ -1,4 +1,4 @@
--#include "id/commit.h"
-+#include "../commit.h"
-
- #define ANGLE_MAJOR_VERSION 2
- #define ANGLE_MINOR_VERSION 1
-diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-index 0de16f4..0e63fa5 100644
---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-@@ -184,4 +184,4 @@ long ConvertDipsToPixels(float dips)
- static const float dipsPerInch = 96.0f;
- return lround((dips * GetLogicalDpi() / dipsPerInch));
- }
--}
-\ No newline at end of file
-+}
-diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index 851b723..6110698 100644
---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
-+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-@@ -6,6 +6,9 @@
-
- // libEGL.cpp: Implements the exported EGL functions.
-
-+#undef EGLAPI
-+#define EGLAPI
-+
- #include <exception>
-
- #include "common/debug.h"
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
-index 2306168..587950a 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.cpp
-@@ -6,6 +6,10 @@
-
- // libGLESv2.cpp: Implements the exported OpenGL ES 2.0 functions.
-
-+#undef GL_APICALL
-+#define GL_APICALL
-+#define GL_GLEXT_PROTOTYPES
-+
- #include "common/version.h"
- #include "common/utilities.h"
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
-index 88dceb3..33557eb 100644
---- a/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
-+++ b/src/3rdparty/angle/src/libGLESv2/libGLESv2.def
-@@ -294,6 +294,3 @@ EXPORTS
- glBindTexImage @158 NONAME
- glCreateRenderer @177 NONAME
- glDestroyRenderer @178 NONAME
--
-- ; Setting up TRACE macro callbacks
-- SetTraceFunctionPointers @284
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index 5c44fe0..bfeaf51 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -11,8 +11,6 @@
- #include "common/features.h"
- #include "common/utilities.h"
-
--#include "third_party/trace_event/trace_event.h"
--
- // Definitions local to the translation unit
- namespace
- {
-@@ -120,7 +118,6 @@ HLSLCompiler::~HLSLCompiler()
-
- bool HLSLCompiler::initialize()
- {
-- TRACE_EVENT0("gpu", "initializeCompiler");
- #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- #if defined(ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES)
- // Find a D3DCompiler module that had already been loaded based on a predefined list of versions.
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-index 8ed1650..91e7552 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-@@ -13,39 +13,39 @@
- #include "libGLESv2/main.h"
- #include "libGLESv2/formatutils.h"
-
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2d11ps.h"
--
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3d11gs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dui11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3di11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3d11ps.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3d11ps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughdepth2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb2dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg2dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr2dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum2dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha2dps.h"
-+
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough3dgs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba3dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgb3dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrg3dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3duips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughr3dips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlum3dps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughlumalpha3dps.h"
-
- #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlef2dps.h"
- #include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/swizzlei2dps.h"
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-index 12905d0..4630762 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-@@ -15,14 +15,14 @@
- #include "libGLESv2/FramebufferAttachment.h"
-
- // Precompiled shaders
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloat11ps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearfloatps.h"
-
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuint11ps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearuintps.h"
-
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsint11ps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/clearsintps.h"
-
- namespace rx
- {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-index 1bc2bd8..a4072d8 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-@@ -22,11 +22,11 @@
- #include "libGLESv2/Context.h"
-
- // Precompiled shaders
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_gs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4f.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4i.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture11_ps_4ui.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturevs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexturegs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4fps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4ips.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/buffertotexture_4uips.h"
-
- namespace rx
- {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-index 3fcacf6..834b7bd 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -12,8 +12,8 @@
- #include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-
- // Precompiled shaders
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2d11vs.h"
--#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2d11ps.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthrough2dvs.h"
-+#include "libGLESv2/renderer/d3d/d3d11/shaders/compiled/passthroughrgba2dps.h"
-
- #include "common/features.h"
- #include "common/NativeWindow.h"
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
-index 6deef2b..b4cf380 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/shaders/Clear11.hlsl
-@@ -13,10 +13,12 @@ struct PS_OutputFloat
- float4 color1 : SV_TARGET1;
- float4 color2 : SV_TARGET2;
- float4 color3 : SV_TARGET3;
-+#if SM4
- float4 color4 : SV_TARGET4;
- float4 color5 : SV_TARGET5;
- float4 color6 : SV_TARGET6;
- float4 color7 : SV_TARGET7;
-+#endif
- };
-
- PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inColor : COLOR)
-@@ -26,10 +28,12 @@ PS_OutputFloat PS_ClearFloat(in float4 inPosition : SV_POSITION, in float4 inCol
- outColor.color1 = inColor;
- outColor.color2 = inColor;
- outColor.color3 = inColor;
-+#if SM4
- outColor.color4 = inColor;
- outColor.color5 = inColor;
- outColor.color6 = inColor;
- outColor.color7 = inColor;
-+#endif
- return outColor;
- }
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
-index d4fcd17..2ca7a9c 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp
-@@ -27,20 +27,20 @@ namespace
-
- const BYTE* const g_shaderCode[] =
- {
-- g_vs20_standardvs,
-- g_vs20_flipyvs,
-- g_ps20_passthroughps,
-- g_ps20_luminanceps,
-- g_ps20_componentmaskps
-+ g_vs20_VS_standard,
-+ g_vs20_VS_flipy,
-+ g_ps20_PS_passthrough,
-+ g_ps20_PS_luminance,
-+ g_ps20_PS_componentmask
- };
-
- const size_t g_shaderSize[] =
- {
-- sizeof(g_vs20_standardvs),
-- sizeof(g_vs20_flipyvs),
-- sizeof(g_ps20_passthroughps),
-- sizeof(g_ps20_luminanceps),
-- sizeof(g_ps20_componentmaskps)
-+ sizeof(g_vs20_VS_standard),
-+ sizeof(g_vs20_VS_flipy),
-+ sizeof(g_ps20_PS_passthrough),
-+ sizeof(g_ps20_PS_luminance),
-+ sizeof(g_ps20_PS_componentmask)
- };
- }
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 3bac4ba..82963ec 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -42,8 +42,6 @@
- #include "common/features.h"
- #include "common/utilities.h"
-
--#include "third_party/trace_event/trace_event.h"
--
- #include <sstream>
-
- // Can also be enabled by defining FORCE_REF_RAST in the project's predefined macros
-@@ -185,7 +183,6 @@ EGLint Renderer9::initialize()
- return EGL_NOT_INITIALIZED;
- }
-
-- TRACE_EVENT0("gpu", "GetModuleHandle_d3d9");
- mD3d9Module = GetModuleHandle(TEXT("d3d9.dll"));
-
- if (mD3d9Module == NULL)
-@@ -202,14 +199,12 @@ EGLint Renderer9::initialize()
- // desktop. Direct3D9Ex is available in Windows Vista and later if suitable drivers are available.
- if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
- {
-- TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
- ASSERT(mD3d9Ex);
- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
- ASSERT(mD3d9);
- }
- else
- {
-- TRACE_EVENT0("gpu", "Direct3DCreate9");
- mD3d9 = Direct3DCreate9(D3D_SDK_VERSION);
- }
-
-@@ -228,7 +223,6 @@ EGLint Renderer9::initialize()
-
- // Give up on getting device caps after about one second.
- {
-- TRACE_EVENT0("gpu", "GetDeviceCaps");
- for (int i = 0; i < 10; ++i)
- {
- result = mD3d9->GetDeviceCaps(mAdapter, mDeviceType, &mDeviceCaps);
-@@ -263,7 +257,6 @@ EGLint Renderer9::initialize()
- }
-
- {
-- TRACE_EVENT0("gpu", "GetAdapterIdentifier");
- mD3d9->GetAdapterIdentifier(mAdapter, 0, &mAdapterIdentifier);
- }
-
-@@ -300,7 +293,6 @@ EGLint Renderer9::initialize()
- static const TCHAR className[] = TEXT("STATIC");
-
- {
-- TRACE_EVENT0("gpu", "CreateWindowEx");
- mDeviceWindow = CreateWindowEx(WS_EX_NOACTIVATE, className, windowName, WS_DISABLED | WS_POPUP, 0, 0, 1, 1, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
- }
-
-@@ -308,7 +300,6 @@ EGLint Renderer9::initialize()
- DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
-
- {
-- TRACE_EVENT0("gpu", "D3d9_CreateDevice");
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
- }
- if (result == D3DERR_OUTOFVIDEOMEMORY || result == E_OUTOFMEMORY || result == D3DERR_DEVICELOST)
-@@ -318,7 +309,6 @@ EGLint Renderer9::initialize()
-
- if (FAILED(result))
- {
-- TRACE_EVENT0("gpu", "D3d9_CreateDevice2");
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_SOFTWARE_VERTEXPROCESSING, &presentParameters, &mDevice);
-
- if (FAILED(result))
-@@ -330,13 +320,11 @@ EGLint Renderer9::initialize()
-
- if (mD3d9Ex)
- {
-- TRACE_EVENT0("gpu", "mDevice_QueryInterface");
- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx);
- ASSERT(SUCCEEDED(result));
- }
-
- {
-- TRACE_EVENT0("gpu", "ShaderCache initialize");
- mVertexShaderCache.initialize(mDevice);
- mPixelShaderCache.initialize(mDevice);
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps
-index dc357d0..eb43eb3 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.ps
-@@ -11,7 +11,7 @@ uniform float4 add : c1;
-
- // Passthrough Pixel Shader
- // Outputs texture 0 sampled at texcoord 0.
--float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
-+float4 PS_passthrough(float4 texcoord : TEXCOORD0) : COLOR
- {
- return tex2D(tex, texcoord.xy);
- };
-@@ -19,7 +19,7 @@ float4 passthroughps(float4 texcoord : TEXCOORD0) : COLOR
- // Luminance Conversion Pixel Shader
- // Performs a mad operation using the LA data from the texture with mult.xw and add.xw.
- // Returns data in the form of llla
--float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
-+float4 PS_luminance(float4 texcoord : TEXCOORD0) : COLOR
- {
- return (tex2D(tex, texcoord.xy).xw * mult.xw + add.xw).xxxy;
- };
-@@ -27,7 +27,7 @@ float4 luminanceps(float4 texcoord : TEXCOORD0) : COLOR
- // RGB/A Component Mask Pixel Shader
- // Performs a mad operation using the texture's RGBA data with mult.xyzw and add.xyzw.
- // Returns data in the form of rgba
--float4 componentmaskps(float4 texcoord : TEXCOORD0) : COLOR
-+float4 PS_componentmask(float4 texcoord : TEXCOORD0) : COLOR
- {
- return tex2D(tex, texcoord.xy) * mult + add;
- };
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
-index 3a36980..3bd611b 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/shaders/Blit.vs
-@@ -17,7 +17,7 @@ uniform float4 halfPixelSize : c0;
- // Outputs the homogenous position as-is.
- // Outputs a tex coord with (0,0) in the upper-left corner of the screen and (1,1) in the bottom right.
- // C0.X must be negative half-pixel width, C0.Y must be half-pixel height. C0.ZW must be 0.
--VS_OUTPUT standardvs(in float4 position : POSITION)
-+VS_OUTPUT VS_standard(in float4 position : POSITION)
- {
- VS_OUTPUT Out;
-
-@@ -32,7 +32,7 @@ VS_OUTPUT standardvs(in float4 position : POSITION)
- // Outputs the homogenous position as-is.
- // Outputs a tex coord with (0,1) in the upper-left corner of the screen and (1,0) in the bottom right.
- // C0.XY must be the half-pixel width and height. C0.ZW must be 0.
--VS_OUTPUT flipyvs(in float4 position : POSITION)
-+VS_OUTPUT VS_flipy(in float4 position : POSITION)
- {
- VS_OUTPUT Out;
-
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch b/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch
new file mode 100644
index 0000000000..1361b8b656
--- /dev/null
+++ b/src/angle/patches/0001-ANGLE-Improve-Windows-Phone-Support.patch
@@ -0,0 +1,439 @@
+From ed09eff731b5d286e0bf6a5958b937a50ecc2362 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Tue, 7 Apr 2015 13:24:59 +0300
+Subject: [PATCH 1/5] ANGLE: Improve Windows Phone Support
+
+This contains compile fixes for Windows Phone as well as improved
+orientation handling.
+
+Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc
+---
+ src/3rdparty/angle/src/common/platform.h | 2 ++
+ .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 2 +-
+ .../src/libANGLE/renderer/d3d/d3d11/NativeWindow.h | 4 +++
+ .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 8 +++--
+ .../libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 40 ++++++++++++++++++++++
+ .../d3d/d3d11/winrt/CoreWindowNativeWindow.cpp | 31 +++++++++++++++--
+ .../d3d/d3d11/winrt/CoreWindowNativeWindow.h | 34 +++++++++++++++++-
+ .../d3d/d3d11/winrt/InspectableNativeWindow.cpp | 12 +++++++
+ .../d3d/d3d11/winrt/InspectableNativeWindow.h | 14 +++++++-
+ src/3rdparty/angle/src/libANGLE/validationEGL.cpp | 4 ++-
+ 10 files changed, 142 insertions(+), 9 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
+index 56db297..4e3851c 100644
+--- a/src/3rdparty/angle/src/common/platform.h
++++ b/src/3rdparty/angle/src/common/platform.h
+@@ -68,7 +68,9 @@
+ # if defined(ANGLE_ENABLE_WINDOWS_STORE)
+ # include <dxgi1_3.h>
+ # if defined(_DEBUG)
++# if WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP
+ # include <DXProgrammableCapture.h>
++# endif
+ # include <dxgidebug.h>
+ # endif
+ # endif
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+index bc7cdcc..fcca904 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+@@ -60,7 +60,7 @@ bool DebugAnnotator11::getStatus()
+ {
+ // ID3DUserDefinedAnnotation::GetStatus doesn't work with the Graphics Diagnostics tools in Visual Studio 2013.
+
+-#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE)
++#if defined(_DEBUG) && defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+ // In the Windows Store, we can use IDXGraphicsAnalysis. The call to GetDebugInterface1 only succeeds if the app is under capture.
+ // This should only be called in DEBUG mode.
+ // If an app links against DXGIGetDebugInterface1 in release mode then it will fail Windows Store ingestion checks.
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+index ce50c32..81b9ea7 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/NativeWindow.h
+@@ -49,11 +49,15 @@ namespace rx
+ class NativeWindow
+ {
+ public:
++ enum RotationFlags { RotateNone = 0, RotateLeft = 1, RotateRight = 2 };
+ explicit NativeWindow(EGLNativeWindowType window);
+
+ bool initialize();
+ bool getClientRect(LPRECT rect);
+ bool isIconic();
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ RotationFlags rotationFlags() const;
++#endif
+ static bool isValidNativeWindow(EGLNativeWindowType window);
+
+ HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+index eba40a4..dbed23f 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+@@ -230,7 +230,11 @@ Renderer11::Renderer11(egl::Display *display)
+ }
+ }
+
++#if defined(ANGLE_ENABLE_WINDOWS_STORE)
++ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
++#else
+ if (requestedMajorVersion == 9 && requestedMinorVersion == 3)
++#endif
+ {
+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
+ }
+@@ -587,10 +591,10 @@ egl::ConfigSet Renderer11::generateConfigs() const
+ config.bindToTextureRGB = (colorBufferFormatInfo.format == GL_RGB);
+ config.bindToTextureRGBA = (colorBufferFormatInfo.format == GL_RGBA || colorBufferFormatInfo.format == GL_BGRA_EXT);
+ config.colorBufferType = EGL_RGB_BUFFER;
+- config.configCaveat = EGL_NONE;
+ config.configID = static_cast<EGLint>(configs.size() + 1);
+ // Can only support a conformant ES2 with feature level greater than 10.0.
+ config.conformant = (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0) ? (EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT_KHR) : EGL_NONE;
++ config.configCaveat = config.conformant == EGL_NONE ? EGL_NON_CONFORMANT_CONFIG : EGL_NONE;
+ config.depthSize = depthStencilBufferFormatInfo.depthBits;
+ config.level = 0;
+ config.matchNativePixmap = EGL_NONE;
+@@ -2290,7 +2294,7 @@ bool Renderer11::getShareHandleSupport() const
+ // chrome needs BGRA. Once chrome fixes this, we should always support them.
+ // PIX doesn't seem to support using share handles, so disable them.
+ // Also disable share handles on Feature Level 9_3, since it doesn't support share handles on RGBA8 textures/swapchains.
+- return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive() && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3);
++ return getRendererExtensions().textureFormatBGRA8888 && !gl::DebugAnnotationsActive();// && !(mFeatureLevel <= D3D_FEATURE_LEVEL_9_3); Qt: we don't care about the 9_3 limitation
+ }
+
+ bool Renderer11::getPostSubBufferSupport() const
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+index 2558528..bcb2505 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+@@ -154,8 +154,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+ const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
+
+ D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ const int textureLength = std::max(backbufferWidth, backbufferHeight);
++ offscreenTextureDesc.Width = textureLength;
++ offscreenTextureDesc.Height = textureLength;
++#else
+ offscreenTextureDesc.Width = backbufferWidth;
+ offscreenTextureDesc.Height = backbufferHeight;
++#endif
+ offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
+ offscreenTextureDesc.MipLevels = 1;
+ offscreenTextureDesc.ArraySize = 1;
+@@ -235,8 +241,14 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
+ if (mDepthBufferFormat != GL_NONE)
+ {
+ D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ const int textureLength = std::max(backbufferWidth, backbufferHeight);
++ depthStencilTextureDesc.Width = textureLength;
++ depthStencilTextureDesc.Height = textureLength;
++#else
+ depthStencilTextureDesc.Width = backbufferWidth;
+ depthStencilTextureDesc.Height = backbufferHeight;
++#endif
+ depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
+ depthStencilTextureDesc.MipLevels = 1;
+ depthStencilTextureDesc.ArraySize = 1;
+@@ -337,6 +349,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+ return EGL_SUCCESS;
+ }
+
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
+ // Can only call resize if we have already created our swap buffer and resources
+ ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
+
+@@ -379,6 +392,12 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
+ }
+
+ return resetOffscreenTexture(backbufferWidth, backbufferHeight);
++#else
++ // Do nothing on Windows Phone apart from updating the internal buffer/width height
++ mWidth = backbufferWidth;
++ mHeight = backbufferHeight;
++ return EGL_SUCCESS;
++#endif
+ }
+
+ EGLint SwapChain11::reset(int backbufferWidth, int backbufferHeight, EGLint swapInterval)
+@@ -539,6 +558,21 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+ float x2 = ((x + width) / float(mWidth)) * 2.0f - 1.0f;
+ float y2 = ((y + height) / float(mHeight)) * 2.0f - 1.0f;
+
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ const float dim = std::max(mWidth, mHeight);
++ float u1 = x / dim;
++ float v1 = y / dim;
++ float u2 = (x + width) / dim;
++ float v2 = (y + height) / dim;
++
++ const NativeWindow::RotationFlags flags = mNativeWindow.rotationFlags();
++ const bool rotateL = flags == NativeWindow::RotateLeft;
++ const bool rotateR = flags == NativeWindow::RotateRight;
++ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
++ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
++ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
++ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
++#else
+ float u1 = x / float(mWidth);
+ float v1 = y / float(mHeight);
+ float u2 = (x + width) / float(mWidth);
+@@ -548,6 +582,7 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
++#endif
+
+ deviceContext->Unmap(mQuadVB, 0);
+
+@@ -577,8 +612,13 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
+ D3D11_VIEWPORT viewport;
+ viewport.TopLeftX = 0;
+ viewport.TopLeftY = 0;
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ viewport.Width = (rotateL || rotateR) ? mHeight : mWidth;
++ viewport.Height = (rotateL || rotateR) ? mWidth : mHeight;
++#else
+ viewport.Width = mWidth;
+ viewport.Height = mHeight;
++#endif
+ viewport.MinDepth = 0.0f;
+ viewport.MaxDepth = 1.0f;
+ deviceContext->RSSetViewports(1, &viewport);
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+index 8cfaa84..350526c 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp
+@@ -8,8 +8,6 @@
+
+ #include "libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h"
+
+-#include <windows.graphics.display.h>
+-
+ using namespace ABI::Windows::Foundation::Collections;
+
+ namespace rx
+@@ -21,6 +19,7 @@ CoreWindowNativeWindow::~CoreWindowNativeWindow()
+
+ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
+ {
++ mOrientationChangedEventToken.value = 0;
+ ComPtr<IPropertySet> props = propertySet;
+ ComPtr<IInspectable> win = window;
+ SIZE swapChainSize = {};
+@@ -68,6 +67,16 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
+
+ if (SUCCEEDED(result))
+ {
++ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformationStatics> displayInformation;
++ result = GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayInformation).Get(), &displayInformation);
++ if (SUCCEEDED(result))
++ {
++ result = displayInformation->GetForCurrentView(&mDisplayInformation);
++ }
++ }
++
++ if (SUCCEEDED(result))
++ {
+ mNewClientRect = mClientRect;
+ mClientRectChanged = false;
+ return registerForSizeChangeEvents();
+@@ -85,6 +94,15 @@ bool CoreWindowNativeWindow::registerForSizeChangeEvents()
+ result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
+ }
+
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ ComPtr<IDisplayOrientationEventHandler> orientationChangedHandler;
++ result = sizeChangedHandler.As(&orientationChangedHandler);
++ if (SUCCEEDED(result))
++ {
++ result = mDisplayInformation->add_OrientationChanged(orientationChangedHandler.Get(), &mOrientationChangedEventToken);
++ }
++#endif
++
+ if (SUCCEEDED(result))
+ {
+ return true;
+@@ -99,7 +117,14 @@ void CoreWindowNativeWindow::unregisterForSizeChangeEvents()
+ {
+ (void)mCoreWindow->remove_SizeChanged(mSizeChangedEventToken);
+ }
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ if (mDisplayInformation)
++ {
++ (void)mDisplayInformation->remove_OrientationChanged(mOrientationChangedEventToken);
++ }
++#endif
+ mSizeChangedEventToken.value = 0;
++ mOrientationChangedEventToken.value = 0;
+ }
+
+ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain)
+@@ -128,7 +153,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
+ if (SUCCEEDED(result))
+ {
+
+-#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++#if 0 //(WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // Qt: allow Windows Phone to resize, but don't modify the backing texture in the swap chain.
+ // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
+ // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
+ // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+index c230c84..59df9d5 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h
+@@ -12,8 +12,10 @@
+ #include "libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h"
+
+ #include <memory>
++#include <windows.graphics.display.h>
+
+ typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
++typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CGraphics__CDisplay__CDisplayInformation_IInspectable_t IDisplayOrientationEventHandler;
+
+ namespace rx
+ {
+@@ -32,11 +34,13 @@ class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enabl
+ private:
+ ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
+ ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
++ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
++ EventRegistrationToken mOrientationChangedEventToken;
+ };
+
+ [uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
+ class CoreWindowSizeChangedHandler :
+- public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
++ public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler, IDisplayOrientationEventHandler>
+ {
+ public:
+ CoreWindowSizeChangedHandler() { }
+@@ -68,6 +72,34 @@ class CoreWindowSizeChangedHandler :
+ return S_OK;
+ }
+
++ IFACEMETHOD(Invoke)(ABI::Windows::Graphics::Display::IDisplayInformation *displayInformation, IInspectable *)
++ {
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++ NativeWindow::RotationFlags flags = NativeWindow::RotateNone;
++ ABI::Windows::Graphics::Display::DisplayOrientations orientation;
++ if (SUCCEEDED(displayInformation->get_CurrentOrientation(&orientation)))
++ {
++ switch (orientation)
++ {
++ case ABI::Windows::Graphics::Display::DisplayOrientations_Landscape:
++ flags = NativeWindow::RotateLeft;
++ break;
++ case ABI::Windows::Graphics::Display::DisplayOrientations_LandscapeFlipped:
++ flags = NativeWindow::RotateRight;
++ break;
++ default:
++ break;
++ }
++ }
++ std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
++ if (host)
++ {
++ host->setRotationFlags(flags);
++ }
++#endif
++ return S_OK;
++ }
++
+ private:
+ std::weak_ptr<InspectableNativeWindow> mHost;
+ };
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+index 7ac53c7..2bf48c5 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp
+@@ -69,6 +69,18 @@ bool NativeWindow::getClientRect(RECT *rect)
+ return false;
+ }
+
++#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
++NativeWindow::RotationFlags NativeWindow::rotationFlags() const
++{
++ if (mImpl)
++ {
++ return mImpl->rotationFlags();
++ }
++
++ return NativeWindow::RotateNone;
++}
++#endif
++
+ bool NativeWindow::isIconic()
+ {
+ return false;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+index e89c900..575bdf8 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h
+@@ -34,7 +34,8 @@ class InspectableNativeWindow
+ mRequiresSwapChainScaling(false),
+ mClientRectChanged(false),
+ mClientRect({0,0,0,0}),
+- mNewClientRect({0,0,0,0})
++ mNewClientRect({0,0,0,0}),
++ mRotationFlags(NativeWindow::RotateNone)
+ {
+ mSizeChangedEventToken.value = 0;
+ }
+@@ -72,12 +73,23 @@ class InspectableNativeWindow
+ }
+ }
+
++ NativeWindow::RotationFlags rotationFlags() const
++ {
++ return mRotationFlags;
++ }
++
++ void setRotationFlags(NativeWindow::RotationFlags flags)
++ {
++ mRotationFlags = flags;
++ }
++
+ protected:
+ bool mSupportsSwapChainResize;
+ bool mRequiresSwapChainScaling;
+ RECT mClientRect;
+ RECT mNewClientRect;
+ bool mClientRectChanged;
++ NativeWindow::RotationFlags mRotationFlags;
+
+ EventRegistrationToken mSizeChangedEventToken;
+ };
+diff --git a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
+index 4e3b44b..12ee6a2 100644
+--- a/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
++++ b/src/3rdparty/angle/src/libANGLE/validationEGL.cpp
+@@ -160,7 +160,7 @@ Error ValidateCreateContext(Display *display, Config *configuration, gl::Context
+ return Error(EGL_BAD_CONFIG);
+ }
+
+- if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR))
++ if (clientMajorVersion == 3 && !(configuration->conformant & EGL_OPENGL_ES3_BIT_KHR) && !(configuration->configCaveat & EGL_NON_CONFORMANT_CONFIG))
+ {
+ return Error(EGL_BAD_CONFIG);
+ }
+@@ -488,11 +488,13 @@ Error ValidateCreatePbufferFromClientBuffer(Display *display, EGLenum buftype, E
+ return Error(EGL_BAD_ATTRIBUTE);
+ }
+
++#if !defined(ANGLE_ENABLE_WINDOWS_STORE) // On Windows Store, we know the originating texture came from D3D11, so bypass this check
+ const Caps &caps = display->getCaps();
+ if (textureFormat != EGL_NO_TEXTURE && !caps.textureNPOT && (!gl::isPow2(width) || !gl::isPow2(height)))
+ {
+ return Error(EGL_BAD_MATCH);
+ }
++#endif
+ }
+
+ return Error(EGL_SUCCESS);
+--
+2.1.4
+
diff --git a/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch b/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch
new file mode 100644
index 0000000000..e28bc797e3
--- /dev/null
+++ b/src/angle/patches/0002-ANGLE-Fix-compilation-with-MinGW.patch
@@ -0,0 +1,927 @@
+From 6f98a957829fd37106fb1f1c9f43a5bad626cdfc Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Wed, 25 Mar 2015 20:21:33 +0200
+Subject: [PATCH 2/5] ANGLE: Fix compilation with MinGW
+
+This adds definition guards for Direct3D 11 and DirectX SDK layers, which
+are only available in very recent versions (4.9.2 rev 4) of MinGW builds.
+It additionally adds a few missing includes needed for compilation.
+
+Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6
+---
+ src/3rdparty/angle/src/common/mathutil.h | 4 +
+ src/3rdparty/angle/src/common/platform.h | 10 +-
+ src/3rdparty/angle/src/libANGLE/angletypes.h | 1 +
+ .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 9 ++
+ .../src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp | 6 +
+ .../src/libANGLE/renderer/d3d/d3d11/Clear11.cpp | 4 +
+ .../renderer/d3d/d3d11/DebugAnnotator11.cpp | 10 ++
+ .../libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h | 2 +
+ .../src/libANGLE/renderer/d3d/d3d11/Query11.cpp | 7 +
+ .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 83 +++++++++--
+ .../src/libANGLE/renderer/d3d/d3d11/Renderer11.h | 3 +-
+ .../renderer/d3d/d3d11/renderer11_utils.cpp | 152 +++++++++++++++++++++
+ .../src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 4 +-
+ 13 files changed, 283 insertions(+), 12 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/common/mathutil.h b/src/3rdparty/angle/src/common/mathutil.h
+index e096b1a..1015bd2 100644
+--- a/src/3rdparty/angle/src/common/mathutil.h
++++ b/src/3rdparty/angle/src/common/mathutil.h
+@@ -119,6 +119,9 @@ inline bool supportsSSE2()
+ return supports;
+ }
+
++#if defined(__GNUC__)
++ supports = __builtin_cpu_supports("sse2");
++#else
+ int info[4];
+ __cpuid(info, 0);
+
+@@ -128,6 +131,7 @@ inline bool supportsSSE2()
+
+ supports = (info[3] >> 26) & 1;
+ }
++#endif
+
+ checked = true;
+
+diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
+index 4e3851c..be4cb94 100644
+--- a/src/3rdparty/angle/src/common/platform.h
++++ b/src/3rdparty/angle/src/common/platform.h
+@@ -59,9 +59,17 @@
+ # if defined(ANGLE_ENABLE_D3D11)
+ # include <d3d10_1.h>
+ # include <d3d11.h>
+-# include <d3d11_1.h>
+ # include <dxgi.h>
++# if defined(__MINGW32__) && !defined(__d3d11sdklayers_h__)
++# define ANGLE_MINGW32_COMPAT
++# endif
++# if defined(_MSC_VER) && _MSC_VER >= 1800
++# define ANGLE_ENABLE_D3D11_1
++# endif
++# if defined(ANGLE_ENABLE_D3D11_1)
++# include <d3d11_1.h>
+ # include <dxgi1_2.h>
++# endif
+ # include <d3dcompiler.h>
+ # endif
+
+diff --git a/src/3rdparty/angle/src/libANGLE/angletypes.h b/src/3rdparty/angle/src/libANGLE/angletypes.h
+index a5f471d..e4e08b5 100644
+--- a/src/3rdparty/angle/src/libANGLE/angletypes.h
++++ b/src/3rdparty/angle/src/libANGLE/angletypes.h
+@@ -13,6 +13,7 @@
+ #include "libANGLE/RefCountObject.h"
+
+ #include <stdint.h>
++#include <float.h>
+
+ namespace gl
+ {
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+index d709dca..9c72d6f 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+@@ -22,6 +22,15 @@ namespace
+
+ #define CREATE_COMPILER_FLAG_INFO(flag) { flag, #flag }
+
++#if defined(ANGLE_MINGW32_COMPAT)
++#ifndef D3DCOMPILE_RESERVED16
++#define D3DCOMPILE_RESERVED16 0x10000
++#endif
++#ifndef D3DCOMPILE_RESERVED17
++#define D3DCOMPILE_RESERVED17 0x20000
++#endif
++#endif
++
+ struct CompilerFlagInfo
+ {
+ UINT mFlag;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+index 3b36c64..d56b0ea 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp
+@@ -12,6 +12,12 @@
+ #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
+ #include "libANGLE/renderer/d3d/d3d11/formatutils11.h"
+
++#if defined(ANGLE_MINGW32_COMPAT)
++typedef enum D3D11_MAP_FLAG {
++ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000
++} D3D11_MAP_FLAG;
++#endif
++
+ namespace rx
+ {
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+index ae373f5..057c3be 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp
+@@ -133,12 +133,14 @@ Clear11::Clear11(Renderer11 *renderer)
+ mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint );
+ }
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ if (renderer->getDeviceContext1IfSupported())
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ mSupportsClearView = (d3d11Options.ClearView != FALSE);
+ }
++#endif
+ }
+
+ Clear11::~Clear11()
+@@ -321,6 +323,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
+
+ if (needScissoredClear)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ // We shouldn't reach here if deviceContext1 is unavailable.
+ ASSERT(deviceContext1);
+
+@@ -331,6 +334,7 @@ gl::Error Clear11::clearFramebuffer(const ClearParameters &clearParams, const gl
+ rect.bottom = clearParams.scissor.y + clearParams.scissor.height;
+
+ deviceContext1->ClearView(framebufferRTV, clearValues, &rect, 1);
++#endif
+ }
+ else
+ {
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+index fcca904..f1fe2bb 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp
+@@ -27,7 +27,9 @@ DebugAnnotator11::~DebugAnnotator11()
+ {
+ if (mInitialized)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ SafeRelease(mUserDefinedAnnotation);
++#endif
+
+ #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
+ FreeLibrary(mD3d11Module);
+@@ -39,21 +41,27 @@ void DebugAnnotator11::beginEvent(const std::wstring &eventName)
+ {
+ initializeDevice();
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->BeginEvent(eventName.c_str());
++#endif
+ }
+
+ void DebugAnnotator11::endEvent()
+ {
+ initializeDevice();
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->EndEvent();
++#endif
+ }
+
+ void DebugAnnotator11::setMarker(const std::wstring &markerName)
+ {
+ initializeDevice();
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation->SetMarker(markerName.c_str());
++#endif
+ }
+
+ bool DebugAnnotator11::getStatus()
+@@ -96,8 +104,10 @@ void DebugAnnotator11::initializeDevice()
+ hr = D3D11CreateDevice(NULL, D3D_DRIVER_TYPE_NULL, nullptr, 0, nullptr, 0, D3D11_SDK_VERSION, &device, nullptr, &context);
+ ASSERT(SUCCEEDED(hr));
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ mUserDefinedAnnotation = d3d11::DynamicCastComObject<ID3DUserDefinedAnnotation>(context);
+ ASSERT(mUserDefinedAnnotation != nullptr);
++#endif
+
+ SafeRelease(device);
+ SafeRelease(context);
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
+index 0638364..3df62b0 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h
+@@ -11,6 +11,8 @@
+
+ #include "common/debug.h"
+
++struct ID3DUserDefinedAnnotation;
++
+ namespace rx
+ {
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
+index e010190..4979ff5 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Query11.cpp
+@@ -13,6 +13,13 @@
+
+ #include <GLES2/gl2ext.h>
+
++#if defined(ANGLE_MINGW32_COMPAT)
++typedef struct D3D11_QUERY_DATA_SO_STATISTICS {
++ UINT64 NumPrimitivesWritten;
++ UINT64 PrimitivesStorageNeeded;
++} D3D11_QUERY_DATA_SO_STATISTICS;
++#endif
++
+ namespace rx
+ {
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+index dbed23f..5291a3a 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
+@@ -62,6 +62,67 @@
+ #define ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS 1
+ #endif
+
++#ifndef __d3d11sdklayers_h__
++#define D3D11_MESSAGE_CATEGORY UINT
++#define D3D11_MESSAGE_SEVERITY UINT
++#define D3D11_MESSAGE_ID UINT
++struct D3D11_MESSAGE;
++typedef struct D3D11_INFO_QUEUE_FILTER_DESC
++{
++ UINT NumCategories;
++ D3D11_MESSAGE_CATEGORY *pCategoryList;
++ UINT NumSeverities;
++ D3D11_MESSAGE_SEVERITY *pSeverityList;
++ UINT NumIDs;
++ D3D11_MESSAGE_ID *pIDList;
++} D3D11_INFO_QUEUE_FILTER_DESC;
++typedef struct D3D11_INFO_QUEUE_FILTER
++{
++ D3D11_INFO_QUEUE_FILTER_DESC AllowList;
++ D3D11_INFO_QUEUE_FILTER_DESC DenyList;
++} D3D11_INFO_QUEUE_FILTER;
++static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
++MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
++{
++public:
++ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
++ virtual void __stdcall ClearStoredMessages() = 0;
++ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
++ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
++ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
++ virtual UINT64 __stdcall GetNumStoredMessages() = 0;
++ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
++ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
++ virtual UINT64 __stdcall GetMessageCountLimit() = 0;
++ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
++ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
++ virtual void __stdcall ClearStorageFilter() = 0;
++ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
++ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
++ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
++ virtual void __stdcall PopStorageFilter() = 0;
++ virtual UINT __stdcall GetStorageFilterStackSize() = 0;
++ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
++ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
++ virtual void __stdcall ClearRetrievalFilter() = 0;
++ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
++ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
++ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
++ virtual void __stdcall PopRetrievalFilter() = 0;
++ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
++ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
++ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
++ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
++ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
++ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
++ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
++ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
++ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
++ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
++ virtual BOOL __stdcall GetMuteDebugOutput() = 0;
++};
++#endif
++
+ namespace rx
+ {
+
+@@ -164,8 +225,7 @@ void CalculateConstantBufferParams(GLintptr offset, GLsizeiptr size, UINT *outFi
+
+ Renderer11::Renderer11(egl::Display *display)
+ : RendererD3D(display),
+- mStateCache(this),
+- mDebug(nullptr)
++ mStateCache(this)
+ {
+ // Initialize global annotator
+ gl::InitializeDebugAnnotations(&mAnnotator);
+@@ -398,7 +458,9 @@ egl::Error Renderer11::initialize()
+ // Cast the DeviceContext to a DeviceContext1.
+ // This could fail on Windows 7 without the Platform Update.
+ // Don't error in this case- just don't use mDeviceContext1.
++#if defined(ANGLE_ENABLE_D3D11_1)
+ mDeviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(mDeviceContext);
++#endif
+
+ IDXGIDevice *dxgiDevice = NULL;
+ result = mDevice->QueryInterface(__uuidof(IDXGIDevice), (void**)&dxgiDevice);
+@@ -421,6 +483,7 @@ egl::Error Renderer11::initialize()
+
+ SafeRelease(dxgiDevice);
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ IDXGIAdapter2 *dxgiAdapter2 = d3d11::DynamicCastComObject<IDXGIAdapter2>(mDxgiAdapter);
+
+ // On D3D_FEATURE_LEVEL_9_*, IDXGIAdapter::GetDesc returns "Software Adapter" for the description string.
+@@ -447,6 +510,7 @@ egl::Error Renderer11::initialize()
+ }
+
+ SafeRelease(dxgiAdapter2);
++#endif
+
+ memset(mDescription, 0, sizeof(mDescription));
+ wcstombs(mDescription, mAdapterDescription.Description, sizeof(mDescription) - 1);
+@@ -463,7 +527,7 @@ egl::Error Renderer11::initialize()
+ // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
+ #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
+ ID3D11InfoQueue *infoQueue;
+- result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
++ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
+
+ if (SUCCEEDED(result))
+ {
+@@ -481,10 +545,6 @@ egl::Error Renderer11::initialize()
+ }
+ #endif
+
+-#if !defined(NDEBUG)
+- mDebug = d3d11::DynamicCastComObject<ID3D11Debug>(mDevice);
+-#endif
+-
+ initializeDevice();
+
+ return egl::Error(EGL_SUCCESS);
+@@ -525,12 +585,14 @@ void Renderer11::initializeDevice()
+
+ const gl::Caps &rendererCaps = getRendererCaps();
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ if (getDeviceContext1IfSupported())
+ {
+ D3D11_FEATURE_DATA_D3D11_OPTIONS d3d11Options;
+ mDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS, &d3d11Options, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS));
+ mSupportsConstantBufferOffsets = (d3d11Options.ConstantBufferOffsetting != FALSE);
+ }
++#endif
+
+ mForceSetVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+ mCurVertexSamplerStates.resize(rendererCaps.maxVertexTextureImageUnits);
+@@ -853,6 +915,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
+ mCurrentConstantBufferVSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferVSSize[uniformBufferIndex] != uniformBufferSize)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ if (mSupportsConstantBufferOffsets && uniformBufferSize != 0)
+ {
+ UINT firstConstant = 0, numConstants = 0;
+@@ -861,6 +924,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
++#endif
+ {
+ ASSERT(uniformBufferOffset == 0);
+ mDeviceContext->VSSetConstantBuffers(getReservedVertexUniformBuffers() + uniformBufferIndex,
+@@ -901,6 +965,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
+ mCurrentConstantBufferPSOffset[uniformBufferIndex] != uniformBufferOffset ||
+ mCurrentConstantBufferPSSize[uniformBufferIndex] != uniformBufferSize)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ if (mSupportsConstantBufferOffsets && uniformBufferSize != 0)
+ {
+ UINT firstConstant = 0, numConstants = 0;
+@@ -909,6 +974,7 @@ gl::Error Renderer11::setUniformBuffers(const gl::Data &data,
+ 1, &constantBuffer, &firstConstant, &numConstants);
+ }
+ else
++#endif
+ {
+ ASSERT(uniformBufferOffset == 0);
+ mDeviceContext->PSSetConstantBuffers(getReservedFragmentUniformBuffers() + uniformBufferIndex,
+@@ -2194,7 +2260,9 @@ void Renderer11::release()
+ SafeRelease(mDxgiFactory);
+ SafeRelease(mDxgiAdapter);
+
++#if defined(ANGLE_ENABLE_D3D11_1)
+ SafeRelease(mDeviceContext1);
++#endif
+
+ if (mDeviceContext)
+ {
+@@ -2204,7 +2272,6 @@ void Renderer11::release()
+ }
+
+ SafeRelease(mDevice);
+- SafeRelease(mDebug);
+
+ if (mD3d11Module)
+ {
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+index d1fec55..cc7d6c2 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.h
+@@ -20,6 +20,8 @@
+ #include "libANGLE/renderer/d3d/d3d11/InputLayoutCache.h"
+ #include "libANGLE/renderer/d3d/d3d11/RenderStateCache.h"
+
++struct ID3D11DeviceContext1;
++
+ namespace gl
+ {
+ class FramebufferAttachment;
+@@ -390,7 +392,6 @@ class Renderer11 : public RendererD3D
+ DXGI_ADAPTER_DESC mAdapterDescription;
+ char mDescription[128];
+ DXGIFactory *mDxgiFactory;
+- ID3D11Debug *mDebug;
+
+ DebugAnnotator11 mAnnotator;
+ };
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+index 70b2b79..63085f4 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
+@@ -20,6 +20,88 @@
+
+ #include <algorithm>
+
++#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY
++# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2
++#endif
++#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT
++# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1
++#endif
++#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT
++# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4
++#endif
++#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT
++# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535
++#endif
++#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT
++# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575
++#endif
++#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION
++# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512
++#endif
++#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION
++# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096
++#endif
++#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
++# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
++#endif
++#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
++# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256
++#endif
++#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
++# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
++#endif
++#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
++# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
++#endif
++#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
++# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
++#endif
++#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
++# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
++#endif
++#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
++# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
++#endif
++#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
++# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
++#endif
++#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
++# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
++#endif
++#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
++# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
++#endif
++#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
++# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
++#endif
++#ifndef D3D11_SO_BUFFER_SLOT_COUNT
++# define D3D11_SO_BUFFER_SLOT_COUNT 4
++#endif
++#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
++# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
++#endif
++#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
++# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
++#endif
++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
++#endif
++#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
++# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
++#endif
++#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
++# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
++#endif
++#ifndef D3D11_PS_INPUT_REGISTER_COUNT
++# define D3D11_PS_INPUT_REGISTER_COUNT 32
++#endif
++#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
++# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
++#endif
++#if defined(ANGLE_MINGW32_COMPAT)
++static const IID WKPDID_D3DDebugObjectName = { 0x429b8c22, 0x9188, 0x4b0c, 0x87, 0x42, 0xac, 0xb0, 0xbf, 0x85, 0xc2, 0x00 };
++#endif
++
+ namespace rx
+ {
+
+@@ -232,7 +314,9 @@ GLint GetMaximumClientVersion(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return 3;
+@@ -298,7 +382,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -316,7 +402,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -336,7 +424,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -356,7 +446,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+@@ -374,7 +466,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -397,7 +491,9 @@ static bool GetFramebufferMultisampleSupport(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -414,7 +510,9 @@ static bool GetFramebufferBlitSupport(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -437,7 +535,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0:
+@@ -453,7 +553,9 @@ static bool GetShaderTextureLODSupport(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return true;
+@@ -472,7 +574,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -490,7 +594,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -508,7 +614,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -526,7 +634,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -544,7 +654,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -562,7 +674,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -586,7 +700,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
+@@ -608,7 +724,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
+@@ -625,7 +743,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
+@@ -645,7 +765,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+ // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -670,7 +792,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -698,7 +822,9 @@ static size_t GetReservedVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+ // We must reserve one output vector for dx_Position.
+ // We also reserve one for gl_Position, which we unconditionally output on Feature Levels 10_0+,
+ // even if it's unused in the shader (e.g. for transform feedback). TODO: This could be improved.
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return 2;
+@@ -720,7 +846,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+@@ -739,7 +867,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -761,7 +891,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
+ // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -786,7 +918,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -805,7 +939,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors(featureLevel);
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -824,7 +960,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -843,7 +981,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -862,7 +1002,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+ case D3D_FEATURE_LEVEL_10_1:
+ case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
+@@ -885,7 +1027,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
+
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -904,7 +1048,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
+
+ case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT;
+@@ -922,7 +1068,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0:
+
+ case D3D_FEATURE_LEVEL_10_1:
+@@ -940,7 +1088,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature
+ {
+ switch (featureLevel)
+ {
++#if defined(ANGLE_ENABLE_D3D11_1)
+ case D3D_FEATURE_LEVEL_11_1:
++#endif
+ case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
+ GetMaximumStreamOutputBuffers(featureLevel);
+
+@@ -1054,6 +1204,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::
+
+ // Setting a large alignment forces uniform buffers to bind with zero offset
+ caps->uniformBufferOffsetAlignment = static_cast<GLuint>(std::numeric_limits<GLint>::max());
++#if defined(ANGLE_ENABLE_D3D11_1)
+ ID3D11DeviceContext1 *deviceContext1 = d3d11::DynamicCastComObject<ID3D11DeviceContext1>(deviceContext);
+
+ if (deviceContext1)
+@@ -1070,6 +1221,7 @@ void GenerateCaps(ID3D11Device *device, ID3D11DeviceContext *deviceContext, gl::
+
+ SafeRelease(deviceContext1);
+ }
++#endif
+
+ caps->maxCombinedUniformBlocks = caps->maxVertexUniformBlocks + caps->maxFragmentUniformBlocks;
+ caps->maxCombinedVertexUniformComponents = (static_cast<GLint64>(caps->maxVertexUniformBlocks) * static_cast<GLint64>(caps->maxUniformBlockSize / 4)) +
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+index c59808d..bf1c367 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+@@ -206,7 +206,7 @@ egl::Error Renderer9::initialize()
+ {
+ TRACE_EVENT0("gpu", "D3d9Ex_QueryInterface");
+ ASSERT(mD3d9Ex);
+- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
++ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
+ ASSERT(mD3d9);
+ }
+ else
+@@ -314,7 +314,7 @@ egl::Error Renderer9::initialize()
+ if (mD3d9Ex)
+ {
+ TRACE_EVENT0("gpu", "mDevice_QueryInterface");
+- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx);
++ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
+ ASSERT(SUCCEEDED(result));
+ }
+
+--
+2.1.4
+
diff --git a/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch b/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch
new file mode 100644
index 0000000000..62300e1e9b
--- /dev/null
+++ b/src/angle/patches/0003-ANGLE-Fix-compilation-on-MSVC2010-2012.patch
@@ -0,0 +1,363 @@
+From 11304df7f66d0d8bc5dfdc960b86b5cac0f18313 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Wed, 8 Apr 2015 17:09:47 +0300
+Subject: [PATCH 3/5] ANGLE: Fix compilation on MSVC2010/2012
+
+Allow the D3D11 renderer to build with the June 2010 DirectX SDK.
+This mainly addresses C++11 language incompatibilities, such as replacing
+range-based for loops with iterators.
+
+Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7
+---
+ src/3rdparty/angle/src/common/angleutils.h | 2 ++
+ src/3rdparty/angle/src/common/platform.h | 9 +++++++
+ .../angle/src/compiler/translator/OutputHLSL.cpp | 31 +++++++++++++---------
+ src/3rdparty/angle/src/libANGLE/Context.cpp | 4 +--
+ src/3rdparty/angle/src/libANGLE/Error.h | 1 +
+ src/3rdparty/angle/src/libANGLE/Framebuffer.cpp | 23 ++++++++--------
+ src/3rdparty/angle/src/libANGLE/State.cpp | 3 ++-
+ src/3rdparty/angle/src/libANGLE/Texture.cpp | 2 +-
+ .../angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp | 6 +++--
+ .../src/libANGLE/renderer/d3d/RendererD3D.cpp | 4 +--
+ .../libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp | 3 ++-
+ 11 files changed, 55 insertions(+), 33 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/common/angleutils.h b/src/3rdparty/angle/src/common/angleutils.h
+index f3d2019..4cf84a3 100644
+--- a/src/3rdparty/angle/src/common/angleutils.h
++++ b/src/3rdparty/angle/src/common/angleutils.h
+@@ -25,12 +25,14 @@ namespace angle
+
+ class NonCopyable
+ {
++#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
+ public:
+ NonCopyable() = default;
+ ~NonCopyable() = default;
+ protected:
+ NonCopyable(const NonCopyable&) = delete;
+ void operator=(const NonCopyable&) = delete;
++#endif
+ };
+
+ }
+diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
+index be4cb94..3a2aa91 100644
+--- a/src/3rdparty/angle/src/common/platform.h
++++ b/src/3rdparty/angle/src/common/platform.h
+@@ -53,7 +53,9 @@
+
+ # if defined(ANGLE_ENABLE_D3D9)
+ # include <d3d9.h>
++# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
+ # include <d3dcompiler.h>
++# endif
+ # endif
+
+ # if defined(ANGLE_ENABLE_D3D11)
+@@ -70,7 +72,9 @@
+ # include <d3d11_1.h>
+ # include <dxgi1_2.h>
+ # endif
++# if !defined(ANGLE_TRANSLATOR_IMPLEMENTATION)
+ # include <d3dcompiler.h>
++# endif
+ # endif
+
+ # if defined(ANGLE_ENABLE_WINDOWS_STORE)
+@@ -83,6 +87,11 @@
+ # endif
+ # endif
+
++# if defined(_MSC_VER) && (_MSC_VER <= 1600)
++# define final
++# define override
++# endif
++
+ # undef near
+ # undef far
+ #endif
+diff --git a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+index c3240f5..94225b8 100644
+--- a/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
++++ b/src/3rdparty/angle/src/compiler/translator/OutputHLSL.cpp
+@@ -158,13 +158,13 @@ OutputHLSL::~OutputHLSL()
+ SafeDelete(mUnfoldShortCircuit);
+ SafeDelete(mStructureHLSL);
+ SafeDelete(mUniformHLSL);
+- for (auto &eqFunction : mStructEqualityFunctions)
++ for (auto it = mStructEqualityFunctions.begin(); it != mStructEqualityFunctions.end(); ++it)
+ {
+- SafeDelete(eqFunction);
++ SafeDelete(*it);
+ }
+- for (auto &eqFunction : mArrayEqualityFunctions)
++ for (auto it = mArrayEqualityFunctions.begin(); it != mArrayEqualityFunctions.end(); ++it)
+ {
+- SafeDelete(eqFunction);
++ SafeDelete(*it);
+ }
+ }
+
+@@ -340,17 +340,17 @@ void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
+ if (!mEqualityFunctions.empty())
+ {
+ out << "\n// Equality functions\n\n";
+- for (const auto &eqFunction : mEqualityFunctions)
++ for (auto it = mEqualityFunctions.cbegin(); it != mEqualityFunctions.cend(); ++it)
+ {
+- out << eqFunction->functionDefinition << "\n";
++ out << (*it)->functionDefinition << "\n";
+ }
+ }
+ if (!mArrayAssignmentFunctions.empty())
+ {
+ out << "\n// Assignment functions\n\n";
+- for (const auto &assignmentFunction : mArrayAssignmentFunctions)
++ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it)
+ {
+- out << assignmentFunction.functionDefinition << "\n";
++ out << it->functionDefinition << "\n";
+ }
+ }
+
+@@ -1858,8 +1858,9 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
+
+ if (!variable->getAsSymbolNode() || variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
+ {
+- for (const auto &seqElement : *sequence)
++ for (auto it = sequence->cbegin(); it != sequence->cend(); ++it)
+ {
++ const auto &seqElement = *it;
+ if (isSingleStatement(seqElement))
+ {
+ mUnfoldShortCircuit->traverse(seqElement);
+@@ -2941,8 +2942,9 @@ void OutputHLSL::writeDeferredGlobalInitializers(TInfoSinkBase &out)
+ << "void initializeDeferredGlobals()\n"
+ << "{\n";
+
+- for (const auto &deferredGlobal : mDeferredGlobalInitializers)
++ for (auto it = mDeferredGlobalInitializers.cbegin(); it != mDeferredGlobalInitializers.cend(); ++it)
+ {
++ const auto &deferredGlobal = *it;
+ TIntermSymbol *symbol = deferredGlobal.first;
+ TIntermTyped *expression = deferredGlobal.second;
+ ASSERT(symbol);
+@@ -2967,8 +2969,9 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
+ {
+ const TFieldList &fields = structure.fields();
+
+- for (const auto &eqFunction : mStructEqualityFunctions)
++ for (auto it = mStructEqualityFunctions.cbegin(); it != mStructEqualityFunctions.cend(); ++it)
+ {
++ auto *eqFunction = *it;
+ if (eqFunction->structure == &structure)
+ {
+ return eqFunction->functionName;
+@@ -3021,8 +3024,9 @@ TString OutputHLSL::addStructEqualityFunction(const TStructure &structure)
+
+ TString OutputHLSL::addArrayEqualityFunction(const TType& type)
+ {
+- for (const auto &eqFunction : mArrayEqualityFunctions)
++ for (auto it = mArrayEqualityFunctions.cbegin(); it != mArrayEqualityFunctions.cend(); ++it)
+ {
++ const auto &eqFunction = *it;
+ if (eqFunction->type == type)
+ {
+ return eqFunction->functionName;
+@@ -3072,8 +3076,9 @@ TString OutputHLSL::addArrayEqualityFunction(const TType& type)
+
+ TString OutputHLSL::addArrayAssignmentFunction(const TType& type)
+ {
+- for (const auto &assignFunction : mArrayAssignmentFunctions)
++ for (auto it = mArrayAssignmentFunctions.cbegin(); it != mArrayAssignmentFunctions.cend(); ++it)
+ {
++ const auto &assignFunction = *it;
+ if (assignFunction.type == type)
+ {
+ return assignFunction.functionName;
+diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp
+index 5ea039f..1da5fda 100644
+--- a/src/3rdparty/angle/src/libANGLE/Context.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Context.cpp
+@@ -158,9 +158,9 @@ Context::~Context()
+ deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
+ }
+
+- for (auto &zeroTexture : mZeroTextures)
++ for (auto it = mZeroTextures.begin(); it != mZeroTextures.end(); ++it)
+ {
+- zeroTexture.second.set(NULL);
++ it->second.set(NULL);
+ }
+ mZeroTextures.clear();
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Error.h b/src/3rdparty/angle/src/libANGLE/Error.h
+index 5812943..896b777 100644
+--- a/src/3rdparty/angle/src/libANGLE/Error.h
++++ b/src/3rdparty/angle/src/libANGLE/Error.h
+@@ -10,6 +10,7 @@
+ #define LIBANGLE_ERROR_H_
+
+ #include "angle_gl.h"
++#include "common/platform.h"
+ #include <EGL/egl.h>
+
+ #include <string>
+diff --git a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
+index 5fa7513..b1dd4a1 100644
+--- a/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Framebuffer.cpp
+@@ -48,9 +48,9 @@ Framebuffer::Data::Data(const Caps &caps)
+
+ Framebuffer::Data::~Data()
+ {
+- for (auto &colorAttachment : mColorAttachments)
++ for (auto it = mColorAttachments.begin(); it != mColorAttachments.end(); ++it)
+ {
+- SafeDelete(colorAttachment);
++ SafeDelete(*it);
+ }
+ SafeDelete(mDepthAttachment);
+ SafeDelete(mStencilAttachment);
+@@ -66,11 +66,11 @@ FramebufferAttachment *Framebuffer::Data::getReadAttachment() const
+
+ FramebufferAttachment *Framebuffer::Data::getFirstColorAttachment() const
+ {
+- for (FramebufferAttachment *colorAttachment : mColorAttachments)
++ for (auto it = mColorAttachments.cbegin(); it != mColorAttachments.cend(); ++it)
+ {
+- if (colorAttachment != nullptr)
++ if (*it != nullptr)
+ {
+- return colorAttachment;
++ return *it;
+ }
+ }
+
+@@ -115,9 +115,9 @@ void Framebuffer::detachRenderbuffer(GLuint renderbufferId)
+
+ void Framebuffer::detachResourceById(GLenum resourceType, GLuint resourceId)
+ {
+- for (auto &colorAttachment : mData.mColorAttachments)
++ for (auto it = mData.mColorAttachments.begin(); it != mData.mColorAttachments.end(); ++it)
+ {
+- DeleteMatchingAttachment(colorAttachment, resourceType, resourceId);
++ DeleteMatchingAttachment(*it, resourceType, resourceId);
+ }
+
+ DeleteMatchingAttachment(mData.mDepthAttachment, resourceType, resourceId);
+@@ -278,8 +278,9 @@ GLenum Framebuffer::checkStatus(const gl::Data &data) const
+ int samples = -1;
+ bool missingAttachment = true;
+
+- for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments)
++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
++ const auto &colorAttachment = *it;
+ if (colorAttachment != nullptr)
+ {
+ if (colorAttachment->getWidth() == 0 || colorAttachment->getHeight() == 0)
+@@ -533,11 +534,11 @@ int Framebuffer::getSamples(const gl::Data &data) const
+ {
+ // for a complete framebuffer, all attachments must have the same sample count
+ // in this case return the first nonzero sample size
+- for (const FramebufferAttachment *colorAttachment : mData.mColorAttachments)
++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
+- if (colorAttachment != nullptr)
++ if (*it != nullptr)
+ {
+- return colorAttachment->getSamples();
++ return (*it)->getSamples();
+ }
+ }
+ }
+diff --git a/src/3rdparty/angle/src/libANGLE/State.cpp b/src/3rdparty/angle/src/libANGLE/State.cpp
+index 15274c6..4c044d2 100644
+--- a/src/3rdparty/angle/src/libANGLE/State.cpp
++++ b/src/3rdparty/angle/src/libANGLE/State.cpp
+@@ -633,8 +633,9 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
+
+ void State::initializeZeroTextures(const TextureMap &zeroTextures)
+ {
+- for (const auto &zeroTexture : zeroTextures)
++ for (auto it = zeroTextures.cbegin(); it != zeroTextures.cend(); ++it)
+ {
++ const auto &zeroTexture = *it;
+ auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
+
+ for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
+diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp
+index 2d68bec..cd4584f 100644
+--- a/src/3rdparty/angle/src/libANGLE/Texture.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp
+@@ -316,7 +316,7 @@ void Texture::setImageDescChain(size_t levels, Extents baseSize, GLenum sizedInt
+ }
+
+ Texture::ImageDesc::ImageDesc()
+- : ImageDesc(Extents(0, 0, 0), GL_NONE)
++ : size(0, 0, 0), internalFormat(GL_NONE)
+ {
+ }
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+index db5f445..add5d62 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/DisplayD3D.cpp
+@@ -276,8 +276,9 @@ bool DisplayD3D::testDeviceLost()
+ egl::Error DisplayD3D::restoreLostDevice()
+ {
+ // Release surface resources to make the Reset() succeed
+- for (auto &surface : mSurfaceSet)
++ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it)
+ {
++ const auto &surface = *it;
+ if (surface->getBoundTexture())
+ {
+ surface->releaseTexImage(EGL_BACK_BUFFER);
+@@ -292,8 +293,9 @@ egl::Error DisplayD3D::restoreLostDevice()
+ }
+
+ // Restore any surfaces that may have been lost
+- for (const auto &surface : mSurfaceSet)
++ for (auto it = mSurfaceSet.cbegin(); it != mSurfaceSet.cend(); ++it)
+ {
++ const auto &surface = *it;
+ SurfaceD3D *surfaceD3D = GetImplAs<SurfaceD3D>(surface);
+
+ egl::Error error = surfaceD3D->resetSwapChain();
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
+index ff9600e..2ce0ce5 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/RendererD3D.cpp
+@@ -47,9 +47,9 @@ RendererD3D::~RendererD3D()
+ void RendererD3D::cleanup()
+ {
+ mScratchMemoryBuffer.resize(0);
+- for (auto &incompleteTexture : mIncompleteTextures)
++ for (auto it = mIncompleteTextures.begin(); it != mIncompleteTextures.end(); ++it)
+ {
+- incompleteTexture.second.set(NULL);
++ it->second.set(NULL);
+ }
+ mIncompleteTextures.clear();
+ }
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+index ab2a902..da01f32 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp
+@@ -64,8 +64,9 @@ static gl::Error InvalidateAttachmentSwizzles(const gl::FramebufferAttachment *a
+
+ gl::Error Framebuffer11::invalidateSwizzles() const
+ {
+- for (gl::FramebufferAttachment *colorAttachment : mData.mColorAttachments)
++ for (auto it = mData.mColorAttachments.cbegin(); it != mData.mColorAttachments.cend(); ++it)
+ {
++ gl::FramebufferAttachment *colorAttachment = *it;
+ gl::Error error = InvalidateAttachmentSwizzles(colorAttachment);
+ if (error.isError())
+ {
+--
+2.1.4
+
diff --git a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch b/src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch
index 801db67682..ff93920317 100644
--- a/src/angle/patches/0008-ANGLE-Dynamically-load-D3D-compiler-from-a-list-or-t.patch
+++ b/src/angle/patches/0004-ANGLE-Dynamically-load-D3D-compiler-from-a-list.patch
@@ -1,8 +1,7 @@
-From 4a5960465d1632ab089320fcbba4af294d58fd9a Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Fri, 7 Nov 2014 14:05:36 +0200
-Subject: [PATCH 08/16] ANGLE: Dynamically load D3D compiler from a list or the
- environment
+From bbb62a69dd2b49d7cc4214937077c22b6997ffac Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Fri, 27 Mar 2015 17:27:38 +0200
+Subject: [PATCH 4/5] ANGLE: Dynamically load D3D compiler from a list
If the default compiler cannot be found, load it from a list of DLL names,
including a non-versioned proxy DLL provided by Qt. On Desktop Windows,
@@ -11,16 +10,16 @@ QT_D3DCOMPILER_DLL.
Change-Id: I0d7a8a8a36cc571836f8fa59ea14513b9b19c19b
---
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 27 ++++++++++++++++++++++
- 1 file changed, 27 insertions(+)
+ .../src/libANGLE/renderer/d3d/HLSLCompiler.cpp | 25 ++++++++++++++++++++++
+ 1 file changed, 25 insertions(+)
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index bfeaf51..9d003b4 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -11,6 +11,10 @@
- #include "common/features.h"
- #include "common/utilities.h"
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+index 9c72d6f..8961a36 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/HLSLCompiler.cpp
+@@ -12,6 +12,10 @@
+
+ #include "third_party/trace_event/trace_event.h"
+#ifndef QT_D3DCOMPILER_DLL
+#define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
@@ -29,7 +28,7 @@ index bfeaf51..9d003b4 100644
// Definitions local to the translation unit
namespace
{
-@@ -132,6 +136,29 @@ bool HLSLCompiler::initialize()
+@@ -143,6 +147,27 @@ bool HLSLCompiler::initialize()
}
#endif // ANGLE_PRELOADED_D3DCOMPILER_MODULE_NAMES
@@ -42,8 +41,6 @@ index bfeaf51..9d003b4 100644
+ defaultCompiler,
+ L"d3dcompiler_47.dll",
+ L"d3dcompiler_46.dll",
-+ L"d3dcompiler_45.dll",
-+ L"d3dcompiler_44.dll",
+ L"d3dcompiler_43.dll",
+ 0
+ };
@@ -60,5 +57,5 @@ index bfeaf51..9d003b4 100644
{
// Load the version of the D3DCompiler DLL associated with the Direct3D version ANGLE was built with.
--
-1.9.4.msysgit.1
+2.1.4
diff --git a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch b/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
deleted file mode 100644
index 45a3f17cca..0000000000
--- a/src/angle/patches/0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
+++ /dev/null
@@ -1,109 +0,0 @@
-From 3a39939b5eba9f788789961c4800ba62618f758c Mon Sep 17 00:00:00 2001
-From: Friedemann Kleint <Friedemann.Kleint@digia.com>
-Date: Tue, 11 Nov 2014 10:26:32 +0200
-Subject: [PATCH 04/16] Make it possible to link ANGLE statically for
- single-thread use.
-
-Fix exports and provide static instances of thread-local
-data depending on QT_OPENGL_ES_2_ANGLE_STATIC.
-
-Change-Id: Ifab25a820adf5953bb3b09036de53dbf7f1a7fd5
----
- src/3rdparty/angle/include/KHR/khrplatform.h | 2 +-
- src/3rdparty/angle/src/libEGL/main.cpp | 10 ++++++++++
- src/3rdparty/angle/src/libGLESv2/main.cpp | 10 ++++++++--
- 3 files changed, 19 insertions(+), 3 deletions(-)
-
-diff --git a/src/3rdparty/angle/include/KHR/khrplatform.h b/src/3rdparty/angle/include/KHR/khrplatform.h
-index c9e6f17..1ac2d3f 100644
---- a/src/3rdparty/angle/include/KHR/khrplatform.h
-+++ b/src/3rdparty/angle/include/KHR/khrplatform.h
-@@ -97,7 +97,7 @@
- *-------------------------------------------------------------------------
- * This precedes the return type of the function in the function prototype.
- */
--#if defined(_WIN32) && !defined(__SCITECH_SNAP__)
-+#if defined(_WIN32) && !defined(__SCITECH_SNAP__) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
- # define KHRONOS_APICALL __declspec(dllimport)
- #elif defined (__SYMBIAN32__)
- # define KHRONOS_APICALL IMPORT_C
-diff --git a/src/3rdparty/angle/src/libEGL/main.cpp b/src/3rdparty/angle/src/libEGL/main.cpp
-index d1489f2..e88cad7 100644
---- a/src/3rdparty/angle/src/libEGL/main.cpp
-+++ b/src/3rdparty/angle/src/libEGL/main.cpp
-@@ -49,6 +49,8 @@ void DeallocateCurrent()
-
- }
-
-+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
-+
- extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
- {
- switch (reason)
-@@ -108,16 +110,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
- return TRUE;
- }
-
-+#endif // !QT_OPENGL_ES_2_ANGLE_STATIC
-+
- namespace egl
- {
-
- Current *GetCurrentData()
- {
-+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
- Current *current = reinterpret_cast<Current*>(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 &current;
-+#endif
- }
-
- void recordError(const Error &error)
-diff --git a/src/3rdparty/angle/src/libGLESv2/main.cpp b/src/3rdparty/angle/src/libGLESv2/main.cpp
-index 3ac00d5..00f63ae 100644
---- a/src/3rdparty/angle/src/libGLESv2/main.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/main.cpp
-@@ -74,7 +74,7 @@ void DeallocateCurrent()
-
- }
-
--#ifdef ANGLE_PLATFORM_WINDOWS
-+#if defined(ANGLE_PLATFORM_WINDOWS) && !defined(QT_OPENGL_ES_2_ANGLE_STATIC)
- extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved)
- {
- switch (reason)
-@@ -117,18 +117,24 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE instance, DWORD reason, LPVOID reserved
-
- return TRUE;
- }
--#endif
-+#endif // ANGLE_PLATFORM_WINDOWS && !QT_OPENGL_ES_2_ANGLE_STATIC
-
- namespace gl
- {
-
- Current *GetCurrentData()
- {
-+#ifndef QT_OPENGL_ES_2_ANGLE_STATIC
- Current *current = reinterpret_cast<Current*>(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 &current;
-+#endif
- }
-
- void makeCurrent(Context *context, egl::Display *display, egl::Surface *surface)
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch
new file mode 100644
index 0000000000..8a5bffebe4
--- /dev/null
+++ b/src/angle/patches/0005-ANGLE-Add-support-for-querying-platform-device.patch
@@ -0,0 +1,84 @@
+From f6bfeecf2c7d14e9fd2b637e6ce9555489e3a256 Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@intopalo.com>
+Date: Fri, 27 Mar 2015 17:58:41 +0200
+Subject: [PATCH 5/5] ANGLE: Add support for querying platform device
+
+The EGL_EXT_device_base extension allows for querying the platform
+device of the graphics hardware via eglQueryDisplayAttribEXT().
+As that extension is not supported by ANGLE, this patch adds similar
+functionality to the existing eglQuerySurfacePointerANGLE API. When
+EGL_DEVICE_EXT is passed as the queried attribute, the underlying
+D3D/DXGI device pointer is passed back to the caller via the value
+argument.
+
+The D3D device is needed for video support in QtMultimedia as well as
+the IDXGIDevice3::Trim() calls required by the Windows Store.
+
+Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428
+---
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp | 7 +++++--
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h | 1 +
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp | 5 +++++
+ src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h | 2 ++
+ 4 files changed, 13 insertions(+), 2 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+index a3c457d..4fde295 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SurfaceD3D.cpp
+@@ -385,8 +385,11 @@ EGLint SurfaceD3D::isPostSubBufferSupported() const
+
+ egl::Error SurfaceD3D::querySurfacePointerANGLE(EGLint attribute, void **value)
+ {
+- ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE);
+- *value = mSwapChain->getShareHandle();
++ ASSERT(attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE || attribute == EGL_DEVICE_EXT);
++ if (attribute == EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE)
++ *value = mSwapChain->getShareHandle();
++ else if (attribute == EGL_DEVICE_EXT)
++ *value = mSwapChain->getDevice();
+ return egl::Error(EGL_SUCCESS);
+ }
+
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
+index 3bde92e..da36e52 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/SwapChainD3D.h
+@@ -41,6 +41,7 @@ class SwapChainD3D : angle::NonCopyable
+ virtual EGLint reset(EGLint backbufferWidth, EGLint backbufferHeight, EGLint swapInterval) = 0;
+ virtual EGLint swapRect(EGLint x, EGLint y, EGLint width, EGLint height) = 0;
+ virtual void recreate() = 0;
++ virtual void *getDevice() { return NULL; }
+
+ virtual RenderTargetD3D *getColorRenderTarget() = 0;
+ virtual RenderTargetD3D *getDepthStencilRenderTarget() = 0;
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+index bcb2505..298f3cc 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp
+@@ -703,4 +703,9 @@ void SwapChain11::recreate()
+ // possibly should use this method instead of reset
+ }
+
++void *rx::SwapChain11::getDevice()
++{
++ return mRenderer->getDevice();
++}
++
+ }
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+index 4ea6778..48c808a 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h
+@@ -43,6 +43,8 @@ class SwapChain11 : public SwapChainD3D
+ EGLint getWidth() const { return mWidth; }
+ EGLint getHeight() const { return mHeight; }
+
++ virtual void *getDevice();
++
+ static SwapChain11 *makeSwapChain11(SwapChainD3D *swapChain);
+
+ private:
+--
+2.1.4
+
diff --git a/src/angle/patches/0009-ANGLE-Support-WinRT.patch b/src/angle/patches/0009-ANGLE-Support-WinRT.patch
deleted file mode 100644
index a38fb4ea13..0000000000
--- a/src/angle/patches/0009-ANGLE-Support-WinRT.patch
+++ /dev/null
@@ -1,837 +0,0 @@
-From 4d150ba3814f824f1cadaedbdb83d0ac79d0e1a2 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Fri, 14 Nov 2014 09:28:11 +0200
-Subject: [PATCH 09/16] ANGLE: Support WinRT
-
-Tweak ANGLE's existing support for WinRT to allow for changing the
-window size on Windows Phone.
-
-Change-Id: Ia312b5318b977838a2953f1f530487cbf24974bc
----
- src/3rdparty/angle/include/EGL/eglplatform.h | 5 +-
- src/3rdparty/angle/src/common/NativeWindow.h | 7 +-
- src/3rdparty/angle/src/common/platform.h | 4 +-
- .../angle/src/common/win32/NativeWindow.cpp | 2 +-
- .../src/common/winrt/CoreWindowNativeWindow.cpp | 87 +++++++++++++---------
- .../src/common/winrt/CoreWindowNativeWindow.h | 48 ++----------
- .../src/common/winrt/InspectableNativeWindow.cpp | 8 +-
- .../src/common/winrt/InspectableNativeWindow.h | 7 +-
- .../common/winrt/SwapChainPanelNativeWindow.cpp | 2 +-
- .../src/common/winrt/SwapChainPanelNativeWindow.h | 2 +-
- src/3rdparty/angle/src/libEGL/Display.h | 1 +
- src/3rdparty/angle/src/libEGL/Surface.cpp | 45 ++++++++---
- src/3rdparty/angle/src/libEGL/Surface.h | 4 +
- src/3rdparty/angle/src/libEGL/libEGL.cpp | 20 +++++
- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 2 +-
- .../libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp | 74 +++++++++++-------
- .../src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h | 2 +
- 17 files changed, 189 insertions(+), 131 deletions(-)
-
-diff --git a/src/3rdparty/angle/include/EGL/eglplatform.h b/src/3rdparty/angle/include/EGL/eglplatform.h
-index 3793e57..2eb3674 100644
---- a/src/3rdparty/angle/include/EGL/eglplatform.h
-+++ b/src/3rdparty/angle/include/EGL/eglplatform.h
-@@ -73,13 +73,14 @@
- #endif
- #include <windows.h>
-
--typedef HDC EGLNativeDisplayType;
- typedef HBITMAP EGLNativePixmapType;
-
--#if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP /* Windows Store */
-+#if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) /* Windows Store */
- #include <inspectable.h>
-+typedef IInspectable* EGLNativeDisplayType;
- typedef IInspectable* EGLNativeWindowType;
- #else
-+typedef HDC EGLNativeDisplayType;
- typedef HWND EGLNativeWindowType;
- #endif
-
-diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h
-index dc5fc8f..9e93aea 100644
---- a/src/3rdparty/angle/src/common/NativeWindow.h
-+++ b/src/3rdparty/angle/src/common/NativeWindow.h
-@@ -44,10 +44,11 @@ typedef IDXGIFactory DXGIFactory;
-
- namespace rx
- {
-+
- class NativeWindow
- {
-- public:
-- explicit NativeWindow(EGLNativeWindowType window);
-+public:
-+ explicit NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display);
-
- bool initialize();
- bool getClientRect(LPRECT rect);
-@@ -58,9 +59,11 @@ class NativeWindow
- DXGISwapChain** swapChain);
-
- inline EGLNativeWindowType getNativeWindow() const { return mWindow; }
-+ inline EGLNativeDisplayType getNativeDisplay() const { return mDisplay; }
-
- private:
- EGLNativeWindowType mWindow;
-+ EGLNativeDisplayType mDisplay;
-
- #if defined(ANGLE_ENABLE_WINDOWS_STORE)
- std::shared_ptr<InspectableNativeWindow> mImpl;
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index cd12dba..0065ec7 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -34,7 +34,7 @@
- #endif
-
- #ifdef ANGLE_PLATFORM_WINDOWS
--# if defined(WINAPI_FAMILY) && WINAPI_FAMILY == WINAPI_FAMILY_PC_APP
-+# if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
- # define ANGLE_ENABLE_WINDOWS_STORE 1
- # endif
- # ifndef STRICT
-@@ -67,7 +67,9 @@
- # if defined(ANGLE_ENABLE_WINDOWS_STORE)
- # include <dxgi1_3.h>
- # if defined(_DEBUG)
-+# if (WINAPI_FAMILY != WINAPI_FAMILY_PHONE_APP)
- # include <DXProgrammableCapture.h>
-+# endif
- # include <dxgidebug.h>
- # endif
- # endif
-diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-index aa2bfa4..2440747 100644
---- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-@@ -16,7 +16,7 @@ bool IsValidEGLNativeWindowType(EGLNativeWindowType window)
- return (IsWindow(window) == TRUE);
- }
-
--NativeWindow::NativeWindow(EGLNativeWindowType window) : mWindow(window)
-+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display) : mWindow(window), mDisplay(display)
- {
- }
-
-diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-index 0e63fa5..9b65c15 100644
---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.cpp
-@@ -6,21 +6,25 @@
-
- // CoreWindowNativeWindow.cpp: NativeWindow for managing ICoreWindow native window types.
-
--#include <windows.graphics.display.h>
-+#include <algorithm>
- #include "common/winrt/CoreWindowNativeWindow.h"
- using namespace ABI::Windows::Foundation::Collections;
-
- namespace rx
- {
-+
-+typedef ITypedEventHandler<ABI::Windows::UI::Core::CoreWindow *, ABI::Windows::UI::Core::WindowSizeChangedEventArgs *> SizeChangedHandler;
-+
- CoreWindowNativeWindow::~CoreWindowNativeWindow()
- {
- unregisterForSizeChangeEvents();
- }
-
--bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
-+bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
- {
- ComPtr<IPropertySet> props = propertySet;
- ComPtr<IInspectable> win = window;
-+ ComPtr<IInspectable> displayInformation = display;
- SIZE swapChainSize = {};
- bool swapChainSizeSpecified = false;
- HRESULT result = S_OK;
-@@ -47,6 +51,29 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
-
- if (SUCCEEDED(result))
- {
-+ result = displayInformation.As(&mDisplayInformation);
-+ }
-+
-+ if (SUCCEEDED(result))
-+ {
-+#if WINAPI_FAMILY==WINAPI_FAMILY_PHONE_APP
-+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation2> displayInformation2;
-+ result = mDisplayInformation.As(&displayInformation2);
-+ ASSERT(SUCCEEDED(result));
-+
-+ result = displayInformation2->get_RawPixelsPerViewPixel(&mScaleFactor);
-+ ASSERT(SUCCEEDED(result));
-+#else
-+ ABI::Windows::Graphics::Display::ResolutionScale resolutionScale;
-+ result = mDisplayInformation->get_ResolutionScale(&resolutionScale);
-+ ASSERT(SUCCEEDED(result));
-+
-+ mScaleFactor = DOUBLE(resolutionScale) / 100.0;
-+#endif
-+ }
-+
-+ if (SUCCEEDED(result))
-+ {
- // If a swapchain size is specfied, then the automatic resize
- // behaviors implemented by the host should be disabled. The swapchain
- // will be still be scaled when being rendered to fit the bounds
-@@ -60,7 +87,14 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
- }
- else
- {
-- result = GetCoreWindowSizeInPixels(mCoreWindow, &mClientRect);
-+ ABI::Windows::Foundation::Rect rect;
-+ HRESULT result = mCoreWindow->get_Bounds(&rect);
-+ if (SUCCEEDED(result))
-+ {
-+ LONG width = std::floor(rect.Width * mScaleFactor + 0.5);
-+ LONG height = std::floor(rect.Height * mScaleFactor + 0.5);
-+ mClientRect = { 0, 0, width, height };
-+ }
- }
- }
-
-@@ -76,12 +110,8 @@ bool CoreWindowNativeWindow::initialize(EGLNativeWindowType window, IPropertySet
-
- bool CoreWindowNativeWindow::registerForSizeChangeEvents()
- {
-- ComPtr<IWindowSizeChangedEventHandler> sizeChangedHandler;
-- HRESULT result = Microsoft::WRL::MakeAndInitialize<CoreWindowSizeChangedHandler>(sizeChangedHandler.ReleaseAndGetAddressOf(), this->shared_from_this());
-- if (SUCCEEDED(result))
-- {
-- result = mCoreWindow->add_SizeChanged(sizeChangedHandler.Get(), &mSizeChangedEventToken);
-- }
-+ HRESULT result = mCoreWindow->add_SizeChanged(Callback<SizeChangedHandler>(this, &CoreWindowNativeWindow::onSizeChanged).Get(),
-+ &mSizeChangedEventToken);
-
- if (SUCCEEDED(result))
- {
-@@ -126,7 +156,7 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
- if (SUCCEEDED(result))
- {
-
--#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+#if (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP) // This block is disabled for Qt applications, as the resize events are expected
- // Test if swapchain supports resize. On Windows Phone devices, this will return DXGI_ERROR_UNSUPPORTED. On
- // other devices DXGI_ERROR_INVALID_CALL should be returned because the combination of flags passed
- // (DXGI_SWAP_CHAIN_FLAG_NONPREROTATED | DXGI_SWAP_CHAIN_FLAG_GDI_COMPATIBLE) are invalid flag combinations.
-@@ -152,36 +182,19 @@ HRESULT CoreWindowNativeWindow::createSwapChain(ID3D11Device *device, DXGIFactor
- return result;
- }
-
--HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize)
-+// Basically, this shouldn't be used on Phone
-+HRESULT CoreWindowNativeWindow::onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *e)
- {
-- ABI::Windows::Foundation::Rect bounds;
-- HRESULT result = coreWindow->get_Bounds(&bounds);
-- if (SUCCEEDED(result))
-+ ABI::Windows::Foundation::Size size;
-+ if (SUCCEEDED(e->get_Size(&size)))
- {
-- *windowSize = { 0, 0, ConvertDipsToPixels(bounds.Width), ConvertDipsToPixels(bounds.Height) };
-+ SIZE windowSizeInPixels = {
-+ std::floor(size.Width * mScaleFactor + 0.5),
-+ std::floor(size.Height * mScaleFactor + 0.5)
-+ };
-+ setNewClientSize(windowSizeInPixels);
- }
-
-- return result;
--}
--
--static float GetLogicalDpi()
--{
-- ComPtr<ABI::Windows::Graphics::Display::IDisplayPropertiesStatics> displayProperties;
-- float dpi = 96.0f;
--
-- if (SUCCEEDED(GetActivationFactory(HStringReference(RuntimeClass_Windows_Graphics_Display_DisplayProperties).Get(), displayProperties.GetAddressOf())))
-- {
-- if (SUCCEEDED(displayProperties->get_LogicalDpi(&dpi)))
-- {
-- return dpi;
-- }
-- }
-- return dpi;
--}
--
--long ConvertDipsToPixels(float dips)
--{
-- static const float dipsPerInch = 96.0f;
-- return lround((dips * GetLogicalDpi() / dipsPerInch));
-+ return S_OK;
- }
- }
-diff --git a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
-index 0c6222d..1c55124 100644
---- a/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
-+++ b/src/3rdparty/angle/src/common/winrt/CoreWindowNativeWindow.h
-@@ -11,67 +11,29 @@
-
- #include "common/winrt/InspectableNativeWindow.h"
- #include <memory>
--
--typedef ABI::Windows::Foundation::__FITypedEventHandler_2_Windows__CUI__CCore__CCoreWindow_Windows__CUI__CCore__CWindowSizeChangedEventArgs_t IWindowSizeChangedEventHandler;
-+#include <windows.graphics.display.h>
-
- namespace rx
- {
--long ConvertDipsToPixels(float dips);
-
- class CoreWindowNativeWindow : public InspectableNativeWindow, public std::enable_shared_from_this<CoreWindowNativeWindow>
- {
- public:
- ~CoreWindowNativeWindow();
-
-- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
-+ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
- bool registerForSizeChangeEvents();
- void unregisterForSizeChangeEvents();
- HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
-
- private:
-+ HRESULT onSizeChanged(ABI::Windows::UI::Core::ICoreWindow *, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *);
-+
- ComPtr<ABI::Windows::UI::Core::ICoreWindow> mCoreWindow;
-+ ComPtr<ABI::Windows::Graphics::Display::IDisplayInformation> mDisplayInformation;
- ComPtr<IMap<HSTRING, IInspectable*>> mPropertyMap;
- };
-
--[uuid(7F924F66-EBAE-40E5-A10B-B8F35E245190)]
--class CoreWindowSizeChangedHandler :
-- public Microsoft::WRL::RuntimeClass<Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, IWindowSizeChangedEventHandler>
--{
-- public:
-- CoreWindowSizeChangedHandler() { }
-- HRESULT RuntimeClassInitialize(std::shared_ptr<InspectableNativeWindow> host)
-- {
-- if (!host)
-- {
-- return E_INVALIDARG;
-- }
--
-- mHost = host;
-- return S_OK;
-- }
--
-- // IWindowSizeChangedEventHandler
-- IFACEMETHOD(Invoke)(ABI::Windows::UI::Core::ICoreWindow *sender, ABI::Windows::UI::Core::IWindowSizeChangedEventArgs *sizeChangedEventArgs)
-- {
-- std::shared_ptr<InspectableNativeWindow> host = mHost.lock();
-- if (host)
-- {
-- ABI::Windows::Foundation::Size windowSize;
-- if (SUCCEEDED(sizeChangedEventArgs->get_Size(&windowSize)))
-- {
-- SIZE windowSizeInPixels = { ConvertDipsToPixels(windowSize.Width), ConvertDipsToPixels(windowSize.Height) };
-- host->setNewClientSize(windowSizeInPixels);
-- }
-- }
--
-- return S_OK;
-- }
--
-- private:
-- std::weak_ptr<InspectableNativeWindow> mHost;
--};
--
--HRESULT GetCoreWindowSizeInPixels(const ComPtr<ABI::Windows::UI::Core::ICoreWindow>& coreWindow, RECT *windowSize);
- }
-
- #endif // COMMON_WINRT_COREWINDOWNATIVEWINDOW_H_
-diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
-index c062a48..0589f6d 100644
---- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.cpp
-@@ -11,9 +11,9 @@
-
- namespace rx
- {
--NativeWindow::NativeWindow(EGLNativeWindowType window)
-+NativeWindow::NativeWindow(EGLNativeWindowType window, EGLNativeDisplayType display)
-+ : mWindow(window), mDisplay(display)
- {
-- mWindow = window;
- }
-
- bool NativeWindow::initialize()
-@@ -40,7 +40,7 @@ bool NativeWindow::initialize()
- mImpl = std::make_shared<CoreWindowNativeWindow>();
- if (mImpl)
- {
-- return mImpl->initialize(mWindow, propertySet.Get());
-+ return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
- }
- }
- else if (IsSwapChainPanel(mWindow, &swapChainPanel))
-@@ -48,7 +48,7 @@ bool NativeWindow::initialize()
- mImpl = std::make_shared<SwapChainPanelNativeWindow>();
- if (mImpl)
- {
-- return mImpl->initialize(mWindow, propertySet.Get());
-+ return mImpl->initialize(mWindow, mDisplay, propertySet.Get());
- }
- }
- else
-diff --git a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
-index c625348..402941a 100644
---- a/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
-+++ b/src/3rdparty/angle/src/common/winrt/InspectableNativeWindow.h
-@@ -32,13 +32,14 @@ class InspectableNativeWindow
- mRequiresSwapChainScaling(false),
- mClientRectChanged(false),
- mClientRect({0,0,0,0}),
-- mNewClientRect({0,0,0,0})
-+ mNewClientRect({0,0,0,0}),
-+ mScaleFactor(1.0)
- {
- mSizeChangedEventToken.value = 0;
- }
- virtual ~InspectableNativeWindow(){}
-
-- virtual bool initialize(EGLNativeWindowType window, IPropertySet *propertySet) = 0;
-+ virtual bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet) = 0;
- virtual HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain) = 0;
- virtual bool registerForSizeChangeEvents() = 0;
- virtual void unregisterForSizeChangeEvents() = 0;
-@@ -49,6 +50,7 @@ class InspectableNativeWindow
- if (mClientRectChanged && mSupportsSwapChainResize)
- {
- mClientRect = mNewClientRect;
-+ mClientRectChanged = false;
- }
-
- *rect = mClientRect;
-@@ -76,6 +78,7 @@ protected:
- RECT mClientRect;
- RECT mNewClientRect;
- bool mClientRectChanged;
-+ DOUBLE mScaleFactor;
-
- EventRegistrationToken mSizeChangedEventToken;
- };
-diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
-index 4e4fb6d..268dfbd 100644
---- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.cpp
-@@ -18,7 +18,7 @@ SwapChainPanelNativeWindow::~SwapChainPanelNativeWindow()
- unregisterForSizeChangeEvents();
- }
-
--bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, IPropertySet *propertySet)
-+bool SwapChainPanelNativeWindow::initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet)
- {
- ComPtr<IPropertySet> props = propertySet;
- ComPtr<IInspectable> win = window;
-diff --git a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
-index e88f554..5bbf274 100644
---- a/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
-+++ b/src/3rdparty/angle/src/common/winrt/SwapChainPanelNativeWindow.h
-@@ -18,7 +18,7 @@ class SwapChainPanelNativeWindow : public InspectableNativeWindow, public std::e
- public:
- ~SwapChainPanelNativeWindow();
-
-- bool initialize(EGLNativeWindowType window, IPropertySet *propertySet);
-+ bool initialize(EGLNativeWindowType window, EGLNativeDisplayType display, IPropertySet *propertySet);
- bool registerForSizeChangeEvents();
- void unregisterForSizeChangeEvents();
- HRESULT createSwapChain(ID3D11Device *device, DXGIFactory *factory, DXGI_FORMAT format, unsigned int width, unsigned int height, DXGISwapChain **swapChain);
-diff --git a/src/3rdparty/angle/src/libEGL/Display.h b/src/3rdparty/angle/src/libEGL/Display.h
-index 378323a..b3ffcc8 100644
---- a/src/3rdparty/angle/src/libEGL/Display.h
-+++ b/src/3rdparty/angle/src/libEGL/Display.h
-@@ -67,6 +67,7 @@ class Display
-
- const char *getExtensionString() const;
- const char *getVendorString() const;
-+ EGLNativeDisplayType getDisplayId() const { return mDisplayId; }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Display);
-diff --git a/src/3rdparty/angle/src/libEGL/Surface.cpp b/src/3rdparty/angle/src/libEGL/Surface.cpp
-index 3414656..b664a85 100644
---- a/src/3rdparty/angle/src/libEGL/Surface.cpp
-+++ b/src/3rdparty/angle/src/libEGL/Surface.cpp
-@@ -31,7 +31,7 @@ namespace egl
- {
-
- Surface::Surface(Display *display, const Config *config, EGLNativeWindowType window, EGLint fixedSize, EGLint width, EGLint height, EGLint postSubBufferSupported)
-- : mDisplay(display), mConfig(config), mNativeWindow(window), mPostSubBufferSupported(postSubBufferSupported)
-+ : mDisplay(display), mConfig(config), mNativeWindow(window, display->getDisplayId()), mPostSubBufferSupported(postSubBufferSupported)
- {
- //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
- mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
-@@ -47,6 +47,8 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
- mSwapInterval = -1;
- mWidth = width;
- mHeight = height;
-+ mFixedWidth = mWidth;
-+ mFixedHeight = mHeight;
- setSwapInterval(1);
- mFixedSize = fixedSize;
-
-@@ -54,7 +56,7 @@ Surface::Surface(Display *display, const Config *config, EGLNativeWindowType win
- }
-
- Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGLint width, EGLint height, EGLenum textureFormat, EGLenum textureType)
-- : mDisplay(display), mNativeWindow(NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
-+ : mDisplay(display), mNativeWindow(NULL, NULL), mConfig(config), mShareHandle(shareHandle), mWidth(width), mHeight(height), mPostSubBufferSupported(EGL_FALSE)
- {
- //TODO(jmadill): MANGLE refactor. (note, can't call makeRendererD3D because of dll export issues)
- mRenderer = static_cast<rx::RendererD3D*>(mDisplay->getRenderer());
-@@ -71,6 +73,8 @@ Surface::Surface(Display *display, const Config *config, HANDLE shareHandle, EGL
- setSwapInterval(1);
- // This constructor is for offscreen surfaces, which are always fixed-size.
- mFixedSize = EGL_TRUE;
-+ mFixedWidth = mWidth;
-+ mFixedHeight = mHeight;
- }
-
- Surface::~Surface()
-@@ -157,10 +161,13 @@ Error Surface::resetSwapChain()
-
- Error Surface::resizeSwapChain(int backbufferWidth, int backbufferHeight)
- {
-- ASSERT(backbufferWidth >= 0 && backbufferHeight >= 0);
- ASSERT(mSwapChain);
-
-- EGLint status = mSwapChain->resize(std::max(1, backbufferWidth), std::max(1, backbufferHeight));
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ backbufferWidth = std::max(1, backbufferWidth);
-+ backbufferHeight = std::max(1, backbufferHeight);
-+#endif
-+ EGLint status = mSwapChain->resize(backbufferWidth, backbufferHeight);
-
- if (status == EGL_CONTEXT_LOST)
- {
-@@ -209,14 +216,14 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- return Error(EGL_SUCCESS);
- }
-
-- if (x + width > mWidth)
-+ if (x + width > abs(mWidth))
- {
-- width = mWidth - x;
-+ width = abs(mWidth) - x;
- }
-
-- if (y + height > mHeight)
-+ if (y + height > abs(mHeight))
- {
-- height = mHeight - y;
-+ height = abs(mHeight) - y;
- }
-
- if (width == 0 || height == 0)
-@@ -224,6 +231,9 @@ Error Surface::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- return Error(EGL_SUCCESS);
- }
-
-+ ASSERT(width > 0);
-+ ASSERT(height > 0);
-+
- EGLint status = mSwapChain->swapRect(x, y, width, height);
-
- if (status == EGL_CONTEXT_LOST)
-@@ -352,6 +362,13 @@ bool Surface::checkForOutOfDateSwapChain()
- sizeDirty = clientWidth != getWidth() || clientHeight != getHeight();
- }
-
-+ if (mFixedSize && (mWidth != mFixedWidth || mHeight != mFixedHeight))
-+ {
-+ clientWidth = mFixedWidth;
-+ clientHeight = mFixedHeight;
-+ sizeDirty = true;
-+ }
-+
- bool wasDirty = (mSwapIntervalDirty || sizeDirty);
-
- if (mSwapIntervalDirty)
-@@ -378,7 +395,7 @@ bool Surface::checkForOutOfDateSwapChain()
-
- Error Surface::swap()
- {
-- return swapRect(0, 0, mWidth, mHeight);
-+ return swapRect(0, 0, abs(mWidth), abs(mHeight));
- }
-
- Error Surface::postSubBuffer(EGLint x, EGLint y, EGLint width, EGLint height)
-@@ -471,6 +488,16 @@ EGLint Surface::isFixedSize() const
- return mFixedSize;
- }
-
-+void Surface::setFixedWidth(EGLint width)
-+{
-+ mFixedWidth = width;
-+}
-+
-+void Surface::setFixedHeight(EGLint height)
-+{
-+ mFixedHeight = height;
-+}
-+
- EGLenum Surface::getFormat() const
- {
- return mConfig->mRenderTargetFormat;
-diff --git a/src/3rdparty/angle/src/libEGL/Surface.h b/src/3rdparty/angle/src/libEGL/Surface.h
-index 662fe21..46382d0 100644
---- a/src/3rdparty/angle/src/libEGL/Surface.h
-+++ b/src/3rdparty/angle/src/libEGL/Surface.h
-@@ -70,6 +70,8 @@ class Surface
- virtual gl::Texture2D *getBoundTexture() const;
-
- EGLint isFixedSize() const;
-+ void setFixedWidth(EGLint width);
-+ void setFixedHeight(EGLint height);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Surface);
-@@ -91,6 +93,8 @@ class Surface
- const egl::Config *mConfig; // EGL config surface was created with
- EGLint mHeight; // Height of surface
- EGLint mWidth; // Width of surface
-+ EGLint mFixedHeight; // Pending height of the surface
-+ EGLint mFixedWidth; // Pending width of the surface
- // EGLint horizontalResolution; // Horizontal dot pitch
- // EGLint verticalResolution; // Vertical dot pitch
- // EGLBoolean largestPBuffer; // If true, create largest pbuffer possible
-diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index 6110698..dc20d85 100644
---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
-+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-@@ -706,6 +706,26 @@ EGLBoolean __stdcall eglSurfaceAttrib(EGLDisplay dpy, EGLSurface surface, EGLint
- return EGL_FALSE;
- }
-
-+ switch (attribute)
-+ {
-+ case EGL_WIDTH:
-+ if (!eglSurface->isFixedSize() || !value) {
-+ recordError(egl::Error(EGL_BAD_PARAMETER));
-+ return EGL_FALSE;
-+ }
-+ eglSurface->setFixedWidth(value);
-+ return EGL_TRUE;
-+ case EGL_HEIGHT:
-+ if (!eglSurface->isFixedSize() || !value) {
-+ recordError(egl::Error(EGL_BAD_PARAMETER));
-+ return EGL_FALSE;
-+ }
-+ eglSurface->setFixedHeight(value);
-+ return EGL_TRUE;
-+ default:
-+ break;
-+ }
-+
- UNIMPLEMENTED(); // FIXME
-
- recordError(egl::Error(EGL_SUCCESS));
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-index 1655f1d..c789cae 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-@@ -231,7 +231,7 @@ class Renderer11 : public RendererD3D
-
- HMODULE mD3d11Module;
- HMODULE mDxgiModule;
-- HDC mDc;
-+ EGLNativeDisplayType mDc;
- std::vector<D3D_FEATURE_LEVEL> mAvailableFeatureLevels;
- D3D_DRIVER_TYPE mDriverType;
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-index 834b7bd..52c8a81 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp
-@@ -42,6 +42,8 @@ SwapChain11::SwapChain11(Renderer11 *renderer, NativeWindow nativeWindow, HANDLE
- mPassThroughPS = NULL;
- mWidth = -1;
- mHeight = -1;
-+ mRotateL = false;
-+ mRotateR = false;
- mSwapInterval = 0;
- mAppCreatedShareHandle = mShareHandle != NULL;
- mPassThroughResourcesInit = false;
-@@ -92,10 +94,11 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- ASSERT(device != NULL);
-
- // D3D11 does not allow zero size textures
-- ASSERT(backbufferWidth >= 1);
-- ASSERT(backbufferHeight >= 1);
-+ ASSERT(backbufferWidth != 0);
-+ ASSERT(backbufferHeight != 0);
-
- // Preserve the render target content
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- ID3D11Texture2D *previousOffscreenTexture = mOffscreenTexture;
- if (previousOffscreenTexture)
- {
-@@ -103,6 +106,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- }
- const int previousWidth = mWidth;
- const int previousHeight = mHeight;
-+#endif
-
- releaseOffscreenTexture();
-
-@@ -136,8 +140,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
- mOffscreenTexture->GetDesc(&offscreenTextureDesc);
-
-- if (offscreenTextureDesc.Width != (UINT)backbufferWidth ||
-- offscreenTextureDesc.Height != (UINT)backbufferHeight ||
-+ if (offscreenTextureDesc.Width != UINT(abs(backbufferWidth)) ||
-+ offscreenTextureDesc.Height != UINT(abs(backbufferHeight)) ||
- offscreenTextureDesc.Format != backbufferFormatInfo.texFormat ||
- offscreenTextureDesc.MipLevels != 1 ||
- offscreenTextureDesc.ArraySize != 1)
-@@ -152,8 +156,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- const bool useSharedResource = !mNativeWindow.getNativeWindow() && mRenderer->getShareHandleSupport();
-
- D3D11_TEXTURE2D_DESC offscreenTextureDesc = {0};
-- offscreenTextureDesc.Width = backbufferWidth;
-- offscreenTextureDesc.Height = backbufferHeight;
-+ offscreenTextureDesc.Width = abs(backbufferWidth);
-+ offscreenTextureDesc.Height = abs(backbufferHeight);
- offscreenTextureDesc.Format = backbufferFormatInfo.texFormat;
- offscreenTextureDesc.MipLevels = 1;
- offscreenTextureDesc.ArraySize = 1;
-@@ -233,8 +237,8 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- if (mDepthBufferFormat != GL_NONE)
- {
- D3D11_TEXTURE2D_DESC depthStencilTextureDesc;
-- depthStencilTextureDesc.Width = backbufferWidth;
-- depthStencilTextureDesc.Height = backbufferHeight;
-+ depthStencilTextureDesc.Width = abs(backbufferWidth);
-+ depthStencilTextureDesc.Height = abs(backbufferHeight);
- depthStencilTextureDesc.Format = depthBufferFormatInfo.texFormat;
- depthStencilTextureDesc.MipLevels = 1;
- depthStencilTextureDesc.ArraySize = 1;
-@@ -286,6 +290,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- mWidth = backbufferWidth;
- mHeight = backbufferHeight;
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE)
- if (previousOffscreenTexture != NULL)
- {
- D3D11_BOX sourceBox = {0};
-@@ -307,6 +312,7 @@ EGLint SwapChain11::resetOffscreenTexture(int backbufferWidth, int backbufferHei
- swapRect(0, 0, mWidth, mHeight);
- }
- }
-+#endif
-
- return EGL_SUCCESS;
- }
-@@ -320,8 +326,16 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- return EGL_BAD_ACCESS;
- }
-
-+ // Windows Phone works around the rotation limitation by using negative values for the swap chain size
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && (WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)
-+ mRotateL = backbufferWidth < 0; // Landscape/InvertedLandscape
-+ mRotateR = backbufferHeight < 0; // InvertedPortrait/InvertedLandscape
-+ backbufferWidth = abs(backbufferWidth);
-+ backbufferHeight = abs(backbufferHeight);
-+#endif
-+
- // EGL allows creating a surface with 0x0 dimension, however, DXGI does not like 0x0 swapchains
-- if (backbufferWidth < 1 || backbufferHeight < 1)
-+ if (backbufferWidth == 0 || backbufferHeight == 0)
- {
- return EGL_SUCCESS;
- }
-@@ -329,6 +343,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- // Can only call resize if we have already created our swap buffer and resources
- ASSERT(mSwapChain && mBackBufferTexture && mBackBufferRTView);
-
-+#if !defined(ANGLE_ENABLE_WINDOWS_STORE) || (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP) // The swap chain is not directly resized on Windows Phone
- SafeRelease(mBackBufferTexture);
- SafeRelease(mBackBufferRTView);
-
-@@ -366,6 +381,7 @@ EGLint SwapChain11::resize(EGLint backbufferWidth, EGLint backbufferHeight)
- {
- d3d11::SetDebugName(mBackBufferRTView, "Back buffer render target");
- }
-+#endif
-
- return resetOffscreenTexture(backbufferWidth, backbufferHeight);
- }
-@@ -512,16 +528,6 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- ID3D11Device *device = mRenderer->getDevice();
- ID3D11DeviceContext *deviceContext = mRenderer->getDeviceContext();
-
-- // Set vertices
-- D3D11_MAPPED_SUBRESOURCE mappedResource;
-- HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-- if (FAILED(result))
-- {
-- return EGL_BAD_ACCESS;
-- }
--
-- d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
--
- // Create a quad in homogeneous coordinates
- float x1 = (x / float(mWidth)) * 2.0f - 1.0f;
- float y1 = (y / float(mHeight)) * 2.0f - 1.0f;
-@@ -533,10 +539,23 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
- float u2 = (x + width) / float(mWidth);
- float v2 = (y + height) / float(mHeight);
-
-- d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, u1, v1);
-- d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, u1, v2);
-- d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, u2, v1);
-- d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, u2, v2);
-+ const bool rotateL = mRotateL;
-+ const bool rotateR = mRotateR;
-+
-+ // Set vertices
-+ D3D11_MAPPED_SUBRESOURCE mappedResource;
-+ HRESULT result = deviceContext->Map(mQuadVB, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
-+ if (FAILED(result))
-+ {
-+ return EGL_BAD_ACCESS;
-+ }
-+
-+ d3d11::PositionTexCoordVertex *vertices = static_cast<d3d11::PositionTexCoordVertex*>(mappedResource.pData);
-+
-+ d3d11::SetPositionTexCoordVertex(&vertices[0], x1, y1, rotateL ? u2 : u1, rotateR ? v2 : v1);
-+ d3d11::SetPositionTexCoordVertex(&vertices[1], x1, y2, rotateR ? u2 : u1, rotateL ? v1 : v2);
-+ d3d11::SetPositionTexCoordVertex(&vertices[2], x2, y1, rotateR ? u1 : u2, rotateL ? v2 : v1);
-+ d3d11::SetPositionTexCoordVertex(&vertices[3], x2, y2, rotateL ? u1 : u2, rotateR ? v1 : v2);
-
- deviceContext->Unmap(mQuadVB, 0);
-
-@@ -564,10 +583,11 @@ EGLint SwapChain11::swapRect(EGLint x, EGLint y, EGLint width, EGLint height)
-
- // Set the viewport
- D3D11_VIEWPORT viewport;
-- viewport.TopLeftX = 0;
-- viewport.TopLeftY = 0;
-- viewport.Width = mWidth;
-- viewport.Height = mHeight;
-+ viewport.TopLeftX = 0.0f;
-+ viewport.TopLeftY = 0.0f;
-+ const bool invertViewport = (mRotateL || mRotateR) && !(mRotateL && mRotateR);
-+ viewport.Width = FLOAT(invertViewport ? mHeight : mWidth);
-+ viewport.Height = FLOAT(invertViewport ? mWidth : mHeight);
- viewport.MinDepth = 0.0f;
- viewport.MaxDepth = 1.0f;
- deviceContext->RSSetViewports(1, &viewport);
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
-index 22401d8..77509ed 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h
-@@ -52,6 +52,8 @@ class SwapChain11 : public SwapChain
- Renderer11 *mRenderer;
- EGLint mHeight;
- EGLint mWidth;
-+ bool mRotateL;
-+ bool mRotateR;
- bool mAppCreatedShareHandle;
- unsigned int mSwapInterval;
- bool mPassThroughResourcesInit;
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch b/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
deleted file mode 100644
index dd2768cf3e..0000000000
--- a/src/angle/patches/0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
+++ /dev/null
@@ -1,637 +0,0 @@
-From 829bf86c57357d3c8ec598b92fcfdb1849e84075 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Tue, 11 Nov 2014 17:11:54 +0200
-Subject: [PATCH 10/16] ANGLE: Enable D3D11 for feature level 9 cards
-
-Enable use of ANGLE on lower-end hardware, such as Surface RT and
-Windows Phone 8.
-
-Change-Id: Ice536802e4eedc1d264abd0dd65960638fce59e4
----
- src/3rdparty/angle/src/libGLESv2/angletypes.cpp | 6 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp | 69 ++++---
- .../src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp | 4 +-
- .../src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp | 7 +-
- .../renderer/d3d/d3d11/PixelTransfer11.cpp | 9 +-
- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 226 +++++++++++++--------
- .../src/libGLESv2/renderer/d3d/d3d11/Renderer11.h | 1 +
- .../renderer/d3d/d3d11/TextureStorage11.cpp | 4 +-
- .../libGLESv2/renderer/d3d/d3d11/formatutils11.cpp | 4 +-
- .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +-
- 10 files changed, 208 insertions(+), 124 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
-index 6fd02e0..5a0cfc5 100644
---- a/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/angletypes.cpp
-@@ -12,6 +12,8 @@
- #include "libGLESv2/State.h"
- #include "libGLESv2/VertexArray.h"
-
-+#include <float.h>
-+
- namespace gl
- {
-
-@@ -24,8 +26,8 @@ SamplerState::SamplerState()
- maxAnisotropy(1.0f),
- baseLevel(0),
- maxLevel(1000),
-- minLod(-1000.0f),
-- maxLod(1000.0f),
-+ minLod(-FLT_MAX),
-+ maxLod(FLT_MAX),
- compareMode(GL_NONE),
- compareFunc(GL_LEQUAL),
- swizzleRed(GL_RED),
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-index 91e7552..06aea9b 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp
-@@ -209,7 +209,7 @@ Blit11::Blit11(Renderer11 *renderer)
- pointSamplerDesc.BorderColor[2] = 0.0f;
- pointSamplerDesc.BorderColor[3] = 0.0f;
- pointSamplerDesc.MinLOD = 0.0f;
-- pointSamplerDesc.MaxLOD = 0.0f;
-+ pointSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
-
- result = device->CreateSamplerState(&pointSamplerDesc, &mPointSampler);
- ASSERT(SUCCEEDED(result));
-@@ -228,7 +228,7 @@ Blit11::Blit11(Renderer11 *renderer)
- linearSamplerDesc.BorderColor[2] = 0.0f;
- linearSamplerDesc.BorderColor[3] = 0.0f;
- linearSamplerDesc.MinLOD = 0.0f;
-- linearSamplerDesc.MaxLOD = 0.0f;
-+ linearSamplerDesc.MaxLOD = mRenderer->isLevel9() ? D3D11_FLOAT32_MAX : 0.0f;
-
- result = device->CreateSamplerState(&linearSamplerDesc, &mLinearSampler);
- ASSERT(SUCCEEDED(result));
-@@ -290,28 +290,31 @@ Blit11::Blit11(Renderer11 *renderer)
- ASSERT(SUCCEEDED(result));
- d3d11::SetDebugName(mQuad2DVS, "Blit11 2D vertex shader");
-
-- result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
-- ASSERT(SUCCEEDED(result));
-- d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
--
-- D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
-+ if (!renderer->isLevel9())
- {
-- { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-- { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-- { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-- };
--
-- result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
-- ASSERT(SUCCEEDED(result));
-- d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
--
-- result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
-- ASSERT(SUCCEEDED(result));
-- d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
-+ result = device->CreatePixelShader(g_PS_PassthroughDepth2D, ArraySize(g_PS_PassthroughDepth2D), NULL, &mDepthPS);
-+ ASSERT(SUCCEEDED(result));
-+ d3d11::SetDebugName(mDepthPS, "Blit11 2D depth pixel shader");
-
-- result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
-- ASSERT(SUCCEEDED(result));
-- d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
-+ D3D11_INPUT_ELEMENT_DESC quad3DLayout[] =
-+ {
-+ { "POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-+ { "LAYER", 0, DXGI_FORMAT_R32_UINT, 0, 8, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-+ { "TEXCOORD", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
-+ };
-+
-+ result = device->CreateInputLayout(quad3DLayout, ArraySize(quad3DLayout), g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), &mQuad3DIL);
-+ ASSERT(SUCCEEDED(result));
-+ d3d11::SetDebugName(mQuad3DIL, "Blit11 3D input layout");
-+
-+ result = device->CreateVertexShader(g_VS_Passthrough3D, ArraySize(g_VS_Passthrough3D), NULL, &mQuad3DVS);
-+ ASSERT(SUCCEEDED(result));
-+ d3d11::SetDebugName(mQuad3DVS, "Blit11 3D vertex shader");
-+
-+ result = device->CreateGeometryShader(g_GS_Passthrough3D, ArraySize(g_GS_Passthrough3D), NULL, &mQuad3DGS);
-+ ASSERT(SUCCEEDED(result));
-+ d3d11::SetDebugName(mQuad3DGS, "Renderer11 copy 3D texture geometry shader");
-+ }
-
- buildShaderMap();
-
-@@ -970,22 +973,27 @@ void Blit11::buildShaderMap()
- ID3D11Device *device = mRenderer->getDevice();
-
- add2DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D RGBA pixel shader" ));
-- add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" ));
-- add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" ));
- add2DBlitShaderToMap(GL_BGRA_EXT, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D BGRA pixel shader" ));
- add2DBlitShaderToMap(GL_RGB, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2D, "Blit11 2D RGB pixel shader" ));
-- add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" ));
-- add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" ));
- add2DBlitShaderToMap(GL_RG, false, d3d11::CompilePS(device, g_PS_PassthroughRG2D, "Blit11 2D RG pixel shader" ));
-- add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" ));
-- add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" ));
- add2DBlitShaderToMap(GL_RED, false, d3d11::CompilePS(device, g_PS_PassthroughR2D, "Blit11 2D R pixel shader" ));
-- add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" ));
-- add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" ));
- add2DBlitShaderToMap(GL_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2D, "Blit11 2D alpha pixel shader" ));
- add2DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum2D, "Blit11 2D lum pixel shader" ));
- add2DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha2D, "Blit11 2D luminance alpha pixel shader"));
-
-+ addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" ));
-+
-+ if (mRenderer->isLevel9())
-+ return;
-+
-+ add2DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DUI, "Blit11 2D RGBA UI pixel shader" ));
-+ add2DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA2DI, "Blit11 2D RGBA I pixel shader" ));
-+ add2DBlitShaderToMap(GL_RGB_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGB2DUI, "Blit11 2D RGB UI pixel shader" ));
-+ add2DBlitShaderToMap(GL_RGB_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGB2DI, "Blit11 2D RGB I pixel shader" ));
-+ add2DBlitShaderToMap(GL_RG_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRG2DUI, "Blit11 2D RG UI pixel shader" ));
-+ add2DBlitShaderToMap(GL_RG_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRG2DI, "Blit11 2D RG I pixel shader" ));
-+ add2DBlitShaderToMap(GL_RED_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughR2DUI, "Blit11 2D R UI pixel shader" ));
-+ add2DBlitShaderToMap(GL_RED_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughR2DI, "Blit11 2D R I pixel shader" ));
- add3DBlitShaderToMap(GL_RGBA, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3D, "Blit11 3D RGBA pixel shader" ));
- add3DBlitShaderToMap(GL_RGBA_INTEGER, false, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DUI, "Blit11 3D UI RGBA pixel shader" ));
- add3DBlitShaderToMap(GL_RGBA_INTEGER, true, d3d11::CompilePS(device, g_PS_PassthroughRGBA3DI, "Blit11 3D I RGBA pixel shader" ));
-@@ -1003,7 +1011,6 @@ void Blit11::buildShaderMap()
- add3DBlitShaderToMap(GL_LUMINANCE, false, d3d11::CompilePS(device, g_PS_PassthroughLum3D, "Blit11 3D luminance pixel shader" ));
- add3DBlitShaderToMap(GL_LUMINANCE_ALPHA, false, d3d11::CompilePS(device, g_PS_PassthroughLumAlpha3D, "Blit11 3D luminance alpha pixel shader"));
-
-- addSwizzleShaderToMap(GL_FLOAT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleF2D, "Blit11 2D F swizzle pixel shader" ));
- addSwizzleShaderToMap(GL_UNSIGNED_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleUI2D, "Blit11 2D UI swizzle pixel shader"));
- addSwizzleShaderToMap(GL_INT, D3D_SRV_DIMENSION_TEXTURE2D, d3d11::CompilePS(device, g_PS_SwizzleI2D, "Blit11 2D I swizzle pixel shader" ));
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
-index 2d5fa3c..5aab379 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp
-@@ -753,7 +753,9 @@ void Buffer11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Ren
-
- case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
- bufferDesc->Usage = D3D11_USAGE_DEFAULT;
-- bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
-+ bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
-+ if (!renderer->isLevel9())
-+ bufferDesc->BindFlags |= D3D11_BIND_STREAM_OUTPUT;
- bufferDesc->CPUAccessFlags = 0;
- break;
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-index 4630762..7185a05 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp
-@@ -104,7 +104,7 @@ Clear11::Clear11(Renderer11 *renderer)
- rsDesc.DepthBias = 0;
- rsDesc.DepthBiasClamp = 0.0f;
- rsDesc.SlopeScaledDepthBias = 0.0f;
-- rsDesc.DepthClipEnable = FALSE;
-+ rsDesc.DepthClipEnable = renderer->isLevel9();
- rsDesc.ScissorEnable = FALSE;
- rsDesc.MultisampleEnable = FALSE;
- rsDesc.AntialiasedLineEnable = FALSE;
-@@ -114,6 +114,11 @@ Clear11::Clear11(Renderer11 *renderer)
- d3d11::SetDebugName(mRasterizerState, "Clear11 masked clear rasterizer state");
-
- mFloatClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_FLOAT, g_VS_ClearFloat, g_PS_ClearFloat);
-+ if (mRenderer->isLevel9()) {
-+ memset(&mUintClearShader, 0, sizeof(ClearShader));
-+ memset(&mIntClearShader, 0, sizeof(ClearShader));
-+ return;
-+ }
- mUintClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_UINT, g_VS_ClearUint, g_PS_ClearUint );
- mIntClearShader = CreateClearShader(device, DXGI_FORMAT_R32G32B32A32_SINT, g_VS_ClearSint, g_PS_ClearSint );
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-index a4072d8..6a3d347 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp
-@@ -133,10 +133,13 @@ gl::Error PixelTransfer11::loadResources()
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture vertex shader.");
- }
-
-- mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
-- if (!mBufferToTextureGS)
-+ if (!mRenderer->isLevel9())
- {
-- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
-+ mBufferToTextureGS = d3d11::CompileGS(device, g_GS_BufferToTexture, "BufferToTexture GS");
-+ if (!mBufferToTextureGS)
-+ {
-+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to create internal buffer to texture geometry shader.");
-+ }
- }
-
- gl::Error error = buildShaderMap();
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index ffc6cc9..f6ba930 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -153,6 +153,24 @@ Renderer11::Renderer11(egl::Display *display, EGLNativeDisplayType hDc, const eg
- }
- }
-
-+#if !defined(ANGLE_ENABLE_D3D9)
-+ if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9)
-+ {
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3);
-+ }
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2);
-+ }
-+ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1)
-+ {
-+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1);
-+ }
-+ }
-+#endif
-+
- mDriverType = (attributes.get(EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_FALSE) == EGL_TRUE) ? D3D_DRIVER_TYPE_WARP
- : D3D_DRIVER_TYPE_HARDWARE;
- }
-@@ -1170,6 +1188,83 @@ gl::Error Renderer11::drawElements(GLenum mode, GLsizei count, GLenum type, cons
- return gl::Error(GL_NO_ERROR);
- }
- }
-+template<typename T>
-+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<const GLubyte*>(indices)[i];
-+ }
-+ data[count] = static_cast<const GLubyte*>(indices)[0];
-+ break;
-+ case GL_UNSIGNED_SHORT:
-+ for (int i = 0; i < count; i++)
-+ {
-+ data[i] = static_cast<const GLushort*>(indices)[i];
-+ }
-+ data[count] = static_cast<const GLushort*>(indices)[0];
-+ break;
-+ case GL_UNSIGNED_INT:
-+ for (int i = 0; i < count; i++)
-+ {
-+ data[i] = static_cast<const GLuint*>(indices)[i];
-+ }
-+ data[count] = static_cast<const GLuint*>(indices)[0];
-+ break;
-+ default: UNREACHABLE();
-+ }
-+}
-+
-+template<typename T>
-+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<const GLubyte*>(indices)[0];
-+ data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
-+ data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
-+ }
-+ break;
-+ case GL_UNSIGNED_SHORT:
-+ for (unsigned int i = 0; i < numTris; i++)
-+ {
-+ data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
-+ data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
-+ data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
-+ }
-+ break;
-+ case GL_UNSIGNED_INT:
-+ for (unsigned int i = 0; i < numTris; i++)
-+ {
-+ data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
-+ data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
-+ data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
-+ }
-+ break;
-+ default: UNREACHABLE();
-+ }
-+}
-
- gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *indices, int minIndex, gl::Buffer *elementArrayBuffer)
- {
-@@ -1189,10 +1284,13 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
- indices = bufferData + offset;
- }
-
-+ // TODO: some level 9 hardware supports 32-bit indices; test and store support instead
-+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-+
- if (!mLineLoopIB)
- {
- mLineLoopIB = new StreamingIndexBufferInterface(this);
-- gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
-+ gl::Error error = mLineLoopIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
- if (error.isError())
- {
- SafeDelete(mLineLoopIB);
-@@ -1203,7 +1301,8 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
- // Checked by Renderer11::applyPrimitiveType
- ASSERT(count >= 0);
-
-- if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / sizeof(unsigned int)))
-+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
-+ if (static_cast<unsigned int>(count) + 1 > (std::numeric_limits<unsigned int>::max() / indexTypeSize))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a 32-bit looping index buffer for GL_LINE_LOOP, too many indices required.");
- }
-@@ -1223,42 +1322,12 @@ gl::Error Renderer11::drawLineLoop(GLsizei count, GLenum type, const GLvoid *ind
- return error;
- }
-
-- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-+ if (indexType == GL_UNSIGNED_SHORT)
-+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned short*>(mappedMemory));
-+ else
-+ fillLineLoopIndices(type, count, indices, reinterpret_cast<unsigned int*>(mappedMemory));
- unsigned int indexBufferOffset = offset;
-
-- switch (type)
-- {
-- case GL_NONE: // Non-indexed draw
-- for (int i = 0; i < count; i++)
-- {
-- data[i] = i;
-- }
-- data[count] = 0;
-- break;
-- case GL_UNSIGNED_BYTE:
-- for (int i = 0; i < count; i++)
-- {
-- data[i] = static_cast<const GLubyte*>(indices)[i];
-- }
-- data[count] = static_cast<const GLubyte*>(indices)[0];
-- break;
-- case GL_UNSIGNED_SHORT:
-- for (int i = 0; i < count; i++)
-- {
-- data[i] = static_cast<const GLushort*>(indices)[i];
-- }
-- data[count] = static_cast<const GLushort*>(indices)[0];
-- break;
-- case GL_UNSIGNED_INT:
-- for (int i = 0; i < count; i++)
-- {
-- data[i] = static_cast<const GLuint*>(indices)[i];
-- }
-- data[count] = static_cast<const GLuint*>(indices)[0];
-- break;
-- default: UNREACHABLE();
-- }
--
- error = mLineLoopIB->unmapBuffer();
- if (error.isError())
- {
-@@ -1300,10 +1369,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
- indices = bufferData + offset;
- }
-
-+ const int indexType = isLevel9() ? GL_UNSIGNED_SHORT : GL_UNSIGNED_INT;
-+
- if (!mTriangleFanIB)
- {
- mTriangleFanIB = new StreamingIndexBufferInterface(this);
-- gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, GL_UNSIGNED_INT);
-+ gl::Error error = mTriangleFanIB->reserveBufferSpace(INITIAL_INDEX_BUFFER_SIZE, indexType);
- if (error.isError())
- {
- SafeDelete(mTriangleFanIB);
-@@ -1316,13 +1387,14 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
-
- const unsigned int numTris = count - 2;
-
-- if (numTris > (std::numeric_limits<unsigned int>::max() / (sizeof(unsigned int) * 3)))
-+ int indexTypeSize = indexType == GL_UNSIGNED_SHORT ? sizeof(unsigned short) : sizeof(unsigned int);
-+ if (numTris > (std::numeric_limits<unsigned int>::max() / (indexTypeSize * 3)))
- {
- return gl::Error(GL_OUT_OF_MEMORY, "Failed to create a scratch index buffer for GL_TRIANGLE_FAN, too many indices required.");
- }
-
-- const unsigned int spaceNeeded = (numTris * 3) * sizeof(unsigned int);
-- gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, GL_UNSIGNED_INT);
-+ const unsigned int spaceNeeded = (numTris * 3) * indexTypeSize;
-+ gl::Error error = mTriangleFanIB->reserveBufferSpace(spaceNeeded, indexType);
- if (error.isError())
- {
- return error;
-@@ -1336,45 +1408,12 @@ gl::Error Renderer11::drawTriangleFan(GLsizei count, GLenum type, const GLvoid *
- return error;
- }
-
-- unsigned int *data = reinterpret_cast<unsigned int*>(mappedMemory);
-- unsigned int indexBufferOffset = offset;
-+ if (indexType == GL_UNSIGNED_SHORT)
-+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned short*>(mappedMemory));
-+ else
-+ fillTriangleFanIndices(type, numTris, indices, reinterpret_cast<unsigned int*>(mappedMemory));
-
-- switch (type)
-- {
-- case GL_NONE: // Non-indexed draw
-- for (unsigned int i = 0; i < numTris; i++)
-- {
-- data[i*3 + 0] = 0;
-- data[i*3 + 1] = i + 1;
-- data[i*3 + 2] = i + 2;
-- }
-- break;
-- case GL_UNSIGNED_BYTE:
-- for (unsigned int i = 0; i < numTris; i++)
-- {
-- data[i*3 + 0] = static_cast<const GLubyte*>(indices)[0];
-- data[i*3 + 1] = static_cast<const GLubyte*>(indices)[i + 1];
-- data[i*3 + 2] = static_cast<const GLubyte*>(indices)[i + 2];
-- }
-- break;
-- case GL_UNSIGNED_SHORT:
-- for (unsigned int i = 0; i < numTris; i++)
-- {
-- data[i*3 + 0] = static_cast<const GLushort*>(indices)[0];
-- data[i*3 + 1] = static_cast<const GLushort*>(indices)[i + 1];
-- data[i*3 + 2] = static_cast<const GLushort*>(indices)[i + 2];
-- }
-- break;
-- case GL_UNSIGNED_INT:
-- for (unsigned int i = 0; i < numTris; i++)
-- {
-- data[i*3 + 0] = static_cast<const GLuint*>(indices)[0];
-- data[i*3 + 1] = static_cast<const GLuint*>(indices)[i + 1];
-- data[i*3 + 2] = static_cast<const GLuint*>(indices)[i + 2];
-- }
-- break;
-- default: UNREACHABLE();
-- }
-+ unsigned int indexBufferOffset = offset;
-
- error = mTriangleFanIB->unmapBuffer();
- if (error.isError())
-@@ -1634,7 +1673,7 @@ gl::Error Renderer11::applyUniforms(const ProgramImpl &program, const std::vecto
- }
-
- // needed for the point sprite geometry shader
-- if (mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
-+ if (mFeatureLevel >= D3D_FEATURE_LEVEL_10_0 && mCurrentGeometryConstantBuffer != mDriverConstantBufferPS)
- {
- mDeviceContext->GSSetConstantBuffers(0, 1, &mDriverConstantBufferPS);
- mCurrentGeometryConstantBuffer = mDriverConstantBufferPS;
-@@ -1938,7 +1977,10 @@ int Renderer11::getMajorShaderModel() const
- {
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MAJOR_VERSION; // 5
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MAJOR_VERSION; // 4
-- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MAJOR_VERSION; // 4
-+ case D3D_FEATURE_LEVEL_10_0:
-+ case D3D_FEATURE_LEVEL_9_3:
-+ case D3D_FEATURE_LEVEL_9_2:
-+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MAJOR_VERSION; // 4
- default: UNREACHABLE(); return 0;
- }
- }
-@@ -1949,7 +1991,10 @@ int Renderer11::getMinorShaderModel() const
- {
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SHADER_MINOR_VERSION; // 0
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SHADER_MINOR_VERSION; // 1
-- case D3D_FEATURE_LEVEL_10_0: return D3D10_SHADER_MINOR_VERSION; // 0
-+ case D3D_FEATURE_LEVEL_10_0:
-+ case D3D_FEATURE_LEVEL_9_3:
-+ case D3D_FEATURE_LEVEL_9_2:
-+ case D3D_FEATURE_LEVEL_9_1: return D3D10_SHADER_MINOR_VERSION; // 0
- default: UNREACHABLE(); return 0;
- }
- }
-@@ -2455,6 +2500,7 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
-
- unsigned int profileMajorVersion = 0;
- unsigned int profileMinorVersion = 0;
-+ const char *profileSuffix = NULL;
- switch (mFeatureLevel)
- {
- case D3D_FEATURE_LEVEL_11_0:
-@@ -2469,12 +2515,30 @@ gl::Error Renderer11::compileToExecutable(gl::InfoLog &infoLog, const std::strin
- profileMajorVersion = 4;
- profileMinorVersion = 0;
- break;
-+ case D3D_FEATURE_LEVEL_9_3:
-+ profileMajorVersion = 4;
-+ profileMinorVersion = 0;
-+ profileSuffix = "_level_9_3";
-+ break;
-+ case D3D_FEATURE_LEVEL_9_2:
-+ profileMajorVersion = 4;
-+ profileMinorVersion = 0;
-+ profileSuffix = "_level_9_2";
-+ break;
-+ case D3D_FEATURE_LEVEL_9_1:
-+ profileMajorVersion = 4;
-+ profileMinorVersion = 0;
-+ profileSuffix = "_level_9_1";
-+ break;
-+ break;
- default:
- UNREACHABLE();
- return gl::Error(GL_INVALID_OPERATION);
- }
-
- std::string profile = FormatString("%s_%u_%u", profileType, profileMajorVersion, profileMinorVersion);
-+ if (profileSuffix)
-+ profile += profileSuffix;
-
- UINT flags = D3DCOMPILE_OPTIMIZATION_LEVEL2;
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-index c789cae..d44bd2f 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h
-@@ -188,6 +188,7 @@ class Renderer11 : public RendererD3D
- ID3D11Device *getDevice() { return mDevice; }
- ID3D11DeviceContext *getDeviceContext() { return mDeviceContext; };
- DXGIFactory *getDxgiFactory() { return mDxgiFactory; };
-+ bool isLevel9() { return mFeatureLevel <= D3D_FEATURE_LEVEL_9_3; }
-
- Blit11 *getBlitter() { return mBlit; }
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
-index 4287918..74af27e 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp
-@@ -744,7 +744,7 @@ gl::Error TextureStorage11_2D::getResource(ID3D11Resource **outResource)
- D3D11_TEXTURE2D_DESC desc;
- desc.Width = mTextureWidth; // Compressed texture size constraints?
- desc.Height = mTextureHeight;
-- desc.MipLevels = mMipLevels;
-+ desc.MipLevels = mRenderer->isLevel9() ? 1 : mMipLevels;
- desc.ArraySize = 1;
- desc.Format = mTextureFormat;
- desc.SampleDesc.Count = 1;
-@@ -863,7 +863,7 @@ gl::Error TextureStorage11_2D::createSRV(int baseLevel, int mipLevels, DXGI_FORM
- srvDesc.Format = format;
- srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
- srvDesc.Texture2D.MostDetailedMip = mTopLevel + baseLevel;
-- srvDesc.Texture2D.MipLevels = mipLevels;
-+ srvDesc.Texture2D.MipLevels = mRenderer->isLevel9() ? -1 : mipLevels;
-
- ID3D11Device *device = mRenderer->getDevice();
- HRESULT result = device->CreateShaderResourceView(texture, &srvDesc, outSRV);
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
-index 1ea916d..90a879e 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp
-@@ -557,7 +557,7 @@ D3D11LoadFunctionMap BuildD3D11LoadFunctionMap()
- InsertLoadFunction(&map, GL_ALPHA, GL_HALF_FLOAT_OES, LoadA16FToRGBA16F );
-
- // From GL_EXT_texture_storage
-- InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadToNative<GLubyte, 1> );
-+ InsertLoadFunction(&map, GL_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadA8ToRGBA8 );
- InsertLoadFunction(&map, GL_LUMINANCE8_EXT, GL_UNSIGNED_BYTE, LoadL8ToRGBA8 );
- InsertLoadFunction(&map, GL_LUMINANCE8_ALPHA8_EXT, GL_UNSIGNED_BYTE, LoadLA8ToRGBA8 );
- InsertLoadFunction(&map, GL_ALPHA32F_EXT, GL_FLOAT, LoadA32FToRGBA32F );
-@@ -795,7 +795,7 @@ static D3D11ES3FormatMap BuildD3D11FormatMap()
-
- // From GL_EXT_texture_storage
- // | GL internal format | D3D11 texture format | D3D11 SRV format | D3D11 RTV format | D3D11 DSV format |
-- InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_A8_UNORM, DXGI_FORMAT_UNKNOWN );
-+ InsertD3D11FormatInfo(&map, GL_ALPHA8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
- InsertD3D11FormatInfo(&map, GL_LUMINANCE8_EXT, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN );
- InsertD3D11FormatInfo(&map, GL_ALPHA32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
- InsertD3D11FormatInfo(&map, GL_LUMINANCE32F_EXT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN );
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index 9ffc32e..cbfe557 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -284,7 +284,7 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
- // From http://msdn.microsoft.com/en-us/library/windows/desktop/ff476876.aspx
- case D3D_FEATURE_LEVEL_9_3:
- case D3D_FEATURE_LEVEL_9_2:
-- case D3D_FEATURE_LEVEL_9_1: return false;
-+ case D3D_FEATURE_LEVEL_9_1: return true; // Provided that mipmaps & wrap modes are not used
-
- default: UNREACHABLE(); return false;
- }
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch b/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch
deleted file mode 100644
index afc9f256a1..0000000000
--- a/src/angle/patches/0012-ANGLE-fix-semantic-index-lookup.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From bbfd3cfcf6e1195d86368b61ce39504ce6acda50 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Wed, 12 Nov 2014 17:09:23 +0200
-Subject: [PATCH 12/16] ANGLE: fix semantic index lookup
-
-The sorted semantic index table was returning a direct mapping to the
-new indices, instead of the old indices. This caused a mismatch in the
-GL type lookup for the translated attribute.
-
-Change-Id: I75d05ed707f56c45210e3dcbc277f894e3dc5a48
----
- src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp | 2 +-
- .../angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
-index 0619023..6d64b38 100644
---- a/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/ProgramBinary.cpp
-@@ -1216,7 +1216,7 @@ void ProgramBinary::sortAttributesByLayout(rx::TranslatedAttribute attributes[MA
- for (int i = 0; i < MAX_VERTEX_ATTRIBS; i++)
- {
- int oldIndex = mAttributesByLayout[i];
-- sortedSemanticIndices[i] = mSemanticIndex[oldIndex];
-+ sortedSemanticIndices[i] = oldIndex;
- attributes[i] = oldTranslatedAttributes[oldIndex];
- }
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
-index e41f238..ff90a6a 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp
-@@ -113,10 +113,10 @@ gl::Error InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl
- // Record the type of the associated vertex shader vector in our key
- // This will prevent mismatched vertex shaders from using the same input layout
- GLint attributeSize;
-- programBinary->getActiveAttribute(ilKey.elementCount, 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
-+ programBinary->getActiveAttribute(sortedSemanticIndices[i], 0, NULL, &attributeSize, &ilKey.elements[ilKey.elementCount].glslElementType, NULL);
-
- ilKey.elements[ilKey.elementCount].desc.SemanticName = semanticName;
-- ilKey.elements[ilKey.elementCount].desc.SemanticIndex = sortedSemanticIndices[i];
-+ ilKey.elements[ilKey.elementCount].desc.SemanticIndex = i;
- ilKey.elements[ilKey.elementCount].desc.Format = vertexFormatInfo.nativeFormat;
- ilKey.elements[ilKey.elementCount].desc.InputSlot = i;
- ilKey.elements[ilKey.elementCount].desc.AlignedByteOffset = 0;
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch b/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch
deleted file mode 100644
index b43dcc368b..0000000000
--- a/src/angle/patches/0013-ANGLE-Add-support-for-querying-platform-device.patch
+++ /dev/null
@@ -1,100 +0,0 @@
-From 5ef9348de2624c21be1c9fddd265fec5a0851d25 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Thu, 13 Nov 2014 15:34:26 +0200
-Subject: [PATCH 13/16] ANGLE: Add support for querying platform device
-
-The EGL_EXT_device_base extension allows for querying the platform
-device of the graphics hardware via eglQueryDisplayAttribEXT().
-As that extension is not supported by ANGLE, this patch adds similar
-functionality to the existing eglQuerySurfacePointerANGLE API. When
-EGL_DEVICE_EXT is passed as the queried attribute, the underlying
-D3D/DXGI device pointer is passed back to the caller via the value
-argument.
-
-The D3D device is needed for video support in QtMultimedia as well as
-the IDXGIDevice3::Trim() calls required by the Windows Store.
-
-Change-Id: Ibdf228d81d6604e56db9dd8597d7cd2983ebc428
----
- src/3rdparty/angle/src/libEGL/libEGL.cpp | 50 +++++++++++++++++++++++++-------
- 1 file changed, 39 insertions(+), 11 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libEGL/libEGL.cpp b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-index dc20d85..68399d6 100644
---- a/src/3rdparty/angle/src/libEGL/libEGL.cpp
-+++ b/src/3rdparty/angle/src/libEGL/libEGL.cpp
-@@ -17,6 +17,9 @@
- #include "libGLESv2/Texture.h"
- #include "libGLESv2/main.h"
- #include "libGLESv2/renderer/SwapChain.h"
-+#if defined(ANGLE_ENABLE_D3D11)
-+# include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
-+#endif
-
- #include "libEGL/main.h"
- #include "libEGL/Display.h"
-@@ -582,25 +585,50 @@ EGLBoolean __stdcall eglQuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surf
- egl::Display *display = static_cast<egl::Display*>(dpy);
- egl::Surface *eglSurface = (egl::Surface*)surface;
-
-- if (!validateSurface(display, eglSurface))
-- {
-- return EGL_FALSE;
-- }
--
-- if (surface == EGL_NO_SURFACE)
-- {
-- recordError(egl::Error(EGL_BAD_SURFACE));
-- return EGL_FALSE;
-- }
--
- switch (attribute)
- {
- case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE:
- {
-+ if (!validateSurface(display, eglSurface))
-+ {
-+ return EGL_FALSE;
-+ }
-+
-+ if (surface == EGL_NO_SURFACE)
-+ {
-+ recordError(egl::Error(EGL_BAD_SURFACE));
-+ return EGL_FALSE;
-+ }
-+
- rx::SwapChain *swapchain = eglSurface->getSwapChain();
- *value = (void*) (swapchain ? swapchain->getShareHandle() : NULL);
- }
- break;
-+#if defined(ANGLE_ENABLE_D3D11)
-+ case EGL_DEVICE_EXT:
-+ {
-+ if (!validateDisplay(display))
-+ {
-+ return EGL_FALSE;
-+ }
-+
-+ rx::Renderer *renderer = display->getRenderer();
-+ if (!renderer)
-+ {
-+ *value = NULL;
-+ break;
-+ }
-+
-+ if (renderer->getMajorShaderModel() < 4)
-+ {
-+ recordError(egl::Error(EGL_BAD_CONTEXT));
-+ return EGL_FALSE;
-+ }
-+
-+ *value = static_cast<rx::Renderer11*>(renderer)->getDevice();
-+ }
-+ break;
-+#endif
- default:
- recordError(egl::Error(EGL_BAD_ATTRIBUTE));
- return EGL_FALSE;
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch b/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
deleted file mode 100644
index 9ceb34d964..0000000000
--- a/src/angle/patches/0014-Let-ANGLE-use-multithreaded-devices-if-necessary.patch
+++ /dev/null
@@ -1,69 +0,0 @@
-From 5b3bc73210ed1847d9bd7a94f06cc0d5de8e0b89 Mon Sep 17 00:00:00 2001
-From: Michael Bruning <michael.bruning@digia.com>
-Date: Thu, 13 Nov 2014 15:40:10 +0200
-Subject: [PATCH 14/16] Let ANGLE use multithreaded devices if necessary.
-
-This is needed to prevent lock-ups in application that use ANGLE from
-multiple threads, as e.g. QtWebEngine based applications do.
-
-The environment variable QT_D3DCREATE_MULTITHREADED is used to
-communicate this from the QtWebEngine module.
-
-Change-Id: Ibd5a5c75eb68af567d420d9a35efb3490c93b27c
----
- src/3rdparty/angle/src/common/platform.h | 1 +
- .../angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 10 ++++++++++
- .../angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 ++++
- 3 files changed, 15 insertions(+)
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 0065ec7..8b2190d 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -57,6 +57,7 @@
-
- # if defined(ANGLE_ENABLE_D3D11)
- # include <d3d10_1.h>
-+# include <d3d10.h>
- # include <d3d11.h>
- # include <d3d11_1.h>
- # include <dxgi.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
-index f6ba930..46b9984 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -258,6 +258,16 @@ EGLint Renderer11::initialize()
- }
-
- #if !defined(ANGLE_ENABLE_WINDOWS_STORE)
-+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
-+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
-+ {
-+ ID3D10Multithread *multithread;
-+ result = mDevice->QueryInterface(IID_PPV_ARGS(&multithread));
-+ ASSERT(SUCCEEDED(result));
-+ result = multithread->SetMultithreadProtected(true);
-+ ASSERT(SUCCEEDED(result));
-+ multithread->Release();
-+ }
- #if !ANGLE_SKIP_DXGI_1_2_CHECK
- // In order to create a swap chain for an HWND owned by another process, DXGI 1.2 is required.
- // The easiest way to check is to query for a IDXGIDevice2.
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 82963ec..4c552b2 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -299,6 +299,10 @@ EGLint Renderer9::initialize()
- D3DPRESENT_PARAMETERS presentParameters = getDefaultPresentParameters();
- DWORD behaviorFlags = D3DCREATE_FPU_PRESERVE | D3DCREATE_NOWINDOWCHANGES;
-
-+ static wchar_t *qt_d3dcreate_multihreaded_var = _wgetenv(L"QT_D3DCREATE_MULTITHREADED");
-+ if (qt_d3dcreate_multihreaded_var && wcsstr(qt_d3dcreate_multihreaded_var, L"1"))
-+ behaviorFlags |= D3DCREATE_MULTITHREADED;
-+
- {
- result = mD3d9->CreateDevice(mAdapter, mDeviceType, mDeviceWindow, behaviorFlags | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE, &presentParameters, &mDevice);
- }
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch b/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
deleted file mode 100644
index f78474f11a..0000000000
--- a/src/angle/patches/0015-ANGLE-Fix-angle-d3d11-on-MSVC2010.patch
+++ /dev/null
@@ -1,536 +0,0 @@
-From d9a9219ea2181dd4c1939d05747a21b67f16a906 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Thu, 13 Nov 2014 16:33:53 +0200
-Subject: [PATCH 15/16] ANGLE: Fix -angle-d3d11 on MSVC2010
-
-Allow the D3D11 renderer to build with the June 2010 DirectX SDK.
-
-Change-Id: I2343acedab16845d6a0d4a53cf3145f583efc4a7
----
- src/3rdparty/angle/src/common/platform.h | 8 +-
- src/3rdparty/angle/src/libGLESv2/Context.cpp | 8 +-
- src/3rdparty/angle/src/libGLESv2/Data.h | 2 +-
- src/3rdparty/angle/src/libGLESv2/State.cpp | 6 +-
- .../src/libGLESv2/renderer/d3d/RendererD3D.cpp | 4 +-
- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 4 +-
- .../renderer/d3d/d3d11/renderer11_utils.cpp | 137 +++++++++++++++++++++
- 7 files changed, 156 insertions(+), 13 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 8b2190d..972eee2 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -52,17 +52,23 @@
-
- # if defined(ANGLE_ENABLE_D3D9)
- # include <d3d9.h>
-+# if !defined(COMPILER_IMPLEMENTATION)
- # include <d3dcompiler.h>
-+# endif
- # endif
-
- # if defined(ANGLE_ENABLE_D3D11)
- # include <d3d10_1.h>
- # include <d3d10.h>
- # include <d3d11.h>
--# include <d3d11_1.h>
- # include <dxgi.h>
-+# if defined(_MSC_VER) && (_MSC_VER >= 1700)
-+# include <d3d11_1.h>
- # include <dxgi1_2.h>
-+# endif
-+# if !defined(COMPILER_IMPLEMENTATION)
- # include <d3dcompiler.h>
-+# endif
- # endif
-
- # if defined(ANGLE_ENABLE_WINDOWS_STORE)
-diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-index fe9b1a2..b87689c 100644
---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-@@ -168,9 +168,9 @@ Context::~Context()
- }
- mIncompleteTextures.clear();
-
-- for (auto &zeroTexture : mZeroTextures)
-+ for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
- {
-- zeroTexture.second.set(NULL);
-+ i->second.set(NULL);
- }
- mZeroTextures.clear();
-
-@@ -354,7 +354,7 @@ void Context::deleteFenceSync(GLsync fenceSync)
-
- void Context::deleteVertexArray(GLuint vertexArray)
- {
-- auto vertexArrayObject = mVertexArrayMap.find(vertexArray);
-+ VertexArrayMap::iterator vertexArrayObject = mVertexArrayMap.find(vertexArray);
-
- if (vertexArrayObject != mVertexArrayMap.end())
- {
-@@ -460,7 +460,7 @@ FenceSync *Context::getFenceSync(GLsync handle) const
-
- VertexArray *Context::getVertexArray(GLuint handle) const
- {
-- auto vertexArray = mVertexArrayMap.find(handle);
-+ VertexArrayMap::const_iterator vertexArray = mVertexArrayMap.find(handle);
-
- if (vertexArray == mVertexArrayMap.end())
- {
-diff --git a/src/3rdparty/angle/src/libGLESv2/Data.h b/src/3rdparty/angle/src/libGLESv2/Data.h
-index cff872a..9234403 100644
---- a/src/3rdparty/angle/src/libGLESv2/Data.h
-+++ b/src/3rdparty/angle/src/libGLESv2/Data.h
-@@ -14,7 +14,7 @@
- namespace gl
- {
-
--struct Data final
-+struct Data
- {
- public:
- Data(GLint clientVersion, const State &state, const Caps &caps,
-diff --git a/src/3rdparty/angle/src/libGLESv2/State.cpp b/src/3rdparty/angle/src/libGLESv2/State.cpp
-index e7acda2..b5b62f5 100644
---- a/src/3rdparty/angle/src/libGLESv2/State.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/State.cpp
-@@ -665,13 +665,13 @@ void State::detachTexture(const TextureMap &zeroTextures, GLuint texture)
-
- void State::initializeZeroTextures(const TextureMap &zeroTextures)
- {
-- for (const auto &zeroTexture : zeroTextures)
-+ for (TextureMap::const_iterator i = zeroTextures.begin(); i != zeroTextures.end(); i++)
- {
-- auto &samplerTextureArray = mSamplerTextures[zeroTexture.first];
-+ TextureBindingVector &samplerTextureArray = mSamplerTextures[i->first];
-
- for (size_t textureUnit = 0; textureUnit < samplerTextureArray.size(); ++textureUnit)
- {
-- samplerTextureArray[textureUnit].set(zeroTexture.second.get());
-+ samplerTextureArray[textureUnit].set(i->second.get());
- }
- }
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-index 6f58243..97da6da 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-@@ -27,9 +27,9 @@ RendererD3D::RendererD3D(egl::Display *display)
-
- RendererD3D::~RendererD3D()
- {
-- for (auto &incompleteTexture : mIncompleteTextures)
-+ for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i)
- {
-- incompleteTexture.second.set(NULL);
-+ i->second.set(NULL);
- }
- mIncompleteTextures.clear();
- }
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index 46b9984..a28fd78 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -873,7 +873,7 @@ bool Renderer11::applyPrimitiveType(GLenum mode, GLsizei count)
-
- void Renderer11::unsetSRVsWithResource(gl::SamplerType samplerType, const ID3D11Resource *resource)
- {
-- auto &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
-+ std::vector<ID3D11ShaderResourceView *> &currentSRVs = (samplerType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
-
- for (size_t resourceIndex = 0; resourceIndex < currentSRVs.size(); ++resourceIndex)
- {
-@@ -3398,7 +3398,7 @@ Workarounds Renderer11::generateWorkarounds() const
-
- void Renderer11::setShaderResource(gl::SamplerType shaderType, UINT resourceSlot, ID3D11ShaderResourceView *srv)
- {
-- auto &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
-+ std::vector<ID3D11ShaderResourceView *> &currentSRVs = (shaderType == gl::SAMPLER_VERTEX ? mCurVertexSRVs : mCurPixelSRVs);
-
- ASSERT(static_cast<size_t>(resourceSlot) < currentSRVs.size());
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index cbfe557..5831c57 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -18,6 +18,85 @@
-
- #include <algorithm>
-
-+#ifndef D3D_FL9_1_DEFAULT_MAX_ANISOTROPY
-+# define D3D_FL9_1_DEFAULT_MAX_ANISOTROPY 2
-+#endif
-+#ifndef D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT
-+# define D3D_FL9_1_SIMULTANEOUS_RENDER_TARGET_COUNT 1
-+#endif
-+#ifndef D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT
-+# define D3D_FL9_3_SIMULTANEOUS_RENDER_TARGET_COUNT 4
-+#endif
-+#ifndef D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT
-+# define D3D_FL9_1_IA_PRIMITIVE_MAX_COUNT 65535
-+#endif
-+#ifndef D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT
-+# define D3D_FL9_2_IA_PRIMITIVE_MAX_COUNT 1048575
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURECUBE_DIMENSION 512
-+#endif
-+#ifndef D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION
-+# define D3D_FL9_3_REQ_TEXTURECUBE_DIMENSION 4096
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURE2D_U_OR_V_DIMENSION 2048
-+#endif
-+#ifndef D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-+# define D3D_FL9_1_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 256
-+#endif
-+#ifndef D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION
-+# define D3D_FL9_3_REQ_TEXTURE2D_U_OR_V_DIMENSION 4096
-+#endif
-+#ifndef D3D11_REQ_TEXTURECUBE_DIMENSION
-+# define D3D11_REQ_TEXTURECUBE_DIMENSION 16384
-+#endif
-+#ifndef D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION
-+# define D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION
-+# define D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION 2048
-+#endif
-+#ifndef D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP
-+# define D3D11_REQ_DRAWINDEXED_INDEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP
-+# define D3D11_REQ_DRAW_VERTEX_COUNT_2_TO_EXP 32
-+#endif
-+#ifndef D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT
-+# define D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D11_STANDARD_VERTEX_ELEMENT_COUNT
-+# define D3D11_STANDARD_VERTEX_ELEMENT_COUNT 32
-+#endif
-+#ifndef D3D10_1_SO_BUFFER_SLOT_COUNT
-+# define D3D10_1_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_SO_BUFFER_SLOT_COUNT
-+# define D3D11_SO_BUFFER_SLOT_COUNT 4
-+#endif
-+#ifndef D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT
-+# define D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT 14
-+#endif
-+#ifndef D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT
-+# define D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT 16
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE
-+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE -8
-+#endif
-+#ifndef D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE
-+# define D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE 7
-+#endif
-+#ifndef D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT
-+# define D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT 4096
-+#endif
-+#ifndef D3D11_PS_INPUT_REGISTER_COUNT
-+# define D3D11_PS_INPUT_REGISTER_COUNT 32
-+#endif
-+#ifndef D3D10_1_VS_OUTPUT_REGISTER_COUNT
-+# define D3D10_1_VS_OUTPUT_REGISTER_COUNT 32
-+#endif
-+
- namespace rx
- {
-
-@@ -276,7 +355,9 @@ static bool GetNPOTTextureSupport(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
-@@ -294,7 +375,9 @@ static float GetMaximumAnisotropy(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_MAX_MAXANISOTROPY;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -314,7 +397,9 @@ static bool GetOcclusionQuerySupport(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return true;
-@@ -334,7 +419,9 @@ static bool GetEventQuerySupport(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
-@@ -352,7 +439,9 @@ static bool GetInstancingSupport(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
-@@ -375,7 +464,9 @@ static bool GetDerivativeInstructionSupport(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0:
-@@ -393,7 +484,9 @@ static size_t GetMaximumSimultaneousRenderTargets(D3D_FEATURE_LEVEL featureLevel
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -411,7 +504,9 @@ static size_t GetMaximum2DTextureSize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_U_OR_V_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -429,7 +524,9 @@ static size_t GetMaximumCubeMapTextureSize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURECUBE_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -447,7 +544,9 @@ static size_t GetMaximum2DTextureArraySize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE2D_ARRAY_AXIS_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -465,7 +564,9 @@ static size_t GetMaximum3DTextureSize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_TEXTURE3D_U_V_OR_W_DIMENSION;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -483,7 +584,9 @@ static size_t GetMaximumViewportSize(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_VIEWPORT_BOUNDS_MAX;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -507,7 +610,9 @@ static size_t GetMaximumDrawIndexedIndexCount(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
-@@ -529,7 +634,9 @@ static size_t GetMaximumDrawVertexCount(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return std::numeric_limits<GLint>::max();
-@@ -546,7 +653,9 @@ static size_t GetMaximumVertexInputSlots(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_STANDARD_VERTEX_ELEMENT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_STANDARD_VERTEX_ELEMENT_COUNT;
-@@ -566,7 +675,9 @@ static size_t GetMaximumVertexUniformVectors(D3D_FEATURE_LEVEL featureLevel)
- // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -591,7 +702,9 @@ static size_t GetMaximumVertexUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedVertexUniformBuffers();
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -618,7 +731,9 @@ static size_t GetMaximumVertexOutputVectors(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
-
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_VS_OUTPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
-@@ -637,7 +752,9 @@ static size_t GetMaximumVertexTextureUnits(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -659,7 +776,9 @@ static size_t GetMaximumPixelUniformVectors(D3D_FEATURE_LEVEL featureLevel)
- // TODO(geofflang): Remove hard-coded limit once the gl-uniform-arrays test can pass
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return 1024; // D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -684,7 +803,9 @@ static size_t GetMaximumPixelUniformBlocks(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT - GetReservedPixelUniformBuffers();
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -703,7 +824,9 @@ static size_t GetMaximumPixelInputVectors(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_PS_INPUT_REGISTER_COUNT - GetReservedVertexOutputVectors();
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -722,7 +845,9 @@ static size_t GetMaximumPixelTextureUnits(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -741,7 +866,9 @@ static int GetMinimumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_NEGATIVE;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -760,7 +887,9 @@ static int GetMaximumTexelOffset(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
- case D3D_FEATURE_LEVEL_10_1:
- case D3D_FEATURE_LEVEL_10_0: return D3D11_COMMONSHADER_TEXEL_OFFSET_MAX_POSITIVE;
-@@ -783,7 +912,9 @@ static size_t GetMaximumConstantBufferSize(D3D_FEATURE_LEVEL featureLevel)
-
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * bytesPerComponent;
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -802,7 +933,9 @@ static size_t GetMaximumStreamOutputBuffers(D3D_FEATURE_LEVEL featureLevel)
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return D3D11_SO_BUFFER_SLOT_COUNT;
-
- case D3D_FEATURE_LEVEL_10_1: return D3D10_1_SO_BUFFER_SLOT_COUNT;
-@@ -820,7 +953,9 @@ static size_t GetMaximumStreamOutputInterleavedComponents(D3D_FEATURE_LEVEL feat
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0:
-
- case D3D_FEATURE_LEVEL_10_1:
-@@ -838,7 +973,9 @@ static size_t GetMaximumStreamOutputSeparateComponents(D3D_FEATURE_LEVEL feature
- {
- switch (featureLevel)
- {
-+#if !defined(_MSC_VER) || (_MSC_VER >= 1800)
- case D3D_FEATURE_LEVEL_11_1:
-+#endif
- case D3D_FEATURE_LEVEL_11_0: return GetMaximumStreamOutputInterleavedComponents(featureLevel) /
- GetMaximumStreamOutputBuffers(featureLevel);
-
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch b/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
deleted file mode 100644
index e3df95d8bf..0000000000
--- a/src/angle/patches/0016-ANGLE-Fix-compilation-with-MinGW-D3D11.patch
+++ /dev/null
@@ -1,169 +0,0 @@
-From 43c8ceb17ccd6d5ae13a07c6d01b45eb40983917 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Tue, 11 Nov 2014 14:36:43 +0200
-Subject: [PATCH 16/16] ANGLE: Fix compilation with MinGW + D3D11
-
-Provide workarounds for things GCC doesn't like, and define a few
-missing definitions not found in the MinGW headers.
-
-Change-Id: I254c208209c0071fae5efb6727f2b3cfd5542da6
----
- src/3rdparty/angle/src/common/platform.h | 73 ++++++++++++++++++++++
- .../src/libGLESv2/renderer/d3d/HLSLCompiler.cpp | 6 ++
- .../libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 2 +-
- .../renderer/d3d/d3d11/renderer11_utils.cpp | 2 +-
- .../src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 4 +-
- 5 files changed, 83 insertions(+), 4 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 972eee2..0001e71 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -81,6 +81,79 @@
- # endif
- # endif
-
-+# if defined(__MINGW32__) // Missing defines on MinGW
-+typedef enum D3D11_MAP_FLAG
-+{
-+ D3D11_MAP_FLAG_DO_NOT_WAIT = 0x100000L
-+} D3D11_MAP_FLAG;
-+typedef struct D3D11_QUERY_DATA_SO_STATISTICS
-+{
-+ UINT64 NumPrimitivesWritten;
-+ UINT64 PrimitivesStorageNeeded;
-+} D3D11_QUERY_DATA_SO_STATISTICS;
-+typedef HRESULT (WINAPI *PFN_D3D11_CREATE_DEVICE)(
-+ IDXGIAdapter *, D3D_DRIVER_TYPE, HMODULE, UINT, CONST D3D_FEATURE_LEVEL *,
-+ UINT FeatureLevels, UINT, ID3D11Device **, D3D_FEATURE_LEVEL *, ID3D11DeviceContext **);
-+#define D3D11_MESSAGE_CATEGORY UINT
-+#define D3D11_MESSAGE_SEVERITY UINT
-+#define D3D11_MESSAGE_ID UINT
-+struct D3D11_MESSAGE;
-+typedef struct D3D11_INFO_QUEUE_FILTER_DESC
-+{
-+ UINT NumCategories;
-+ D3D11_MESSAGE_CATEGORY *pCategoryList;
-+ UINT NumSeverities;
-+ D3D11_MESSAGE_SEVERITY *pSeverityList;
-+ UINT NumIDs;
-+ D3D11_MESSAGE_ID *pIDList;
-+} D3D11_INFO_QUEUE_FILTER_DESC;
-+typedef struct D3D11_INFO_QUEUE_FILTER
-+{
-+ D3D11_INFO_QUEUE_FILTER_DESC AllowList;
-+ D3D11_INFO_QUEUE_FILTER_DESC DenyList;
-+} D3D11_INFO_QUEUE_FILTER;
-+static const IID IID_ID3D11InfoQueue = { 0x6543dbb6, 0x1b48, 0x42f5, 0xab, 0x82, 0xe9, 0x7e, 0xc7, 0x43, 0x26, 0xf6 };
-+MIDL_INTERFACE("6543dbb6-1b48-42f5-ab82-e97ec74326f6") ID3D11InfoQueue : public IUnknown
-+{
-+public:
-+ virtual HRESULT __stdcall SetMessageCountLimit(UINT64) = 0;
-+ virtual void __stdcall ClearStoredMessages() = 0;
-+ virtual HRESULT __stdcall GetMessage(UINT64, D3D11_MESSAGE *, SIZE_T *) = 0;
-+ virtual UINT64 __stdcall GetNumMessagesAllowedByStorageFilter() = 0;
-+ virtual UINT64 __stdcall GetNumMessagesDeniedByStorageFilter() = 0;
-+ virtual UINT64 __stdcall GetNumStoredMessages() = 0;
-+ virtual UINT64 __stdcall GetNumStoredMessagesAllowedByRetrievalFilter() = 0;
-+ virtual UINT64 __stdcall GetNumMessagesDiscardedByMessageCountLimit() = 0;
-+ virtual UINT64 __stdcall GetMessageCountLimit() = 0;
-+ virtual HRESULT __stdcall AddStorageFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
-+ virtual HRESULT __stdcall GetStorageFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
-+ virtual void __stdcall ClearStorageFilter() = 0;
-+ virtual HRESULT __stdcall PushEmptyStorageFilter() = 0;
-+ virtual HRESULT __stdcall PushCopyOfStorageFilter() = 0;
-+ virtual HRESULT __stdcall PushStorageFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
-+ virtual void __stdcall PopStorageFilter() = 0;
-+ virtual UINT __stdcall GetStorageFilterStackSize() = 0;
-+ virtual HRESULT __stdcall AddRetrievalFilterEntries(D3D11_INFO_QUEUE_FILTER *) = 0;
-+ virtual HRESULT __stdcall GetRetrievalFilter(D3D11_INFO_QUEUE_FILTER *, SIZE_T *) = 0;
-+ virtual void __stdcall ClearRetrievalFilter() = 0;
-+ virtual HRESULT __stdcall PushEmptyRetrievalFilter() = 0;
-+ virtual HRESULT __stdcall PushCopyOfRetrievalFilter() = 0;
-+ virtual HRESULT __stdcall PushRetrievalFilter(D3D11_INFO_QUEUE_FILTER *) = 0;
-+ virtual void __stdcall PopRetrievalFilter() = 0;
-+ virtual UINT __stdcall GetRetrievalFilterStackSize() = 0;
-+ virtual HRESULT __stdcall AddMessage(D3D11_MESSAGE_CATEGORY, D3D11_MESSAGE_SEVERITY, D3D11_MESSAGE_ID, LPCSTR) = 0;
-+ virtual HRESULT __stdcall AddApplicationMessage(D3D11_MESSAGE_SEVERITY, LPCSTR) = 0;
-+ virtual HRESULT __stdcall SetBreakOnCategory(D3D11_MESSAGE_CATEGORY, BOOL) = 0;
-+ virtual HRESULT __stdcall SetBreakOnSeverity(D3D11_MESSAGE_SEVERITY, BOOL) = 0;
-+ virtual HRESULT __stdcall SetBreakOnID(D3D11_MESSAGE_ID, BOOL) = 0;
-+ virtual BOOL __stdcall GetBreakOnCategory(D3D11_MESSAGE_CATEGORY) = 0;
-+ virtual BOOL __stdcall GetBreakOnSeverity(D3D11_MESSAGE_SEVERITY) = 0;
-+ virtual BOOL __stdcall GetBreakOnID(D3D11_MESSAGE_ID) = 0;
-+ virtual void __stdcall SetMuteDebugOutput(BOOL) = 0;
-+ virtual BOOL __stdcall GetMuteDebugOutput() = 0;
-+};
-+#endif // __MINGW32__
-+
- # undef near
- # undef far
- #endif
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-index 9d003b4..776d92b 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp
-@@ -14,6 +14,12 @@
- #ifndef QT_D3DCOMPILER_DLL
- #define QT_D3DCOMPILER_DLL D3DCOMPILER_DLL
- #endif
-+#ifndef D3DCOMPILE_RESERVED16
-+#define D3DCOMPILE_RESERVED16 (1 << 16)
-+#endif
-+#ifndef D3DCOMPILE_RESERVED17
-+#define D3DCOMPILE_RESERVED17 (1 << 17)
-+#endif
-
- // Definitions local to the translation unit
- namespace
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index a28fd78..e6d7f30 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -333,7 +333,7 @@ EGLint Renderer11::initialize()
- // Disable some spurious D3D11 debug warnings to prevent them from flooding the output log
- #if defined(ANGLE_SUPPRESS_D3D11_HAZARD_WARNINGS) && defined(_DEBUG)
- ID3D11InfoQueue *infoQueue;
-- result = mDevice->QueryInterface(__uuidof(ID3D11InfoQueue), (void **)&infoQueue);
-+ result = mDevice->QueryInterface(IID_ID3D11InfoQueue, (void **)&infoQueue);
-
- if (SUCCEEDED(result))
- {
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-index 5831c57..121aa3b 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp
-@@ -1196,7 +1196,7 @@ void SetPositionLayerTexCoord3DVertex(PositionLayerTexCoord3DVertex* vertex, flo
-
- HRESULT SetDebugName(ID3D11DeviceChild *resource, const char *name)
- {
--#if defined(_DEBUG)
-+#if defined(_DEBUG) && !defined(__MINGW32__)
- return resource->SetPrivateData(WKPDID_D3DDebugObjectName, strlen(name), name);
- #else
- return S_OK;
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 4c552b2..601cd24 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -200,7 +200,7 @@ EGLint Renderer9::initialize()
- if (ANGLE_D3D9EX == ANGLE_ENABLED && Direct3DCreate9ExPtr && SUCCEEDED(Direct3DCreate9ExPtr(D3D_SDK_VERSION, &mD3d9Ex)))
- {
- ASSERT(mD3d9Ex);
-- mD3d9Ex->QueryInterface(__uuidof(IDirect3D9), reinterpret_cast<void**>(&mD3d9));
-+ mD3d9Ex->QueryInterface(IID_IDirect3D9, reinterpret_cast<void**>(&mD3d9));
- ASSERT(mD3d9);
- }
- else
-@@ -324,7 +324,7 @@ EGLint Renderer9::initialize()
-
- if (mD3d9Ex)
- {
-- result = mDevice->QueryInterface(__uuidof(IDirect3DDevice9Ex), (void**)&mDeviceEx);
-+ result = mDevice->QueryInterface(IID_IDirect3DDevice9Ex, (void**)&mDeviceEx);
- ASSERT(SUCCEEDED(result));
- }
-
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch b/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch
deleted file mode 100644
index 4ada6d41d2..0000000000
--- a/src/angle/patches/0017-ANGLE-Fix-compilation-with-D3D9.patch
+++ /dev/null
@@ -1,62 +0,0 @@
-From d7839cc052de126cc3b457fe41963fd9c7e91846 Mon Sep 17 00:00:00 2001
-From: Kai Koehne <kai.koehne@theqtcompany.com>
-Date: Mon, 17 Nov 2014 15:10:10 +0100
-Subject: [PATCH] ANGLE: Fix compilation with D3D9
-
-Fixes a regression introduced in c6df5fe3ed0f2a722 that
-broke compilation with d3d9 (namely, -target xp).
-
-Task-number: QTBUG-42714
-Change-Id: I1a5e9682d5463bfa082a5d0c062399a131a7cf52
----
- src/3rdparty/angle/src/common/NativeWindow.h | 7 ++++++-
- src/3rdparty/angle/src/common/platform.h | 1 +
- src/3rdparty/angle/src/common/win32/NativeWindow.cpp | 2 +-
- 3 files changed, 8 insertions(+), 2 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/NativeWindow.h b/src/3rdparty/angle/src/common/NativeWindow.h
-index 9e93aea..c4a0e42 100644
---- a/src/3rdparty/angle/src/common/NativeWindow.h
-+++ b/src/3rdparty/angle/src/common/NativeWindow.h
-@@ -54,7 +54,12 @@ public:
- bool getClientRect(LPRECT rect);
- bool isIconic();
-
-- HRESULT createSwapChain(ID3D11Device* device, DXGIFactory* factory,
-+# if defined(ANGLE_ENABLE_D3D11)
-+ typedef ID3D11Device Device;
-+#else
-+ typedef IDirect3DDevice9 Device;
-+#endif
-+ HRESULT createSwapChain(Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, UINT width, UINT height,
- DXGISwapChain** swapChain);
-
-diff --git a/src/3rdparty/angle/src/common/platform.h b/src/3rdparty/angle/src/common/platform.h
-index 0001e71..5bf97f9 100644
---- a/src/3rdparty/angle/src/common/platform.h
-+++ b/src/3rdparty/angle/src/common/platform.h
-@@ -52,6 +52,7 @@
-
- # if defined(ANGLE_ENABLE_D3D9)
- # include <d3d9.h>
-+# include <dxgi.h>
- # if !defined(COMPILER_IMPLEMENTATION)
- # include <d3dcompiler.h>
- # endif
-diff --git a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-index 2440747..46082a2 100644
---- a/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-+++ b/src/3rdparty/angle/src/common/win32/NativeWindow.cpp
-@@ -35,7 +35,7 @@ bool NativeWindow::isIconic()
- return IsIconic(mWindow) == TRUE;
- }
-
--HRESULT NativeWindow::createSwapChain(ID3D11Device* device, DXGIFactory* factory,
-+HRESULT NativeWindow::createSwapChain(NativeWindow::Device* device, DXGIFactory* factory,
- DXGI_FORMAT format, unsigned int width, unsigned int height,
- DXGISwapChain** swapChain)
- {
---
-1.9.4.msysgit.0
-
diff --git a/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch b/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch
deleted file mode 100644
index 97847ad684..0000000000
--- a/src/angle/patches/0018-ANGLE-Fix-releasing-textures-after-we-kill-D3D11.patch
+++ /dev/null
@@ -1,106 +0,0 @@
-From 014d3fcf6011109491b0489da9c1abb1fdc6dbdc Mon Sep 17 00:00:00 2001
-From: Kai Koehne <kai.koehne@theqtcompany.com>
-Date: Mon, 24 Nov 2014 10:52:03 +0100
-Subject: [PATCH] ANGLE: Fix releasing textures after we kill D3D11
-
-Cherry-pick upstream commit cc4cd2925b9a4f1142a86df131345a861c9d7cd9
-to fix crashes on exit.
-
-Task-number: QTBUG-42772
-Change-Id: Ib74be17f2b5fdd58f9e0568e1da74ba19e943019
----
- src/3rdparty/angle/src/libGLESv2/Context.cpp | 6 ------
- src/3rdparty/angle/src/libGLESv2/Context.h | 1 -
- src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp | 5 +++++
- src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h | 2 ++
- src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp | 2 ++
- src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp | 2 ++
- 6 files changed, 11 insertions(+), 7 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/Context.cpp b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-index b87689c..3772da6 100644
---- a/src/3rdparty/angle/src/libGLESv2/Context.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/Context.cpp
-@@ -162,12 +162,6 @@ Context::~Context()
- deleteTransformFeedback(mTransformFeedbackMap.begin()->first);
- }
-
-- for (TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); i++)
-- {
-- i->second.set(NULL);
-- }
-- mIncompleteTextures.clear();
--
- for (TextureMap::iterator i = mZeroTextures.begin(); i != mZeroTextures.end(); i++)
- {
- i->second.set(NULL);
-diff --git a/src/3rdparty/angle/src/libGLESv2/Context.h b/src/3rdparty/angle/src/libGLESv2/Context.h
-index 1e890de..0699592 100644
---- a/src/3rdparty/angle/src/libGLESv2/Context.h
-+++ b/src/3rdparty/angle/src/libGLESv2/Context.h
-@@ -247,7 +247,6 @@ class Context
- int mClientVersion;
-
- TextureMap mZeroTextures;
-- TextureMap mIncompleteTextures;
-
- typedef std::unordered_map<GLuint, Framebuffer*> FramebufferMap;
- FramebufferMap mFramebufferMap;
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-index 97da6da..5cddd8a 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.cpp
-@@ -27,6 +27,11 @@ RendererD3D::RendererD3D(egl::Display *display)
-
- RendererD3D::~RendererD3D()
- {
-+ cleanup();
-+}
-+
-+void RendererD3D::cleanup()
-+{
- for (gl::TextureMap::iterator i = mIncompleteTextures.begin(); i != mIncompleteTextures.end(); ++i)
- {
- i->second.set(NULL);
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
-index 9919207..a2f7787 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/RendererD3D.h
-@@ -160,6 +160,8 @@ class RendererD3D : public Renderer
- const gl::Rectangle *scissor, bool blitRenderTarget,
- bool blitDepth, bool blitStencil, GLenum filter) = 0;
-
-+ void cleanup();
-+
- egl::Display *mDisplay;
-
- private:
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-index e6d7f30..777308e 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp
-@@ -1870,6 +1870,8 @@ bool Renderer11::testDeviceResettable()
-
- void Renderer11::release()
- {
-+ RendererD3D::cleanup();
-+
- releaseShaderCompiler();
- releaseDeviceResources();
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-index 601cd24..18e6e2d 100644
---- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp
-@@ -151,6 +151,8 @@ Renderer9::~Renderer9()
-
- void Renderer9::release()
- {
-+ RendererD3D::cleanup();
-+
- releaseShaderCompiler();
- releaseDeviceResources();
-
---
-1.9.4.msysgit.0
-
diff --git a/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch b/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch
deleted file mode 100644
index 5fa244c1b5..0000000000
--- a/src/angle/patches/0019-ANGLE-Fix-handling-of-shader-source-with-fixed-lengt.patch
+++ /dev/null
@@ -1,37 +0,0 @@
-From 5e277b05a16e7be24d36c600f158f8119ee583d8 Mon Sep 17 00:00:00 2001
-From: Andrew Knight <andrew.knight@theqtcompany.com>
-Date: Mon, 1 Dec 2014 11:58:08 +0200
-Subject: [PATCH] ANGLE: Fix handling of shader source with fixed length
-
-This is a cherry-pick of upstream f60fab6d154f4c9bf599e92976cd8cee7f8633e0
-(See https://chromium-review.googlesource.com/231612)
-
-Task-number: QTBUG-42882
-Change-Id: I7b4bdc4b68a1b93ff514f09ce35dbf4e9360af9b
----
- src/3rdparty/angle/src/libGLESv2/Shader.cpp | 9 ++++++++-
- 1 file changed, 8 insertions(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-index 1cc17a0..5bca746 100644
---- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-@@ -51,7 +51,14 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le
-
- for (int i = 0; i < count; i++)
- {
-- stream << string[i];
-+ if (length == nullptr || length[i] < 0)
-+ {
-+ stream.write(string[i], std::strlen(string[i]));
-+ }
-+ else
-+ {
-+ stream.write(string[i], length[i]);
-+ }
- }
-
- mSource = stream.str();
---
-1.9.4.msysgit.1
-
diff --git a/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch b/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch
deleted file mode 100644
index 324244f6eb..0000000000
--- a/src/angle/patches/0020-ANGLE-Do-not-use-std-strlen.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 071b8936386b0b44475c91511d85479e5c633bc5 Mon Sep 17 00:00:00 2001
-From: Kai Koehne <kai.koehne@theqtcompany.com>
-Date: Thu, 11 Dec 2014 13:54:23 +0100
-Subject: [PATCH] ANGLE: Do not use std::strlen
-
-This is a cherry-pick from upstream change
-
-e7cfb3dd2029c1bfe5c175ad994c03cac221ad4d
-
-Change-Id: Iefe01545319f9ad268c0c6bf8e8b2181e09d8a84
----
- src/3rdparty/angle/src/libGLESv2/Shader.cpp | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/src/3rdparty/angle/src/libGLESv2/Shader.cpp b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-index 5bca746..024ef8f 100644
---- a/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-+++ b/src/3rdparty/angle/src/libGLESv2/Shader.cpp
-@@ -53,7 +53,7 @@ void Shader::setSource(GLsizei count, const char *const *string, const GLint *le
- {
- if (length == nullptr || length[i] < 0)
- {
-- stream.write(string[i], std::strlen(string[i]));
-+ stream.write(string[i], strlen(string[i]));
- }
- else
- {
---
-1.9.4.msysgit.0
-
diff --git a/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch b/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch
deleted file mode 100644
index 49b229d905..0000000000
--- a/src/angle/patches/0020-ANGLE-Fix-compilation-with-MSVC2013-Update4.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-From a48dfb3f1ecb57a59084c0e87155506586b73188 Mon Sep 17 00:00:00 2001
-From: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
-Date: Thu, 11 Dec 2014 13:11:55 +0100
-Subject: [PATCH] [ANGLE] Fix compilation with MSVC2013 Update4
-
-Update4 provides a native Sleep implementation. Hence the wrapper
-needs to be disabled.
-
-Change-Id: I162da45934b02c262ac09b557c66c3363c276e54
----
- src/3rdparty/angle/src/common/utilities.cpp | 2 +-
- src/3rdparty/angle/src/common/utilities.h | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/3rdparty/angle/src/common/utilities.cpp b/src/3rdparty/angle/src/common/utilities.cpp
-index 9d797a6..924573e 100644
---- a/src/3rdparty/angle/src/common/utilities.cpp
-+++ b/src/3rdparty/angle/src/common/utilities.cpp
-@@ -486,7 +486,7 @@ void writeFile(const char* path, const void* content, size_t size)
- }
- #endif // !ANGLE_ENABLE_WINDOWS_STORE
-
--#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
-
- void Sleep(unsigned long dwMilliseconds)
- {
-diff --git a/src/3rdparty/angle/src/common/utilities.h b/src/3rdparty/angle/src/common/utilities.h
-index 2cf6bed..7583d3e 100644
---- a/src/3rdparty/angle/src/common/utilities.h
-+++ b/src/3rdparty/angle/src/common/utilities.h
-@@ -51,7 +51,7 @@ std::string getTempPath();
- void writeFile(const char* path, const void* data, size_t size);
- #endif
-
--#if defined(ANGLE_ENABLE_WINDOWS_STORE)
-+#if defined(ANGLE_ENABLE_WINDOWS_STORE) && _MSC_FULL_VER < 180031101
- void Sleep(_In_ unsigned long dwMilliseconds);
- #endif
-
---
-1.9.4.msysgit.2
-
diff --git a/src/angle/src/common/common.pri b/src/angle/src/common/common.pri
index 7d3f46d65f..63b80347d1 100644
--- a/src/angle/src/common/common.pri
+++ b/src/angle/src/common/common.pri
@@ -46,20 +46,4 @@ win32-msvc2012|win32-msvc2013|winrt {
}
}
-static: DEFINES *= QT_OPENGL_ES_2_ANGLE_STATIC
-
-HEADERS += \
- $$ANGLE_DIR/src/common/angleutils.h \
- $$ANGLE_DIR/src/common/debug.h \
- $$ANGLE_DIR/src/common/mathutil.h \
- $$ANGLE_DIR/src/common/platform.h \
- $$ANGLE_DIR/src/common/RefCountObject.h \
- $$ANGLE_DIR/src/common/tls.h \
- $$ANGLE_DIR/src/common/version.h
-
-SOURCES += \
- $$ANGLE_DIR/src/common/angleutils.cpp \
- $$ANGLE_DIR/src/common/debug.cpp \
- $$ANGLE_DIR/src/common/RefCountObject.cpp \
- $$ANGLE_DIR/src/common/tls.cpp
-
+static: DEFINES *= LIBGLESV2_EXPORT_H_ ANGLE_EXPORT=
diff --git a/src/angle/src/compiler/preprocessor/preprocessor.pro b/src/angle/src/compiler/preprocessor/preprocessor.pro
index 420cb90b36..8c5b1555dc 100644
--- a/src/angle/src/compiler/preprocessor/preprocessor.pro
+++ b/src/angle/src/compiler/preprocessor/preprocessor.pro
@@ -48,7 +48,7 @@ flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
-bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
+bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --output=${QMAKE_FILE_BASE}.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}.cpp
bison.input = BISON_SOURCES
bison.dependency_type = TYPE_C
diff --git a/src/angle/src/compiler/translator.pro b/src/angle/src/compiler/translator.pro
index 6f0128d6de..e9d16ca5af 100644
--- a/src/angle/src/compiler/translator.pro
+++ b/src/angle/src/compiler/translator.pro
@@ -1,14 +1,11 @@
CONFIG += static
include(../config.pri)
-# Mingw 4.7 chokes on implicit move semantics, so disable C++11 here
-mingw: CONFIG -= c++11
-
INCLUDEPATH += \
$$ANGLE_DIR/src \
$$ANGLE_DIR/include
-DEFINES += _SECURE_SCL=0 _LIB COMPILER_IMPLEMENTATION
+DEFINES += _SECURE_SCL=0 _LIB ANGLE_TRANSLATOR_IMPLEMENTATION ANGLE_TRANSLATOR_STATIC ANGLE_ENABLE_HLSL
FLEX_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.l
BISON_SOURCES = $$ANGLE_DIR/src/compiler/translator/glslang.y
@@ -23,26 +20,31 @@ HEADERS += \
$$ANGLE_DIR/src/common/platform.h \
$$ANGLE_DIR/src/common/tls.h \
$$ANGLE_DIR/src/common/utilities.h \
+ $$ANGLE_DIR/src/compiler/translator/blocklayout.h \
+ $$ANGLE_DIR/src/compiler/translator/blocklayoutHLSL.h \
$$ANGLE_DIR/src/compiler/translator/BaseTypes.h \
$$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.h \
+ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorGLSL.h \
+ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorHLSL.h \
$$ANGLE_DIR/src/compiler/translator/Common.h \
- $$ANGLE_DIR/src/compiler/translator/Compiler.h \
$$ANGLE_DIR/src/compiler/translator/compilerdebug.h \
+ $$ANGLE_DIR/src/compiler/translator/Compiler.h \
$$ANGLE_DIR/src/compiler/translator/ConstantUnion.h \
- $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \
$$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphBuilder.h \
+ $$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraph.h \
$$ANGLE_DIR/src/compiler/translator/depgraph/DependencyGraphOutput.h \
$$ANGLE_DIR/src/compiler/translator/DetectCallDepth.h \
$$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.h \
$$ANGLE_DIR/src/compiler/translator/Diagnostics.h \
$$ANGLE_DIR/src/compiler/translator/DirectiveHandler.h \
$$ANGLE_DIR/src/compiler/translator/ExtensionBehavior.h \
+ $$ANGLE_DIR/src/compiler/translator/EmulatePrecision.h \
$$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.h \
$$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.h \
$$ANGLE_DIR/src/compiler/translator/HashNames.h \
$$ANGLE_DIR/src/compiler/translator/InfoSink.h \
- $$ANGLE_DIR/src/compiler/translator/Initialize.h \
$$ANGLE_DIR/src/compiler/translator/InitializeDll.h \
+ $$ANGLE_DIR/src/compiler/translator/Initialize.h \
$$ANGLE_DIR/src/compiler/translator/InitializeParseContext.h \
$$ANGLE_DIR/src/compiler/translator/InitializeVariables.h \
$$ANGLE_DIR/src/compiler/translator/intermediate.h \
@@ -51,21 +53,23 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/translator/MMap.h \
$$ANGLE_DIR/src/compiler/translator/NodeSearch.h \
$$ANGLE_DIR/src/compiler/translator/osinclude.h \
+ $$ANGLE_DIR/src/compiler/translator/Operator.h \
$$ANGLE_DIR/src/compiler/translator/OutputESSL.h \
- $$ANGLE_DIR/src/compiler/translator/OutputGLSL.h \
$$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.h \
+ $$ANGLE_DIR/src/compiler/translator/OutputGLSL.h \
$$ANGLE_DIR/src/compiler/translator/OutputHLSL.h \
$$ANGLE_DIR/src/compiler/translator/ParseContext.h \
$$ANGLE_DIR/src/compiler/translator/PoolAlloc.h \
$$ANGLE_DIR/src/compiler/translator/Pragma.h \
$$ANGLE_DIR/src/compiler/translator/QualifierAlive.h \
$$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.h \
- $$ANGLE_DIR/src/compiler/translator/RemoveTree.h \
+ $$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.h \
$$ANGLE_DIR/src/compiler/translator/RenameFunction.h \
$$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.h \
$$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.h \
$$ANGLE_DIR/src/compiler/translator/SearchSymbol.h \
$$ANGLE_DIR/src/compiler/translator/ShHandle.h \
+ $$ANGLE_DIR/src/compiler/translator/SimplifyArrayAssignment.h \
$$ANGLE_DIR/src/compiler/translator/StructureHLSL.h \
$$ANGLE_DIR/src/compiler/translator/SymbolTable.h \
$$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.h \
@@ -74,13 +78,14 @@ HEADERS += \
$$ANGLE_DIR/src/compiler/translator/TranslatorGLSL.h \
$$ANGLE_DIR/src/compiler/translator/TranslatorHLSL.h \
$$ANGLE_DIR/src/compiler/translator/Types.h \
- $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.h \
$$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuitAST.h \
+ $$ANGLE_DIR/src/compiler/translator/UnfoldShortCircuit.h \
$$ANGLE_DIR/src/compiler/translator/UniformHLSL.h \
- $$ANGLE_DIR/src/compiler/translator/UtilsHLSL.h \
$$ANGLE_DIR/src/compiler/translator/util.h \
+ $$ANGLE_DIR/src/compiler/translator/UtilsHLSL.h \
$$ANGLE_DIR/src/compiler/translator/ValidateLimitations.h \
$$ANGLE_DIR/src/compiler/translator/ValidateOutputs.h \
+ $$ANGLE_DIR/src/compiler/translator/ValidateSwitch.h \
$$ANGLE_DIR/src/compiler/translator/VariableInfo.h \
$$ANGLE_DIR/src/compiler/translator/VariablePacker.h \
$$ANGLE_DIR/src/compiler/translator/VersionGLSL.h \
@@ -89,7 +94,11 @@ HEADERS += \
SOURCES += \
$$ANGLE_DIR/src/common/tls.cpp \
+ $$ANGLE_DIR/src/compiler/translator/blocklayout.cpp \
+ $$ANGLE_DIR/src/compiler/translator/blocklayoutHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulator.cpp \
+ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorGLSL.cpp \
+ $$ANGLE_DIR/src/compiler/translator/BuiltInFunctionEmulatorHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/CodeGen.cpp \
$$ANGLE_DIR/src/compiler/translator/Compiler.cpp \
$$ANGLE_DIR/src/compiler/translator/compilerdebug.cpp \
@@ -101,6 +110,7 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/translator/DetectDiscontinuity.cpp \
$$ANGLE_DIR/src/compiler/translator/Diagnostics.cpp \
$$ANGLE_DIR/src/compiler/translator/DirectiveHandler.cpp \
+ $$ANGLE_DIR/src/compiler/translator/EmulatePrecision.cpp \
$$ANGLE_DIR/src/compiler/translator/FlagStd140Structs.cpp \
$$ANGLE_DIR/src/compiler/translator/ForLoopUnroll.cpp \
$$ANGLE_DIR/src/compiler/translator/InfoSink.cpp \
@@ -113,6 +123,7 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/translator/intermOut.cpp \
$$ANGLE_DIR/src/compiler/translator/IntermTraverse.cpp \
$$ANGLE_DIR/src/compiler/translator/LoopInfo.cpp \
+ $$ANGLE_DIR/src/compiler/translator/Operator.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputESSL.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputGLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/OutputGLSLBase.cpp \
@@ -122,12 +133,13 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/translator/PoolAlloc.cpp \
$$ANGLE_DIR/src/compiler/translator/QualifierAlive.cpp \
$$ANGLE_DIR/src/compiler/translator/RegenerateStructNames.cpp \
- $$ANGLE_DIR/src/compiler/translator/RemoveTree.cpp \
+ $$ANGLE_DIR/src/compiler/translator/RemoveSwitchFallThrough.cpp \
$$ANGLE_DIR/src/compiler/translator/RewriteElseBlocks.cpp \
$$ANGLE_DIR/src/compiler/translator/ScalarizeVecAndMatConstructorArgs.cpp \
$$ANGLE_DIR/src/compiler/translator/SearchSymbol.cpp \
$$ANGLE_DIR/src/compiler/translator/ShaderLang.cpp \
$$ANGLE_DIR/src/compiler/translator/ShaderVars.cpp \
+ $$ANGLE_DIR/src/compiler/translator/SimplifyArrayAssignment.cpp \
$$ANGLE_DIR/src/compiler/translator/StructureHLSL.cpp \
$$ANGLE_DIR/src/compiler/translator/SymbolTable.cpp \
$$ANGLE_DIR/src/compiler/translator/timing/RestrictFragmentShaderTiming.cpp \
@@ -143,6 +155,7 @@ SOURCES += \
$$ANGLE_DIR/src/compiler/translator/util.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateLimitations.cpp \
$$ANGLE_DIR/src/compiler/translator/ValidateOutputs.cpp \
+ $$ANGLE_DIR/src/compiler/translator/ValidateSwitch.cpp \
$$ANGLE_DIR/src/compiler/translator/VariableInfo.cpp \
$$ANGLE_DIR/src/compiler/translator/VariablePacker.cpp \
$$ANGLE_DIR/src/compiler/translator/VersionGLSL.cpp \
@@ -157,7 +170,7 @@ flex.dependency_type = TYPE_C
flex.variable_out = GENERATED_SOURCES
QMAKE_EXTRA_COMPILERS += flex
-bison.commands = $$addGnuPath(bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
+bison.commands = $$addGnuPath(win_bison) --no-lines --skeleton=yacc.c --defines=${QMAKE_FILE_BASE}_tab.h \
--output=${QMAKE_FILE_BASE}_tab.cpp ${QMAKE_FILE_NAME}
bison.output = ${QMAKE_FILE_BASE}_tab.h
bison.input = BISON_SOURCES
diff --git a/src/angle/src/config.pri b/src/angle/src/config.pri
index 9a7bc8a68c..0d75245ec5 100644
--- a/src/angle/src/config.pri
+++ b/src/angle/src/config.pri
@@ -37,8 +37,6 @@ DEFINES += _WINDOWS \
NOMINMAX \
WIN32_LEAN_AND_MEAN=1
-!winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK
-
CONFIG += angle_d3d11 # Remove to disable D3D11 renderer
equals(QMAKE_TARGET_OS, xp): CONFIG -= angle_d3d11
@@ -70,11 +68,12 @@ msvc {
# 4245: 'conversion' : conversion from 'type1' to 'type2', signed/unsigned mismatch
# 4267: coversion from 'size_t' to 'int', possible loss of data
# 4275: non - DLL-interface classkey 'identifier' used as base for DLL-interface classkey 'identifier'
+ # 4480: nonstandard extension used: specifying underlying type for enum
# 4512: 'class' : assignment operator could not be generated
# 4702: unreachable code
# 4996: Function call with parameters that may be unsafe
QMAKE_CFLAGS_WARN_ON -= -W3
- QMAKE_CFLAGS_WARN_ON += -W4 -wd"4100" -wd"4127" -wd"4189" -wd"4239" -wd"4244" -wd"4245" -wd"4267" -wd"4275" -wd"4512" -wd"4702" -wd"4996"
+ QMAKE_CFLAGS_WARN_ON += -W4 -wd"4100" -wd"4127" -wd"4189" -wd"4239" -wd"4244" -wd"4245" -wd"4267" -wd"4275" -wd"4512" -wd"4702" -wd"4996" -wd"4480"
# Optimizations
# /Oy: Omits frame pointer (x86 only).
# /Gy: Enables function-level linking.
diff --git a/src/angle/src/libEGL/libEGL.pro b/src/angle/src/libEGL/libEGL.pro
index a16249309f..94fcebda6b 100644
--- a/src/angle/src/libEGL/libEGL.pro
+++ b/src/angle/src/libEGL/libEGL.pro
@@ -5,40 +5,13 @@ winrt: LIBS_PRIVATE += -ld3d11
LIBS_PRIVATE += -ldxguid -L$$QT_BUILD_TREE/lib -l$$qtLibraryTarget(libGLESv2)
+DEFINES += GL_APICALL= GL_GLEXT_PROTOTYPES= EGLAPI= LIBEGL_IMPLEMENTATION
+
HEADERS += \
- $$ANGLE_DIR/src/common/NativeWindow.h \
- $$ANGLE_DIR/src/libEGL/AttributeMap.h \
- $$ANGLE_DIR/src/libEGL/Config.h \
- $$ANGLE_DIR/src/libEGL/Display.h \
- $$ANGLE_DIR/src/libEGL/Error.h \
- $$ANGLE_DIR/src/libEGL/main.h \
- $$ANGLE_DIR/src/libEGL/resource.h \
- $$ANGLE_DIR/src/libEGL/ShaderCache.h \
- $$ANGLE_DIR/src/libEGL/Surface.h
+ $$ANGLE_DIR/src/libEGL/resource.h
SOURCES += \
- $$ANGLE_DIR/src/libEGL/AttributeMap.cpp \
- $$ANGLE_DIR/src/libEGL/Config.cpp \
- $$ANGLE_DIR/src/libEGL/Display.cpp \
- $$ANGLE_DIR/src/libEGL/Error.cpp \
- $$ANGLE_DIR/src/libEGL/libEGL.cpp \
- $$ANGLE_DIR/src/libEGL/main.cpp \
- $$ANGLE_DIR/src/libEGL/Surface.cpp
-
-!winrt {
- SOURCES += \
- $$ANGLE_DIR/src/common/win32/NativeWindow.cpp
-} else {
- HEADERS += \
- $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \
- $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \
- $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h
-
- SOURCES += \
- $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \
- $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \
- $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp
-}
+ $$ANGLE_DIR/src/libEGL/libEGL.cpp
!static {
DEF_FILE = $$ANGLE_DIR/src/libEGL/$${TARGET}.def
diff --git a/src/angle/src/libGLESv2/libGLESv2.pro b/src/angle/src/libGLESv2/libGLESv2.pro
index 705768d17d..1bf9af0436 100644
--- a/src/angle/src/libGLESv2/libGLESv2.pro
+++ b/src/angle/src/libGLESv2/libGLESv2.pro
@@ -1,7 +1,7 @@
CONFIG += simd installed
include(../common/common.pri)
-INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libGLESv2
+INCLUDEPATH += $$OUT_PWD/.. $$ANGLE_DIR/src/libANGLE
# Remember to adapt tools/configure/configureapp.cpp if the Direct X version changes.
!winrt: \
@@ -20,237 +20,310 @@ for(libname, STATICLIBS) {
PRE_TARGETDEPS += $$staticlib
}
+DEFINES += LIBANGLE_IMPLEMENTATION LIBGLESV2_IMPLEMENTATION GL_APICALL= GL_GLEXT_PROTOTYPES= EGLAPI=
+!winrt: DEFINES += ANGLE_ENABLE_D3D9 ANGLE_SKIP_DXGI_1_2_CHECK
+
HEADERS += \
$$ANGLE_DIR/src/common/blocklayout.h \
+ $$ANGLE_DIR/src/common/NativeWindow.h \
$$ANGLE_DIR/src/common/shadervars.h \
$$ANGLE_DIR/src/common/utilities.h \
- $$ANGLE_DIR/src/common/NativeWindow.h \
- $$ANGLE_DIR/src/libGLESv2/angletypes.h \
- $$ANGLE_DIR/src/libGLESv2/BinaryStream.h \
- $$ANGLE_DIR/src/libGLESv2/Buffer.h \
- $$ANGLE_DIR/src/libGLESv2/Caps.h \
- $$ANGLE_DIR/src/libGLESv2/Context.h \
- $$ANGLE_DIR/src/libGLESv2/Data.h \
- $$ANGLE_DIR/src/libGLESv2/Error.h \
- $$ANGLE_DIR/src/libGLESv2/Fence.h \
- $$ANGLE_DIR/src/libGLESv2/formatutils.h \
- $$ANGLE_DIR/src/libGLESv2/Framebuffer.h \
- $$ANGLE_DIR/src/libGLESv2/FramebufferAttachment.h \
- $$ANGLE_DIR/src/libGLESv2/HandleAllocator.h \
- $$ANGLE_DIR/src/libGLESv2/ImageIndex.h \
- $$ANGLE_DIR/src/libGLESv2/main.h \
- $$ANGLE_DIR/src/libGLESv2/Program.h \
- $$ANGLE_DIR/src/libGLESv2/ProgramBinary.h \
- $$ANGLE_DIR/src/libGLESv2/Query.h \
- $$ANGLE_DIR/src/libGLESv2/queryconversions.h \
- $$ANGLE_DIR/src/libGLESv2/Renderbuffer.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/BufferImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/copyvertex.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ImageD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexBuffer.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexArrayImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexBuffer.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/vertexconversion.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexDataManager.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/FenceImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/generatemip.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/Image.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/imageformats.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/IndexCacheRange.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/QueryImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/ShaderExecutable.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/ShaderImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/SwapChain.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/TextureImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/TextureFeedbackImpl.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/VertexDeclarationCache.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/Workarounds.h \
+ $$ANGLE_DIR/src/common/MemoryBuffer.h \
+ $$ANGLE_DIR/src/common/angleutils.h \
+ $$ANGLE_DIR/src/common/debug.h \
+ $$ANGLE_DIR/src/common/event_tracer.h \
+ $$ANGLE_DIR/src/libANGLE/angletypes.h \
+ $$ANGLE_DIR/src/libANGLE/AttributeMap.h \
+ $$ANGLE_DIR/src/libANGLE/BinaryStream.h \
+ $$ANGLE_DIR/src/libANGLE/Buffer.h \
+ $$ANGLE_DIR/src/libANGLE/Caps.h \
+ $$ANGLE_DIR/src/libANGLE/Compiler.h \
+ $$ANGLE_DIR/src/libANGLE/Config.h \
+ $$ANGLE_DIR/src/libANGLE/Constants.h \
+ $$ANGLE_DIR/src/libANGLE/Context.h \
+ $$ANGLE_DIR/src/libANGLE/Data.h \
+ $$ANGLE_DIR/src/libANGLE/Display.h \
+ $$ANGLE_DIR/src/libANGLE/Error.h \
+ $$ANGLE_DIR/src/libANGLE/features.h \
+ $$ANGLE_DIR/src/libANGLE/Fence.h \
+ $$ANGLE_DIR/src/libANGLE/formatutils.h \
+ $$ANGLE_DIR/src/libANGLE/Framebuffer.h \
+ $$ANGLE_DIR/src/libANGLE/FramebufferAttachment.h \
+ $$ANGLE_DIR/src/libANGLE/HandleAllocator.h \
+ $$ANGLE_DIR/src/libANGLE/ImageIndex.h \
+ $$ANGLE_DIR/src/libANGLE/Program.h \
+ $$ANGLE_DIR/src/libANGLE/Query.h \
+ $$ANGLE_DIR/src/libANGLE/queryconversions.h \
+ $$ANGLE_DIR/src/libANGLE/RefCountObject.h \
+ $$ANGLE_DIR/src/libANGLE/Renderbuffer.h \
+ $$ANGLE_DIR/src/libANGLE/ResourceManager.h \
+ $$ANGLE_DIR/src/libANGLE/Sampler.h \
+ $$ANGLE_DIR/src/libANGLE/Shader.h \
+ $$ANGLE_DIR/src/libANGLE/State.h \
+ $$ANGLE_DIR/src/libANGLE/Surface.h \
+ $$ANGLE_DIR/src/libANGLE/Texture.h \
+ $$ANGLE_DIR/src/libANGLE/TransformFeedback.h \
+ $$ANGLE_DIR/src/libANGLE/Uniform.h \
+ $$ANGLE_DIR/src/libANGLE/validationEGL.h \
+ $$ANGLE_DIR/src/libANGLE/validationES.h \
+ $$ANGLE_DIR/src/libANGLE/validationES2.h \
+ $$ANGLE_DIR/src/libANGLE/validationES3.h \
+ $$ANGLE_DIR/src/libANGLE/VertexArray.h \
+ $$ANGLE_DIR/src/libANGLE/VertexAttribute.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/generatemip.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/imageformats.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderTargetD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderExecutableD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/SurfaceD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/SwapChainD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureStorage.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/BufferImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/CompilerImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/FenceNVImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/FenceSyncImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/FramebufferImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/Image.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/ImplFactory.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/IndexRangeCache.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/ProgramImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/QueryImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/RenderbufferImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/Renderer.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/ShaderImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/TextureImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/TransformFeedbackImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/VertexArrayImpl.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/Workarounds.h \
+ $$ANGLE_DIR/src/libANGLE/resource.h \
+ $$ANGLE_DIR/src/libANGLE/ResourceManager.h \
+ $$ANGLE_DIR/src/libANGLE/Sampler.h \
+ $$ANGLE_DIR/src/libANGLE/Shader.h \
+ $$ANGLE_DIR/src/libANGLE/State.h \
+ $$ANGLE_DIR/src/libANGLE/Texture.h \
+ $$ANGLE_DIR/src/libANGLE/TransformFeedback.h \
+ $$ANGLE_DIR/src/libANGLE/Uniform.h \
+ $$ANGLE_DIR/src/libANGLE/validationES2.h \
+ $$ANGLE_DIR/src/libANGLE/validationES3.h \
+ $$ANGLE_DIR/src/libANGLE/validationES.h \
+ $$ANGLE_DIR/src/libANGLE/VertexArray.h \
+ $$ANGLE_DIR/src/libANGLE/VertexAttribute.h \
+ $$ANGLE_DIR/src/libANGLE/vertexconversion.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_egl.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.h \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.h \
+ $$ANGLE_DIR/src/libGLESv2/global_state.h \
$$ANGLE_DIR/src/libGLESv2/resource.h \
- $$ANGLE_DIR/src/libGLESv2/ResourceManager.h \
- $$ANGLE_DIR/src/libGLESv2/Sampler.h \
- $$ANGLE_DIR/src/libGLESv2/Shader.h \
- $$ANGLE_DIR/src/libGLESv2/State.h \
- $$ANGLE_DIR/src/libGLESv2/Texture.h \
- $$ANGLE_DIR/src/libGLESv2/TransformFeedback.h \
- $$ANGLE_DIR/src/libGLESv2/Uniform.h \
- $$ANGLE_DIR/src/libGLESv2/validationES.h \
- $$ANGLE_DIR/src/libGLESv2/validationES2.h \
- $$ANGLE_DIR/src/libGLESv2/validationES3.h \
- $$ANGLE_DIR/src/libGLESv2/VertexArray.h \
- $$ANGLE_DIR/src/libGLESv2/VertexAttribute.h \
- $$ANGLE_DIR/src/libGLESv2/vertexconversion.h \
- $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.h \
+ $$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.h
SOURCES += \
- $$ANGLE_DIR/src/common/blocklayout.cpp \
$$ANGLE_DIR/src/common/mathutil.cpp \
$$ANGLE_DIR/src/common/utilities.cpp \
+ $$ANGLE_DIR/src/common/MemoryBuffer.cpp \
+ $$ANGLE_DIR/src/common/angleutils.cpp \
+ $$ANGLE_DIR/src/common/debug.cpp \
+ $$ANGLE_DIR/src/common/event_tracer.cpp \
$$ANGLE_DIR/src/third_party/murmurhash/MurmurHash3.cpp \
- $$ANGLE_DIR/src/libGLESv2/angletypes.cpp \
- $$ANGLE_DIR/src/libGLESv2/Buffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/Caps.cpp \
- $$ANGLE_DIR/src/libGLESv2/Context.cpp \
- $$ANGLE_DIR/src/libGLESv2/Data.cpp \
- $$ANGLE_DIR/src/libGLESv2/Error.cpp \
- $$ANGLE_DIR/src/libGLESv2/Fence.cpp \
- $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp \
- $$ANGLE_DIR/src/libGLESv2/Framebuffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/FramebufferAttachment.cpp \
- $$ANGLE_DIR/src/libGLESv2/formatutils.cpp \
- $$ANGLE_DIR/src/libGLESv2/HandleAllocator.cpp \
- $$ANGLE_DIR/src/libGLESv2/ImageIndex.cpp \
- $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp \
- $$ANGLE_DIR/src/libGLESv2/main.cpp \
- $$ANGLE_DIR/src/libGLESv2/Program.cpp \
- $$ANGLE_DIR/src/libGLESv2/ProgramBinary.cpp \
- $$ANGLE_DIR/src/libGLESv2/Query.cpp \
- $$ANGLE_DIR/src/libGLESv2/queryconversions.cpp \
- $$ANGLE_DIR/src/libGLESv2/Renderbuffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/ResourceManager.cpp \
- $$ANGLE_DIR/src/libGLESv2/Sampler.cpp \
- $$ANGLE_DIR/src/libGLESv2/Shader.cpp \
- $$ANGLE_DIR/src/libGLESv2/State.cpp \
- $$ANGLE_DIR/src/libGLESv2/Texture.cpp \
- $$ANGLE_DIR/src/libGLESv2/TransformFeedback.cpp \
- $$ANGLE_DIR/src/libGLESv2/Uniform.cpp \
- $$ANGLE_DIR/src/libGLESv2/validationES.cpp \
- $$ANGLE_DIR/src/libGLESv2/validationES2.cpp \
- $$ANGLE_DIR/src/libGLESv2/validationES3.cpp \
- $$ANGLE_DIR/src/libGLESv2/VertexArray.cpp \
- $$ANGLE_DIR/src/libGLESv2/VertexAttribute.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/copyimage.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/loadimage.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/Image.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/IndexRangeCache.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/ProgramImpl.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/RenderbufferImpl.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/Renderer.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/RenderTarget.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/BufferD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/DynamicHLSL.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/HLSLCompiler.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ImageD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexBuffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/IndexDataManager.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/MemoryBuffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ProgramD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RenderbufferD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/RendererD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/ShaderD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TextureStorage.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/TransformFeedbackD3D.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexBuffer.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/VertexDataManager.cpp
+ $$ANGLE_DIR/src/libANGLE/angletypes.cpp \
+ $$ANGLE_DIR/src/libANGLE/AttributeMap.cpp \
+ $$ANGLE_DIR/src/libANGLE/Buffer.cpp \
+ $$ANGLE_DIR/src/libANGLE/Caps.cpp \
+ $$ANGLE_DIR/src/libANGLE/Compiler.cpp \
+ $$ANGLE_DIR/src/libANGLE/Config.cpp \
+ $$ANGLE_DIR/src/libANGLE/Context.cpp \
+ $$ANGLE_DIR/src/libANGLE/Data.cpp \
+ $$ANGLE_DIR/src/libANGLE/Display.cpp \
+ $$ANGLE_DIR/src/libANGLE/Error.cpp \
+ $$ANGLE_DIR/src/libANGLE/Fence.cpp \
+ $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.cpp \
+ $$ANGLE_DIR/src/libANGLE/formatutils.cpp \
+ $$ANGLE_DIR/src/libANGLE/Framebuffer.cpp \
+ $$ANGLE_DIR/src/libANGLE/FramebufferAttachment.cpp \
+ $$ANGLE_DIR/src/libANGLE/HandleAllocator.cpp \
+ $$ANGLE_DIR/src/libANGLE/ImageIndex.cpp \
+ $$ANGLE_DIR/src/libANGLE/Platform.cpp \
+ $$ANGLE_DIR/src/libANGLE/Program.cpp \
+ $$ANGLE_DIR/src/libANGLE/Query.cpp \
+ $$ANGLE_DIR/src/libANGLE/queryconversions.cpp \
+ $$ANGLE_DIR/src/libANGLE/RefCountObject.cpp \
+ $$ANGLE_DIR/src/libANGLE/Renderbuffer.cpp \
+ $$ANGLE_DIR/src/libANGLE/ResourceManager.cpp \
+ $$ANGLE_DIR/src/libANGLE/Sampler.cpp \
+ $$ANGLE_DIR/src/libANGLE/Shader.cpp \
+ $$ANGLE_DIR/src/libANGLE/State.cpp \
+ $$ANGLE_DIR/src/libANGLE/Surface.cpp \
+ $$ANGLE_DIR/src/libANGLE/Texture.cpp \
+ $$ANGLE_DIR/src/libANGLE/TransformFeedback.cpp \
+ $$ANGLE_DIR/src/libANGLE/Uniform.cpp \
+ $$ANGLE_DIR/src/libANGLE/validationEGL.cpp \
+ $$ANGLE_DIR/src/libANGLE/validationES.cpp \
+ $$ANGLE_DIR/src/libANGLE/validationES2.cpp \
+ $$ANGLE_DIR/src/libANGLE/validationES3.cpp \
+ $$ANGLE_DIR/src/libANGLE/VertexArray.cpp \
+ $$ANGLE_DIR/src/libANGLE/VertexAttribute.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/DisplayImpl.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/IndexRangeCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/ProgramImpl.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/RenderbufferImpl.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/Renderer.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/SurfaceImpl.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/BufferD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/CompilerD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/copyimage.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/DisplayD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/DynamicHLSL.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/formatutilsD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/FramebufferD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/HLSLCompiler.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ImageD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexBuffer.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/IndexDataManager.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimage.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/loadimageSSE2.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ProgramD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderbufferD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RendererD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/RenderTargetD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/ShaderExecutableD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/SurfaceD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TextureStorage.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/TransformFeedbackD3D.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexBuffer.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/VertexDataManager.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_egl.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_egl_ext.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_2_0_ext.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0.cpp \
+ $$ANGLE_DIR/src/libGLESv2/entry_points_gles_3_0_ext.cpp \
+ $$ANGLE_DIR/src/libGLESv2/global_state.cpp \
+ $$ANGLE_DIR/src/libGLESv2/libGLESv2.cpp
+
angle_d3d11 {
HEADERS += \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Blit11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Buffer11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Clear11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Fence11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/formatutils11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Image11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Query11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Renderer11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.h
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Buffer11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Clear11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Fence11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/formatutils11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.h
SOURCES += \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Blit11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Buffer11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Clear11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Fence11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/formatutils11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Image11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/IndexBuffer11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/InputLayoutCache.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/PixelTransfer11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Query11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/Renderer11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/renderer11_utils.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderTarget11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/RenderStateCache.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/ShaderExecutable11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/SwapChain11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/TextureStorage11.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/VertexBuffer11.cpp
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Blit11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Buffer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Clear11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/DebugAnnotator11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Fence11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Framebuffer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/formatutils11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Image11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/IndexBuffer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/InputLayoutCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/PixelTransfer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Query11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderTarget11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/RenderStateCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/ShaderExecutable11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/SwapChain11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/Trim11.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/VertexBuffer11.cpp
}
-SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp
-
!winrt {
HEADERS += \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/formatutils9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Image9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Query9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Renderer9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.h \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Blit9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Buffer9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Fence9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/formatutils9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Image9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Query9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Renderer9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/SwapChain9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.h \
$$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.h
SOURCES += \
- $$ANGLE_DIR/src/common/win32/NativeWindow.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Blit9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Buffer9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Fence9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/formatutils9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Image9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/IndexBuffer9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Query9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/Renderer9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/renderer9_utils.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/RenderTarget9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/ShaderExecutable9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/SwapChain9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/TextureStorage9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexBuffer9.cpp \
- $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/VertexDeclarationCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Blit9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Buffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/DebugAnnotator9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Fence9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Framebuffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/formatutils9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Image9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/IndexBuffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Query9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/renderer9_utils.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/RenderTarget9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/ShaderExecutable9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/SwapChain9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/TextureStorage9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexBuffer9.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/VertexDeclarationCache.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/win32/NativeWindow.cpp \
$$ANGLE_DIR/src/third_party/systeminfo/SystemInfo.cpp
} else {
HEADERS += \
- $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.h \
- $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.h \
- $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.h
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.h \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.h
SOURCES += \
- $$ANGLE_DIR/src/common/winrt/CoreWindowNativeWindow.cpp \
- $$ANGLE_DIR/src/common/winrt/InspectableNativeWindow.cpp \
- $$ANGLE_DIR/src/common/winrt/SwapChainPanelNativeWindow.cpp
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/CoreWindowNativeWindow.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/InspectableNativeWindow.cpp \
+ $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/winrt/SwapChainPanelNativeWindow.cpp
}
!static {
@@ -259,87 +332,234 @@ SSE2_SOURCES += $$ANGLE_DIR/src/libGLESv2/renderer/loadimageSSE2.cpp
}
float_converter.target = float_converter
-float_converter.commands = python $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.py \
- > $$ANGLE_DIR/src/libGLESv2/Float16ToFloat32.cpp
+float_converter.commands = python $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.py \
+ > $$ANGLE_DIR/src/libANGLE/Float16ToFloat32.cpp
QMAKE_EXTRA_TARGETS += float_converter
-# Generate the shader header files.
-SHADER9_INPUT_DIR = $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d9/shaders
-SHADER11_INPUT_DIR = $$ANGLE_DIR/src/libGLESv2/renderer/d3d/d3d11/shaders
+# HLSL shaders
+BLITVS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.vs
+standardvs.input = BLITVS
+standardvs.type = vs_2_0
+standardvs.output = standardvs.h
+flipyvs.input = BLITVS
+flipyvs.type = vs_2_0
+flipyvs.output = flipyvs.h
+
+BLITPS = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d9/shaders/Blit.ps
+passthroughps.input = BLITPS
+passthroughps.type = ps_2_0
+passthroughps.output = passthroughps.h
+luminanceps.input = BLITPS
+luminanceps.type = ps_2_0
+luminanceps.output = luminanceps.h
+componentmaskps.input = BLITPS
+componentmaskps.type = ps_2_0
+componentmaskps.output = componentmaskps.h
-BLITPS_INPUT = $$SHADER9_INPUT_DIR/Blit.ps
-BLITPS.shaders = PS_passthrough PS_luminance PS_componentmask
-BLITPS.profile = 2_0
+PASSTHROUGH2D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough2D11.hlsl
+VS_Passthrough2D.input = PASSTHROUGH2D
+VS_Passthrough2D.type = vs_4_0_level_9_3
+VS_Passthrough2D.output = passthrough2d11vs.h
+PS_PassthroughRGBA2D.input = PASSTHROUGH2D
+PS_PassthroughRGBA2D.type = ps_4_0_level_9_3
+PS_PassthroughRGBA2D.output = passthroughrgba2d11ps.h
+PS_PassthroughRGB2D.input = PASSTHROUGH2D
+PS_PassthroughRGB2D.type = ps_4_0_level_9_3
+PS_PassthroughRGB2D.output = passthroughrgb2d11ps.h
+PS_PassthroughRG2D.input = PASSTHROUGH2D
+PS_PassthroughRG2D.type = ps_4_0_level_9_3
+PS_PassthroughRG2D.output = passthroughrg2d11ps.h
+PS_PassthroughR2D.input = PASSTHROUGH2D
+PS_PassthroughR2D.type = ps_4_0_level_9_3
+PS_PassthroughR2D.output = passthroughr2d11ps.h
+PS_PassthroughLum2D.input = PASSTHROUGH2D
+PS_PassthroughLum2D.type = ps_4_0_level_9_3
+PS_PassthroughLum2D.output = passthroughlum2d11ps.h
+PS_PassthroughLumAlpha2D.input = PASSTHROUGH2D
+PS_PassthroughLumAlpha2D.type = ps_4_0_level_9_3
+PS_PassthroughLumAlpha2D.output = passthroughlumalpha2d11ps.h
+PS_PassthroughDepth2D.input = PASSTHROUGH2D
+PS_PassthroughDepth2D.type = ps_4_0
+PS_PassthroughDepth2D.output = passthroughdepth2d11ps.h
+PS_PassthroughRGBA2DUI.input = PASSTHROUGH2D
+PS_PassthroughRGBA2DUI.type = ps_4_0
+PS_PassthroughRGBA2DUI.output = passthroughrgba2dui11ps.h
+PS_PassthroughRGBA2DI.input = PASSTHROUGH2D
+PS_PassthroughRGBA2DI.type = ps_4_0
+PS_PassthroughRGBA2DI.output = passthroughrgba2di11ps.h
+PS_PassthroughRGB2DUI.input = PASSTHROUGH2D
+PS_PassthroughRGB2DUI.type = ps_4_0
+PS_PassthroughRGB2DUI.output = passthroughrgb2dui11ps.h
+PS_PassthroughRGB2DI.input = PASSTHROUGH2D
+PS_PassthroughRGB2DI.type = ps_4_0
+PS_PassthroughRGB2DI.output = passthroughrgb2di11ps.h
+PS_PassthroughRG2DUI.input = PASSTHROUGH2D
+PS_PassthroughRG2DUI.type = ps_4_0
+PS_PassthroughRG2DUI.output = passthroughrg2dui11ps.h
+PS_PassthroughRG2DI.input = PASSTHROUGH2D
+PS_PassthroughRG2DI.type = ps_4_0
+PS_PassthroughRG2DI.output = passthroughrg2di11ps.h
+PS_PassthroughR2DUI.input = PASSTHROUGH2D
+PS_PassthroughR2DUI.type = ps_4_0
+PS_PassthroughR2DUI.output = passthroughr2dui11ps.h
+PS_PassthroughR2DI.input = PASSTHROUGH2D
+PS_PassthroughR2DI.type = ps_4_0
+PS_PassthroughR2DI.output = passthroughr2di11ps.h
-BLITVS_INPUT = $$SHADER9_INPUT_DIR/Blit.vs
-BLITVS.shaders = VS_standard VS_flipy
-BLITVS.profile = 2_0
+CLEAR = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Clear11.hlsl
+VS_ClearFloat.input = CLEAR
+VS_ClearFloat.type = vs_4_0_level_9_3
+VS_ClearFloat.output = clearfloat11vs.h
+PS_ClearFloat_FL9.input = CLEAR
+PS_ClearFloat_FL9.type = ps_4_0_level_9_3
+PS_ClearFloat_FL9.output = clearfloat11_fl9ps.h
+PS_ClearFloat.input = CLEAR
+PS_ClearFloat.type = ps_4_0
+PS_ClearFloat.output = clearfloat11ps.h
+VS_ClearUint.input = CLEAR
+VS_ClearUint.type = vs_4_0
+VS_ClearUint.output = clearuint11vs.h
+PS_ClearUint.input = CLEAR
+PS_ClearUint.type = ps_4_0
+PS_ClearUint.output = clearuint11ps.h
+VS_ClearSint.input = CLEAR
+VS_ClearSint.type = vs_4_0
+VS_ClearSint.output = clearsint11vs.h
+PS_ClearSint.input = CLEAR
+PS_ClearSint.type = ps_4_0
+PS_ClearSint.output = clearsint11ps.h
-BUFFERTOTEXTURE_INPUT = $$SHADER11_INPUT_DIR/BufferToTexture11.hlsl
-BUFFERTOTEXTURE.shaders = \
- PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI \
- VS_BufferToTexture GS_BufferToTexture
-BUFFERTOTEXTURE.profile = 4_0
+PASSTHROUGH3D = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Passthrough3D11.hlsl
+VS_Passthrough3D.input = PASSTHROUGH3D
+VS_Passthrough3D.type = vs_4_0
+VS_Passthrough3D.output = passthrough3d11vs.h
+GS_Passthrough3D.input = PASSTHROUGH3D
+GS_Passthrough3D.type = gs_4_0
+GS_Passthrough3D.output = passthrough3d11gs.h
+PS_PassthroughRGBA3D.input = PASSTHROUGH3D
+PS_PassthroughRGBA3D.type = ps_4_0
+PS_PassthroughRGBA3D.output = passthroughrgba3d11ps.h
+PS_PassthroughRGBA3DUI.input = PASSTHROUGH3D
+PS_PassthroughRGBA3DUI.type = ps_4_0
+PS_PassthroughRGBA3DUI.output = passthroughrgba3dui11ps.h
+PS_PassthroughRGBA3DI.input = PASSTHROUGH3D
+PS_PassthroughRGBA3DI.type = ps_4_0
+PS_PassthroughRGBA3DI.output = passthroughrgba3di11ps.h
+PS_PassthroughRGB3D.input = PASSTHROUGH3D
+PS_PassthroughRGB3D.type = ps_4_0
+PS_PassthroughRGB3D.output = passthroughrgb3d11ps.h
+PS_PassthroughRGB3DUI.input = PASSTHROUGH3D
+PS_PassthroughRGB3DUI.type = ps_4_0
+PS_PassthroughRGB3DUI.output = passthroughrgb3dui11ps.h
+PS_PassthroughRGB3DI.input = PASSTHROUGH3D
+PS_PassthroughRGB3DI.type = ps_4_0
+PS_PassthroughRGB3DI.output = passthroughrgb3di11ps.h
+PS_PassthroughRG3D.input = PASSTHROUGH3D
+PS_PassthroughRG3D.type = ps_4_0
+PS_PassthroughRG3D.output = passthroughrg3d11ps.h
+PS_PassthroughRG3DUI.input = PASSTHROUGH3D
+PS_PassthroughRG3DUI.type = ps_4_0
+PS_PassthroughRG3DUI.output = passthroughrg3dui11ps.h
+PS_PassthroughRG3DI.input = PASSTHROUGH3D
+PS_PassthroughRG3DI.type = ps_4_0
+PS_PassthroughRG3DI.output = passthroughrg3di11ps.h
+PS_PassthroughR3D.input = PASSTHROUGH3D
+PS_PassthroughR3D.type = ps_4_0
+PS_PassthroughR3D.output = passthroughr3d11ps.h
+PS_PassthroughR3DUI.input = PASSTHROUGH3D
+PS_PassthroughR3DUI.type = ps_4_0
+PS_PassthroughR3DUI.output = passthroughr3dui11ps.h
+PS_PassthroughR3DI.input = PASSTHROUGH3D
+PS_PassthroughR3DI.type = ps_4_0
+PS_PassthroughR3DI.output = passthroughr3di11ps.h
+PS_PassthroughLum3D.input = PASSTHROUGH3D
+PS_PassthroughLum3D.type = ps_4_0
+PS_PassthroughLum3D.output = passthroughlum3d11ps.h
+PS_PassthroughLumAlpha3D.input = PASSTHROUGH3D
+PS_PassthroughLumAlpha3D.type = ps_4_0
+PS_PassthroughLumAlpha3D.output = passthroughlumalpha3d11ps.h
-CLEAR_INPUT = $$SHADER11_INPUT_DIR/Clear11.hlsl
-CLEAR.shaders = \
- PS_ClearUint PS_ClearSint \
- VS_ClearUint VS_ClearSint
-CLEAR.shaders_compat = PS_ClearFloat VS_ClearFloat
-CLEAR.profile = 4_0
+SWIZZLE = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/Swizzle11.hlsl
+PS_SwizzleF2D.input = SWIZZLE
+PS_SwizzleF2D.type = ps_4_0
+PS_SwizzleF2D.output = swizzlef2dps.h
+PS_SwizzleI2D.input = SWIZZLE
+PS_SwizzleI2D.type = ps_4_0
+PS_SwizzleI2D.output = swizzlei2dps.h
+PS_SwizzleUI2D.input = SWIZZLE
+PS_SwizzleUI2D.type = ps_4_0
+PS_SwizzleUI2D.output = swizzleui2dps.h
+PS_SwizzleF3D.input = SWIZZLE
+PS_SwizzleF3D.type = ps_4_0
+PS_SwizzleF3D.output = swizzlef3dps.h
+PS_SwizzleI3D.input = SWIZZLE
+PS_SwizzleI3D.type = ps_4_0
+PS_SwizzleI3D.output = swizzlei3dps.h
+PS_SwizzleUI3D.input = SWIZZLE
+PS_SwizzleUI3D.type = ps_4_0
+PS_SwizzleUI3D.output = swizzleui3dps.h
+PS_SwizzleF2DArray.input = SWIZZLE
+PS_SwizzleF2DArray.type = ps_4_0
+PS_SwizzleF2DArray.output = swizzlef2darrayps.h
+PS_SwizzleI2DArray.input = SWIZZLE
+PS_SwizzleI2DArray.type = ps_4_0
+PS_SwizzleI2DArray.output = swizzlei2darrayps.h
+PS_SwizzleUI2DArray.input = SWIZZLE
+PS_SwizzleUI2DArray.type = ps_4_0
+PS_SwizzleUI2DArray.output = swizzleui2darrayps.h
-PASSTHROUGH2D_INPUT = $$SHADER11_INPUT_DIR/Passthrough2D11.hlsl
-PASSTHROUGH2D.shaders = \
- PS_PassthroughRGBA2DUI PS_PassthroughRGBA2DI \
- PS_PassthroughRGB2DUI PS_PassthroughRGB2DI \
- PS_PassthroughRG2DUI PS_PassthroughRG2DI \
- PS_PassthroughR2DUI PS_PassthroughR2DI \
- PS_PassthroughDepth2D
-PASSTHROUGH2D.shaders_compat = \
- PS_PassthroughRGBA2D PS_PassthroughRGB2D \
- PS_PassthroughRG2D PS_PassthroughR2D \
- PS_PassthroughLum2D PS_PassthroughLumAlpha2D \
- VS_Passthrough2D
-PASSTHROUGH2D.profile = 4_0
+BUFFERTOTEXTURE = $$ANGLE_DIR/src/libANGLE/renderer/d3d/d3d11/shaders/BufferToTexture11.hlsl
+VS_BufferToTexture.input = BUFFERTOTEXTURE
+VS_BufferToTexture.type = vs_4_0
+VS_BufferToTexture.output = buffertotexture11_vs.h
+GS_BufferToTexture.input = BUFFERTOTEXTURE
+GS_BufferToTexture.type = gs_4_0
+GS_BufferToTexture.output = buffertotexture11_gs.h
+PS_BufferToTexture_4F.input = BUFFERTOTEXTURE
+PS_BufferToTexture_4F.type = ps_4_0
+PS_BufferToTexture_4F.output = buffertotexture11_ps_4f.h
+PS_BufferToTexture_4I.input = BUFFERTOTEXTURE
+PS_BufferToTexture_4I.type = ps_4_0
+PS_BufferToTexture_4I.output = buffertotexture11_ps_4i.h
+PS_BufferToTexture_4UI.input = BUFFERTOTEXTURE
+PS_BufferToTexture_4UI.type = ps_4_0
+PS_BufferToTexture_4UI.output = buffertotexture11_ps_4ui.h
-PASSTHROUGH3D_INPUT = $$SHADER11_INPUT_DIR/Passthrough3D11.hlsl
-PASSTHROUGH3D.shaders = \
+# D3D11
+angle_d3d11: SHADERS = VS_Passthrough2D \
+ PS_PassthroughRGB2D PS_PassthroughRGB2DUI PS_PassthroughRGB2DI \
+ PS_PassthroughRGBA2D PS_PassthroughRGBA2DUI PS_PassthroughRGBA2DI \
+ PS_PassthroughRG2D PS_PassthroughRG2DUI PS_PassthroughRG2DI \
+ PS_PassthroughR2D PS_PassthroughR2DUI PS_PassthroughR2DI \
+ PS_PassthroughLum2D PS_PassthroughLumAlpha2D PS_PassthroughDepth2D \
+ VS_ClearFloat VS_ClearUint VS_ClearSint \
+ PS_ClearFloat PS_ClearFloat_FL9 PS_ClearUint PS_ClearSint \
+ VS_Passthrough3D GS_Passthrough3D \
PS_PassthroughRGBA3D PS_PassthroughRGBA3DUI PS_PassthroughRGBA3DI \
PS_PassthroughRGB3D PS_PassthroughRGB3DUI PS_PassthroughRGB3DI \
PS_PassthroughRG3D PS_PassthroughRG3DUI PS_PassthroughRG3DI \
PS_PassthroughR3D PS_PassthroughR3DUI PS_PassthroughR3DI \
PS_PassthroughLum3D PS_PassthroughLumAlpha3D \
- VS_Passthrough3D GS_Passthrough3D
-PASSTHROUGH3D.profile = 4_0
-
-SWIZZLE_INPUT = $$SHADER11_INPUT_DIR/Swizzle11.hlsl
-SWIZZLE.shaders = \
- PS_SwizzleI2D PS_SwizzleUI2D \
+ PS_SwizzleF2D PS_SwizzleI2D PS_SwizzleUI2D \
PS_SwizzleF3D PS_SwizzleI3D PS_SwizzleUI3D \
- PS_SwizzleF2DArray PS_SwizzleI2DArray PS_SwizzleUI2DArray
-SWIZZLE.shaders_compat = PS_SwizzleF2D
-SWIZZLE.profile = 4_0
+ PS_SwizzleF2DArray PS_SwizzleI2DArray PS_SwizzleUI2DArray \
+ VS_BufferToTexture GS_BufferToTexture \
+ PS_BufferToTexture_4F PS_BufferToTexture_4I PS_BufferToTexture_4UI
-angle_d3d11: FXC_JOBS = BUFFERTOTEXTURE CLEAR PASSTHROUGH2D PASSTHROUGH3D SWIZZLE
-!winrt: FXC_JOBS += BLITPS BLITVS
+# D3D9
+!winrt: SHADERS += standardvs flipyvs passthroughps luminanceps componentmaskps
-for (JOB, FXC_JOBS) {
- INPUT = $${JOB}_INPUT
- OUT_DIR = $$OUT_PWD/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libGLESv2)/compiled
- SHADERS_COMPAT = $$eval($${JOB}.shaders_compat)
- SHADERS = $$eval($${JOB}.shaders) $$SHADERS_COMPAT
- for(SHADER, SHADERS) {
- TYPE = $$lower($$section(SHADER, _, 0, 0))
- PROFILE = $${TYPE}_$$eval($${JOB}.profile)
- contains(SHADERS_COMPAT, $$SHADER): PROFILE = $${PROFILE}_level_9_1
- fxc_$${SHADER}_$${PROFILE}.commands = $$FXC /nologo /E $${SHADER} /T $${PROFILE} /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
- fxc_$${SHADER}_$${PROFILE}.output = $$OUT_DIR/$$section(SHADER, _, 1)$${TYPE}.h
- fxc_$${SHADER}_$${PROFILE}.input = $$INPUT
- fxc_$${SHADER}_$${PROFILE}.dependency_type = TYPE_C
- fxc_$${SHADER}_$${PROFILE}.variable_out = HEADERS
- fxc_$${SHADER}_$${PROFILE}.CONFIG += target_predeps
- QMAKE_EXTRA_COMPILERS += fxc_$${SHADER}_$${PROFILE}
- }
+# Generate headers
+for (SHADER, SHADERS) {
+ INPUT = $$eval($${SHADER}.input)
+ OUT_DIR = $$OUT_PWD/libANGLE/$$relative_path($$dirname($$INPUT), $$ANGLE_DIR/src/libANGLE)/compiled
+ fxc_$${SHADER}.commands = $$FXC /nologo /E $${SHADER} /T $$eval($${SHADER}.type) /Fh ${QMAKE_FILE_OUT} ${QMAKE_FILE_NAME}
+ fxc_$${SHADER}.output = $$OUT_DIR/$$eval($${SHADER}.output)
+ fxc_$${SHADER}.input = $$INPUT
+ fxc_$${SHADER}.dependency_type = TYPE_C
+ fxc_$${SHADER}.variable_out = HEADERS
+ fxc_$${SHADER}.CONFIG += target_predeps
+ QMAKE_EXTRA_COMPILERS += fxc_$${SHADER}
}
khr_headers.files = $$ANGLE_DIR/include/KHR/khrplatform.h
diff --git a/src/corelib/codecs/qiconvcodec.cpp b/src/corelib/codecs/qiconvcodec.cpp
index bf4e8f26f3..5a1ba51f65 100644
--- a/src/corelib/codecs/qiconvcodec.cpp
+++ b/src/corelib/codecs/qiconvcodec.cpp
@@ -323,6 +323,8 @@ static bool setByteOrder(iconv_t cd)
if (iconv(cd, inBytesPtr, &inBytesLeft, &outBytes, &outBytesLeft) == (size_t) -1) {
return false;
}
+#else
+ Q_UNUSED(cd);
#endif // NO_BOM
return true;
diff --git a/src/corelib/doc/src/resource-system.qdoc b/src/corelib/doc/src/resource-system.qdoc
index d1509346c0..cbb2d4efb3 100644
--- a/src/corelib/doc/src/resource-system.qdoc
+++ b/src/corelib/doc/src/resource-system.qdoc
@@ -136,7 +136,7 @@
\image resources.png Building resources into an application
Currently, Qt always stores the data directly in the executable,
- even on Windows and Mac OS X, where the operating system provides
+ even on Windows, OS X, and iOS, where the operating system provides
native support for resources. This might change in a future Qt
release.
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 33a24a3866..f8a8a436be 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -921,7 +921,7 @@
# endif // Q_OS_QNX
# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \
&& ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
-// Mac OS X: Apple has not updated libstdc++ since 2007, which means it does not have
+// Apple has not updated libstdc++ since 2007, which means it does not have
// <initializer_list> or std::move. Let's disable these features
# undef Q_COMPILER_INITIALIZER_LISTS
# undef Q_COMPILER_RVALUE_REFS
@@ -937,7 +937,7 @@
# endif
# endif
# if defined(Q_COMPILER_THREADSAFE_STATICS) && defined(Q_OS_MAC)
-// Mac OS X: Apple's low-level implementation of the C++ support library
+// Apple's low-level implementation of the C++ support library
// (libc++abi.dylib, shared between libstdc++ and libc++) has deadlocks. The
// C++11 standard requires the deadlocks to be removed, so this will eventually
// be fixed; for now, let's disable this.
diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h
index c766b4d1c3..32b2a26992 100644
--- a/src/corelib/global/qnamespace.h
+++ b/src/corelib/global/qnamespace.h
@@ -492,6 +492,7 @@ public:
AA_UseOpenGLES = 16,
AA_UseSoftwareOpenGL = 17,
AA_ShareOpenGLContexts = 18,
+ AA_SetPalette = 19,
// Add new attributes before this line
AA_AttributeCount
diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc
index daf55cfd3a..6340dfeb65 100644
--- a/src/corelib/global/qnamespace.qdoc
+++ b/src/corelib/global/qnamespace.qdoc
@@ -111,7 +111,7 @@
shown in any menus unless specifically set by the
QAction::iconVisibleInMenu property.
Menus that are currently open or menus already created in the native
- Mac OS X menubar \e{may not} pick up a change in this attribute. Changes
+ OS X menubar \e{may not} pick up a change in this attribute. Changes
in the QAction::iconVisibleInMenu property will always be picked up.
\value AA_NativeWindows Ensures that widgets have native windows.
@@ -129,9 +129,9 @@
\value AA_DontUseNativeMenuBar All menubars created while this attribute is
set to true won't be used as a native menubar (e.g, the menubar at
- the top of the main screen on Mac OS X or at the bottom in Windows CE).
+ the top of the main screen on OS X or at the bottom in Windows CE).
- \value AA_MacDontSwapCtrlAndMeta On Mac OS X by default, Qt swaps the
+ \value AA_MacDontSwapCtrlAndMeta On OS X by default, Qt swaps the
Control and Meta (Command) keys (i.e., whenever Control is pressed, Qt
sends Meta, and whenever Meta is pressed Control is sent). When this
attribute is true, Qt will not do the flip. \l QKeySequence::StandardKey
@@ -194,6 +194,9 @@
instances that belong to different top-level windows. This value has
been added in Qt 5.4.
+ \value AA_SetPalette Indicates whether a palette was explicitly set on the
+ QApplication/QGuiApplication. This value has been added in Qt 5.5.
+
The following values are obsolete:
\value AA_ImmediateWidgetCreation This attribute is no longer fully
@@ -294,7 +297,7 @@
\omitvalue KeyboardModifierMask
- \note On Mac OS X, the \c ControlModifier value corresponds to
+ \note On OS X, the \c ControlModifier value corresponds to
the Command keys on the Macintosh keyboard, and the \c MetaModifier value
corresponds to the Control keys. The \c KeypadModifier value will also be set
when an arrow key is pressed as the arrow keys are considered part of the
@@ -312,7 +315,7 @@
This enum provides shorter names for the keyboard modifier keys
supported by Qt.
- \note On Mac OS X, the \c CTRL value corresponds to
+ \note On OS X, the \c CTRL value corresponds to
the Command keys on the Macintosh keyboard, and the \c META value
corresponds to the Control keys.
@@ -913,34 +916,34 @@
\value WA_MacOpaqueSizeGrip Indicates that the native Carbon size grip
should be opaque instead of transparent (the default). This attribute
- is only applicable to Mac OS X and is set by the widget's author.
+ is only applicable to OS X and is set by the widget's author.
\value WA_MacShowFocusRect Indicates that this widget should get a
QFocusFrame around it. Some widgets draw their own focus halo
regardless of this attribute. Not that the QWidget::focusPolicy
also plays the main role in whether something is given focus or
not, this only controls whether or not this gets the focus
- frame. This attribute is only applicable to Mac OS X.
+ frame. This attribute is only applicable to OS X.
\value WA_MacNormalSize Indicates the widget should have the
- normal size for widgets in Mac OS X. This attribute is only
- applicable to Mac OS X.
+ normal size for widgets in OS X. This attribute is only
+ applicable to OS X.
\value WA_MacSmallSize Indicates the widget should have the small
- size for widgets in Mac OS X. This attribute is only applicable to
- Mac OS X.
+ size for widgets in OS X. This attribute is only applicable to
+ OS X.
\value WA_MacMiniSize Indicates the widget should have the mini
- size for widgets in Mac OS X. This attribute is only applicable to
- Mac OS X.
+ size for widgets in OS X. This attribute is only applicable to
+ OS X.
\value WA_MacVariableSize Indicates the widget can choose between
alternative sizes for widgets to avoid clipping.
- This attribute is only applicable to Mac OS X.
+ This attribute is only applicable to OS X.
\value WA_MacBrushedMetal Indicates the widget should be drawn in
the brushed metal style as supported by the windowing system. This
- attribute is only applicable to Mac OS X.
+ attribute is only applicable to OS X.
\omitvalue WA_MacMetalStyle
@@ -1090,14 +1093,14 @@
\b Warning: This flag must \e never be set or cleared by the widget's author.
\value WA_WindowModified Indicates that the window is marked as modified.
- On some platforms this flag will do nothing, on others (including Mac OS X
+ On some platforms this flag will do nothing, on others (including OS X
and Windows) the window will take a modified appearance. This flag is set
or cleared by QWidget::setWindowModified().
\value WA_WindowPropagation Makes a toplevel window inherit font and
palette from its parent.
- \value WA_MacAlwaysShowToolWindow On Mac OS X, show the tool window even
+ \value WA_MacAlwaysShowToolWindow On OS X, show the tool window even
when the application is not active. By default, all tool windows are
hidden when the application is inactive.
@@ -1280,8 +1283,8 @@
\value Key_PageUp
\value Key_PageDown
\value Key_Shift
- \value Key_Control On Mac OS X, this corresponds to the Command keys.
- \value Key_Meta On Mac OS X, this corresponds to the Control keys.
+ \value Key_Control On OS X, this corresponds to the Command keys.
+ \value Key_Meta On OS X, this corresponds to the Control keys.
On Windows keyboards, this key is mapped to the
Windows key.
\value Key_Alt
@@ -1919,7 +1922,7 @@
\value TabFocus the widget accepts focus by tabbing.
\value ClickFocus the widget accepts focus by clicking.
\value StrongFocus the widget accepts focus by both tabbing
- and clicking. On Mac OS X this will also
+ and clicking. On OS X this will also
be indicate that the widget accepts tab focus
when in 'Text/List focus mode'.
\value WheelFocus like Qt::StrongFocus plus the widget accepts
@@ -2025,7 +2028,7 @@
system supports it, a tool window can be decorated
with a somewhat lighter frame. It can also be
combined with Qt::FramelessWindowHint.
- On Mac OS X, tool windows correspond to the
+ On OS X, tool windows correspond to the
\l{http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_concept/chapter_2_section_2.html}{Floating}
class of windows. This means that the window lives on a
level above normal windows; it impossible to put a normal
@@ -2114,10 +2117,10 @@
\value WindowContextHelpButtonHint Adds a context help button to dialogs.
On some platforms this implies Qt::WindowSystemMenuHint for it to work.
- \value MacWindowToolBarButtonHint On Mac OS X adds a tool bar button (i.e.,
+ \value MacWindowToolBarButtonHint On OS X adds a tool bar button (i.e.,
the oblong button that is on the top right of windows that have toolbars).
- \value WindowFullscreenButtonHint On Mac OS X adds a fullscreen button.
+ \value WindowFullscreenButtonHint On OS X adds a fullscreen button.
\value BypassGraphicsProxyWidget Prevents the window and its children from
automatically embedding themselves into a QGraphicsProxyWidget if the
@@ -2141,7 +2144,7 @@
that support _NET_WM_STATE_BELOW atom. If a window always
on the bottom has a parent, the parent will also be left on
the bottom. This window hint is currently not implemented
- for Mac OS X.
+ for OS X.
\value WindowOkButtonHint Adds an OK button to the window decoration of a dialog.
Only supported for Windows CE.
@@ -2985,7 +2988,7 @@
\value CoarseTimer Coarse timers try to keep accuracy within 5% of the desired interval
\value VeryCoarseTimer Very coarse timers only keep full second accuracy
- On UNIX (including Linux and Mac OS X), Qt will keep millisecond accuracy
+ On UNIX (including Linux, OS X, and iOS), Qt will keep millisecond accuracy
for Qt::PreciseTimer. For Qt::CoarseTimer, the interval will be adjusted up
to 5% to align the timer with other timers that are expected to fire at or
around the same time. The objective is to make most timers wake up at the
diff --git a/src/corelib/io/qabstractfileengine.cpp b/src/corelib/io/qabstractfileengine.cpp
index 45e81a6cdc..07270eb790 100644
--- a/src/corelib/io/qabstractfileengine.cpp
+++ b/src/corelib/io/qabstractfileengine.cpp
@@ -299,7 +299,7 @@ QAbstractFileEngine *QAbstractFileEngine::create(const QString &fileName)
the file system (i.e. not a file or directory).
\value FileType The file is a regular file to the file system
(i.e. not a link or directory)
- \value BundleType The file is a Mac OS X bundle implies DirectoryType
+ \value BundleType OS X and iOS: the file is a bundle; implies DirectoryType
\value DirectoryType The file is a directory in the file system
(i.e. not a link or file).
diff --git a/src/corelib/io/qdir.cpp b/src/corelib/io/qdir.cpp
index 7fa53bd850..3a9ae2ee6d 100644
--- a/src/corelib/io/qdir.cpp
+++ b/src/corelib/io/qdir.cpp
@@ -219,7 +219,7 @@ bool QDirSortItemComparator::operator()(const QDirSortItem &n1, const QDirSortIt
if ((qt_cmp_si_sort_flags & QDir::DirsLast) && (f1->item.isDir() != f2->item.isDir()))
return !f1->item.isDir();
- int r = 0;
+ qint64 r = 0;
int sortBy = (qt_cmp_si_sort_flags & QDir::SortByMask)
| (qt_cmp_si_sort_flags & QDir::Type);
@@ -1818,8 +1818,8 @@ QFileInfoList QDir::drives()
}
/*!
- Returns the native directory separator: "/" under Unix (including
- Mac OS X) and "\\" under Windows.
+ Returns the native directory separator: "/" under Unix
+ and "\\" under Windows.
You do not need to use this function to build file paths. If you
always use "/", Qt will translate your paths to conform to the
diff --git a/src/corelib/io/qfile.cpp b/src/corelib/io/qfile.cpp
index 5cc1e82e75..ce1684a943 100644
--- a/src/corelib/io/qfile.cpp
+++ b/src/corelib/io/qfile.cpp
@@ -199,9 +199,9 @@ QAbstractFileEngine *QFilePrivate::engine() const
\section1 Platform Specific Issues
- File permissions are handled differently on Linux/Mac OS X and
+ File permissions are handled differently on Unix-like systems and
Windows. In a non \l{QIODevice::isWritable()}{writable}
- directory on Linux, files cannot be created. This is not always
+ directory on Unix-like systems, files cannot be created. This is not always
the case on Windows, where, for instance, the 'My Documents'
directory usually is not writable, but it is still possible to
create files in it.
diff --git a/src/corelib/io/qfileinfo.cpp b/src/corelib/io/qfileinfo.cpp
index bf83464eab..8a86ec5858 100644
--- a/src/corelib/io/qfileinfo.cpp
+++ b/src/corelib/io/qfileinfo.cpp
@@ -234,7 +234,7 @@ QDateTime &QFileInfoPrivate::getFileTime(QAbstractFileEngine::FileTime request)
isSymLink(). The symLinkTarget() function provides the name of the file
the symlink points to.
- On Unix (including Mac OS X), the symlink has the same size() has
+ On Unix (including OS X and iOS), the symlink has the same size() has
the file it points to, because Unix handles symlinks
transparently; similarly, opening a symlink using QFile
effectively opens the link's target. For example:
@@ -753,7 +753,7 @@ QString QFileInfo::fileName() const
\since 4.3
Returns the name of the bundle.
- On Mac OS X this returns the proper localized name for a bundle if the
+ On OS X and iOS this returns the proper localized name for a bundle if the
path isBundle(). On all other platforms an empty QString is returned.
Example:
@@ -1029,7 +1029,7 @@ bool QFileInfo::isDir() const
/*!
\since 4.3
Returns \c true if this object points to a bundle or to a symbolic
- link to a bundle on Mac OS X; otherwise returns \c false.
+ link to a bundle on OS X and iOS; otherwise returns \c false.
\sa isDir(), isSymLink(), isFile()
*/
@@ -1050,7 +1050,7 @@ bool QFileInfo::isBundle() const
Returns \c true if this object points to a symbolic link (or to a
shortcut on Windows); otherwise returns \c false.
- On Unix (including Mac OS X), opening a symlink effectively opens
+ On Unix (including OS X and iOS), opening a symlink effectively opens
the \l{symLinkTarget()}{link's target}. On Windows, it opens the \c
.lnk file itself.
diff --git a/src/corelib/io/qfilesystemengine.cpp b/src/corelib/io/qfilesystemengine.cpp
index 4817266a31..df41457a18 100644
--- a/src/corelib/io/qfilesystemengine.cpp
+++ b/src/corelib/io/qfilesystemengine.cpp
@@ -323,7 +323,7 @@ void QFileSystemMetaData::fillFromDirEnt(const QT_DIRENT &entry)
}
}
#elif defined(_DIRENT_HAVE_D_TYPE) || defined(Q_OS_BSD4)
- // BSD4 includes Mac OS X
+ // BSD4 includes OS X and iOS
// ### This will clear all entry flags and knownFlagsMask
switch (entry.d_type)
diff --git a/src/corelib/io/qfilesystemengine_unix.cpp b/src/corelib/io/qfilesystemengine_unix.cpp
index 44a270d1fd..c4fb709ddf 100644
--- a/src/corelib/io/qfilesystemengine_unix.cpp
+++ b/src/corelib/io/qfilesystemengine_unix.cpp
@@ -432,7 +432,7 @@ bool QFileSystemEngine::fillMetaData(const QFileSystemEntry &entry, QFileSystemM
what |= QFileSystemMetaData::DirectoryType;
}
if (what & QFileSystemMetaData::HiddenAttribute) {
- // Mac OS >= 10.5: st_flags & UF_HIDDEN
+ // OS X >= 10.5: st_flags & UF_HIDDEN
what |= QFileSystemMetaData::PosixStatFlags;
}
#endif // defined(Q_OS_MACX)
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 221cea3bea..5cca3c323e 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -1218,7 +1218,7 @@ QString QFileSystemEngine::rootPath()
ret = QDir::fromNativeSeparators(QString::fromWCharArray(finalWinPath.GetRawBuffer(nullptr)));
#else
- QString ret = QString::fromLatin1(qgetenv("SystemDrive").constData());
+ QString ret = QString::fromLatin1(qgetenv("SystemDrive"));
if (ret.isEmpty())
ret = QLatin1String("c:");
ret.append(QLatin1Char('/'));
@@ -1253,12 +1253,12 @@ QString QFileSystemEngine::homePath()
}
#endif
if (ret.isEmpty() || !QFile::exists(ret)) {
- ret = QString::fromLocal8Bit(qgetenv("USERPROFILE").constData());
+ ret = QString::fromLocal8Bit(qgetenv("USERPROFILE"));
if (ret.isEmpty() || !QFile::exists(ret)) {
- ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE").constData())
- + QString::fromLocal8Bit(qgetenv("HOMEPATH").constData());
+ ret = QString::fromLocal8Bit(qgetenv("HOMEDRIVE"))
+ + QString::fromLocal8Bit(qgetenv("HOMEPATH"));
if (ret.isEmpty() || !QFile::exists(ret)) {
- ret = QString::fromLocal8Bit(qgetenv("HOME").constData());
+ ret = QString::fromLocal8Bit(qgetenv("HOME"));
if (ret.isEmpty() || !QFile::exists(ret)) {
#if defined(Q_OS_WINCE)
ret = QLatin1String("\\My Documents");
diff --git a/src/corelib/io/qfilesystemwatcher.cpp b/src/corelib/io/qfilesystemwatcher.cpp
index 753f271a63..0bd46400d3 100644
--- a/src/corelib/io/qfilesystemwatcher.cpp
+++ b/src/corelib/io/qfilesystemwatcher.cpp
@@ -185,7 +185,7 @@ void QFileSystemWatcherPrivate::_q_directoryChanged(const QString &path, bool re
the file system monitor. Also note that your process may have
other file descriptors open in addition to the ones for files
being monitored, and these other open descriptors also count in
- the total. Mac OS X 10.5 and up use a different backend and do not
+ the total. OS X 10.5 and up use a different backend and do not
suffer from this issue.
diff --git a/src/corelib/io/qfilesystemwatcher.h b/src/corelib/io/qfilesystemwatcher.h
index 57dac802e8..13d1782913 100644
--- a/src/corelib/io/qfilesystemwatcher.h
+++ b/src/corelib/io/qfilesystemwatcher.h
@@ -62,16 +62,8 @@ public:
QStringList directories() const;
Q_SIGNALS:
- void fileChanged(const QString &path
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void directoryChanged(const QString &path
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void fileChanged(const QString &path, QPrivateSignal);
+ void directoryChanged(const QString &path, QPrivateSignal);
private:
Q_PRIVATE_SLOT(d_func(), void _q_fileChanged(const QString &path, bool removed))
diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp
index 13ede56d2a..ddbd24338b 100644
--- a/src/corelib/io/qfsfileengine.cpp
+++ b/src/corelib/io/qfsfileengine.cpp
@@ -603,7 +603,7 @@ qint64 QFSFileEnginePrivate::readFdFh(char *data, qint64 len)
result = fread(data + readBytes, 1, size_t(len - readBytes), fh);
eof = feof(fh);
if (retry && eof && result == 0) {
- // On Mac OS, this is needed, e.g., if a file was written to
+ // On OS X, this is needed, e.g., if a file was written to
// through another stream since our last read. See test
// tst_QFile::appendAndRead
QT_FSEEK(fh, QT_FTELL(fh), SEEK_SET); // re-sync stream.
@@ -875,7 +875,7 @@ bool QFSFileEngine::supportsExtension(Extension extension) const
/*! \fn QFileInfoList QFSFileEngine::drives()
For Windows, returns the list of drives in the file system as a list
- of QFileInfo objects. On unix, Mac OS X and Windows CE, only the
+ of QFileInfo objects. On Unix and Windows CE, only the
root path is returned. On Windows, this function returns all drives
(A:\, C:\, D:\, etc.).
diff --git a/src/corelib/io/qiodevice.cpp b/src/corelib/io/qiodevice.cpp
index 7a87a78c60..47484ad596 100644
--- a/src/corelib/io/qiodevice.cpp
+++ b/src/corelib/io/qiodevice.cpp
@@ -666,7 +666,7 @@ bool QIODevice::seek(qint64 pos)
For some devices, atEnd() can return true even though there is more data
to read. This special case only applies to devices that generate data in
direct response to you calling read() (e.g., \c /dev or \c /proc files on
- Unix and Mac OS X, or console input / \c stdin on all platforms).
+ Unix and OS X, or console input / \c stdin on all platforms).
\sa bytesAvailable(), read(), isSequential()
*/
@@ -989,8 +989,8 @@ QByteArray QIODevice::readAll()
// Size is unknown, read incrementally.
qint64 readResult;
do {
- result.resize(result.size() + QIODEVICE_BUFFERSIZE);
- readResult = read(result.data() + readBytes, result.size() - readBytes);
+ result.resize(readBytes + QIODEVICE_BUFFERSIZE);
+ readResult = read(result.data() + readBytes, QIODEVICE_BUFFERSIZE);
if (readResult > 0 || readBytes == 0)
readBytes += readResult;
} while (readResult > 0);
diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp
index c663681aaa..b817a24c74 100644
--- a/src/corelib/io/qlockfile_unix.cpp
+++ b/src/corelib/io/qlockfile_unix.cpp
@@ -102,7 +102,7 @@ static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1);
/*!
\internal
Checks that the OS isn't using POSIX locks to emulate flock().
- Mac OS X is one of those.
+ OS X is one of those.
*/
static bool fcntlWorksAfterFlock()
{
diff --git a/src/corelib/io/qloggingcategory.cpp b/src/corelib/io/qloggingcategory.cpp
index 4631a00f5f..e6bc7caaeb 100644
--- a/src/corelib/io/qloggingcategory.cpp
+++ b/src/corelib/io/qloggingcategory.cpp
@@ -159,7 +159,7 @@ static void setBoolLane(QBasicAtomicInt *atomic, bool enable, int shift)
by QStandardPaths::GenericConfigLocation, e.g.
\list
- \li on Mac OS X: \c ~/Library/Preferences
+ \li on OS X and iOS: \c ~/Library/Preferences
\li on Unix: \c ~/.config, \c /etc/xdg
\li on Windows: \c %LOCALAPPDATA%, \c %ProgramData%,
\l QCoreApplication::applicationDirPath(),
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index 80eb08b01b..38bd588c37 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -36,6 +36,9 @@
#include <qdebug.h>
#include <qdir.h>
+#if defined(Q_OS_WIN)
+#include <qtimer.h>
+#endif
#if defined QPROCESS_DEBUG
#include <qstring.h>
#include <ctype.h>
@@ -819,7 +822,7 @@ QProcessPrivate::QProcessPrivate()
emittedReadyRead = false;
emittedBytesWritten = false;
#ifdef Q_OS_WIN
- notifier = 0;
+ stdinWriteTrigger = 0;
processFinishedNotifier = 0;
#endif // Q_OS_WIN
}
@@ -848,6 +851,10 @@ void QProcessPrivate::cleanup()
delete pid;
pid = 0;
}
+ if (stdinWriteTrigger) {
+ delete stdinWriteTrigger;
+ stdinWriteTrigger = 0;
+ }
if (processFinishedNotifier) {
delete processFinishedNotifier;
processFinishedNotifier = 0;
@@ -878,12 +885,6 @@ void QProcessPrivate::cleanup()
delete deathNotifier;
deathNotifier = 0;
}
-#ifdef Q_OS_WIN
- if (notifier) {
- delete notifier;
- notifier = 0;
- }
-#endif
closeChannel(&stdoutChannel);
closeChannel(&stderrChannel);
closeChannel(&stdinChannel);
@@ -1953,10 +1954,24 @@ qint64 QProcess::writeData(const char *data, qint64 len)
return 0;
}
+#if defined(Q_OS_WIN)
+ if (!d->stdinWriteTrigger) {
+ d->stdinWriteTrigger = new QTimer;
+ d->stdinWriteTrigger->setSingleShot(true);
+ QObjectPrivate::connect(d->stdinWriteTrigger, &QTimer::timeout,
+ d, &QProcessPrivate::_q_canWrite);
+ }
+#endif
+
if (len == 1) {
d->stdinChannel.buffer.putChar(*data);
+#ifdef Q_OS_WIN
+ if (!d->stdinWriteTrigger->isActive())
+ d->stdinWriteTrigger->start();
+#else
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
+#endif
#if defined QPROCESS_DEBUG
qDebug("QProcess::writeData(%p \"%s\", %lld) == 1 (written to buffer)",
data, qt_prettyDebug(data, len, 16).constData(), len);
@@ -1966,8 +1981,13 @@ qint64 QProcess::writeData(const char *data, qint64 len)
char *dest = d->stdinChannel.buffer.reserve(len);
memcpy(dest, data, len);
+#ifdef Q_OS_WIN
+ if (!d->stdinWriteTrigger->isActive())
+ d->stdinWriteTrigger->start();
+#else
if (d->stdinChannel.notifier)
d->stdinChannel.notifier->setEnabled(true);
+#endif
#if defined QPROCESS_DEBUG
qDebug("QProcess::writeData(%p \"%s\", %lld) == %lld (written to buffer)",
data, qt_prettyDebug(data, len, 16).constData(), len, len);
diff --git a/src/corelib/io/qprocess.h b/src/corelib/io/qprocess.h
index 65af469c18..078217ea0b 100644
--- a/src/corelib/io/qprocess.h
+++ b/src/corelib/io/qprocess.h
@@ -223,30 +223,14 @@ public Q_SLOTS:
void kill();
Q_SIGNALS:
- void started(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void started(QPrivateSignal);
void finished(int exitCode); // ### Qt 6: merge the two signals with a default value
void finished(int exitCode, QProcess::ExitStatus exitStatus);
void error(QProcess::ProcessError error);
- void stateChanged(QProcess::ProcessState state
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void stateChanged(QProcess::ProcessState state, QPrivateSignal);
- void readyReadStandardOutput(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void readyReadStandardError(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void readyReadStandardOutput(QPrivateSignal);
+ void readyReadStandardError(QPrivateSignal);
protected:
void setProcessState(ProcessState state);
@@ -266,7 +250,6 @@ private:
Q_PRIVATE_SLOT(d_func(), bool _q_canWrite())
Q_PRIVATE_SLOT(d_func(), bool _q_startupNotification())
Q_PRIVATE_SLOT(d_func(), bool _q_processDied())
- Q_PRIVATE_SLOT(d_func(), void _q_notified())
friend class QProcessManager;
};
diff --git a/src/corelib/io/qprocess_p.h b/src/corelib/io/qprocess_p.h
index 5654b404fe..f6bd64fb87 100644
--- a/src/corelib/io/qprocess_p.h
+++ b/src/corelib/io/qprocess_p.h
@@ -303,7 +303,6 @@ public:
bool _q_canWrite();
bool _q_startupNotification();
bool _q_processDied();
- void _q_notified();
QProcess::ProcessChannel processChannel;
QProcess::ProcessChannelMode processChannelMode;
@@ -342,8 +341,7 @@ public:
int forkfd;
#ifdef Q_OS_WIN
- // the wonderful windows notifier
- QTimer *notifier;
+ QTimer *stdinWriteTrigger;
QWinEventNotifier *processFinishedNotifier;
#endif
diff --git a/src/corelib/io/qprocess_unix.cpp b/src/corelib/io/qprocess_unix.cpp
index d9ed8d5d43..ed0193c256 100644
--- a/src/corelib/io/qprocess_unix.cpp
+++ b/src/corelib/io/qprocess_unix.cpp
@@ -1110,10 +1110,6 @@ bool QProcessPrivate::waitForDeadChild()
return true;
}
-void QProcessPrivate::_q_notified()
-{
-}
-
#if defined(QPROCESS_USE_SPAWN)
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDirectory, qint64 *pid)
{
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 563286e3e9..cef961ecbd 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -41,7 +41,6 @@
#include <qelapsedtimer.h>
#include <qfileinfo.h>
#include <qregexp.h>
-#include <qtimer.h>
#include <qwineventnotifier.h>
#include <private/qthread_p.h>
#include <qdebug.h>
@@ -58,8 +57,6 @@ QT_BEGIN_NAMESPACE
//#define QPROCESS_DEBUG
-#define NOTIFYTIMEOUT 100
-
static void qt_create_pipe(Q_PIPE *pipe, bool isInputPipe)
{
// Anomymous pipes do not support asynchronous I/O. Thus we
@@ -543,9 +540,6 @@ void QProcessPrivate::startProcess()
processFinishedNotifier = new QWinEventNotifier(pid->hProcess, q);
QObject::connect(processFinishedNotifier, SIGNAL(activated(HANDLE)), q, SLOT(_q_processDied()));
processFinishedNotifier->setEnabled(true);
- notifier = new QTimer(q);
- QObject::connect(notifier, SIGNAL(timeout()), q, SLOT(_q_notified()));
- notifier->start(NOTIFYTIMEOUT);
}
_q_startupNotification();
@@ -810,6 +804,8 @@ qint64 QProcessPrivate::writeToStdin(const char *data, qint64 maxlen)
if (!stdinChannel.writer) {
stdinChannel.writer = new QWindowsPipeWriter(stdinChannel.pipe[1], q);
+ QObjectPrivate::connect(stdinChannel.writer, &QWindowsPipeWriter::canWrite,
+ this, &QProcessPrivate::_q_canWrite);
stdinChannel.writer->start();
}
@@ -828,17 +824,6 @@ bool QProcessPrivate::waitForWrite(int msecs)
return false;
}
-void QProcessPrivate::_q_notified()
-{
- notifier->stop();
-
- if (!stdinChannel.buffer.isEmpty() && (!stdinChannel.writer || stdinChannel.writer->waitForWrite(0)))
- _q_canWrite();
-
- if (processState != QProcess::NotRunning)
- notifier->start(NOTIFYTIMEOUT);
-}
-
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
QString args = qt_create_commandline(program, arguments);
diff --git a/src/corelib/io/qprocess_wince.cpp b/src/corelib/io/qprocess_wince.cpp
index bf19c81f25..53767758c2 100644
--- a/src/corelib/io/qprocess_wince.cpp
+++ b/src/corelib/io/qprocess_wince.cpp
@@ -288,10 +288,6 @@ bool QProcessPrivate::waitForWrite(int msecs)
return false;
}
-void QProcessPrivate::_q_notified()
-{
-}
-
bool QProcessPrivate::startDetached(const QString &program, const QStringList &arguments, const QString &workingDir, qint64 *pid)
{
Q_UNUSED(workingDir);
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index 780f57c1c7..afe68125d4 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -1915,7 +1915,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
Users normally expect an application to remember its settings
(window sizes and positions, options, etc.) across sessions. This
information is often stored in the system registry on Windows,
- and in XML preferences files on Mac OS X. On Unix systems, in the
+ and in property list files on OS X and iOS. On Unix systems, in the
absence of a standard, many applications (including the KDE
applications) use INI text files.
@@ -1960,8 +1960,8 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\snippet settings/settings.cpp 4
(Here, we also specify the organization's Internet domain. When
- the Internet domain is set, it is used on Mac OS X instead of the
- organization name, since Mac OS X applications conventionally use
+ the Internet domain is set, it is used on OS X and iOS instead of the
+ organization name, since OS X and iOS applications conventionally use
Internet domains to identify themselves. If no domain is set, a
fake domain is derived from the organization name. See the
\l{Platform-Specific Notes} below for details.)
@@ -2019,7 +2019,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
Setting keys can contain any Unicode characters. The Windows
registry and INI files use case-insensitive keys, whereas the
- Carbon Preferences API on Mac OS X uses case-sensitive keys. To
+ CFPreferences API on OS X and iOS uses case-sensitive keys. To
avoid portability problems, follow these simple rules:
\list 1
@@ -2222,7 +2222,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
in the application's home directory.
If the file format is IniFormat, the following files are
- used on Unix and Mac OS X:
+ used on Unix, OS X, and iOS:
\list 1
\li \c{$HOME/.config/MySoft/Star Runner.ini} (Qt for Embedded Linux: \c{$HOME/Settings/MySoft/Star Runner.ini})
@@ -2250,7 +2250,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
in the application's home directory.
The paths for the \c .ini and \c .conf files can be changed using
- setPath(). On Unix and Mac OS X, the user can override them by
+ setPath(). On Unix, OS X, and iOS the user can override them by
setting the \c XDG_CONFIG_HOME environment variable; see
setPath() for details.
@@ -2267,7 +2267,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
You can then use the QSettings object to read and write settings
in the file.
- On Mac OS X, you can access XML-based \c .plist files by passing
+ On OS X and iOS, you can access property list \c .plist files by passing
QSettings::NativeFormat as second argument. For example:
\snippet code/src_corelib_io_qsettings.cpp 3
@@ -2321,13 +2321,13 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
limitations is to store the settings using the IniFormat
instead of the NativeFormat.
- \li On Mac OS X, allKeys() will return some extra keys for global
+ \li On OS X and iOS, allKeys() will return some extra keys for global
settings that apply to all applications. These keys can be
read using value() but cannot be changed, only shadowed.
Calling setFallbacksEnabled(false) will hide these global
settings.
- \li On Mac OS X, the CFPreferences API used by QSettings expects
+ \li On OS X and iOS, the CFPreferences API used by QSettings expects
Internet domain names rather than organization names. To
provide a uniform API, QSettings derives a fake domain name
from the organization name (unless the organization name
@@ -2344,7 +2344,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\snippet code/src_corelib_io_qsettings.cpp 7
- \li On Mac OS X, permissions to access settings not belonging to the
+ \li On OS X, permissions to access settings not belonging to the
current user (i.e. SystemScope) have changed with 10.7 (Lion). Prior to
that version, users having admin rights could access these. For 10.7 and
10.8 (Mountain Lion), only root can. However, 10.9 (Mavericks) changes
@@ -2384,7 +2384,7 @@ void QConfFileSettingsPrivate::ensureSectionParsed(QConfFile *confFile,
\value NativeFormat Store the settings using the most
appropriate storage format for the platform.
On Windows, this means the system registry;
- on Mac OS X, this means the CFPreferences
+ on OS X and iOS, this means the CFPreferences
API; on Unix, this means textual
configuration files in INI format.
\value IniFormat Store the settings in INI files.
@@ -2547,7 +2547,7 @@ QSettings::QSettings(Format format, Scope scope, const QString &organization,
If \a format is QSettings::NativeFormat, the meaning of \a
fileName depends on the platform. On Unix, \a fileName is the
- name of an INI file. On Mac OS X, \a fileName is the name of a
+ name of an INI file. On OS X and iOS, \a fileName is the name of a
\c .plist file. On Windows, \a fileName is a path in the system
registry.
@@ -2600,7 +2600,7 @@ QSettings::QSettings(const QString &fileName, Format format, QObject *parent)
called, the QSettings object will not be able to read or write
any settings, and status() will return AccessError.
- On Mac OS X, if both a name and an Internet domain are specified
+ On OS X and iOS, if both a name and an Internet domain are specified
for the organization, the domain is preferred over the name. On
other platforms, the name is preferred over the domain.
@@ -3116,7 +3116,7 @@ bool QSettings::isWritable() const
exists, the previous value is overwritten.
Note that the Windows registry and INI files use case-insensitive
- keys, whereas the Carbon Preferences API on Mac OS X uses
+ keys, whereas the CFPreferences API on OS X and iOS uses
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
@@ -3155,7 +3155,7 @@ void QSettings::setValue(const QString &key, const QVariant &value)
\snippet code/src_corelib_io_qsettings.cpp 25
Note that the Windows registry and INI files use case-insensitive
- keys, whereas the Carbon Preferences API on Mac OS X uses
+ keys, whereas the CFPreferences API on OS X and iOS uses
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
@@ -3190,7 +3190,7 @@ void QSettings::remove(const QString &key)
relative to that group.
Note that the Windows registry and INI files use case-insensitive
- keys, whereas the Carbon Preferences API on Mac OS X uses
+ keys, whereas the CFPreferences API on OS X and iOS uses
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
@@ -3252,7 +3252,7 @@ bool QSettings::event(QEvent *event)
returned.
Note that the Windows registry and INI files use case-insensitive
- keys, whereas the Carbon Preferences API on Mac OS X uses
+ keys, whereas the CFPreferences API on OS X and iOS uses
case-sensitive keys. To avoid portability problems, see the
\l{Section and Key Syntax} rules.
@@ -3355,18 +3355,18 @@ void QSettings::setUserIniPath(const QString &dir)
\row \li SystemScope \li \c /etc/xdg
\row \li{1,2} Qt for Embedded Linux \li{1,2} NativeFormat, IniFormat \li UserScope \li \c $HOME/Settings
\row \li SystemScope \li \c /etc/xdg
- \row \li{1,2} Mac OS X \li{1,2} IniFormat \li UserScope \li \c $HOME/.config
+ \row \li{1,2} OS X and iOS \li{1,2} IniFormat \li UserScope \li \c $HOME/.config
\row \li SystemScope \li \c /etc/xdg
\endtable
- The default UserScope paths on Unix and Mac OS X (\c
+ The default UserScope paths on Unix, OS X, and iOS (\c
$HOME/.config or $HOME/Settings) can be overridden by the user by setting the
\c XDG_CONFIG_HOME environment variable. The default SystemScope
- paths on Unix and Mac OS X (\c /etc/xdg) can be overridden when
+ paths on Unix, OS X, and iOS (\c /etc/xdg) can be overridden when
building the Qt library using the \c configure script's \c
-sysconfdir flag (see QLibraryInfo for details).
- Setting the NativeFormat paths on Windows and Mac OS X has no
+ Setting the NativeFormat paths on Windows, OS X, and iOS has no
effect.
\warning This function doesn't affect existing QSettings objects.
diff --git a/src/corelib/io/qstorageinfo_unix.cpp b/src/corelib/io/qstorageinfo_unix.cpp
index d120d7569a..7823787711 100644
--- a/src/corelib/io/qstorageinfo_unix.cpp
+++ b/src/corelib/io/qstorageinfo_unix.cpp
@@ -122,7 +122,11 @@ public:
inline QByteArray device() const;
private:
#if defined(Q_OS_BSD4)
+# if defined(Q_OS_NETBSD)
+ struct statvfs *stat_buf;
+# else
struct statfs *stat_buf;
+# endif
int entryCount;
int currentIndex;
#elif defined(Q_OS_SOLARIS)
@@ -206,7 +210,7 @@ inline bool QStorageIterator::isValid() const
inline bool QStorageIterator::next()
{
- return ::getmntent(fp, &mnt) == Q_NULLPTR;
+ return ::getmntent(fp, &mnt) == 0;
}
inline QString QStorageIterator::rootPath() const
diff --git a/src/corelib/itemmodels/qabstractitemmodel.h b/src/corelib/itemmodels/qabstractitemmodel.h
index c4f705e858..5ca7bd0123 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.h
+++ b/src/corelib/itemmodels/qabstractitemmodel.h
@@ -246,82 +246,26 @@ Q_SIGNALS:
void layoutChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
void layoutAboutToBeChanged(const QList<QPersistentModelIndex> &parents = QList<QPersistentModelIndex>(), QAbstractItemModel::LayoutChangeHint hint = QAbstractItemModel::NoLayoutChangeHint);
- void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void rowsInserted(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void rowsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal);
+ void rowsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal);
- void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void rowsRemoved(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void rowsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal);
+ void rowsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal);
- void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void columnsInserted(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void columnsAboutToBeInserted(const QModelIndex &parent, int first, int last, QPrivateSignal);
+ void columnsInserted(const QModelIndex &parent, int first, int last, QPrivateSignal);
- void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void columnsRemoved(const QModelIndex &parent, int first, int last
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void columnsAboutToBeRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal);
+ void columnsRemoved(const QModelIndex &parent, int first, int last, QPrivateSignal);
- void modelAboutToBeReset(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void modelReset(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void modelAboutToBeReset(QPrivateSignal);
+ void modelReset(QPrivateSignal);
- void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void rowsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationRow, QPrivateSignal);
+ void rowsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row, QPrivateSignal);
- void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void columnsAboutToBeMoved( const QModelIndex &sourceParent, int sourceStart, int sourceEnd, const QModelIndex &destinationParent, int destinationColumn, QPrivateSignal);
+ void columnsMoved( const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column, QPrivateSignal);
public Q_SLOTS:
virtual bool submit();
diff --git a/src/corelib/itemmodels/qabstractproxymodel.h b/src/corelib/itemmodels/qabstractproxymodel.h
index afd5a1f616..dc8d2d4dc8 100644
--- a/src/corelib/itemmodels/qabstractproxymodel.h
+++ b/src/corelib/itemmodels/qabstractproxymodel.h
@@ -92,11 +92,7 @@ public:
Qt::DropActions supportedDropActions() const Q_DECL_OVERRIDE;
Q_SIGNALS:
- void sourceModelChanged(
-#if !defined(qdoc)
- QPrivateSignal
-#endif
- );
+ void sourceModelChanged(QPrivateSignal);
protected Q_SLOTS:
void resetInternalData();
diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp
index 5057c0415a..05d58ac028 100644
--- a/src/corelib/kernel/qcoreapplication.cpp
+++ b/src/corelib/kernel/qcoreapplication.cpp
@@ -695,7 +695,7 @@ QCoreApplication::QCoreApplication(QCoreApplicationPrivate &p)
If you are doing graphical changes inside a loop that does not
return to the event loop on asynchronous window systems like X11
- or double buffered window systems like Mac OS X, and you want to
+ or double buffered window systems like Quartz (OS X and iOS), and you want to
visualize these changes immediately (e.g. Splash Screens), call
this function.
@@ -2002,7 +2002,7 @@ void QCoreApplicationPrivate::setApplicationFilePath(const QString &path)
directory, and you run the \c{regexp} example, this function will
return "C:/Qt/examples/tools/regexp".
- On Mac OS X this will point to the directory actually containing the
+ On OS X and iOS this will point to the directory actually containing the
executable, which may be inside of an application bundle (if the
application is bundled).
diff --git a/src/corelib/kernel/qcoreapplication.h b/src/corelib/kernel/qcoreapplication.h
index e1fc364cd1..1cd835daae 100644
--- a/src/corelib/kernel/qcoreapplication.h
+++ b/src/corelib/kernel/qcoreapplication.h
@@ -171,11 +171,7 @@ public Q_SLOTS:
static void quit();
Q_SIGNALS:
- void aboutToQuit(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void aboutToQuit(QPrivateSignal);
void organizationNameChanged();
void organizationDomainChanged();
diff --git a/src/corelib/kernel/qcoreapplication_win.cpp b/src/corelib/kernel/qcoreapplication_win.cpp
index 4649c151f7..396d2f740a 100644
--- a/src/corelib/kernel/qcoreapplication_win.cpp
+++ b/src/corelib/kernel/qcoreapplication_win.cpp
@@ -184,28 +184,6 @@ Q_CORE_EXPORT void __cdecl qWinMain(HINSTANCE instance, HINSTANCE prevInstance,
#ifndef QT_NO_QOBJECT
-void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
-{
- QThreadData *data = object->d_func()->threadData;
-
- QMutexLocker locker(&data->postEventList.mutex);
- if (data->postEventList.size() == 0)
- return;
- for (int i = 0; i < data->postEventList.size(); ++i) {
- const QPostEvent & pe = data->postEventList.at(i);
- if (pe.receiver == object
- && pe.event
- && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
- && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
- --pe.receiver->d_func()->postedEvents;
- pe.event->posted = false;
- delete pe.event;
- const_cast<QPostEvent &>(pe).event = 0;
- return;
- }
- }
-}
-
#if defined(Q_OS_WIN) && !defined(QT_NO_DEBUG_STREAM)
/*****************************************************************************
Convenience functions for convert WM_* messages into human readable strings,
@@ -1050,4 +1028,28 @@ QDebug operator<<(QDebug dbg, const MSG &msg)
#endif // !defined(Q_OS_WINRT)
+#ifndef QT_NO_QOBJECT
+void QCoreApplicationPrivate::removePostedTimerEvent(QObject *object, int timerId)
+{
+ QThreadData *data = object->d_func()->threadData;
+
+ QMutexLocker locker(&data->postEventList.mutex);
+ if (data->postEventList.size() == 0)
+ return;
+ for (int i = 0; i < data->postEventList.size(); ++i) {
+ const QPostEvent &pe = data->postEventList.at(i);
+ if (pe.receiver == object
+ && pe.event
+ && (pe.event->type() == QEvent::Timer || pe.event->type() == QEvent::ZeroTimerEvent)
+ && static_cast<QTimerEvent *>(pe.event)->timerId() == timerId) {
+ --pe.receiver->d_func()->postedEvents;
+ pe.event->posted = false;
+ delete pe.event;
+ const_cast<QPostEvent &>(pe).event = 0;
+ return;
+ }
+ }
+}
+#endif // QT_NO_QOBJECT
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp
index 0a68de8871..98514c56af 100644
--- a/src/corelib/kernel/qcoreevent.cpp
+++ b/src/corelib/kernel/qcoreevent.cpp
@@ -167,7 +167,7 @@ QT_BEGIN_NAMESPACE
\value NonClientAreaMouseButtonPress A mouse button press occurred outside the client area.
\value NonClientAreaMouseButtonRelease A mouse button release occurred outside the client area.
\value NonClientAreaMouseMove A mouse move occurred outside the client area.
- \value MacSizeChange The user changed his widget sizes (Mac OS X only).
+ \value MacSizeChange The user changed his widget sizes (OS X only).
\value MetaCall An asynchronous method invocation via QMetaObject::invokeMethod().
\value ModifiedChange Widgets modification state has been changed.
\value MouseButtonDblClick Mouse press again (QMouseEvent).
@@ -211,7 +211,7 @@ QT_BEGIN_NAMESPACE
\omitvalue ThemeChange
\value ThreadChange The object is moved to another thread. This is the last event sent to this object in the previous thread. See QObject::moveToThread().
\value Timer Regular timer events (QTimerEvent).
- \value ToolBarChange The toolbar button is toggled on Mac OS X.
+ \value ToolBarChange The toolbar button is toggled on OS X.
\value ToolTip A tooltip was requested (QHelpEvent).
\value ToolTipChange The widget's tooltip has changed.
\value TouchBegin Beginning of a sequence of touch-screen or track-pad events (QTouchEvent).
diff --git a/src/corelib/kernel/qeventdispatcher_blackberry.cpp b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
index e0ce53bff1..796daaa50a 100644
--- a/src/corelib/kernel/qeventdispatcher_blackberry.cpp
+++ b/src/corelib/kernel/qeventdispatcher_blackberry.cpp
@@ -49,6 +49,8 @@
#define qEventDispatcherDebug QT_NO_QDEBUG_MACRO()
#endif
+QT_BEGIN_NAMESPACE
+
class BpsChannelScopeSwitcher
{
public:
diff --git a/src/corelib/kernel/qeventdispatcher_winrt.cpp b/src/corelib/kernel/qeventdispatcher_winrt.cpp
index 5e4ef937b9..cc8e961be1 100644
--- a/src/corelib/kernel/qeventdispatcher_winrt.cpp
+++ b/src/corelib/kernel/qeventdispatcher_winrt.cpp
@@ -54,62 +54,20 @@ using namespace ABI::Windows::ApplicationModel::Core;
QT_BEGIN_NAMESPACE
-class QZeroTimerEvent : public QTimerEvent
-{
-public:
- explicit inline QZeroTimerEvent(int timerId)
- : QTimerEvent(timerId)
- { t = QEvent::ZeroTimerEvent; }
-};
-
-struct WinRTTimerInfo // internal timer info
-{
- WinRTTimerInfo(int timerId, int timerInterval, Qt::TimerType timerType, QObject *object, QEventDispatcherWinRT *dispatcher)
- : isFinished(false), id(timerId), interval(timerInterval), timerType(timerType), obj(object), inTimerEvent(false), dispatcher(dispatcher)
- {
- }
-
- void cancel()
+#define INTERRUPT_HANDLE 0
+#define INVALID_TIMER_ID -1
+
+struct WinRTTimerInfo : public QAbstractEventDispatcher::TimerInfo {
+ WinRTTimerInfo(int timerId = INVALID_TIMER_ID, int interval = 0, Qt::TimerType timerType = Qt::CoarseTimer,
+ QObject *obj = 0, quint64 tt = 0) :
+ QAbstractEventDispatcher::TimerInfo(timerId, interval, timerType),
+ inEvent(false), object(obj), targetTime(tt)
{
- if (isFinished) {
- delete this;
- return;
- }
- isFinished = true;
- if (!timer)
- return;
-
- HRESULT hr = timer->Cancel();
- RETURN_VOID_IF_FAILED("Failed to cancel timer");
}
- HRESULT timerExpired(IThreadPoolTimer *)
- {
- if (isFinished)
- return S_OK;
- if (dispatcher)
- QCoreApplication::postEvent(dispatcher, new QTimerEvent(id));
- return S_OK;
- }
-
- HRESULT timerDestroyed(IThreadPoolTimer *)
- {
- if (isFinished)
- delete this;
- else
- isFinished = true;
- return S_OK;
- }
-
- bool isFinished;
- int id;
- int interval;
- Qt::TimerType timerType;
- quint64 timeout; // - when to actually fire
- QObject *obj; // - object to receive events
- bool inTimerEvent;
- ComPtr<IThreadPoolTimer> timer;
- QPointer<QEventDispatcherWinRT> dispatcher;
+ bool inEvent;
+ QObject *object;
+ quint64 targetTime;
};
class QEventDispatcherWinRTPrivate : public QAbstractEventDispatcherPrivate
@@ -121,13 +79,63 @@ public:
~QEventDispatcherWinRTPrivate();
private:
- QHash<int, WinRTTimerInfo*> timerDict;
-
ComPtr<IThreadPoolTimerStatics> timerFactory;
ComPtr<ICoreDispatcher> coreDispatcher;
QPointer<QThread> thread;
- bool interrupt;
+ QHash<int, QObject *> timerIdToObject;
+ QVector<WinRTTimerInfo> timerInfos;
+ QHash<HANDLE, int> timerHandleToId;
+ QHash<int, HANDLE> timerIdToHandle;
+ QHash<int, HANDLE> timerIdToCancelHandle;
+
+ void addTimer(int id, int interval, Qt::TimerType type, QObject *obj,
+ HANDLE handle, HANDLE cancelHandle)
+ {
+ // Zero timer events do not need these handles.
+ if (interval > 0) {
+ timerHandleToId.insert(handle, id);
+ timerIdToHandle.insert(id, handle);
+ timerIdToCancelHandle.insert(id, cancelHandle);
+ }
+ timerIdToObject.insert(id, obj);
+ const quint64 targetTime = qt_msectime() + interval;
+ const WinRTTimerInfo info(id, interval, type, obj, targetTime);
+ if (id >= timerInfos.size())
+ timerInfos.resize(id + 1);
+ timerInfos[id] = info;
+ timerIdToObject.insert(id, obj);
+ }
+
+ bool removeTimer(int id)
+ {
+ if (id >= timerInfos.size())
+ return false;
+
+ WinRTTimerInfo &info = timerInfos[id];
+ if (info.timerId == INVALID_TIMER_ID)
+ return false;
+
+ if (info.interval > 0 && (!timerIdToHandle.contains(id) || !timerIdToCancelHandle.contains(id)))
+ return false;
+
+ info.timerId = INVALID_TIMER_ID;
+
+ // Remove invalid timerinfos from the vector's end, if the timer with the highest id was removed
+ int lastTimer = timerInfos.size() - 1;
+ while (lastTimer >= 0 && timerInfos.at(lastTimer).timerId == INVALID_TIMER_ID)
+ --lastTimer;
+ if (lastTimer >= 0 && lastTimer != timerInfos.size() - 1)
+ timerInfos.resize(lastTimer + 1);
+ timerIdToObject.remove(id);
+ // ... remove handle from all lists
+ if (info.interval > 0) {
+ HANDLE handle = timerIdToHandle.take(id);
+ timerHandleToId.remove(handle);
+ SetEvent(timerIdToCancelHandle.take(id));
+ }
+ return true;
+ }
void fetchCoreDispatcher()
{
@@ -183,8 +191,7 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
if (d->thread && d->thread != QThread::currentThread())
d->fetchCoreDispatcher();
- bool didProcess = false;
- forever {
+ do {
// Process native events
if (d->coreDispatcher) {
boolean hasThreadAccess;
@@ -197,23 +204,32 @@ bool QEventDispatcherWinRT::processEvents(QEventLoop::ProcessEventsFlags flags)
}
// Dispatch accumulated user events
- didProcess = sendPostedEvents(flags);
- if (didProcess)
- break;
+ if (sendPostedEvents(flags))
+ return true;
- if (d->interrupt)
- break;
+ emit aboutToBlock();
+ const QVector<HANDLE> timerHandles = d->timerIdToHandle.values().toVector();
+ DWORD waitResult = WaitForMultipleObjectsEx(timerHandles.count(), timerHandles.constData(), FALSE, 1, TRUE);
+ if (waitResult >= WAIT_OBJECT_0 && waitResult < WAIT_OBJECT_0 + timerHandles.count()) {
+ const HANDLE handle = timerHandles.value(waitResult - WAIT_OBJECT_0);
+ const int timerId = d->timerHandleToId.value(handle);
+ if (timerId == INTERRUPT_HANDLE)
+ break;
- // Short sleep if there is nothing to do
- if (!(flags & QEventLoop::WaitForMoreEvents))
- break;
+ WinRTTimerInfo &info = d->timerInfos[timerId];
+ Q_ASSERT(info.timerId != INVALID_TIMER_ID);
- emit aboutToBlock();
- WaitForSingleObjectEx(GetCurrentThread(), 1, FALSE);
+ QCoreApplication::postEvent(this, new QTimerEvent(timerId));
+
+ // Update timer's targetTime
+ const quint64 targetTime = qt_msectime() + info.interval;
+ info.targetTime = targetTime;
+ emit awake();
+ return true;
+ }
emit awake();
- }
- d->interrupt = false;
- return didProcess;
+ } while (flags & QEventLoop::WaitForMoreEvents);
+ return false;
}
bool QEventDispatcherWinRT::sendPostedEvents(QEventLoop::ProcessEventsFlags flags)
@@ -246,104 +262,121 @@ void QEventDispatcherWinRT::registerTimer(int timerId, int interval, Qt::TimerTy
{
Q_UNUSED(timerType);
-#ifndef QT_NO_DEBUG
if (timerId < 1 || interval < 0 || !object) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::registerTimer: invalid arguments");
+#endif
return;
} else if (object->thread() != thread() || thread() != QThread::currentThread()) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::registerTimer: timers cannot be started from another thread");
+#endif
return;
}
-#endif
Q_D(QEventDispatcherWinRT);
-
- WinRTTimerInfo *t = new WinRTTimerInfo(timerId, interval, timerType, object, this);
- t->timeout = qt_msectime() + interval;
- d->timerDict.insert(t->id, t);
-
// Don't use timer factory for zero-delay timers
if (interval == 0u) {
- QCoreApplication::postEvent(this, new QZeroTimerEvent(timerId));
+ d->addTimer(timerId, interval, timerType, object, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE);
+ QCoreApplication::postEvent(this, new QTimerEvent(timerId));
return;
}
TimeSpan period;
period.Duration = interval ? (interval * 10000) : 1; // TimeSpan is based on 100-nanosecond units
+ IThreadPoolTimer *timer;
+ const HANDLE handle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE);
+ const HANDLE cancelHandle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE);
HRESULT hr = d->timerFactory->CreatePeriodicTimerWithCompletion(
- Callback<ITimerElapsedHandler>(t, &WinRTTimerInfo::timerExpired).Get(), period,
- Callback<ITimerDestroyedHandler>(t, &WinRTTimerInfo::timerDestroyed).Get(), &t->timer);
+ Callback<ITimerElapsedHandler>([handle, cancelHandle](IThreadPoolTimer *timer) {
+ DWORD cancelResult = WaitForSingleObjectEx(cancelHandle, 0, TRUE);
+ if (cancelResult == WAIT_OBJECT_0) {
+ timer->Cancel();
+ return S_OK;
+ }
+ if (!SetEvent(handle)) {
+ Q_ASSERT_X(false, "QEventDispatcherWinRT::registerTimer",
+ "SetEvent should never fail here");
+ return S_OK;
+ }
+ return S_OK;
+ }).Get(), period,
+ Callback<ITimerDestroyedHandler>([handle, cancelHandle](IThreadPoolTimer *) {
+ CloseHandle(handle);
+ CloseHandle(cancelHandle);
+ return S_OK;
+ }).Get(), &timer);
if (FAILED(hr)) {
qErrnoWarning(hr, "Failed to create periodic timer");
- delete t;
- d->timerDict.remove(t->id);
+ CloseHandle(handle);
+ CloseHandle(cancelHandle);
return;
}
+ d->addTimer(timerId, interval, timerType, object, handle, cancelHandle);
}
bool QEventDispatcherWinRT::unregisterTimer(int timerId)
{
-#ifndef QT_NO_DEBUG
if (timerId < 1) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::unregisterTimer: invalid argument");
+#endif
return false;
}
if (thread() != QThread::currentThread()) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::unregisterTimer: timers cannot be stopped from another thread");
+#endif
return false;
}
-#endif
+ // As we post all timer events internally, they have to pe removed to prevent stray events
+ QCoreApplicationPrivate::removePostedTimerEvent(this, timerId);
Q_D(QEventDispatcherWinRT);
-
- WinRTTimerInfo *t = d->timerDict.take(timerId);
- if (!t)
- return false;
-
- t->cancel();
- return true;
+ return d->removeTimer(timerId);
}
bool QEventDispatcherWinRT::unregisterTimers(QObject *object)
{
-#ifndef QT_NO_DEBUG
if (!object) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::unregisterTimers: invalid argument");
+#endif
return false;
}
QThread *currentThread = QThread::currentThread();
if (object->thread() != thread() || thread() != currentThread) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::unregisterTimers: timers cannot be stopped from another thread");
+#endif
return false;
}
-#endif
Q_D(QEventDispatcherWinRT);
- for (QHash<int, WinRTTimerInfo *>::iterator it = d->timerDict.begin(); it != d->timerDict.end();) {
- if (it.value()->obj == object) {
- it.value()->cancel();
- it = d->timerDict.erase(it);
- continue;
- }
- ++it;
+ foreach (int id, d->timerIdToObject.keys()) {
+ if (d->timerIdToObject.value(id) == object)
+ unregisterTimer(id);
}
+
return true;
}
QList<QAbstractEventDispatcher::TimerInfo> QEventDispatcherWinRT::registeredTimers(QObject *object) const
{
if (!object) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT:registeredTimers: invalid argument");
+#endif
return QList<TimerInfo>();
}
Q_D(const QEventDispatcherWinRT);
- QList<TimerInfo> list;
- foreach (const WinRTTimerInfo *t, d->timerDict) {
- if (t->obj == object)
- list.append(TimerInfo(t->id, t->interval, t->timerType));
+ QList<TimerInfo> timerInfos;
+ foreach (const WinRTTimerInfo &info, d->timerInfos) {
+ if (info.object == object)
+ timerInfos.append(info);
}
- return list;
+ return timerInfos;
}
bool QEventDispatcherWinRT::registerEventNotifier(QWinEventNotifier *notifier)
@@ -361,27 +394,30 @@ void QEventDispatcherWinRT::unregisterEventNotifier(QWinEventNotifier *notifier)
int QEventDispatcherWinRT::remainingTime(int timerId)
{
-#ifndef QT_NO_DEBUG
if (timerId < 1) {
+#ifndef QT_NO_DEBUG
qWarning("QEventDispatcherWinRT::remainingTime: invalid argument");
+#endif
return -1;
}
-#endif
Q_D(QEventDispatcherWinRT);
- if (WinRTTimerInfo *t = d->timerDict.value(timerId)) {
- const quint64 currentTime = qt_msectime();
- if (currentTime < t->timeout) {
- // time to wait
- return t->timeout - currentTime;
- } else {
- return 0;
- }
- }
-
+ const WinRTTimerInfo timerInfo = d->timerInfos.at(timerId);
+ if (timerInfo.timerId == INVALID_TIMER_ID) {
#ifndef QT_NO_DEBUG
- qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId);
+ qWarning("QEventDispatcherWinRT::remainingTime: timer id %d not found", timerId);
#endif
+ return -1;
+ }
+
+ const quint64 currentTime = qt_msectime();
+ if (currentTime < timerInfo.targetTime) {
+ // time to wait
+ return timerInfo.targetTime - currentTime;
+ } else {
+ return 0;
+ }
+
return -1;
}
@@ -392,7 +428,7 @@ void QEventDispatcherWinRT::wakeUp()
void QEventDispatcherWinRT::interrupt()
{
Q_D(QEventDispatcherWinRT);
- d->interrupt = true;
+ SetEvent(d->timerIdToHandle.value(INTERRUPT_HANDLE));
}
void QEventDispatcherWinRT::flush()
@@ -405,55 +441,60 @@ void QEventDispatcherWinRT::startingUp()
void QEventDispatcherWinRT::closingDown()
{
- Q_D(QEventDispatcherWinRT);
- d->timerDict.clear();
}
bool QEventDispatcherWinRT::event(QEvent *e)
{
Q_D(QEventDispatcherWinRT);
- bool ret = false;
switch (e->type()) {
- case QEvent::ZeroTimerEvent:
- ret = true;
- // fall through
case QEvent::Timer: {
QTimerEvent *timerEvent = static_cast<QTimerEvent *>(e);
const int id = timerEvent->timerId();
- if (WinRTTimerInfo *t = d->timerDict.value(id)) {
- if (t->inTimerEvent) // but don't allow event to recurse
- break;
- t->inTimerEvent = true;
+ Q_ASSERT(id < d->timerInfos.size());
+ WinRTTimerInfo &info = d->timerInfos[id];
+ Q_ASSERT(info.timerId != INVALID_TIMER_ID);
- QTimerEvent te(id);
- QCoreApplication::sendEvent(t->obj, &te);
+ if (info.inEvent) // but don't allow event to recurse
+ break;
+ info.inEvent = true;
- if (t = d->timerDict.value(id)) {
- if (t->interval == 0 && t->inTimerEvent) {
- // post the next zero timer event as long as the timer was not restarted
- QCoreApplication::postEvent(this, new QZeroTimerEvent(id));
- }
- t->inTimerEvent = false;
- }
+ QTimerEvent te(id);
+ QCoreApplication::sendEvent(d->timerIdToObject.value(id), &te);
+
+ // The timer might have been removed in the meanwhile
+ if (id >= d->timerInfos.size())
+ break;
+
+ info = d->timerInfos[id];
+ if (info.timerId == INVALID_TIMER_ID)
+ break;
+
+ if (info.interval == 0 && info.inEvent) {
+ // post the next zero timer event as long as the timer was not restarted
+ QCoreApplication::postEvent(this, new QTimerEvent(id));
}
+ info.inEvent = false;
}
default:
break;
}
- return ret ? true : QAbstractEventDispatcher::event(e);
+ return QAbstractEventDispatcher::event(e);
}
QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate()
- : interrupt(false)
{
CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_System_Threading_ThreadPoolTimer).Get(), &timerFactory);
- if (FAILED(hr))
- qWarning("QEventDispatcherWinRTPrivate::QEventDispatcherWinRTPrivate: Could not obtain timer factory: %lx", hr);
+ Q_ASSERT_SUCCEEDED(hr);
+ HANDLE interruptHandle = CreateEventEx(NULL, NULL, NULL, SYNCHRONIZE|EVENT_MODIFY_STATE);
+ timerIdToHandle.insert(INTERRUPT_HANDLE, interruptHandle);
+ timerHandleToId.insert(interruptHandle, INTERRUPT_HANDLE);
+ timerInfos.reserve(256);
}
QEventDispatcherWinRTPrivate::~QEventDispatcherWinRTPrivate()
{
+ CloseHandle(timerIdToHandle.value(INTERRUPT_HANDLE));
CoUninitialize();
}
diff --git a/src/corelib/kernel/qmetatype.cpp b/src/corelib/kernel/qmetatype.cpp
index d4a69ee4b9..3b70ef92ed 100644
--- a/src/corelib/kernel/qmetatype.cpp
+++ b/src/corelib/kernel/qmetatype.cpp
@@ -872,13 +872,17 @@ static inline int qMetaTypeStaticType(const char *typeName, int length)
\internal
Similar to QMetaType::type(), but only looks in the custom set of
types, and doesn't lock the mutex.
+ The extra \a firstInvalidIndex parameter is an easy way to avoid
+ iterating over customTypes() a second time in registerNormalizedType().
*/
-static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
+static int qMetaTypeCustomType_unlocked(const char *typeName, int length, int *firstInvalidIndex = 0)
{
const QVector<QCustomTypeInfo> * const ct = customTypes();
if (!ct)
return QMetaType::UnknownType;
+ if (firstInvalidIndex)
+ *firstInvalidIndex = -1;
for (int v = 0; v < ct->count(); ++v) {
const QCustomTypeInfo &customInfo = ct->at(v);
if ((length == customInfo.typeName.size())
@@ -887,6 +891,8 @@ static int qMetaTypeCustomType_unlocked(const char *typeName, int length)
return customInfo.alias;
return v + QMetaType::User;
}
+ if (firstInvalidIndex && (*firstInvalidIndex < 0) && customInfo.typeName.isEmpty())
+ *firstInvalidIndex = v;
}
return QMetaType::UnknownType;
}
@@ -907,6 +913,39 @@ int QMetaType::registerType(const char *typeName, Deleter deleter,
/*!
\internal
+ \since 5.5
+
+ Unregisters the user type with the given \a typeId and all its aliases.
+ Returns \c true if the type was unregistered or \c false otherwise.
+
+ This function was added for QML to be able to deregister types after
+ they are unloaded to prevent an infinite increase in custom types for
+ applications that are unloading/reloading components often.
+ */
+bool QMetaType::unregisterType(int type)
+{
+ QWriteLocker locker(customTypesLock());
+ QVector<QCustomTypeInfo> *ct = customTypes();
+
+ // check if user type
+ if ((type < User) || ((type - User) >= ct->size()))
+ return false;
+
+ // only types without Q_DECLARE_METATYPE can be unregistered
+ if (ct->data()[type - User].flags & WasDeclaredAsMetaType)
+ return false;
+
+ // invalidate type and all its alias entries
+ for (int v = 0; v < ct->count(); ++v) {
+ if (((v + User) == type) || (ct->at(v).alias == type))
+ ct->data()[v].typeName.clear();
+ }
+ return true;
+}
+
+
+/*!
+ \internal
\since 5.0
Registers a user type for marshalling, with \a typeName, a \a
@@ -977,8 +1016,10 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
int previousFlags = 0;
if (idx == UnknownType) {
QWriteLocker locker(customTypesLock());
+ int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
- normalizedTypeName.size());
+ normalizedTypeName.size(),
+ &posInVector);
if (idx == UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
@@ -992,8 +1033,13 @@ int QMetaType::registerNormalizedType(const NS(QByteArray) &normalizedTypeName,
inf.size = size;
inf.flags = flags;
inf.metaObject = metaObject;
- idx = ct->size() + User;
- ct->append(inf);
+ if (posInVector == -1) {
+ idx = ct->size() + User;
+ ct->append(inf);
+ } else {
+ idx = posInVector + User;
+ ct->data()[posInVector] = inf;
+ }
return idx;
}
@@ -1075,14 +1121,19 @@ int QMetaType::registerNormalizedTypedef(const NS(QByteArray) &normalizedTypeNam
if (idx == UnknownType) {
QWriteLocker locker(customTypesLock());
+ int posInVector = -1;
idx = qMetaTypeCustomType_unlocked(normalizedTypeName.constData(),
- normalizedTypeName.size());
+ normalizedTypeName.size(),
+ &posInVector);
if (idx == UnknownType) {
QCustomTypeInfo inf;
inf.typeName = normalizedTypeName;
inf.alias = aliasId;
- ct->append(inf);
+ if (posInVector == -1)
+ ct->append(inf);
+ else
+ ct->data()[posInVector] = inf;
return aliasId;
}
}
diff --git a/src/corelib/kernel/qmetatype.h b/src/corelib/kernel/qmetatype.h
index aa8d826ed9..1e2a860d8c 100644
--- a/src/corelib/kernel/qmetatype.h
+++ b/src/corelib/kernel/qmetatype.h
@@ -484,6 +484,7 @@ public:
int size,
QMetaType::TypeFlags flags,
const QMetaObject *metaObject);
+ static bool unregisterType(int type);
static int registerNormalizedType(const QT_PREPEND_NAMESPACE(QByteArray) &normalizedTypeName, Deleter deleter,
Creator creator,
Destructor destructor,
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 31c749dc13..fb4c5cceb9 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -1394,7 +1394,7 @@ bool QObject::eventFilter(QObject * /* watched */, QEvent * /* event */)
\sa signalsBlocked()
*/
-bool QObject::blockSignals(bool block)
+bool QObject::blockSignals(bool block) Q_DECL_NOTHROW
{
Q_D(QObject);
bool previous = d->blockSig;
@@ -1475,7 +1475,7 @@ void QObject::moveToThread(QThread *targetThread)
currentData->thread, d->threadData->thread, targetData ? targetData->thread : Q_NULLPTR);
#ifdef Q_OS_MAC
- qWarning("On Mac OS X, you might be loading two sets of Qt binaries into the same process. "
+ qWarning("You might be loading two sets of Qt binaries into the same process. "
"Check that all plugins are compiled against the right Qt binaries. Export "
"DYLD_PRINT_LIBRARIES=1 and check that only one set of binaries are being loaded.");
#endif
diff --git a/src/corelib/kernel/qobject.h b/src/corelib/kernel/qobject.h
index 42d18d6c41..5f61dd984f 100644
--- a/src/corelib/kernel/qobject.h
+++ b/src/corelib/kernel/qobject.h
@@ -137,8 +137,8 @@ public:
inline bool isWidgetType() const { return d_ptr->isWidget; }
inline bool isWindowType() const { return d_ptr->isWindow; }
- inline bool signalsBlocked() const { return d_ptr->blockSig; }
- bool blockSignals(bool b);
+ inline bool signalsBlocked() const Q_DECL_NOTHROW { return d_ptr->blockSig; }
+ bool blockSignals(bool b) Q_DECL_NOTHROW;
QThread *thread() const;
void moveToThread(QThread *thread);
@@ -413,11 +413,7 @@ public:
Q_SIGNALS:
void destroyed(QObject * = 0);
- void objectNameChanged(const QString &objectName
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void objectNameChanged(const QString &objectName, QPrivateSignal);
public:
inline QObject *parent() const { return d_ptr->parent; }
@@ -552,17 +548,17 @@ Q_CORE_EXPORT QDebug operator<<(QDebug, const QObject *);
class QSignalBlocker
{
public:
- inline explicit QSignalBlocker(QObject *o);
- inline explicit QSignalBlocker(QObject &o);
+ inline explicit QSignalBlocker(QObject *o) Q_DECL_NOTHROW;
+ inline explicit QSignalBlocker(QObject &o) Q_DECL_NOTHROW;
inline ~QSignalBlocker();
#ifdef Q_COMPILER_RVALUE_REFS
- inline QSignalBlocker(QSignalBlocker &&other);
- inline QSignalBlocker &operator=(QSignalBlocker &&other);
+ inline QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW;
+ inline QSignalBlocker &operator=(QSignalBlocker &&other) Q_DECL_NOTHROW;
#endif
- inline void reblock();
- inline void unblock();
+ inline void reblock() Q_DECL_NOTHROW;
+ inline void unblock() Q_DECL_NOTHROW;
private:
Q_DISABLE_COPY(QSignalBlocker)
QObject * m_o;
@@ -570,20 +566,20 @@ private:
bool m_inhibited;
};
-QSignalBlocker::QSignalBlocker(QObject *o)
+QSignalBlocker::QSignalBlocker(QObject *o) Q_DECL_NOTHROW
: m_o(o),
m_blocked(o && o->blockSignals(true)),
m_inhibited(false)
{}
-QSignalBlocker::QSignalBlocker(QObject &o)
+QSignalBlocker::QSignalBlocker(QObject &o) Q_DECL_NOTHROW
: m_o(&o),
m_blocked(o.blockSignals(true)),
m_inhibited(false)
{}
#ifdef Q_COMPILER_RVALUE_REFS
-QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
+QSignalBlocker::QSignalBlocker(QSignalBlocker &&other) Q_DECL_NOTHROW
: m_o(other.m_o),
m_blocked(other.m_blocked),
m_inhibited(other.m_inhibited)
@@ -591,7 +587,7 @@ QSignalBlocker::QSignalBlocker(QSignalBlocker &&other)
other.m_o = 0;
}
-QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other)
+QSignalBlocker &QSignalBlocker::operator=(QSignalBlocker &&other) Q_DECL_NOTHROW
{
if (this != &other) {
// if both *this and other block the same object's signals:
@@ -614,13 +610,13 @@ QSignalBlocker::~QSignalBlocker()
m_o->blockSignals(m_blocked);
}
-void QSignalBlocker::reblock()
+void QSignalBlocker::reblock() Q_DECL_NOTHROW
{
if (m_o) m_o->blockSignals(true);
m_inhibited = false;
}
-void QSignalBlocker::unblock()
+void QSignalBlocker::unblock() Q_DECL_NOTHROW
{
if (m_o) m_o->blockSignals(m_blocked);
m_inhibited = true;
diff --git a/src/corelib/kernel/qppsattribute.cpp b/src/corelib/kernel/qppsattribute.cpp
index e4f7339e6c..f91a6d02d6 100644
--- a/src/corelib/kernel/qppsattribute.cpp
+++ b/src/corelib/kernel/qppsattribute.cpp
@@ -37,6 +37,8 @@
#include <QDebug>
#include <QVariant>
+QT_BEGIN_NAMESPACE
+
///////////////////////////
//
// QPpsAttributePrivate
@@ -298,3 +300,5 @@ QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute)
return dbg;
}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qppsattribute_p.h b/src/corelib/kernel/qppsattribute_p.h
index 528cbbc0ca..5ed0daaad0 100644
--- a/src/corelib/kernel/qppsattribute_p.h
+++ b/src/corelib/kernel/qppsattribute_p.h
@@ -57,8 +57,6 @@ class QPpsAttribute;
typedef QList<QPpsAttribute> QPpsAttributeList;
typedef QMap<QString, QPpsAttribute> QPpsAttributeMap;
-Q_DECLARE_METATYPE(QPpsAttributeList)
-Q_DECLARE_METATYPE(QPpsAttributeMap)
class Q_CORE_EXPORT QPpsAttribute
{
@@ -128,4 +126,7 @@ Q_CORE_EXPORT QDebug operator<<(QDebug dbg, const QPpsAttribute &attribute);
QT_END_NAMESPACE
+Q_DECLARE_METATYPE(QPpsAttributeList)
+Q_DECLARE_METATYPE(QPpsAttributeMap)
+
#endif // QPPSATTRIBUTE_P_H
diff --git a/src/corelib/kernel/qppsobject.cpp b/src/corelib/kernel/qppsobject.cpp
index e9b455bfba..76508f12c5 100644
--- a/src/corelib/kernel/qppsobject.cpp
+++ b/src/corelib/kernel/qppsobject.cpp
@@ -50,6 +50,8 @@
#include <sys/pps.h>
+QT_BEGIN_NAMESPACE
+
///////////////////////////////////////////////////////////////////////////////
static inline void safeAssign(bool *pointer, bool value)
{
@@ -954,3 +956,5 @@ int QPpsObject::sendMessage(const QString &path, const QByteArray &ppsData)
return EOK;
}
+
+QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qsocketnotifier.h b/src/corelib/kernel/qsocketnotifier.h
index c6e9d1e13f..4bafbfa69f 100644
--- a/src/corelib/kernel/qsocketnotifier.h
+++ b/src/corelib/kernel/qsocketnotifier.h
@@ -59,11 +59,7 @@ public Q_SLOTS:
void setEnabled(bool);
Q_SIGNALS:
- void activated(int socket
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void activated(int socket, QPrivateSignal);
protected:
bool event(QEvent *) Q_DECL_OVERRIDE;
diff --git a/src/corelib/kernel/qtimer.h b/src/corelib/kernel/qtimer.h
index dc948228b4..163ef75291 100644
--- a/src/corelib/kernel/qtimer.h
+++ b/src/corelib/kernel/qtimer.h
@@ -141,11 +141,7 @@ public Q_SLOTS:
void stop();
Q_SIGNALS:
- void timeout(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void timeout(QPrivateSignal);
protected:
void timerEvent(QTimerEvent *) Q_DECL_OVERRIDE;
diff --git a/src/corelib/kernel/qwineventnotifier.h b/src/corelib/kernel/qwineventnotifier.h
index 07a0b29d97..95fdff07ce 100644
--- a/src/corelib/kernel/qwineventnotifier.h
+++ b/src/corelib/kernel/qwineventnotifier.h
@@ -61,11 +61,7 @@ public Q_SLOTS:
void setEnabled(bool enable);
Q_SIGNALS:
- void activated(HANDLE hEvent
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
+ void activated(HANDLE hEvent, QPrivateSignal);
protected:
bool event(QEvent * e);
diff --git a/src/corelib/mimetypes/qmimedatabase.cpp b/src/corelib/mimetypes/qmimedatabase.cpp
index b919e1c48a..bec7a79e8f 100644
--- a/src/corelib/mimetypes/qmimedatabase.cpp
+++ b/src/corelib/mimetypes/qmimedatabase.cpp
@@ -238,7 +238,7 @@ bool QMimeDatabasePrivate::inherits(const QString &mime, const QString &parent)
The MIME type database is provided by the freedesktop.org shared-mime-info
project. If the MIME type database cannot be found on the system, as is the case
- on most Windows and Mac OS X systems, Qt will use its own copy of it.
+ on most Windows, OS X, and iOS systems, Qt will use its own copy of it.
Applications which want to define custom MIME types need to install an
XML file into the locations searched for MIME definitions.
diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp
index c843d029af..920e02ae5a 100644
--- a/src/corelib/plugin/qlibrary.cpp
+++ b/src/corelib/plugin/qlibrary.cpp
@@ -599,7 +599,7 @@ bool QLibraryPrivate::loadPlugin()
\row \li Unix/Linux \li \c .so
\row \li AIX \li \c .a
\row \li HP-UX \li \c .sl, \c .so (HP-UXi)
- \row \li Mac OS X \li \c .dylib, \c .bundle, \c .so
+ \row \li OS X and iOS \li \c .dylib, \c .bundle, \c .so
\endtable
Trailing versioning numbers on Unix are ignored.
@@ -836,7 +836,7 @@ QLibrary::QLibrary(QObject *parent)
We recommend omitting the file's suffix in \a fileName, since
QLibrary will automatically look for the file with the appropriate
suffix in accordance with the platform, e.g. ".so" on Unix,
- ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
QLibrary::QLibrary(const QString& fileName, QObject *parent)
:QObject(parent), d(0), did_load(false)
@@ -853,7 +853,7 @@ QLibrary::QLibrary(const QString& fileName, QObject *parent)
We recommend omitting the file's suffix in \a fileName, since
QLibrary will automatically look for the file with the appropriate
suffix in accordance with the platform, e.g. ".so" on Unix,
- ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
:QObject(parent), d(0), did_load(false)
@@ -869,7 +869,7 @@ QLibrary::QLibrary(const QString& fileName, int verNum, QObject *parent)
We recommend omitting the file's suffix in \a fileName, since
QLibrary will automatically look for the file with the appropriate
suffix in accordance with the platform, e.g. ".so" on Unix,
- ".dylib" on Mac OS X, and ".dll" on Windows. (See \l{fileName}.)
+ ".dylib" on OS X and iOS, and ".dll" on Windows. (See \l{fileName}.)
*/
QLibrary::QLibrary(const QString& fileName, const QString &version, QObject *parent)
:QObject(parent), d(0), did_load(false)
diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp
index 2800656c13..2756414d70 100644
--- a/src/corelib/plugin/qpluginloader.cpp
+++ b/src/corelib/plugin/qpluginloader.cpp
@@ -139,7 +139,7 @@ QPluginLoader::QPluginLoader(QObject *parent)
To be loadable, the file's suffix must be a valid suffix for a
loadable library in accordance with the platform, e.g. \c .so on
- Unix, - \c .dylib on Mac OS X, and \c .dll on Windows. The suffix
+ Unix, - \c .dylib on OS X and iOS, and \c .dll on Windows. The suffix
can be verified with QLibrary::isLibrary().
\sa setFileName()
diff --git a/src/corelib/statemachine/qabstractstate.h b/src/corelib/statemachine/qabstractstate.h
index b6eb742acb..592c841c18 100644
--- a/src/corelib/statemachine/qabstractstate.h
+++ b/src/corelib/statemachine/qabstractstate.h
@@ -58,16 +58,8 @@ public:
bool active() const;
Q_SIGNALS:
- void entered(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void exited(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void entered(QPrivateSignal);
+ void exited(QPrivateSignal);
void activeChanged(bool active);
protected:
diff --git a/src/corelib/statemachine/qabstracttransition.h b/src/corelib/statemachine/qabstracttransition.h
index 0f1bbdad71..768a364a4b 100644
--- a/src/corelib/statemachine/qabstracttransition.h
+++ b/src/corelib/statemachine/qabstracttransition.h
@@ -78,21 +78,9 @@ public:
#endif
Q_SIGNALS:
- void triggered(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void targetStateChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void targetStatesChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void triggered(QPrivateSignal);
+ void targetStateChanged(QPrivateSignal);
+ void targetStatesChanged(QPrivateSignal);
protected:
virtual bool eventTest(QEvent *event) = 0;
diff --git a/src/corelib/statemachine/qhistorystate.h b/src/corelib/statemachine/qhistorystate.h
index 31f0d3121b..549be15ab0 100644
--- a/src/corelib/statemachine/qhistorystate.h
+++ b/src/corelib/statemachine/qhistorystate.h
@@ -65,16 +65,8 @@ public:
void setHistoryType(HistoryType type);
Q_SIGNALS:
- void defaultStateChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void historyTypeChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void defaultStateChanged(QPrivateSignal);
+ void historyTypeChanged(QPrivateSignal);
protected:
void onEntry(QEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/corelib/statemachine/qsignaltransition.h b/src/corelib/statemachine/qsignaltransition.h
index 8b9e63404a..bc56f4e9b7 100644
--- a/src/corelib/statemachine/qsignaltransition.h
+++ b/src/corelib/statemachine/qsignaltransition.h
@@ -67,16 +67,8 @@ protected:
bool event(QEvent *e) Q_DECL_OVERRIDE;
Q_SIGNALS:
- void senderObjectChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void signalChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void senderObjectChanged(QPrivateSignal);
+ void signalChanged(QPrivateSignal);
private:
Q_DISABLE_COPY(QSignalTransition)
diff --git a/src/corelib/statemachine/qstate.h b/src/corelib/statemachine/qstate.h
index b1f2ad05bc..a74c782027 100644
--- a/src/corelib/statemachine/qstate.h
+++ b/src/corelib/statemachine/qstate.h
@@ -103,31 +103,11 @@ public:
#endif
Q_SIGNALS:
- void finished(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void propertiesAssigned(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void childModeChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void initialStateChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void errorStateChanged(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void finished(QPrivateSignal);
+ void propertiesAssigned(QPrivateSignal);
+ void childModeChanged(QPrivateSignal);
+ void initialStateChanged(QPrivateSignal);
+ void errorStateChanged(QPrivateSignal);
protected:
void onEntry(QEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp
index a681688d46..f103bec591 100644
--- a/src/corelib/statemachine/qstatemachine.cpp
+++ b/src/corelib/statemachine/qstatemachine.cpp
@@ -177,6 +177,98 @@ QT_BEGIN_NAMESPACE
// #define QSTATEMACHINE_DEBUG
// #define QSTATEMACHINE_RESTORE_PROPERTIES_DEBUG
+/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+function isDescendant(state1, state2)
+
+Returns 'true' if state1 is a descendant of state2 (a child, or a child of a child, or a child of a
+child of a child, etc.) Otherwise returns 'false'.
+*/
+static inline bool isDescendant(const QAbstractState *state1, const QAbstractState *state2)
+{
+ Q_ASSERT(state1 != 0);
+
+ for (QAbstractState *it = state1->parentState(); it != 0; it = it->parentState()) {
+ if (it == state2)
+ return true;
+ }
+
+ return false;
+}
+
+static bool containsDecendantOf(const QSet<QAbstractState *> &states, const QAbstractState *node)
+{
+ Q_FOREACH (QAbstractState *s, states)
+ if (isDescendant(s, node))
+ return true;
+
+ return false;
+}
+
+/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+function getProperAncestors(state1, state2)
+
+If state2 is null, returns the set of all ancestors of state1 in ancestry order (state1's parent
+followed by the parent's parent, etc. up to an including the <scxml> element). If state2 is
+non-null, returns in ancestry order the set of all ancestors of state1, up to but not including
+state2. (A "proper ancestor" of a state is its parent, or the parent's parent, or the parent's
+parent's parent, etc.))If state2 is state1's parent, or equal to state1, or a descendant of state1,
+this returns the empty set.
+*/
+static QVector<QState*> getProperAncestors(const QAbstractState *state, const QAbstractState *upperBound)
+{
+ Q_ASSERT(state != 0);
+ QVector<QState*> result;
+ result.reserve(16);
+ for (QState *it = state->parentState(); it && it != upperBound; it = it->parentState()) {
+ result.append(it);
+ }
+ return result;
+}
+
+/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+function getEffectiveTargetStates(transition)
+
+Returns the states that will be the target when 'transition' is taken, dereferencing any history states.
+
+function getEffectiveTargetStates(transition)
+ targets = new OrderedSet()
+ for s in transition.target
+ if isHistoryState(s):
+ if historyValue[s.id]:
+ targets.union(historyValue[s.id])
+ else:
+ targets.union(getEffectiveTargetStates(s.transition))
+ else:
+ targets.add(s)
+ return targets
+*/
+static QSet<QAbstractState *> getEffectiveTargetStates(QAbstractTransition *transition)
+{
+ QSet<QAbstractState *> targets;
+ foreach (QAbstractState *s, transition->targetStates()) {
+ if (QHistoryState *historyState = QStateMachinePrivate::toHistoryState(s)) {
+ QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(historyState)->configuration;
+ if (!historyConfiguration.isEmpty()) {
+ // There is a saved history, so apply that.
+ targets.unite(historyConfiguration.toSet());
+ } else if (QAbstractState *defaultState = historyState->defaultState()) {
+ // Qt does not support initial transitions, but uses the default state of the history state for this.
+ targets.insert(defaultState);
+ } else {
+ // Woops, we found a history state without a default state. That's not valid!
+ QStateMachinePrivate *m = QStateMachinePrivate::get(historyState->machine());
+ m->setError(QStateMachine::NoDefaultStateInHistoryStateError, historyState);
+ }
+ } else {
+ targets.insert(s);
+ }
+ }
+ return targets;
+}
+
template <class T>
static uint qHash(const QPointer<T> &p)
{ return qHash(p.data()); }
@@ -246,21 +338,30 @@ static int indexOfDescendant(QState *s, QAbstractState *desc)
QList<QAbstractState*> childStates = QStatePrivate::get(s)->childStates();
for (int i = 0; i < childStates.size(); ++i) {
QAbstractState *c = childStates.at(i);
- if ((c == desc) || QStateMachinePrivate::isDescendantOf(desc, c)) {
+ if ((c == desc) || isDescendant(desc, c)) {
return i;
}
}
return -1;
}
+bool QStateMachinePrivate::transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2)
+{
+ QState *s1 = t1->sourceState(), *s2 = t2->sourceState();
+ if (s1 == s2)
+ return QStatePrivate::get(s1)->transitions().indexOf(t1) < QStatePrivate::get(s2)->transitions().indexOf(t2);
+ else
+ return stateEntryLessThan(t1->sourceState(), t2->sourceState());
+}
+
bool QStateMachinePrivate::stateEntryLessThan(QAbstractState *s1, QAbstractState *s2)
{
if (s1->parent() == s2->parent()) {
return s1->parent()->children().indexOf(s1)
< s2->parent()->children().indexOf(s2);
- } else if (isDescendantOf(s1, s2)) {
+ } else if (isDescendant(s1, s2)) {
return false;
- } else if (isDescendantOf(s2, s1)) {
+ } else if (isDescendant(s2, s1)) {
return true;
} else {
Q_ASSERT(s1->machine() != 0);
@@ -276,9 +377,9 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState
if (s1->parent() == s2->parent()) {
return s2->parent()->children().indexOf(s2)
< s1->parent()->children().indexOf(s1);
- } else if (isDescendantOf(s1, s2)) {
+ } else if (isDescendant(s1, s2)) {
return true;
- } else if (isDescendantOf(s2, s1)) {
+ } else if (isDescendant(s2, s1)) {
return false;
} else {
Q_ASSERT(s1->machine() != 0);
@@ -289,17 +390,20 @@ bool QStateMachinePrivate::stateExitLessThan(QAbstractState *s1, QAbstractState
}
}
-QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) const
+QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states, bool onlyCompound) const
{
if (states.isEmpty())
return 0;
- QList<QState*> ancestors = properAncestors(states.at(0), rootState()->parentState());
+ QVector<QState*> ancestors = getProperAncestors(states.at(0), rootState()->parentState());
for (int i = 0; i < ancestors.size(); ++i) {
QState *anc = ancestors.at(i);
+ if (onlyCompound && !isCompound(anc))
+ continue;
+
bool ok = true;
for (int j = states.size() - 1; (j > 0) && ok; --j) {
const QAbstractState *s = states.at(j);
- if (!isDescendantOf(s, anc))
+ if (!isDescendant(s, anc))
ok = false;
}
if (ok)
@@ -308,40 +412,26 @@ QState *QStateMachinePrivate::findLCA(const QList<QAbstractState*> &states) cons
return 0;
}
-bool QStateMachinePrivate::isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const
+QState *QStateMachinePrivate::findLCCA(const QList<QAbstractState*> &states) const
{
- QSet<QAbstractTransition*>::const_iterator it;
- for (it = transitions.constBegin(); it != transitions.constEnd(); ++it) {
- QAbstractTransition *t = *it;
- QList<QAbstractState*> lst = t->targetStates();
- if (!lst.isEmpty()) {
- lst.prepend(t->sourceState());
- QAbstractState *lca = findLCA(lst);
- if (isDescendantOf(s, lca)) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q_func() << ':' << transitions << "preempts selection of a transition from"
- << s << "because" << s << "is a descendant of" << lca;
-#endif
- return true;
- }
- }
- }
- return false;
+ return findLCA(states, true);
}
-QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event) const
+QList<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event)
{
Q_Q(const QStateMachine);
- QSet<QAbstractTransition*> enabledTransitions;
- QSet<QAbstractState*>::const_iterator it;
+
+ QVarLengthArray<QAbstractState *> configuration_sorted;
+ foreach (QAbstractState *s, configuration) {
+ if (isAtomic(s))
+ configuration_sorted.append(s);
+ }
+ std::sort(configuration_sorted.begin(), configuration_sorted.end(), stateEntryLessThan);
+
+ QList<QAbstractTransition*> enabledTransitions;
const_cast<QStateMachine*>(q)->beginSelectTransitions(event);
- for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- QAbstractState *state = *it;
- if (!isAtomic(state))
- continue;
- if (isPreempted(state, enabledTransitions))
- continue;
- QList<QState*> lst = properAncestors(state, rootState()->parentState());
+ foreach (QAbstractState *state, configuration_sorted) {
+ QVector<QState*> lst = getProperAncestors(state, Q_NULLPTR);
if (QState *grp = toStandardState(state))
lst.prepend(grp);
bool found = false;
@@ -354,28 +444,93 @@ QSet<QAbstractTransition*> QStateMachinePrivate::selectTransitions(QEvent *event
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q << ": selecting transition" << t;
#endif
- enabledTransitions.insert(t);
+ enabledTransitions.append(t);
found = true;
break;
}
}
}
}
+
+ if (!enabledTransitions.isEmpty()) {
+ removeConflictingTransitions(enabledTransitions);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": enabled transitions after removing conflicts:" << enabledTransitions;
+#endif
+ }
const_cast<QStateMachine*>(q)->endSelectTransitions(event);
return enabledTransitions;
}
+/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+function removeConflictingTransitions(enabledTransitions):
+ filteredTransitions = new OrderedSet()
+ // toList sorts the transitions in the order of the states that selected them
+ for t1 in enabledTransitions.toList():
+ t1Preempted = false;
+ transitionsToRemove = new OrderedSet()
+ for t2 in filteredTransitions.toList():
+ if computeExitSet([t1]).hasIntersection(computeExitSet([t2])):
+ if isDescendant(t1.source, t2.source):
+ transitionsToRemove.add(t2)
+ else:
+ t1Preempted = true
+ break
+ if not t1Preempted:
+ for t3 in transitionsToRemove.toList():
+ filteredTransitions.delete(t3)
+ filteredTransitions.add(t1)
+
+ return filteredTransitions
+*/
+void QStateMachinePrivate::removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions)
+{
+ QList<QAbstractTransition*> filteredTransitions;
+ filteredTransitions.reserve(enabledTransitions.size());
+ std::sort(enabledTransitions.begin(), enabledTransitions.end(), transitionStateEntryLessThan);
+
+ Q_FOREACH (QAbstractTransition *t1, enabledTransitions) {
+ bool t1Preempted = false;
+ QVarLengthArray<QAbstractTransition *> transitionsToRemove;
+ QSet<QAbstractState*> exitSetT1 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t1);
+ Q_FOREACH (QAbstractTransition *t2, filteredTransitions) {
+ QSet<QAbstractState*> exitSetT2 = computeExitSet_Unordered(QList<QAbstractTransition*>() << t2);
+ if (!exitSetT1.intersect(exitSetT2).isEmpty()) {
+ if (isDescendant(t1->sourceState(), t2->sourceState())) {
+ transitionsToRemove.append(t2);
+ } else {
+ t1Preempted = true;
+ break;
+ }
+ }
+ }
+ if (!t1Preempted) {
+ Q_FOREACH (QAbstractTransition *t3, transitionsToRemove)
+ filteredTransitions.removeAll(t3);
+ filteredTransitions.append(t1);
+ }
+ }
+
+ enabledTransitions = filteredTransitions;
+}
+
void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransition*> &enabledTransitions)
{
#ifdef QSTATEMACHINE_DEBUG
qDebug() << q_func() << ": begin microstep( enabledTransitions:" << enabledTransitions << ')';
qDebug() << q_func() << ": configuration before exiting states:" << configuration;
#endif
- QList<QAbstractState*> exitedStates = computeStatesToExit(enabledTransitions);
+ QList<QAbstractState*> exitedStates = computeExitSet(enabledTransitions);
QHash<RestorableId, QVariant> pendingRestorables = computePendingRestorables(exitedStates);
QSet<QAbstractState*> statesForDefaultEntry;
- QList<QAbstractState*> enteredStates = computeStatesToEnter(enabledTransitions, statesForDefaultEntry);
+ QList<QAbstractState*> enteredStates = computeEntrySet(enabledTransitions, statesForDefaultEntry);
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": computed exit set:" << exitedStates;
+ qDebug() << q_func() << ": computed entry set:" << enteredStates;
+#endif
QHash<QAbstractState*, QList<QPropertyAssignment> > assignmentsForEnteredStates =
computePropertyAssignments(enteredStates, pendingRestorables);
@@ -409,38 +564,63 @@ void QStateMachinePrivate::microstep(QEvent *event, const QList<QAbstractTransit
#endif
}
-QList<QAbstractState*> QStateMachinePrivate::computeStatesToExit(const QList<QAbstractTransition*> &enabledTransitions)
+/* The function as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+procedure computeExitSet(enabledTransitions)
+
+For each transition t in enabledTransitions, if t is targetless then do nothing, else compute the
+transition's domain. (This will be the source state in the case of internal transitions) or the
+least common compound ancestor state of the source state and target states of t (in the case of
+external transitions. Add to the statesToExit set all states in the configuration that are
+descendants of the domain.
+
+function computeExitSet(transitions)
+ statesToExit = new OrderedSet
+ for t in transitions:
+ if (t.target):
+ domain = getTransitionDomain(t)
+ for s in configuration:
+ if isDescendant(s,domain):
+ statesToExit.add(s)
+ return statesToExit
+*/
+QList<QAbstractState*> QStateMachinePrivate::computeExitSet(const QList<QAbstractTransition*> &enabledTransitions)
+{
+ QList<QAbstractState*> statesToExit_sorted = computeExitSet_Unordered(enabledTransitions).toList();
+ std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
+ return statesToExit_sorted;
+}
+
+QSet<QAbstractState*> QStateMachinePrivate::computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions)
{
QSet<QAbstractState*> statesToExit;
-// QSet<QAbstractState*> statesToSnapshot;
for (int i = 0; i < enabledTransitions.size(); ++i) {
QAbstractTransition *t = enabledTransitions.at(i);
- QList<QAbstractState*> lst = t->targetStates();
- if (lst.isEmpty())
- continue;
- lst.prepend(t->sourceState());
- QAbstractState *lca = findLCA(lst);
- if (lca == 0) {
- setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
- lst = pendingErrorStates.toList();
+ QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList();
+ QAbstractState *domain = getTransitionDomain(t, effectiveTargetStates);
+ if (domain == Q_NULLPTR && !t->targetStates().isEmpty()) {
+ // So we didn't find the least common ancestor for the source and target states of the
+ // transition. If there were not target states, that would be fine: then the transition
+ // will fire any events or signals, but not exit the state.
+ //
+ // However, there are target states, so it's either a node without a parent (or parent's
+ // parent, etc), or the state belongs to a different state machine. Either way, this
+ // makes the state machine invalid.
+ if (error == QStateMachine::NoError)
+ setError(QStateMachine::NoCommonAncestorForTransitionError, t->sourceState());
+ QList<QAbstractState *> lst = pendingErrorStates.toList();
lst.prepend(t->sourceState());
- lca = findLCA(lst);
- Q_ASSERT(lca != 0);
+ domain = findLCCA(lst);
+ Q_ASSERT(domain != 0);
}
- {
- QSet<QAbstractState*>::const_iterator it;
- for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
- QAbstractState *s = *it;
- if (isDescendantOf(s, lca))
- statesToExit.insert(s);
- }
+ Q_FOREACH (QAbstractState* s, configuration) {
+ if (isDescendant(s, domain))
+ statesToExit.insert(s);
}
}
- QList<QAbstractState*> statesToExit_sorted = statesToExit.toList();
- std::sort(statesToExit_sorted.begin(), statesToExit_sorted.end(), stateExitLessThan);
- return statesToExit_sorted;
+ return statesToExit;
}
void QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractState*> &statesToExit_sorted,
@@ -457,7 +637,7 @@ void QStateMachinePrivate::exitStates(QEvent *event, const QList<QAbstractState*
for (it = configuration.constBegin(); it != configuration.constEnd(); ++it) {
QAbstractState *s0 = *it;
if (QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) {
- if (isAtomic(s0) && isDescendantOf(s0, s))
+ if (isAtomic(s0) && isDescendant(s0, s))
QHistoryStatePrivate::get(h)->configuration.append(s0);
} else if (s0->parentState() == s) {
QHistoryStatePrivate::get(h)->configuration.append(s0);
@@ -500,30 +680,20 @@ void QStateMachinePrivate::executeTransitionContent(QEvent *event, const QList<Q
}
}
-QList<QAbstractState*> QStateMachinePrivate::computeStatesToEnter(const QList<QAbstractTransition *> &enabledTransitions,
- QSet<QAbstractState *> &statesForDefaultEntry)
+QList<QAbstractState*> QStateMachinePrivate::computeEntrySet(const QList<QAbstractTransition *> &enabledTransitions,
+ QSet<QAbstractState *> &statesForDefaultEntry)
{
QSet<QAbstractState*> statesToEnter;
if (pendingErrorStates.isEmpty()) {
- for (int i = 0; i < enabledTransitions.size(); ++i) {
- QAbstractTransition *t = enabledTransitions.at(i);
- QList<QAbstractState*> lst = t->targetStates();
- if (lst.isEmpty())
- continue;
- QAbstractState *src = t->sourceState();
- if (src)
- lst.prepend(src);
- QState *lca = findLCA(lst);
- for (int j = src ? 1 : 0; j < lst.size(); ++j) {
- QAbstractState *s = lst.at(j);
- addStatesToEnter(s, lca, statesToEnter, statesForDefaultEntry);
+ Q_FOREACH (QAbstractTransition *t, enabledTransitions) {
+ Q_FOREACH (QAbstractState *s, t->targetStates()) {
+ addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
}
- if (isParallel(lca)) {
- QList<QAbstractState*> lcac = QStatePrivate::get(lca)->childStates();
- foreach (QAbstractState* child,lcac) {
- if (!statesToEnter.contains(child))
- addStatesToEnter(child,lca,statesToEnter,statesForDefaultEntry);
- }
+
+ QList<QAbstractState *> effectiveTargetStates = getEffectiveTargetStates(t).toList();
+ QAbstractState *ancestor = getTransitionDomain(t, effectiveTargetStates);
+ Q_FOREACH (QAbstractState *s, effectiveTargetStates) {
+ addAncestorStatesToEnter(s, ancestor, statesToEnter, statesForDefaultEntry);
}
}
}
@@ -542,6 +712,51 @@ QList<QAbstractState*> QStateMachinePrivate::computeStatesToEnter(const QList<QA
return statesToEnter_sorted;
}
+/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+function getTransitionDomain(transition)
+
+Return the compound state such that 1) all states that are exited or entered as a result of taking
+'transition' are descendants of it 2) no descendant of it has this property.
+
+function getTransitionDomain(t)
+ tstates = getEffectiveTargetStates(t)
+ if not tstates:
+ return null
+ elif t.type == "internal" and isCompoundState(t.source) and tstates.every(lambda s: isDescendant(s,t.source)):
+ return t.source
+ else:
+ return findLCCA([t.source].append(tstates))
+*/
+QAbstractState *QStateMachinePrivate::getTransitionDomain(QAbstractTransition *t, const QList<QAbstractState *> &effectiveTargetStates) const
+{
+ if (effectiveTargetStates.isEmpty())
+ return 0;
+
+#if 0
+ // Qt only has external transitions, so skip the special case for the internal transitions
+ if (QState *tSource = t->sourceState()) {
+ if (isCompound(tSource)) {
+ bool allDescendants = true;
+ Q_FOREACH (QAbstractState *s, effectiveTargetStates) {
+ if (!isDescendant(s, tSource)) {
+ allDescendants = false;
+ break;
+ }
+ }
+
+ if (allDescendants)
+ return tSource;
+ }
+ }
+#endif
+
+ QList<QAbstractState *> states(effectiveTargetStates);
+ if (QAbstractState *src = t->sourceState())
+ states.prepend(src);
+ return findLCCA(states);
+}
+
void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
const QList<QAbstractState*> &statesToEnter_sorted,
const QSet<QAbstractState*> &statesForDefaultEntry,
@@ -610,10 +825,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState
QState *parent = s->parentState();
if (parent) {
if (parent != rootState()) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": emitting finished signal for" << parent;
-#endif
- QStatePrivate::get(parent)->emitFinished();
+ QFinalState *finalState = qobject_cast<QFinalState *>(s);
+ Q_ASSERT(finalState);
+ emitStateFinished(parent, finalState);
}
QState *grandparent = parent->parentState();
if (grandparent && isParallel(grandparent)) {
@@ -627,10 +841,9 @@ void QStateMachinePrivate::enterStates(QEvent *event, const QList<QAbstractState
}
}
if (allChildStatesFinal && (grandparent != rootState())) {
-#ifdef QSTATEMACHINE_DEBUG
- qDebug() << q << ": emitting finished signal for" << grandparent;
-#endif
- QStatePrivate::get(grandparent)->emitFinished();
+ QFinalState *finalState = qobject_cast<QFinalState *>(s);
+ Q_ASSERT(finalState);
+ emitStateFinished(grandparent, finalState);
}
}
}
@@ -719,30 +932,126 @@ void QStateMachinePrivate::addStatesToEnter(QAbstractState *s, QState *root,
}
}
-void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QState *root,
+/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ has a bug. See
+ * QTBUG-44963 for details. The algorithm here is as described in
+ * http://www.w3.org/Voice/2013/scxml-irp/SCXML.htm as of Friday March 13, 2015.
+
+procedure addDescendantStatesToEnter(state,statesToEnter,statesForDefaultEntry, defaultHistoryContent):
+ if isHistoryState(state):
+ if historyValue[state.id]:
+ for s in historyValue[state.id]:
+ addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
+ for s in historyValue[state.id]:
+ addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
+ else:
+ defaultHistoryContent[state.parent.id] = state.transition.content
+ for s in state.transition.target:
+ addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
+ for s in state.transition.target:
+ addAncestorStatesToEnter(s, state.parent, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
+ else:
+ statesToEnter.add(state)
+ if isCompoundState(state):
+ statesForDefaultEntry.add(state)
+ for s in state.initial.transition.target:
+ addDescendantStatesToEnter(s,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
+ for s in state.initial.transition.target:
+ addAncestorStatesToEnter(s, state, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
+ else:
+ if isParallelState(state):
+ for child in getChildStates(state):
+ if not statesToEnter.some(lambda s: isDescendant(s,child)):
+ addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
+*/
+void QStateMachinePrivate::addDescendantStatesToEnter(QAbstractState *state,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry)
+{
+ if (QHistoryState *h = toHistoryState(state)) {
+ QList<QAbstractState*> historyConfiguration = QHistoryStatePrivate::get(h)->configuration;
+ if (!historyConfiguration.isEmpty()) {
+ Q_FOREACH (QAbstractState *s, historyConfiguration)
+ addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
+ Q_FOREACH (QAbstractState *s, historyConfiguration)
+ addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry);
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": restoring"
+ << ((QHistoryStatePrivate::get(h)->historyType == QHistoryState::DeepHistory) ? "deep" : "shallow")
+ << "history from" << state << ':' << historyConfiguration;
+#endif
+ } else {
+ QList<QAbstractState*> defaultHistoryContent;
+ if (QHistoryStatePrivate::get(h)->defaultState)
+ defaultHistoryContent.append(QHistoryStatePrivate::get(h)->defaultState);
+
+ if (defaultHistoryContent.isEmpty()) {
+ setError(QStateMachine::NoDefaultStateInHistoryStateError, h);
+ } else {
+ Q_FOREACH (QAbstractState *s, defaultHistoryContent)
+ addDescendantStatesToEnter(s, statesToEnter, statesForDefaultEntry);
+ Q_FOREACH (QAbstractState *s, defaultHistoryContent)
+ addAncestorStatesToEnter(s, state->parentState(), statesToEnter, statesForDefaultEntry);
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q_func() << ": initial history targets for" << state << ':' << defaultHistoryContent;
+#endif
+ }
+ }
+ } else {
+ if (state == rootState()) {
+ // Error has already been set by exitStates().
+ Q_ASSERT(error != QStateMachine::NoError);
+ return;
+ }
+ statesToEnter.insert(state);
+ if (isCompound(state)) {
+ statesForDefaultEntry.insert(state);
+ if (QAbstractState *initial = toStandardState(state)->initialState()) {
+ Q_ASSERT(initial->machine() == q_func());
+
+ // Qt does not support initial transitions (which is a problem for parallel states).
+ // The way it simulates this for other states, is by having a single initial state.
+ statesForDefaultEntry.insert(initial);
+
+ addDescendantStatesToEnter(initial, statesToEnter, statesForDefaultEntry);
+ addAncestorStatesToEnter(initial, state, statesToEnter, statesForDefaultEntry);
+ } else {
+ setError(QStateMachine::NoInitialStateError, state);
+ return;
+ }
+ } else if (isParallel(state)) {
+ QState *grp = toStandardState(state);
+ Q_FOREACH (QAbstractState *child, QStatePrivate::get(grp)->childStates()) {
+ if (!containsDecendantOf(statesToEnter, child))
+ addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry);
+ }
+ }
+ }
+}
+
+
+/* The algorithm as described in http://www.w3.org/TR/2014/WD-scxml-20140529/ :
+
+procedure addAncestorStatesToEnter(state, ancestor, statesToEnter, statesForDefaultEntry, defaultHistoryContent)
+ for anc in getProperAncestors(state,ancestor):
+ statesToEnter.add(anc)
+ if isParallelState(anc):
+ for child in getChildStates(anc):
+ if not statesToEnter.some(lambda s: isDescendant(s,child)):
+ addDescendantStatesToEnter(child,statesToEnter,statesForDefaultEntry, defaultHistoryContent)
+*/
+void QStateMachinePrivate::addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor,
QSet<QAbstractState*> &statesToEnter,
QSet<QAbstractState*> &statesForDefaultEntry)
{
- QList<QState*> ancs = properAncestors(s, root);
- for (int i = 0; i < ancs.size(); ++i) {
- QState *anc = ancs.at(i);
+ Q_FOREACH (QState *anc, getProperAncestors(s, ancestor)) {
if (!anc->parentState())
continue;
statesToEnter.insert(anc);
if (isParallel(anc)) {
- QList<QAbstractState*> lst = QStatePrivate::get(anc)->childStates();
- for (int j = 0; j < lst.size(); ++j) {
- QAbstractState *child = lst.at(j);
- bool hasDescendantInList = false;
- QSet<QAbstractState*>::const_iterator it;
- for (it = statesToEnter.constBegin(); it != statesToEnter.constEnd(); ++it) {
- if (isDescendantOf(*it, child)) {
- hasDescendantInList = true;
- break;
- }
- }
- if (!hasDescendantInList)
- addStatesToEnter(child, anc, statesToEnter, statesForDefaultEntry);
+ Q_FOREACH (QAbstractState *child, QStatePrivate::get(anc)->childStates()) {
+ if (!containsDecendantOf(statesToEnter, child))
+ addDescendantStatesToEnter(child, statesToEnter, statesForDefaultEntry);
}
}
}
@@ -780,27 +1089,6 @@ bool QStateMachinePrivate::isAtomic(const QAbstractState *s) const
|| (ss && QStatePrivate::get(ss)->isMachine && (ss != rootState()));
}
-
-bool QStateMachinePrivate::isDescendantOf(const QAbstractState *state, const QAbstractState *other)
-{
- Q_ASSERT(state != 0);
- for (QAbstractState *s = state->parentState(); s != 0; s = s->parentState()) {
- if (s == other)
- return true;
- }
- return false;
-}
-
-QList<QState*> QStateMachinePrivate::properAncestors(const QAbstractState *state, const QState *upperBound)
-{
- Q_ASSERT(state != 0);
- QList<QState*> result;
- for (QState *s = state->parentState(); s && s != upperBound; s = s->parentState()) {
- result.append(s);
- }
- return result;
-}
-
QState *QStateMachinePrivate::toStandardState(QAbstractState *state)
{
if (state && (QAbstractStatePrivate::get(state)->stateType == QAbstractStatePrivate::StandardState))
@@ -1082,6 +1370,9 @@ void QStateMachinePrivate::setError(QStateMachine::Error errorCode, QAbstractSta
Q_ASSERT(currentErrorState != rootState());
if (currentErrorState != 0) {
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": entering error state" << currentErrorState << "from" << currentContext;
+#endif
QState *lca = findLCA(QList<QAbstractState*>() << currentErrorState << currentContext);
addStatesToEnter(currentErrorState, lca, pendingErrorStates, pendingErrorStatesForDefaultEntry);
} else {
@@ -1385,8 +1676,7 @@ void QStateMachinePrivate::_q_start()
executeTransitionContent(&nullEvent, transitions);
QList<QAbstractState*> exitedStates = QList<QAbstractState*>();
QSet<QAbstractState*> statesForDefaultEntry;
- QList<QAbstractState*> enteredStates = computeStatesToEnter(transitions,
- statesForDefaultEntry);
+ QList<QAbstractState*> enteredStates = computeEntrySet(transitions, statesForDefaultEntry);
QHash<RestorableId, QVariant> pendingRestorables;
QHash<QAbstractState*, QList<QPropertyAssignment> > assignmentsForEnteredStates =
computePropertyAssignments(enteredStates, pendingRestorables);
@@ -1440,7 +1730,7 @@ void QStateMachinePrivate::_q_process()
processing = false;
break;
}
- QSet<QAbstractTransition*> enabledTransitions;
+ QList<QAbstractTransition*> enabledTransitions;
QEvent *e = new QEvent(QEvent::None);
enabledTransitions = selectTransitions(e);
if (enabledTransitions.isEmpty()) {
@@ -1477,7 +1767,7 @@ void QStateMachinePrivate::_q_process()
if (!enabledTransitions.isEmpty()) {
didChange = true;
q->beginMicrostep(e);
- microstep(e, enabledTransitions.toList());
+ microstep(e, enabledTransitions);
q->endMicrostep(e);
}
else {
@@ -1666,6 +1956,18 @@ void QStateMachinePrivate::endMacrostep(bool didChange)
}
+void QStateMachinePrivate::emitStateFinished(QState *forState, QFinalState *guiltyState)
+{
+ Q_UNUSED(guiltyState);
+ Q_ASSERT(guiltyState);
+
+#ifdef QSTATEMACHINE_DEBUG
+ qDebug() << q << ": emitting finished signal for" << forState;
+#endif
+
+ QStatePrivate::get(forState)->emitFinished();
+}
+
namespace _QStateMachine_Internal{
class GoToStateTransition : public QAbstractTransition
diff --git a/src/corelib/statemachine/qstatemachine.h b/src/corelib/statemachine/qstatemachine.h
index 7837e6ec5f..d6c3b7bfa7 100644
--- a/src/corelib/statemachine/qstatemachine.h
+++ b/src/corelib/statemachine/qstatemachine.h
@@ -145,16 +145,8 @@ public Q_SLOTS:
void setRunning(bool running);
Q_SIGNALS:
- void started(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void stopped(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void started(QPrivateSignal);
+ void stopped(QPrivateSignal);
void runningChanged(bool running);
diff --git a/src/corelib/statemachine/qstatemachine_p.h b/src/corelib/statemachine/qstatemachine_p.h
index b7f2644255..a66232ee88 100644
--- a/src/corelib/statemachine/qstatemachine_p.h
+++ b/src/corelib/statemachine/qstatemachine_p.h
@@ -100,8 +100,10 @@ public:
static QStateMachinePrivate *get(QStateMachine *q);
- QState *findLCA(const QList<QAbstractState*> &states) const;
+ QState *findLCA(const QList<QAbstractState*> &states, bool onlyCompound = false) const;
+ QState *findLCCA(const QList<QAbstractState*> &states) const;
+ static bool transitionStateEntryLessThan(QAbstractTransition *t1, QAbstractTransition *t2);
static bool stateEntryLessThan(QAbstractState *s1, QAbstractState *s2);
static bool stateExitLessThan(QAbstractState *s1, QAbstractState *s2);
@@ -122,16 +124,17 @@ public:
void clearHistory();
QAbstractTransition *createInitialTransition() const;
+ void removeConflictingTransitions(QList<QAbstractTransition*> &enabledTransitions);
void microstep(QEvent *event, const QList<QAbstractTransition*> &transitionList);
virtual void noMicrostep();
virtual void processedPendingEvents(bool didChange);
virtual void beginMacrostep();
virtual void endMacrostep(bool didChange);
- bool isPreempted(const QAbstractState *s, const QSet<QAbstractTransition*> &transitions) const;
- QSet<QAbstractTransition*> selectTransitions(QEvent *event) const;
+ QList<QAbstractTransition *> selectTransitions(QEvent *event);
void exitStates(QEvent *event, const QList<QAbstractState *> &statesToExit_sorted,
const QHash<QAbstractState*, QList<QPropertyAssignment> > &assignmentsForEnteredStates);
- QList<QAbstractState*> computeStatesToExit(const QList<QAbstractTransition*> &enabledTransitions);
+ QList<QAbstractState*> computeExitSet(const QList<QAbstractTransition*> &enabledTransitions);
+ QSet<QAbstractState*> computeExitSet_Unordered(const QList<QAbstractTransition*> &enabledTransitions);
void executeTransitionContent(QEvent *event, const QList<QAbstractTransition*> &transitionList);
void enterStates(QEvent *event, const QList<QAbstractState*> &exitedStates_sorted,
const QList<QAbstractState*> &statesToEnter_sorted,
@@ -141,12 +144,17 @@ public:
, const QList<QAbstractAnimation*> &selectedAnimations
#endif
);
- QList<QAbstractState*> computeStatesToEnter(const QList<QAbstractTransition*> &enabledTransitions,
- QSet<QAbstractState*> &statesForDefaultEntry);
+ QList<QAbstractState*> computeEntrySet(const QList<QAbstractTransition*> &enabledTransitions,
+ QSet<QAbstractState*> &statesForDefaultEntry);
+ QAbstractState *getTransitionDomain(QAbstractTransition *t,
+ const QList<QAbstractState *> &effectiveTargetStates) const;
+ void addDescendantStatesToEnter(QAbstractState *state,
+ QSet<QAbstractState*> &statesToEnter,
+ QSet<QAbstractState*> &statesForDefaultEntry);
void addStatesToEnter(QAbstractState *s, QState *root,
QSet<QAbstractState*> &statesToEnter,
QSet<QAbstractState*> &statesForDefaultEntry);
- void addAncestorStatesToEnter(QAbstractState *s, QState *root,
+ void addAncestorStatesToEnter(QAbstractState *s, QAbstractState *ancestor,
QSet<QAbstractState*> &statesToEnter,
QSet<QAbstractState*> &statesForDefaultEntry);
@@ -160,8 +168,6 @@ public:
static bool isParallel(const QAbstractState *s);
bool isCompound(const QAbstractState *s) const;
bool isAtomic(const QAbstractState *s) const;
- static bool isDescendantOf(const QAbstractState *s, const QAbstractState *other);
- static QList<QState*> properAncestors(const QAbstractState *s, const QState *upperBound);
void goToState(QAbstractState *targetState);
@@ -192,6 +198,8 @@ public:
void processEvents(EventProcessingMode processingMode);
void cancelAllDelayedEvents();
+ virtual void emitStateFinished(QState *forState, QFinalState *guiltyState);
+
#ifndef QT_NO_PROPERTIES
class RestorableId {
QPointer<QObject> guard;
diff --git a/src/corelib/thread/qreadwritelock.cpp b/src/corelib/thread/qreadwritelock.cpp
index 0ea8c4c00f..e6477bf5e0 100644
--- a/src/corelib/thread/qreadwritelock.cpp
+++ b/src/corelib/thread/qreadwritelock.cpp
@@ -136,27 +136,11 @@ void QReadWriteLock::lockForRead()
{
QMutexLocker lock(&d->mutex);
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()",
- "Overflow in lock counter");
- return;
- }
- }
-
while (d->accessCount < 0 || d->waitingWriters) {
++d->waitingReaders;
d->readerWait.wait(&d->mutex);
--d->waitingReaders;
}
- if (d->recursive)
- d->currentReaders.insert(self, 1);
++d->accessCount;
Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::lockForRead()", "Overflow in lock counter");
@@ -182,24 +166,8 @@ bool QReadWriteLock::tryLockForRead()
{
QMutexLocker lock(&d->mutex);
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
- "Overflow in lock counter");
- return true;
- }
- }
-
if (d->accessCount < 0)
return false;
- if (d->recursive)
- d->currentReaders.insert(self, 1);
++d->accessCount;
Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
@@ -230,20 +198,6 @@ bool QReadWriteLock::tryLockForRead(int timeout)
{
QMutexLocker lock(&d->mutex);
- Qt::HANDLE self = 0;
- if (d->recursive) {
- self = QThread::currentThreadId();
-
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- ++it.value();
- ++d->accessCount;
- Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()",
- "Overflow in lock counter");
- return true;
- }
- }
-
while (d->accessCount < 0 || d->waitingWriters) {
++d->waitingReaders;
bool success = d->readerWait.wait(&d->mutex, timeout < 0 ? ULONG_MAX : ulong(timeout));
@@ -251,8 +205,6 @@ bool QReadWriteLock::tryLockForRead(int timeout)
if (!success)
return false;
}
- if (d->recursive)
- d->currentReaders.insert(self, 1);
++d->accessCount;
Q_ASSERT_X(d->accessCount > 0, "QReadWriteLock::tryLockForRead()", "Overflow in lock counter");
@@ -412,15 +364,6 @@ void QReadWriteLock::unlock()
bool unlocked = false;
if (d->accessCount > 0) {
// releasing a read lock
- if (d->recursive) {
- Qt::HANDLE self = QThread::currentThreadId();
- QHash<Qt::HANDLE, int>::iterator it = d->currentReaders.find(self);
- if (it != d->currentReaders.end()) {
- if (--it.value() <= 0)
- d->currentReaders.erase(it);
- }
- }
-
unlocked = --d->accessCount == 0;
} else if (d->accessCount < 0 && ++d->accessCount == 0) {
// released a write lock
diff --git a/src/corelib/thread/qreadwritelock_p.h b/src/corelib/thread/qreadwritelock_p.h
index e57c0e403f..15a6d1f57e 100644
--- a/src/corelib/thread/qreadwritelock_p.h
+++ b/src/corelib/thread/qreadwritelock_p.h
@@ -69,7 +69,6 @@ struct QReadWriteLockPrivate
bool recursive;
Qt::HANDLE currentWriter;
- QHash<Qt::HANDLE, int> currentReaders;
};
QT_END_NAMESPACE
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index 58755b9625..bfc469583d 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -106,16 +106,8 @@ public:
static void usleep(unsigned long);
Q_SIGNALS:
- void started(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
- void finished(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void started(QPrivateSignal);
+ void finished(QPrivateSignal);
protected:
virtual void run();
diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp
index 996ed1779d..77093c9cf1 100644
--- a/src/corelib/thread/qthread_unix.cpp
+++ b/src/corelib/thread/qthread_unix.cpp
@@ -400,7 +400,7 @@ int QThread::idealThreadCount() Q_DECL_NOTHROW
cores = (int)psd.psd_proc_cnt;
}
#elif defined(Q_OS_BSD4)
- // FreeBSD, OpenBSD, NetBSD, BSD/OS, Mac OS X
+ // FreeBSD, OpenBSD, NetBSD, BSD/OS, OS X, iOS
size_t len = sizeof(cores);
int mib[2];
mib[0] = CTL_HW;
diff --git a/src/corelib/tools/qbytearraylist.h b/src/corelib/tools/qbytearraylist.h
index 9cd241a87b..f8539ca07a 100644
--- a/src/corelib/tools/qbytearraylist.h
+++ b/src/corelib/tools/qbytearraylist.h
@@ -55,6 +55,10 @@ class QByteArrayList : public QList<QByteArray>
template <> struct QListSpecialMethods<QByteArray>
#endif
{
+#ifndef Q_QDOC
+protected:
+ ~QListSpecialMethods() {}
+#endif
public:
inline QByteArray join() const
{ return QtPrivate::QByteArrayList_join(self(), 0, 0); }
diff --git a/src/corelib/tools/qelapsedtimer.cpp b/src/corelib/tools/qelapsedtimer.cpp
index 82f890478d..41e8b4854d 100644
--- a/src/corelib/tools/qelapsedtimer.cpp
+++ b/src/corelib/tools/qelapsedtimer.cpp
@@ -131,7 +131,7 @@ QT_BEGIN_NAMESPACE
\value SystemTime The human-readable system time. This clock is not monotonic.
\value MonotonicClock The system's monotonic clock, usually found in Unix systems. This clock is monotonic and does not overflow.
\value TickCounter The system's tick counter, used on Windows systems. This clock may overflow.
- \value MachAbsoluteTime The Mach kernel's absolute time (Mac OS X). This clock is monotonic and does not overflow.
+ \value MachAbsoluteTime The Mach kernel's absolute time (OS X and iOS). This clock is monotonic and does not overflow.
\value PerformanceCounter The high-resolution performance counter provided by Windows. This clock is monotonic and does not overflow.
\section2 SystemTime
@@ -173,8 +173,8 @@ QT_BEGIN_NAMESPACE
\section2 MachAbsoluteTime
This clock type is based on the absolute time presented by Mach kernels,
- such as that found on Mac OS X. This clock type is presented separately
- from MonotonicClock since Mac OS X is also a Unix system and may support
+ such as that found on OS X. This clock type is presented separately
+ from MonotonicClock since OS X and iOS are also Unix systems and may support
a POSIX monotonic clock with values differing from the Mach absolute
time.
diff --git a/src/corelib/tools/qlist.h b/src/corelib/tools/qlist.h
index 85e4570f45..1e002633df 100644
--- a/src/corelib/tools/qlist.h
+++ b/src/corelib/tools/qlist.h
@@ -63,8 +63,13 @@ QT_BEGIN_NAMESPACE
template <typename T> class QVector;
template <typename T> class QSet;
-template <typename T> struct QListSpecialMethods { };
+template <typename T> struct QListSpecialMethods
+{
+protected:
+ ~QListSpecialMethods() {}
+};
template <> struct QListSpecialMethods<QByteArray>;
+template <> struct QListSpecialMethods<QString>;
struct Q_CORE_EXPORT QListData {
// tags for tag-dispatching of QList implementations,
diff --git a/src/corelib/tools/qscopedvaluerollback.h b/src/corelib/tools/qscopedvaluerollback.h
index 66110b88f6..2db2ad869c 100644
--- a/src/corelib/tools/qscopedvaluerollback.h
+++ b/src/corelib/tools/qscopedvaluerollback.h
@@ -43,21 +43,19 @@ class QScopedValueRollback
{
public:
explicit QScopedValueRollback(T &var) :
- varRef(var)
+ varRef(var), oldValue(var)
{
- oldValue = varRef;
}
explicit QScopedValueRollback(T &var, T value) :
- varRef(var)
+ varRef(var), oldValue(var)
{
- oldValue = varRef;
- varRef = value;
+ varRef = qMove(value);
}
~QScopedValueRollback()
{
- varRef = oldValue;
+ varRef = qMove(oldValue);
}
void commit()
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 63139c97fd..373d25c6ad 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -5348,7 +5348,7 @@ int QString::compare_helper(const QChar *data1, int length1, QLatin1String s2,
platform-dependent manner. Use this function to present sorted
lists of strings to the user.
- On Mac OS X since Qt 4.3, this function compares according the
+ On OS X and iOS this function compares according the
"Order for sorted lists" setting in the International preferences panel.
\sa compare(), QLocale
@@ -7816,7 +7816,7 @@ QString QString::multiArg(int numArgs, const QString **args) const
Constructs a new QString containing a copy of the \a string CFString.
- \note this function is only available on Mac OS X and iOS.
+ \note this function is only available on OS X and iOS.
*/
/*! \fn CFStringRef QString::toCFString() const
@@ -7825,7 +7825,7 @@ QString QString::multiArg(int numArgs, const QString **args) const
Creates a CFString from a QString. The caller owns the CFString and is
responsible for releasing it.
- \note this function is only available on Mac OS X and iOS.
+ \note this function is only available on OS X and iOS.
*/
/*! \fn QString QString::fromNSString(const NSString *string)
@@ -7833,7 +7833,7 @@ QString QString::multiArg(int numArgs, const QString **args) const
Constructs a new QString containing a copy of the \a string NSString.
- \note this function is only available on Mac OS X and iOS.
+ \note this function is only available on OS X and iOS.
*/
/*! \fn NSString QString::toNSString() const
@@ -7841,7 +7841,7 @@ QString QString::multiArg(int numArgs, const QString **args) const
Creates a NSString from a QString. The NSString is autoreleased.
- \note this function is only available on Mac OS X and iOS.
+ \note this function is only available on OS X and iOS.
*/
/*! \fn bool QString::isSimpleText() const
@@ -9052,7 +9052,7 @@ QStringRef QStringRef::appendTo(QString *string) const
platform-dependent manner. Use this function to present sorted
lists of strings to the user.
- On Mac OS X, this function compares according the
+ On OS X and iOS, this function compares according the
"Order for sorted lists" setting in the International prefereces panel.
\sa compare(), QLocale
diff --git a/src/corelib/tools/qstringlist.h b/src/corelib/tools/qstringlist.h
index 89785208c8..8288e430fa 100644
--- a/src/corelib/tools/qstringlist.h
+++ b/src/corelib/tools/qstringlist.h
@@ -57,6 +57,10 @@ class QStringList : public QList<QString>
template <> struct QListSpecialMethods<QString>
#endif
{
+#ifndef Q_QDOC
+protected:
+ ~QListSpecialMethods() {}
+#endif
public:
inline void sort(Qt::CaseSensitivity cs = Qt::CaseSensitive);
inline int removeDuplicates();
diff --git a/src/corelib/tools/qtimeline.h b/src/corelib/tools/qtimeline.h
index 388e88d641..21139b37a8 100644
--- a/src/corelib/tools/qtimeline.h
+++ b/src/corelib/tools/qtimeline.h
@@ -115,26 +115,10 @@ public Q_SLOTS:
void toggleDirection();
Q_SIGNALS:
- void valueChanged(qreal x
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void frameChanged(int
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void stateChanged(QTimeLine::State newState
-#if !defined(Q_QDOC)
- , QPrivateSignal
-#endif
- );
- void finished(
-#if !defined(Q_QDOC)
- QPrivateSignal
-#endif
- );
+ void valueChanged(qreal x, QPrivateSignal);
+ void frameChanged(int, QPrivateSignal);
+ void stateChanged(QTimeLine::State newState, QPrivateSignal);
+ void finished(QPrivateSignal);
protected:
void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE;
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index c2ee99a2d8..3627045a40 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -183,7 +183,7 @@ Q_GLOBAL_STATIC(QTimeZoneSingleton, global_tz);
given moment then you should use a Qt::TimeSpec of Qt::LocalTime.
The method systemTimeZoneId() returns the current system IANA time zone
- ID which on OSX and Linux will always be correct. On Windows this ID is
+ ID which on Unix-like systems will always be correct. On Windows this ID is
translated from the Windows system ID using an internal translation
table and the user's selected country. As a consequence there is a small
chance any Windows install may have IDs not known by Qt, in which case
diff --git a/src/dbus/qdbusintegrator.cpp b/src/dbus/qdbusintegrator.cpp
index 6269d9ece3..b310483d11 100644
--- a/src/dbus/qdbusintegrator.cpp
+++ b/src/dbus/qdbusintegrator.cpp
@@ -554,7 +554,7 @@ qDBusSignalFilter(DBusConnection *connection, DBusMessage *message, void *data)
bool QDBusConnectionPrivate::handleMessage(const QDBusMessage &amsg)
{
const QDBusSpyHookList *list = qDBusSpyHookList();
- for (int i = 0; i < list->size(); ++i) {
+ for (int i = 0; list && i < list->size(); ++i) {
qDBusDebug() << "calling the message spy hook";
(*(*list)[i])(amsg);
}
@@ -1038,6 +1038,15 @@ QDBusConnectionPrivate::~QDBusConnectionPrivate()
"Timer and socket errors will follow and the program will probably crash",
qPrintable(name));
+ if (mode == ClientMode) {
+ // the bus service object holds a reference back to us;
+ // we need to destroy it before we finish destroying ourselves
+ Q_ASSERT(ref.load() == 0);
+ QObject *obj = (QObject *)busService;
+ disconnect(obj, Q_NULLPTR, this, Q_NULLPTR);
+ delete obj;
+ }
+
closeConnection();
rootNode.children.clear(); // free resources
qDeleteAll(cachedMetaObjects);
diff --git a/src/dbus/qdbusserver.cpp b/src/dbus/qdbusserver.cpp
index 2fc7c75d83..cf1b6e9665 100644
--- a/src/dbus/qdbusserver.cpp
+++ b/src/dbus/qdbusserver.cpp
@@ -111,6 +111,7 @@ QDBusServer::~QDBusServer()
}
d->serverConnectionNames.clear();
}
+ d->ref.store(0);
d->deleteLater();
}
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index b35012d4fe..cac3d268c5 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -4347,11 +4347,15 @@ int QImage::bitPlaneCount() const
static QImage smoothScaled(const QImage &source, int w, int h) {
QImage src = source;
- bool canSkipConversion = (src.format() == QImage::Format_RGB32 || src.format() == QImage::Format_ARGB32_Premultiplied);
+ switch (src.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32_Premultiplied:
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- canSkipConversion = canSkipConversion || (src.format() == QImage::Format_RGBX8888 || src.format() == QImage::Format_RGBA8888_Premultiplied);
+ case QImage::Format_RGBX8888:
#endif
- if (!canSkipConversion) {
+ case QImage::Format_RGBA8888_Premultiplied:
+ break;
+ default:
if (src.hasAlphaChannel())
src = src.convertToFormat(QImage::Format_ARGB32_Premultiplied);
else
diff --git a/src/gui/image/qimage_conversions.cpp b/src/gui/image/qimage_conversions.cpp
index 28e3a48689..8cb886e09b 100644
--- a/src/gui/image/qimage_conversions.cpp
+++ b/src/gui/image/qimage_conversions.cpp
@@ -117,7 +117,7 @@ static const uint *QT_FASTCALL convertRGB32ToARGB32PM(uint *buffer, const uint *
return buffer;
}
-#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__)
extern const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
#endif
@@ -144,7 +144,7 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
if (src->format == QImage::Format_RGB32)
convertToARGB32PM = convertRGB32ToARGB32PM;
if (dest->format == QImage::Format_RGB32) {
-#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__)
if (qCpuHasFeature(SSE4_1))
convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
else
@@ -193,7 +193,7 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
if (data->format == QImage::Format_RGB32)
convertToARGB32PM = convertRGB32ToARGB32PM;
if (dst_format == QImage::Format_RGB32) {
-#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__)
if (qCpuHasFeature(SSE4_1))
convertFromARGB32PM = convertRGB32FromARGB32PM_sse4;
else
diff --git a/src/gui/image/qimage_sse4.cpp b/src/gui/image/qimage_sse4.cpp
index 5fad4f572a..fb63f5bff9 100644
--- a/src/gui/image/qimage_sse4.cpp
+++ b/src/gui/image/qimage_sse4.cpp
@@ -33,7 +33,6 @@
#include <qimage.h>
#include <private/qdrawhelper_p.h>
-#include <private/qdrawingprimitive_sse2_p.h>
#include <private/qimage_p.h>
#include <private/qsimd_p.h>
@@ -45,7 +44,7 @@ const uint *QT_FASTCALL convertRGB32FromARGB32PM_sse4(uint *buffer, const uint *
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = 0xff000000 | qUnpremultiply_sse4(src[i]);
+ buffer[i] = 0xff000000 | qUnpremultiply(src[i]);
return buffer;
}
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index 35e74946ee..402f5005fd 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -584,6 +584,6 @@ void QClipboard::emitChanged(Mode mode)
emit changed(mode);
}
-#endif // QT_NO_CLIPBOARD
-
QT_END_NAMESPACE
+
+#endif // QT_NO_CLIPBOARD
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 9f73f019a3..926ec16f19 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -185,6 +185,7 @@ extern void qRegisterGuiVariant();
#ifndef QT_NO_ANIMATION
extern void qRegisterGuiGetInterpolator();
#endif
+extern void qInitBlendFunctions();
extern void qInitDrawhelperAsm();
extern void qInitImageConversions();
@@ -1279,6 +1280,8 @@ void QGuiApplicationPrivate::init()
if (platform_integration == 0)
createPlatformIntegration();
+ // Set up blend function tables.
+ qInitBlendFunctions();
// Set up which span functions should be used in raster engine...
qInitDrawhelperAsm();
// and QImage conversion functions
@@ -2754,6 +2757,7 @@ void QGuiApplication::setPalette(const QPalette &pal)
else
*QGuiApplicationPrivate::app_pal = pal;
applicationResourceFlags |= ApplicationPaletteExplicitlySet;
+ QCoreApplication::setAttribute(Qt::AA_SetPalette);
emit qGuiApp->paletteChanged(*QGuiApplicationPrivate::app_pal);
}
@@ -2837,6 +2841,9 @@ void QGuiApplication::setWindowIcon(const QIcon &icon)
if (!QGuiApplicationPrivate::app_icon)
QGuiApplicationPrivate::app_icon = new QIcon();
*QGuiApplicationPrivate::app_icon = icon;
+ if (QGuiApplicationPrivate::platform_integration
+ && QGuiApplicationPrivate::platform_integration->hasCapability(QPlatformIntegration::ApplicationIcon))
+ QGuiApplicationPrivate::platform_integration->setApplicationIcon(icon);
if (QGuiApplicationPrivate::is_app_running && !QGuiApplicationPrivate::is_app_closing)
QGuiApplicationPrivate::self->notifyWindowIconChanged();
}
diff --git a/src/gui/kernel/qpaintdevicewindow.cpp b/src/gui/kernel/qpaintdevicewindow.cpp
index b32ab3b34d..ff661d017d 100644
--- a/src/gui/kernel/qpaintdevicewindow.cpp
+++ b/src/gui/kernel/qpaintdevicewindow.cpp
@@ -60,6 +60,9 @@ QT_BEGIN_NAMESPACE
\note Subsequent calls to this function before the next paint
event will get ignored.
+
+ \note For non-exposed windows the update is deferred until the
+ window becomes exposed again.
*/
void QPaintDeviceWindow::update()
{
@@ -70,26 +73,34 @@ void QPaintDeviceWindow::update()
Marks the \a rect of the window as dirty and schedules a repaint.
\note Subsequent calls to this function before the next paint
- event will get ignored.
+ event will get ignored, but \a rect is added to the region to update.
+
+ \note For non-exposed windows the update is deferred until the
+ window becomes exposed again.
*/
void QPaintDeviceWindow::update(const QRect &rect)
{
Q_D(QPaintDeviceWindow);
d->dirtyRegion += rect;
- requestUpdate();
+ if (isExposed())
+ requestUpdate();
}
/*!
Marks the \a region of the window as dirty and schedules a repaint.
\note Subsequent calls to this function before the next paint
- event will get ignored.
+ event will get ignored, but \a region is added to the region to update.
+
+ \note For non-exposed windows the update is deferred until the
+ window becomes exposed again.
*/
void QPaintDeviceWindow::update(const QRegion &region)
{
Q_D(QPaintDeviceWindow);
d->dirtyRegion += region;
- requestUpdate();
+ if (isExposed())
+ requestUpdate();
}
/*!
@@ -168,6 +179,9 @@ void QPaintDeviceWindow::exposeEvent(QExposeEvent *exposeEvent)
// sometimes relative to the parent, depending on the platform plugin.
// We require local coords here.
d->doFlush(QRect(QPoint(0, 0), size()));
+ } else if (!d->dirtyRegion.isEmpty()) {
+ // Updates while non-exposed were ignored. Schedule an update now.
+ requestUpdate();
}
}
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index f2a92e10df..4d973d47a5 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -231,6 +231,8 @@ QPlatformServices *QPlatformIntegration::services() const
implementation for QOpenGLContext::getProcAddress() and support returning a function
pointer also for the standard, non-extension functions. This capability is a
prerequisite for dynamic OpenGL loading.
+
+ \value ApplicationIcon The platform supports setting the application icon. (since 5.5)
*/
/*!
@@ -394,6 +396,8 @@ QVariant QPlatformIntegration::styleHint(StyleHint hint) const
return QPlatformTheme::defaultThemeHint(QPlatformTheme::TabFocusBehavior);
case ReplayMousePressOutsidePopup:
return true;
+ case ItemViewActivateItemOnSingleClick:
+ return QPlatformTheme::defaultThemeHint(QPlatformTheme::ItemViewActivateItemOnSingleClick);
}
return 0;
@@ -544,4 +548,16 @@ QOpenGLContext::OpenGLModuleType QPlatformIntegration::openGLModuleType()
}
#endif
+/*!
+ \since 5.5
+
+ Platform integration function for setting the application icon.
+
+ \sa QGuiApplication::setWindowIcon()
+*/
+void QPlatformIntegration::setApplicationIcon(const QIcon &icon) const
+{
+ Q_UNUSED(icon);
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index 34639e6929..2aa502b3d2 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -90,7 +90,8 @@ public:
WindowManagement,
SyncState,
RasterGLSurface,
- AllGLFunctionsQueryable
+ AllGLFunctionsQueryable,
+ ApplicationIcon
};
virtual ~QPlatformIntegration() { }
@@ -146,7 +147,8 @@ public:
ShowIsMaximized,
MousePressAndHoldInterval,
TabFocusBehavior,
- ReplayMousePressOutsidePopup
+ ReplayMousePressOutsidePopup,
+ ItemViewActivateItemOnSingleClick
};
virtual QVariant styleHint(StyleHint hint) const;
@@ -169,7 +171,7 @@ public:
#ifndef QT_NO_OPENGL
virtual QOpenGLContext::OpenGLModuleType openGLModuleType();
#endif
-
+ virtual void setApplicationIcon(const QIcon &icon) const;
protected:
void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index aa49d64309..36a71fe2da 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -434,6 +434,8 @@ QVariant QPlatformTheme::themeHint(ThemeHint hint) const
return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::PasswordMaskCharacter);
case QPlatformTheme::MousePressAndHoldInterval:
return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::MousePressAndHoldInterval);
+ case QPlatformTheme::ItemViewActivateItemOnSingleClick:
+ return QGuiApplicationPrivate::platformIntegration()->styleHint(QPlatformIntegration::ItemViewActivateItemOnSingleClick);
default:
return QPlatformTheme::defaultThemeHint(hint);
}
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index b7af2e759f..7ff0f9f860 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -377,4 +377,16 @@ Qt::TabFocusBehavior QStyleHints::tabFocusBehavior() const
return Qt::TabFocusBehavior(themeableHint(QPlatformTheme::TabFocusBehavior, QPlatformIntegration::TabFocusBehavior).toInt());
}
+/*!
+ \property QStyleHints::singleClickActivation
+ \brief \c true if items should be activated by single click, \b false
+ if they should be activated by double click instead.
+
+ \since 5.5
+*/
+bool QStyleHints::singleClickActivation() const
+{
+ return themeableHint(QPlatformTheme::ItemViewActivateItemOnSingleClick, QPlatformIntegration::ItemViewActivateItemOnSingleClick).toBool();
+}
+
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 5fbc851ee9..82eb8a6f7d 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -61,6 +61,7 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(int startDragVelocity READ startDragVelocity STORED false CONSTANT FINAL)
Q_PROPERTY(bool useRtlExtensions READ useRtlExtensions STORED false CONSTANT FINAL)
Q_PROPERTY(Qt::TabFocusBehavior tabFocusBehavior READ tabFocusBehavior STORED false CONSTANT FINAL)
+ Q_PROPERTY(bool singleClickActivation READ singleClickActivation STORED false CONSTANT FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -83,6 +84,7 @@ public:
bool useRtlExtensions() const;
bool setFocusOnTouchRelease() const;
Qt::TabFocusBehavior tabFocusBehavior() const;
+ bool singleClickActivation() const;
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 19f7cafbcb..e697efe31c 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1075,6 +1075,10 @@ Qt::ScreenOrientation QWindow::contentOrientation() const
Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
+ \note For windows not backed by a platform window, meaning that create() was not
+ called, the function will fall back to QGuiApplication::devicePixelRatio() which in
+ turn returns the highest screen device pixel ratio found on the system.
+
\sa QScreen::devicePixelRatio(), QGuiApplication::devicePixelRatio()
*/
qreal QWindow::devicePixelRatio() const
diff --git a/src/gui/opengl/qopengl.cpp b/src/gui/opengl/qopengl.cpp
index 61d0614724..c8d33df4ba 100644
--- a/src/gui/opengl/qopengl.cpp
+++ b/src/gui/opengl/qopengl.cpp
@@ -36,6 +36,7 @@
#include "qopenglcontext.h"
#include "qopenglfunctions.h"
+#include "qoffscreensurface.h"
#include <QtCore/QDebug>
#include <QtCore/QJsonDocument>
@@ -89,8 +90,8 @@ QOpenGLExtensionMatcher::QOpenGLExtensionMatcher()
}
/* Helpers to read out the list of features matching a device from
- * a Chromium driver bug list of the format using a subset of keys
- * (namely, matching by gl_vendor RegExp is not implemented):
+ * a Chromium driver bug list. Note that not all keys are supported and
+ * some may behave differently: gl_vendor is a substring match instead of regex.
{
"entries": [
{
@@ -291,14 +292,14 @@ static bool matches(const QJsonObject &object,
const QJsonValue vendorV = object.value(vendorIdKey());
if (vendorV.isString()) {
- if (gpu.vendorId != vendorV.toString().toUInt(Q_NULLPTR, /* base */ 0))
- return false;
+ if (gpu.vendorId != vendorV.toString().toUInt(Q_NULLPTR, /* base */ 0))
+ return false;
} else {
if (object.contains(glVendorKey())) {
- qWarning().nospace() << "Id " << object.value(idKey()).toInt()
- << ": Matching by " << glVendorKey() << " is not implemented.";
- return false;
- }
+ const QByteArray glVendorV = object.value(glVendorKey()).toString().toUtf8();
+ if (!gpu.glVendor.contains(glVendorV))
+ return false;
+ }
}
if (gpu.deviceId) {
@@ -447,5 +448,30 @@ QSet<QString> QOpenGLConfig::gpuFeatures(const Gpu &gpu, const QString &fileName
return gpuFeatures(gpu, OsTypeTerm::hostOs(), OsTypeTerm::hostKernelVersion(), fileName);
}
+QOpenGLConfig::Gpu QOpenGLConfig::Gpu::fromContext()
+{
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ QScopedPointer<QOpenGLContext> tmpContext;
+ QScopedPointer<QOffscreenSurface> tmpSurface;
+ if (!ctx) {
+ tmpContext.reset(new QOpenGLContext);
+ if (!tmpContext->create()) {
+ qWarning("QOpenGLConfig::Gpu::fromContext: Failed to create temporary context");
+ return QOpenGLConfig::Gpu();
+ }
+ tmpSurface.reset(new QOffscreenSurface);
+ tmpSurface->setFormat(tmpContext->format());
+ tmpSurface->create();
+ tmpContext->makeCurrent(tmpSurface.data());
+ }
+
+ QOpenGLConfig::Gpu gpu;
+ ctx = QOpenGLContext::currentContext();
+ const GLubyte *p = ctx->functions()->glGetString(GL_VENDOR);
+ if (p)
+ gpu.glVendor = QByteArray(reinterpret_cast<const char *>(p));
+
+ return gpu;
+}
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopengl_p.h b/src/gui/opengl/qopengl_p.h
index e04ae05120..980e02aea6 100644
--- a/src/gui/opengl/qopengl_p.h
+++ b/src/gui/opengl/qopengl_p.h
@@ -74,16 +74,34 @@ private:
class Q_GUI_EXPORT QOpenGLConfig
{
public:
- struct Gpu {
+ struct Q_GUI_EXPORT Gpu {
Gpu() : vendorId(0), deviceId(0) {}
- bool isValid() const { return deviceId; }
+ bool isValid() const { return deviceId || !glVendor.isEmpty(); }
bool equals(const Gpu &other) const {
- return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion;
+ return vendorId == other.vendorId && deviceId == other.deviceId && driverVersion == other.driverVersion
+ && glVendor == other.glVendor;
}
uint vendorId;
uint deviceId;
QVersionNumber driverVersion;
+ QByteArray glVendor;
+
+ static Gpu fromDevice(uint vendorId, uint deviceId, QVersionNumber driverVersion) {
+ Gpu gpu;
+ gpu.vendorId = vendorId;
+ gpu.deviceId = deviceId;
+ gpu.driverVersion = driverVersion;
+ return gpu;
+ }
+
+ static Gpu fromGLVendor(const QByteArray &glVendor) {
+ Gpu gpu;
+ gpu.glVendor = glVendor;
+ return gpu;
+ }
+
+ static Gpu fromContext();
};
static QSet<QString> gpuFeatures(const Gpu &gpu,
diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp
index 9bc9926b70..baa702a982 100644
--- a/src/gui/opengl/qopengltexture.cpp
+++ b/src/gui/opengl/qopengltexture.cpp
@@ -120,7 +120,8 @@ QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarge
swizzleMask[2] = QOpenGLTexture::BlueValue;
swizzleMask[3] = QOpenGLTexture::AlphaValue;
- wrapModes[0] = wrapModes[1] = wrapModes[2] = QOpenGLTexture::ClampToEdge;
+ wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
+ ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
}
QOpenGLTexturePrivate::~QOpenGLTexturePrivate()
@@ -215,7 +216,8 @@ void QOpenGLTexturePrivate::destroy()
swizzleMask[2] = QOpenGLTexture::BlueValue;
swizzleMask[3] = QOpenGLTexture::AlphaValue;
- wrapModes[0] = wrapModes[1] = wrapModes[2] = QOpenGLTexture::ClampToEdge;
+ wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
+ ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
}
void QOpenGLTexturePrivate::bind()
@@ -1393,7 +1395,7 @@ QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::Coordin
case QOpenGLTexture::DirectionT:
case QOpenGLTexture::DirectionR:
- qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
+ qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
return QOpenGLTexture::Repeat;
}
break;
@@ -1413,7 +1415,7 @@ QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::Coordin
return wrapModes[1];
case QOpenGLTexture::DirectionR:
- qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
+ qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
return QOpenGLTexture::Repeat;
}
break;
diff --git a/src/gui/opengl/qopengltexturehelper.cpp b/src/gui/opengl/qopengltexturehelper.cpp
index 3635a7dd1b..440fdad081 100644
--- a/src/gui/opengl/qopengltexturehelper.cpp
+++ b/src/gui/opengl/qopengltexturehelper.cpp
@@ -179,7 +179,7 @@ QOpenGLTextureHelper::QOpenGLTextureHelper(QOpenGLContext *context)
GetTexParameteriv = ::glGetTexParameteriv;
GetTexParameterfv = ::glGetTexParameterfv;
GetTexImage = 0;
- TexImage2D = ::glTexImage2D;
+ TexImage2D = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLenum , GLint , GLint , GLsizei , GLsizei , GLint , GLenum , GLenum , const GLvoid *)>(::glTexImage2D);
TexImage1D = 0;
TexParameteriv = ::glTexParameteriv;
TexParameteri = ::glTexParameteri;
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index bd98f4ae46..791b5f1a9a 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -96,7 +96,8 @@ SOURCES += \
SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
-SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp
+SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
+ painting/qimagescale_sse4.cpp
AVX2_SOURCES += painting/qdrawhelper_avx2.cpp
!ios {
diff --git a/src/gui/painting/qblendfunctions.cpp b/src/gui/painting/qblendfunctions.cpp
index 478fe6564c..b3710411c9 100644
--- a/src/gui/painting/qblendfunctions.cpp
+++ b/src/gui/painting/qblendfunctions.cpp
@@ -432,10 +432,10 @@ static void qt_blend_argb32pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
}
template<QtPixelOrder PixelOrder>
-void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+static void qt_blend_rgb32_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb32_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
@@ -496,10 +496,10 @@ static void qt_blend_a2rgb30pm_on_a2rgb30pm(uchar *destPixels, int dbpl,
}
-void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
- const uchar *srcPixels, int sbpl,
- int w, int h,
- int const_alpha)
+static void qt_blend_rgb30_on_rgb30(uchar *destPixels, int dbpl,
+ const uchar *srcPixels, int sbpl,
+ int w, int h,
+ int const_alpha)
{
#ifdef QT_DEBUG_DRAW
fprintf(stdout, "qt_blend_rgb30_on_rgb30: dst=(%p, %d), src=(%p, %d), dim=(%d, %d) alpha=%d\n",
@@ -740,2071 +740,75 @@ void qt_transform_image_argb32_on_argb32(uchar *destPixels, int dbpl,
}
}
-SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGRs30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_scale_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_scale_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_scale_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_scale_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_scale_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_scale_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_scale_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_scale_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- }
-};
-
+SrcOverScaleFunc qScaleFunctions[QImage::NImageFormats][QImage::NImageFormats];
+SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats];
+SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats];
-SrcOverBlendFunc qBlendFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb16, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_blend_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
-#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_blend_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_blend_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
-#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+void qInitBlendFunctions()
+{
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_scale_image_argb32_on_rgb16;
+ qScaleFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_scale_image_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_blend_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_blend_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_scale_image_rgb32_on_rgb32;
+ qScaleFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_scale_image_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderBGR>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_BGR30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_RGB30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_blend_rgb32_on_rgb30<PixelOrderRGB>, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_BGR30,
- qt_blend_a2bgr30pm_on_a2rgb30pm, // Format_A2BGR30_Premultiplied,
- qt_blend_rgb30_on_rgb30, // Format_RGB30,
- qt_blend_a2rgb30pm_on_a2rgb30pm, // Format_A2RGB30_Premultiplied,
- 0, 0,
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- }
-};
-SrcOverTransformFunc qTransformFunctions[QImage::NImageFormats][QImage::NImageFormats] = {
- { // Format_Invalid
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Mono
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_MonoLSB
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Indexed8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB32_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- qt_transform_image_rgb32_on_rgb32, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_argb32, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB16
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- qt_transform_image_argb32_on_rgb16, // Format_ARGB32_Premultiplied,
- qt_transform_image_rgb16_on_rgb16, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8565_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB666
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB6666_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB555
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB8555_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB444
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_ARGB4444_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBX8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb16;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32_on_rgb16;
+ qBlendFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_blend_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_transform_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_transform_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_blend_rgb32_on_rgb32;
+ qBlendFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_blend_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGBA8888_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_BGR30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderBGR>;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_BGR30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_RGB30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2BGR30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_RGB30][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB32] = qt_blend_rgb32_on_rgb30<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_blend_argb32pm_on_a2rgb30pm<PixelOrderRGB>;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_BGR30] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2BGR30_Premultiplied] = qt_blend_a2bgr30pm_on_a2rgb30pm;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_RGB30] = qt_blend_rgb30_on_rgb30;
+ qBlendFunctions[QImage::Format_A2RGB30_Premultiplied][QImage::Format_A2RGB30_Premultiplied] = qt_blend_a2rgb30pm_on_a2rgb30pm;
+
+ qTransformFunctions[QImage::Format_RGB32][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGB32][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_RGB32] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_ARGB32_Premultiplied][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_ARGB32_Premultiplied] = qt_transform_image_argb32_on_rgb16;
+ qTransformFunctions[QImage::Format_RGB16][QImage::Format_RGB16] = qt_transform_image_rgb16_on_rgb16;
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
- qt_transform_image_rgb32_on_rgb32, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- qt_transform_image_argb32_on_argb32, // Format_RGBA8888_Premultiplied,
-#else
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
+ qTransformFunctions[QImage::Format_RGBX8888][QImage::Format_RGBX8888] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGBX8888][QImage::Format_RGBA8888_Premultiplied] = qt_transform_image_argb32_on_argb32;
+ qTransformFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBX8888] = qt_transform_image_rgb32_on_rgb32;
+ qTransformFunctions[QImage::Format_RGBA8888_Premultiplied][QImage::Format_RGBA8888_Premultiplied] = qt_transform_image_argb32_on_argb32;
#endif
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_BGR30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2BGR30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_RGB30
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_A2RGB30_Premultiplied
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Alpha8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
- { // Format_Grayscale8
- 0, // Format_Invalid,
- 0, // Format_Mono,
- 0, // Format_MonoLSB,
- 0, // Format_Indexed8,
- 0, // Format_RGB32,
- 0, // Format_ARGB32,
- 0, // Format_ARGB32_Premultiplied,
- 0, // Format_RGB16,
- 0, // Format_ARGB8565_Premultiplied,
- 0, // Format_RGB666,
- 0, // Format_ARGB6666_Premultiplied,
- 0, // Format_RGB555,
- 0, // Format_ARGB8555_Premultiplied,
- 0, // Format_RGB888,
- 0, // Format_RGB444,
- 0, // Format_ARGB4444_Premultiplied,
- 0, // Format_RGBX8888,
- 0, // Format_RGBA8888,
- 0, // Format_RGBA8888_Premultiplied,
- 0, // Format_BGR30,
- 0, // Format_A2BGR30_Premultiplied,
- 0, // Format_RGB30,
- 0, // Format_A2RGB30_Premultiplied,
- 0, // Format_Alpha8
- 0, // Format_Grayscale8
- },
-};
+}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qdrawhelper.cpp b/src/gui/painting/qdrawhelper.cpp
index 954c4c539a..b3f9fd9f60 100644
--- a/src/gui/painting/qdrawhelper.cpp
+++ b/src/gui/painting/qdrawhelper.cpp
@@ -1798,43 +1798,6 @@ static inline uint interpolate_4_pixels_16(uint tl, uint tr, uint bl, uint br, i
#endif
#if defined(__SSE2__)
-static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
-{
- // First interpolate right and left pixels in parallel.
- __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl));
- __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br));
- vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128());
- vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128());
- vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx));
- vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx));
- __m128i vtb = _mm_add_epi16(vl, vr);
- vtb = _mm_srli_epi16(vtb, 8);
- // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop)
-
- // Now the last interpolate between top and bottom interpolations.
- const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0));
- const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0));
- const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty);
- vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8));
- // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb }
- vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add.
- vtb = _mm_srli_epi32(vtb, 8);
- vtb = _mm_packs_epi32(vtb, _mm_setzero_si128());
- vtb = _mm_packus_epi16(vtb, _mm_setzero_si128());
- return _mm_cvtsi128_si32(vtb);
-}
-#else
-static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
-{
- uint idistx = 256 - distx;
- uint idisty = 256 - disty;
- uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
- uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
- return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
-}
-#endif
-
-#if defined(__SSE2__)
static inline QRgba64 interpolate_4_pixels_rgb64(QRgba64 t[], QRgba64 b[], uint distx, uint disty)
{
const __m128i vdistx = _mm_shufflelo_epi16(_mm_cvtsi32_si128(distx), _MM_SHUFFLE(0, 0, 0, 0));
@@ -2556,10 +2519,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
int x2;
fetchTransformedBilinear_pixelBounds<blendType>(image_width, image_x1, image_x2, x1, x2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
}
@@ -2614,10 +2584,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
fy += fdy;
@@ -2699,10 +2676,17 @@ static const uint *QT_FASTCALL fetchTransformedBilinear(uint *buffer, const Oper
const uchar *s1 = data->texture.scanLine(y1);
const uchar *s2 = data->texture.scanLine(y2);
- buf1[i * 2 + 0] = fetch(s1, x1);
- buf1[i * 2 + 1] = fetch(s1, x2);
- buf2[i * 2 + 0] = fetch(s2, x1);
- buf2[i * 2 + 1] = fetch(s2, x2);
+ if (layout->bpp == QPixelLayout::BPP32) {
+ buf1[i * 2 + 0] = ((const uint*)s1)[x1];
+ buf1[i * 2 + 1] = ((const uint*)s1)[x2];
+ buf2[i * 2 + 0] = ((const uint*)s2)[x1];
+ buf2[i * 2 + 1] = ((const uint*)s2)[x2];
+ } else {
+ buf1[i * 2 + 0] = fetch(s1, x1);
+ buf1[i * 2 + 1] = fetch(s1, x2);
+ buf2[i * 2 + 0] = fetch(s2, x1);
+ buf2[i * 2 + 1] = fetch(s2, x2);
+ }
fx += fdx;
fy += fdy;
@@ -6368,24 +6352,22 @@ void qInitDrawhelperAsm()
}
#endif // SSSE3
-#if QT_COMPILER_SUPPORTS_SSE4_1
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1) && !defined(__SSE4_1__)
if (qCpuHasFeature(SSE4_1)) {
-#if !defined(__SSE4_1__)
extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
- qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
- qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4;
-#endif
extern const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
extern const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
extern const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
+ qPixelLayouts[QImage::Format_ARGB32].convertToARGB32PM = convertARGB32ToARGB32PM_sse4;
+ qPixelLayouts[QImage::Format_RGBA8888].convertToARGB32PM = convertRGBA8888ToARGB32PM_sse4;
qPixelLayouts[QImage::Format_ARGB32].convertFromARGB32PM = convertARGB32FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBA8888].convertFromARGB32PM = convertRGBA8888FromARGB32PM_sse4;
qPixelLayouts[QImage::Format_RGBX8888].convertFromARGB32PM = convertRGBXFromARGB32PM_sse4;
}
#endif
-#if QT_COMPILER_SUPPORTS_AVX2 && !defined(__AVX2__)
+#if defined(QT_COMPILER_SUPPORTS_AVX2) && !defined(__AVX2__)
if (qCpuHasFeature(AVX2)) {
extern const uint *QT_FASTCALL convertARGB32ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
extern const uint *QT_FASTCALL convertRGBA8888ToARGB32PM_avx2(uint *buffer, const uint *src, int count, const QPixelLayout *, const QRgb *);
diff --git a/src/gui/painting/qdrawhelper_p.h b/src/gui/painting/qdrawhelper_p.h
index 019e1864f9..f8865a6f7e 100644
--- a/src/gui/painting/qdrawhelper_p.h
+++ b/src/gui/painting/qdrawhelper_p.h
@@ -634,6 +634,42 @@ static Q_ALWAYS_INLINE uint BYTE_MUL(uint x, uint a) {
}
#endif
+#ifdef __SSE2__
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ // First interpolate right and left pixels in parallel.
+ __m128i vl = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tl), _mm_cvtsi32_si128(bl));
+ __m128i vr = _mm_unpacklo_epi32(_mm_cvtsi32_si128(tr), _mm_cvtsi32_si128(br));
+ vl = _mm_unpacklo_epi8(vl, _mm_setzero_si128());
+ vr = _mm_unpacklo_epi8(vr, _mm_setzero_si128());
+ vl = _mm_mullo_epi16(vl, _mm_set1_epi16(256 - distx));
+ vr = _mm_mullo_epi16(vr, _mm_set1_epi16(distx));
+ __m128i vtb = _mm_add_epi16(vl, vr);
+ vtb = _mm_srli_epi16(vtb, 8);
+ // vtb now contains the result of the first two interpolate calls vtb = unpacked((xbot << 64) | xtop)
+
+ // Now the last interpolate between top and bottom interpolations.
+ const __m128i vidisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(256 - disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vdisty = _mm_shufflelo_epi16(_mm_cvtsi32_si128(disty), _MM_SHUFFLE(0, 0, 0, 0));
+ const __m128i vmuly = _mm_unpacklo_epi16(vidisty, vdisty);
+ vtb = _mm_unpacklo_epi16(vtb, _mm_srli_si128(vtb, 8));
+ // vtb now contains the colors of top and bottom interleaved { ta, ba, tr, br, tg, bg, tb, bb }
+ vtb = _mm_madd_epi16(vtb, vmuly); // Multiply and horizontal add.
+ vtb = _mm_srli_epi32(vtb, 8);
+ vtb = _mm_packs_epi32(vtb, _mm_setzero_si128());
+ vtb = _mm_packus_epi16(vtb, _mm_setzero_si128());
+ return _mm_cvtsi128_si32(vtb);
+}
+#else
+static inline uint interpolate_4_pixels(uint tl, uint tr, uint bl, uint br, uint distx, uint disty)
+{
+ uint idistx = 256 - distx;
+ uint idisty = 256 - disty;
+ uint xtop = INTERPOLATE_PIXEL_256(tl, idistx, tr, distx);
+ uint xbot = INTERPOLATE_PIXEL_256(bl, idistx, br, distx);
+ return INTERPOLATE_PIXEL_256(xtop, idisty, xbot, disty);
+}
+#endif
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
static Q_ALWAYS_INLINE quint32 RGBA2ARGB(quint32 x) {
diff --git a/src/gui/painting/qdrawhelper_sse4.cpp b/src/gui/painting/qdrawhelper_sse4.cpp
index 43a3958997..8e0b2cbb18 100644
--- a/src/gui/painting/qdrawhelper_sse4.cpp
+++ b/src/gui/painting/qdrawhelper_sse4.cpp
@@ -32,7 +32,6 @@
****************************************************************************/
#include <private/qdrawhelper_p.h>
-#include <private/qdrawingprimitive_sse2_p.h>
#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
@@ -54,7 +53,7 @@ const uint *QT_FASTCALL convertARGB32FromARGB32PM_sse4(uint *buffer, const uint
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = qUnpremultiply_sse4(src[i]);
+ buffer[i] = qUnpremultiply(src[i]);
return buffer;
}
@@ -62,7 +61,7 @@ const uint *QT_FASTCALL convertRGBA8888FromARGB32PM_sse4(uint *buffer, const uin
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(qUnpremultiply_sse4(src[i]));
+ buffer[i] = ARGB2RGBA(qUnpremultiply(src[i]));
return buffer;
}
@@ -70,7 +69,7 @@ const uint *QT_FASTCALL convertRGBXFromARGB32PM_sse4(uint *buffer, const uint *s
const QPixelLayout *, const QRgb *)
{
for (int i = 0; i < count; ++i)
- buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply_sse4(src[i]));
+ buffer[i] = ARGB2RGBA(0xff000000 | qUnpremultiply(src[i]));
return buffer;
}
diff --git a/src/gui/painting/qdrawingprimitive_sse2_p.h b/src/gui/painting/qdrawingprimitive_sse2_p.h
index 4d0790a502..fbee06e157 100644
--- a/src/gui/painting/qdrawingprimitive_sse2_p.h
+++ b/src/gui/painting/qdrawingprimitive_sse2_p.h
@@ -236,25 +236,4 @@ QT_END_NAMESPACE
#endif // __SSE2__
-QT_BEGIN_NAMESPACE
-#if QT_COMPILER_SUPPORTS_HERE(SSE4_1)
-QT_FUNCTION_TARGET(SSE4_1)
-inline QRgb qUnpremultiply_sse4(QRgb p)
-{
- const uint alpha = qAlpha(p);
- const uint invAlpha = qt_inv_premul_factor[alpha];
- const __m128i via = _mm_set1_epi32(invAlpha);
- const __m128i vr = _mm_set1_epi32(0x8000);
- __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p));
- vl = _mm_mullo_epi32(vl, via);
- vl = _mm_add_epi32(vl, vr);
- vl = _mm_srai_epi32(vl, 16);
- vl = _mm_insert_epi32(vl, alpha, 3);
- vl = _mm_packus_epi32(vl, _mm_setzero_si128());
- vl = _mm_packus_epi16(vl, _mm_setzero_si128());
- return _mm_cvtsi128_si32(vl);
-}
-#endif
-QT_END_NAMESPACE
-
#endif // QDRAWINGPRIMITIVE_SSE2_P_H
diff --git a/src/gui/painting/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index 58e9112dd6..5f1b25e189 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -38,10 +38,6 @@
QT_BEGIN_NAMESPACE
-namespace QImageScale {
- struct QImageScaleInfo;
-}
-
typedef void (*qt_qimageScaleFunc)(QImageScale::QImageScaleInfo *isi, unsigned int *dest,
int dxx, int dyy, int dx, int dy, int dw,
int dh, int dow, int sow);
@@ -105,15 +101,7 @@ qt_qimageScaleFunc qt_qimageScaleRgb = qt_qimageScaleAARGB;
namespace QImageScale {
- struct QImageScaleInfo {
- int *xpoints;
- const unsigned int **ypoints;
- int *xapoints, *yapoints;
- int xup_yup;
- };
-
- const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh,
- int dh);
+ const unsigned int** qimageCalcYPoints(const unsigned int *src, int sw, int sh, int dh);
int* qimageCalcXPoints(int sw, int dw);
int* qimageCalcApoints(int s, int d, int up);
QImageScaleInfo* qimageFreeScaleInfo(QImageScaleInfo *isi);
@@ -134,16 +122,11 @@ using namespace QImageScale;
#define G_VAL(p) (qGreen(*p))
#define B_VAL(p) (qBlue(*p))
-#define INV_XAP (256 - xapoints[x])
-#define XAP (xapoints[x])
-#define INV_YAP (256 - yapoints[dyy + y])
-#define YAP (yapoints[dyy + y])
-
const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int sw, int sh, int dh)
{
const unsigned int **p;
- int i, j = 0, rv = 0;
+ int j = 0, rv = 0;
qint64 val, inc;
if(dh < 0){
@@ -155,12 +138,12 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int up = qAbs(dh) >= sh;
val = up ? 0x8000 * sh / dh - 0x8000 : 0;
inc = (((qint64)sh) << 16) / dh;
- for(i = 0; i < dh; i++){
+ for (int i = 0; i < dh; i++) {
p[j++] = src + qMax(0LL, val >> 16) * sw;
val += inc;
}
- if(rv){
- for(i = dh / 2; --i >= 0; ){
+ if (rv) {
+ for (int i = dh / 2; --i >= 0; ) {
const unsigned int *tmp = p[i];
p[i] = p[dh - i - 1];
p[dh - i - 1] = tmp;
@@ -171,7 +154,7 @@ const unsigned int** QImageScale::qimageCalcYPoints(const unsigned int *src,
int* QImageScale::qimageCalcXPoints(int sw, int dw)
{
- int *p, i, j = 0, rv = 0;
+ int *p, j = 0, rv = 0;
qint64 val, inc;
if(dw < 0){
@@ -183,13 +166,13 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
int up = qAbs(dw) >= sw;
val = up ? 0x8000 * sw / dw - 0x8000 : 0;
inc = (((qint64)sw) << 16) / dw;
- for(i = 0; i < dw; i++){
+ for (int i = 0; i < dw; i++) {
p[j++] = qMax(0LL, val >> 16);
val += inc;
}
- if(rv){
- for(i = dw / 2; --i >= 0; ){
+ if (rv) {
+ for (int i = dw / 2; --i >= 0; ) {
int tmp = p[i];
p[i] = p[dw - i - 1];
p[dw - i - 1] = tmp;
@@ -200,7 +183,7 @@ int* QImageScale::qimageCalcXPoints(int sw, int dw)
int* QImageScale::qimageCalcApoints(int s, int d, int up)
{
- int *p, i, j = 0, rv = 0;
+ int *p, j = 0, rv = 0;
if(d < 0){
rv = 1;
@@ -214,7 +197,7 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
val = 0x8000 * s / d - 0x8000;
inc = (((qint64)s) << 16) / d;
- for(i = 0; i < d; i++){
+ for (int i = 0; i < d; i++) {
int pos = val >> 16;
if (pos < 0)
p[j++] = 0;
@@ -226,14 +209,12 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
}
}
/* scaling down */
- else{
- qint64 val, inc;
- int ap, Cp;
- val = 0;
- inc = (((qint64)s) << 16) / d;
- Cp = ((d << 14) / s) + 1;
- for(i = 0; i < d; i++){
- ap = ((0x100 - ((val >> 8) & 0xff)) * Cp) >> 8;
+ else {
+ qint64 val = 0;
+ qint64 inc = (((qint64)s) << 16) / d;
+ int Cp = (((d << 14) + s - 1) / s);
+ for (int i = 0; i < d; i++) {
+ int ap = ((0x10000 - (val & 0xffff)) * Cp) >> 16;
p[j] = ap | (Cp << 16);
j++;
val += inc;
@@ -241,13 +222,13 @@ int* QImageScale::qimageCalcApoints(int s, int d, int up)
}
if(rv){
int tmp;
- for(i = d / 2; --i >= 0; ){
+ for (int i = d / 2; --i >= 0; ) {
tmp = p[i];
p[i] = p[d - i - 1];
p[d - i - 1] = tmp;
}
}
- return(p);
+ return p;
}
QImageScaleInfo* QImageScale::qimageFreeScaleInfo(QImageScaleInfo *isi)
@@ -297,700 +278,500 @@ QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
return(isi);
}
-/* FIXME: NEED to optimize ScaleAARGBA - currently its "ok" but needs work*/
-/* scale by area sampling */
-static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
+template<bool RGB>
+void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+#endif
+
+static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
{
- const unsigned int *sptr;
- unsigned int *dptr;
- int x, y, end;
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
- end = dxx + dw;
- /* scaling up both ways */
- if(isi->xup_yup == 3){
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- /* calculate the source line we'll scan from */
- dptr = dest + dx + ((y + dy) * dow);
- sptr = ypoints[dyy + y];
- if(YAP > 0){
- for(x = dxx; x < end; x++){
- int r, g, b, a;
- int rr, gg, bb, aa;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- a = A_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- a += A_VAL(pix) * XAP;
- pix += sow;
- rr = R_VAL(pix) * XAP;
- gg = G_VAL(pix) * XAP;
- bb = B_VAL(pix) * XAP;
- aa = A_VAL(pix) * XAP;
- pix--;
- rr += R_VAL(pix) * INV_XAP;
- gg += G_VAL(pix) * INV_XAP;
- bb += B_VAL(pix) * INV_XAP;
- aa += A_VAL(pix) * INV_XAP;
- r = ((rr * YAP) + (r * INV_YAP)) >> 16;
- g = ((gg * YAP) + (g * INV_YAP)) >> 16;
- b = ((bb * YAP) + (b * INV_YAP)) >> 16;
- a = ((aa * YAP) + (a * INV_YAP)) >> 16;
- *dptr++ = qRgba(r, g, b, a);
- }
- else{
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_YAP;
- g = G_VAL(pix) * INV_YAP;
- b = B_VAL(pix) * INV_YAP;
- a = A_VAL(pix) * INV_YAP;
- pix += sow;
- r += R_VAL(pix) * YAP;
- g += G_VAL(pix) * YAP;
- b += B_VAL(pix) * YAP;
- a += A_VAL(pix) * YAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- a >>= 8;
- *dptr++ = qRgba(r, g, b, a);
- }
- }
+ int end = dxx + dw;
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ /* calculate the source line we'll scan from */
+ const unsigned int *sptr = ypoints[dyy + y];
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ const int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ if (xap > 0)
+ *dptr = interpolate_4_pixels(pix[0], pix[1], pix[sow], pix[sow + 1], xap, yap);
+ else
+ *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap);
+ dptr++;
}
- else{
- for(x = dxx; x < end; x++){
- int r, g, b, a;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- a = A_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- a += A_VAL(pix) * XAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- a >>= 8;
- *dptr++ = qRgba(r, g, b, a);
- }
- else
- *dptr++ = sptr[xpoints[x] ];
- }
+ } else {
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *pix = sptr + xpoints[x];
+ const int xap = xapoints[x];
+ *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
+ dptr++;
}
}
}
+}
+
+/* scale by area sampling */
+static void qt_qimageScaleAARGBA(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ /* scaling up both ways */
+ if (isi->xup_yup == 3){
+ qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
/* if we're scaling down vertically */
- else if(isi->xup_yup == 1){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cy, j;
- const unsigned int *pix;
- int r, g, b, a, rr, gg, bb, aa;
- int yap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- a = A_VAL(pix) * yap;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix += sow;
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- a += A_VAL(pix) * Cy;
- }
- if(j > 0){
- pix += sow;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
- }
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + 1;
- rr = R_VAL(pix) * yap;
- gg = G_VAL(pix) * yap;
- bb = B_VAL(pix) * yap;
- aa = A_VAL(pix) * yap;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix += sow;
- rr += R_VAL(pix) * Cy;
- gg += G_VAL(pix) * Cy;
- bb += B_VAL(pix) * Cy;
- aa += A_VAL(pix) * Cy;
- }
- if(j > 0){
- pix += sow;
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- aa += A_VAL(pix) * j;
- }
- r = r * INV_XAP;
- g = g * INV_XAP;
- b = b * INV_XAP;
- a = a * INV_XAP;
- r = (r + ((rr * XAP))) >> 12;
- g = (g + ((gg * XAP))) >> 12;
- b = (b + ((bb * XAP))) >> 12;
- a = (a + ((aa * XAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- a >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 1) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally */
- else if(isi->xup_yup == 2){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, j;
- const unsigned int *pix;
- int r, g, b, a, rr, gg, bb, aa;
- int xap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
- a = A_VAL(pix) * xap;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- pix++;
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- a += A_VAL(pix) * Cx;
- }
- if(j > 0){
- pix++;
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- a += A_VAL(pix) * j;
- }
- if(YAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + sow;
- rr = R_VAL(pix) * xap;
- gg = G_VAL(pix) * xap;
- bb = B_VAL(pix) * xap;
- aa = A_VAL(pix) * xap;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- pix++;
- rr += R_VAL(pix) * Cx;
- gg += G_VAL(pix) * Cx;
- bb += B_VAL(pix) * Cx;
- aa += A_VAL(pix) * Cx;
- }
- if(j > 0){
- pix++;
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- aa += A_VAL(pix) * j;
- }
- r = r * INV_YAP;
- g = g * INV_YAP;
- b = b * INV_YAP;
- a = a * INV_YAP;
- r = (r + ((rr * YAP))) >> 12;
- g = (g + ((gg * YAP))) >> 12;
- b = (b + ((bb * YAP))) >> 12;
- a = (a + ((aa * YAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- a >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, a >> 10);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 2) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
/* if we're scaling down horizontally & vertically */
- else{
- /*\ 'Correct' version, with math units prepared for MMXification:
- |*| The operation 'b = (b * c) >> 16' translates to pmulhw,
- |*| so the operation 'b = (b * c) >> d' would translate to
- |*| psllw (16 - d), %mmb; pmulh %mmc, %mmb
- \*/
- int Cx, Cy, i, j;
- const unsigned int *pix;
- int a, r, g, b, ax, rx, gx, bx;
- int xap, yap;
-
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- sptr = ypoints[dyy + y] + xpoints[x];
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
-
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r = (rx >> 5) * yap;
- g = (gx >> 5) * yap;
- b = (bx >> 5) * yap;
- a = (ax >> 5) * yap;
-
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r += (rx >> 5) * Cy;
- g += (gx >> 5) * Cy;
- b += (bx >> 5) * Cy;
- a += (ax >> 5) * Cy;
- }
- if(j > 0){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- ax = A_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- ax += A_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- ax += A_VAL(pix) * i;
- }
-
- r += (rx >> 5) * j;
- g += (gx >> 5) * j;
- b += (bx >> 5) * j;
- a += (ax >> 5) * j;
- }
-
- *dptr = qRgba(r >> 23, g >> 23, b >> 23, a >> 23);
- dptr++;
+ else {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_xy_sse4<false>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGBA_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+}
+
+inline static void qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b, int &a)
+{
+ r = R_VAL(pix) * xap;
+ g = G_VAL(pix) * xap;
+ b = B_VAL(pix) * xap;
+ a = A_VAL(pix) * xap;
+ int j;
+ for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
+ pix++;
+ r += R_VAL(pix) * Cx;
+ g += G_VAL(pix) * Cx;
+ b += B_VAL(pix) * Cx;
+ a += A_VAL(pix) * Cx;
+ }
+ pix++;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+ a += A_VAL(pix) * j;
+}
+
+inline static void qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b, int &a)
+{
+ r = R_VAL(pix) * yap;
+ g = G_VAL(pix) * yap;
+ b = B_VAL(pix) * yap;
+ a = A_VAL(pix) * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
+ pix += sow;
+ r += R_VAL(pix) * Cy;
+ g += G_VAL(pix) * Cy;
+ b += B_VAL(pix) * Cy;
+ a += A_VAL(pix) * Cy;
+ }
+ pix += sow;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+ a += A_VAL(pix) * j;
+}
+
+static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b, a;
+ qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, r, g, b, a);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ int rr, gg, bb, aa;
+ qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ a = a * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
+ a = (a + (aa * xap)) >> 8;
}
+ *dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
}
}
}
-/* scale by area sampling - IGNORE the ALPHA byte*/
-static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
{
- const unsigned int *sptr;
- unsigned int *dptr;
- int x, y, end;
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
- end = dxx + dw;
- /* scaling up both ways */
- if(isi->xup_yup == 3){
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- /* calculate the source line we'll scan from */
- dptr = dest + dx + ((y + dy) * dow);
- sptr = ypoints[dyy + y];
- if(YAP > 0){
- for(x = dxx; x < end; x++){
- int r = 0, g = 0, b = 0;
- int rr = 0, gg = 0, bb = 0;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- pix += sow;
- rr = R_VAL(pix) * XAP;
- gg = G_VAL(pix) * XAP;
- bb = B_VAL(pix) * XAP;
- pix --;
- rr += R_VAL(pix) * INV_XAP;
- gg += G_VAL(pix) * INV_XAP;
- bb += B_VAL(pix) * INV_XAP;
- r = ((rr * YAP) + (r * INV_YAP)) >> 16;
- g = ((gg * YAP) + (g * INV_YAP)) >> 16;
- b = ((bb * YAP) + (b * INV_YAP)) >> 16;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- else{
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_YAP;
- g = G_VAL(pix) * INV_YAP;
- b = B_VAL(pix) * INV_YAP;
- pix += sow;
- r += R_VAL(pix) * YAP;
- g += G_VAL(pix) * YAP;
- b += B_VAL(pix) * YAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- }
- }
- else{
- for(x = dxx; x < end; x++){
- int r = 0, g = 0, b = 0;
- const unsigned int *pix;
-
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * INV_XAP;
- g = G_VAL(pix) * INV_XAP;
- b = B_VAL(pix) * INV_XAP;
- pix++;
- r += R_VAL(pix) * XAP;
- g += G_VAL(pix) * XAP;
- b += B_VAL(pix) * XAP;
- r >>= 8;
- g >>= 8;
- b >>= 8;
- *dptr++ = qRgba(r, g, b, 0xff);
- }
- else
- *dptr++ = sptr[xpoints[x] ];
- }
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b, a;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, r, g, b, a);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ int rr, gg, bb, aa;
+ qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, rr, gg, bb, aa);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ a = a * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ a = (a + (aa * yap)) >> 8;
}
+ *dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
+ dptr++;
}
}
- /* if we're scaling down vertically */
- else if(isi->xup_yup == 1){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cy, j;
- const unsigned int *pix;
- int r, g, b, rr, gg, bb;
- int yap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * yap;
- g = G_VAL(pix) * yap;
- b = B_VAL(pix) * yap;
- pix += sow;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- r += R_VAL(pix) * Cy;
- g += G_VAL(pix) * Cy;
- b += B_VAL(pix) * Cy;
- pix += sow;
- }
- if(j > 0){
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- }
- if(XAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + 1;
- rr = R_VAL(pix) * yap;
- gg = G_VAL(pix) * yap;
- bb = B_VAL(pix) * yap;
- pix += sow;
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- rr += R_VAL(pix) * Cy;
- gg += G_VAL(pix) * Cy;
- bb += B_VAL(pix) * Cy;
- pix += sow;
- }
- if(j > 0){
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- }
- r = r * INV_XAP;
- g = g * INV_XAP;
- b = b * INV_XAP;
- r = (r + ((rr * XAP))) >> 12;
- g = (g + ((gg * XAP))) >> 12;
- b = (b + ((bb * XAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
- dptr++;
+}
+
+static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int rx, gx, bx, ax;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+
+ int r = ((rx>>4) * yap);
+ int g = ((gx>>4) * yap);
+ int b = ((bx>>4) * yap);
+ int a = ((ax>>4) * yap);
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+ r += ((rx>>4) * Cy);
+ g += ((gx>>4) * Cy);
+ b += ((bx>>4) * Cy);
+ a += ((ax>>4) * Cy);
}
+ sptr += sow;
+ qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, rx, gx, bx, ax);
+
+ r += ((rx>>4) * j);
+ g += ((gx>>4) * j);
+ b += ((bx>>4) * j);
+ a += ((ax>>4) * j);
+
+ *dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
+ dptr++;
}
}
+}
+
+static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow);
+
+/* scale by area sampling - IGNORE the ALPHA byte*/
+static void qt_qimageScaleAARGB(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ /* scaling up both ways */
+ if (isi->xup_yup == 3) {
+ qt_qimageScaleAARGBA_up_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+ /* if we're scaling down vertically */
+ else if (isi->xup_yup == 1) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_up_x_down_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
/* if we're scaling down horizontally */
- else if(isi->xup_yup == 2){
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, j;
- const unsigned int *pix;
- int r, g, b, rr, gg, bb;
- int xap;
-
- /* go through every scanline in the output buffer */
- for(y = 0; y < dh; y++){
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- pix = ypoints[dyy + y] + xpoints[x];
- r = R_VAL(pix) * xap;
- g = G_VAL(pix) * xap;
- b = B_VAL(pix) * xap;
- pix++;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- r += R_VAL(pix) * Cx;
- g += G_VAL(pix) * Cx;
- b += B_VAL(pix) * Cx;
- pix++;
- }
- if(j > 0){
- r += R_VAL(pix) * j;
- g += G_VAL(pix) * j;
- b += B_VAL(pix) * j;
- }
- if(YAP > 0){
- pix = ypoints[dyy + y] + xpoints[x] + sow;
- rr = R_VAL(pix) * xap;
- gg = G_VAL(pix) * xap;
- bb = B_VAL(pix) * xap;
- pix++;
- for(j = (1 << 14) - xap; j > Cx; j -= Cx){
- rr += R_VAL(pix) * Cx;
- gg += G_VAL(pix) * Cx;
- bb += B_VAL(pix) * Cx;
- pix++;
- }
- if(j > 0){
- rr += R_VAL(pix) * j;
- gg += G_VAL(pix) * j;
- bb += B_VAL(pix) * j;
- }
- r = r * INV_YAP;
- g = g * INV_YAP;
- b = b * INV_YAP;
- r = (r + ((rr * YAP))) >> 12;
- g = (g + ((gg * YAP))) >> 12;
- b = (b + ((bb * YAP))) >> 12;
- }
- else{
- r >>= 4;
- g >>= 4;
- b >>= 4;
- }
- *dptr = qRgba(r >> 10, g >> 10, b >> 10, 0xff);
- dptr++;
- }
- }
+ else if (isi->xup_yup == 2) {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_down_x_up_y(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
}
- /* fully optimized (i think) - onyl change of algorithm can help */
/* if we're scaling down horizontally & vertically */
- else{
- /*\ 'Correct' version, with math units prepared for MMXification \*/
- int Cx, Cy, i, j;
- const unsigned int *pix;
- int r, g, b, rx, gx, bx;
- int xap, yap;
-
- for(y = 0; y < dh; y++){
- Cy = YAP >> 16;
- yap = YAP & 0xffff;
-
- dptr = dest + dx + ((y + dy) * dow);
- for(x = dxx; x < end; x++){
- Cx = XAP >> 16;
- xap = XAP & 0xffff;
-
- sptr = ypoints[dyy + y] + xpoints[x];
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r = (rx >> 5) * yap;
- g = (gx >> 5) * yap;
- b = (bx >> 5) * yap;
-
- for(j = (1 << 14) - yap; j > Cy; j -= Cy){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r += (rx >> 5) * Cy;
- g += (gx >> 5) * Cy;
- b += (bx >> 5) * Cy;
- }
- if(j > 0){
- pix = sptr;
- sptr += sow;
- rx = R_VAL(pix) * xap;
- gx = G_VAL(pix) * xap;
- bx = B_VAL(pix) * xap;
- pix++;
- for(i = (1 << 14) - xap; i > Cx; i -= Cx){
- rx += R_VAL(pix) * Cx;
- gx += G_VAL(pix) * Cx;
- bx += B_VAL(pix) * Cx;
- pix++;
- }
- if(i > 0){
- rx += R_VAL(pix) * i;
- gx += G_VAL(pix) * i;
- bx += B_VAL(pix) * i;
- }
-
- r += (rx >> 5) * j;
- g += (gx >> 5) * j;
- b += (bx >> 5) * j;
- }
-
- *dptr = qRgb(r >> 23, g >> 23, b >> 23);
- dptr++;
+ else {
+#ifdef QT_COMPILER_SUPPORTS_SSE4_1
+ if (qCpuHasFeature(SSE4_1))
+ qt_qimageScaleAARGBA_down_xy_sse4<true>(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ else
+#endif
+ qt_qimageScaleAARGB_down_xy(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ }
+}
+
+
+inline static void qt_qimageScaleAARGB_helper_x(const unsigned int *pix, int xap, int Cx, int &r, int &g, int &b)
+{
+ r = R_VAL(pix) * xap;
+ g = G_VAL(pix) * xap;
+ b = B_VAL(pix) * xap;
+ int j;
+ for (j = (1 << 14) - xap; j > Cx; j -= Cx ){
+ pix++;
+ r += R_VAL(pix) * Cx;
+ g += G_VAL(pix) * Cx;
+ b += B_VAL(pix) * Cx;
+ }
+ pix++;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+}
+
+inline static void qt_qimageScaleAARGB_helper_y(const unsigned int *pix, int yap, int Cy, int sow, int &r, int &g, int &b)
+{
+ r = R_VAL(pix) * yap;
+ g = G_VAL(pix) * yap;
+ b = B_VAL(pix) * yap;
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy ){
+ pix += sow;
+ r += R_VAL(pix) * Cy;
+ g += G_VAL(pix) * Cy;
+ b += B_VAL(pix) * Cy;
+ }
+ pix += sow;
+ r += R_VAL(pix) * j;
+ g += G_VAL(pix) * j;
+ b += B_VAL(pix) * j;
+}
+
+static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b;
+ qt_qimageScaleAARGB_helper_y(sptr, yap, Cy, sow, r, g, b);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ int rr, bb, gg;
+ qt_qimageScaleAARGB_helper_y(sptr + 1, yap, Cy, sow, rr, gg, bb);
+
+ r = r * (256 - xap);
+ g = g * (256 - xap);
+ b = b * (256 - xap);
+ r = (r + (rr * xap)) >> 8;
+ g = (g + (gg * xap)) >> 8;
+ b = (b + (bb * xap)) >> 8;
}
+ *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
}
}
}
-#if 0
-static void qt_qimageScaleAARGBASetup(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
{
- qInitDrawhelperAsm();
- qt_qimageScaleAARGBA(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int r, g, b;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, r, g, b);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ int rr, bb, gg;
+ qt_qimageScaleAARGB_helper_x(sptr + sow, xap, Cx, rr, gg, bb);
+
+ r = r * (256 - yap);
+ g = g * (256 - yap);
+ b = b * (256 - yap);
+ r = (r + (rr * yap)) >> 8;
+ g = (g + (gg * yap)) >> 8;
+ b = (b + (bb * yap)) >> 8;
+ }
+ *dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
+ }
+ }
}
-static void qt_qimageScaleAARGBSetup(QImageScaleInfo *isi, unsigned int *dest,
- int dxx, int dyy, int dx, int dy, int dw,
- int dh, int dow, int sow)
+static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy, int dw,
+ int dh, int dow, int sow)
{
- qInitDrawhelperAsm();
- qt_qimageScaleAARGB(isi, dest, dxx, dyy, dx, dy, dw, dh, dow, sow);
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ int rx, gx, bx;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ int r = (rx >> 4) * yap;
+ int g = (gx >> 4) * yap;
+ int b = (bx >> 4) * yap;
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ r += (rx >> 4) * Cy;
+ g += (gx >> 4) * Cy;
+ b += (bx >> 4) * Cy;
+ }
+ sptr += sow;
+ qt_qimageScaleAARGB_helper_x(sptr, xap, Cx, rx, gx, bx);
+
+ r += (rx >> 4) * j;
+ g += (gx >> 4) * j;
+ b += (bx >> 4) * j;
+
+ *dptr = qRgb(r >> 24, g >> 24, b >> 24);
+ dptr++;
+ }
+ }
}
-#endif
QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
{
@@ -1012,7 +793,7 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
return QImage();
}
- if (src.format() == QImage::Format_ARGB32_Premultiplied || src.format() == QImage::Format_RGBA8888_Premultiplied)
+ if (src.hasAlphaChannel())
qt_qimageScaleArgb(scaleinfo, (unsigned int *)buffer.scanLine(0),
0, 0, 0, 0, dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qimagescale_p.h b/src/gui/painting/qimagescale_p.h
index 512ec6488e..c35aea451a 100644
--- a/src/gui/painting/qimagescale_p.h
+++ b/src/gui/painting/qimagescale_p.h
@@ -53,6 +53,15 @@ QT_BEGIN_NAMESPACE
*/
QImage qSmoothScaleImage(const QImage &img, int w, int h);
+namespace QImageScale {
+ struct QImageScaleInfo {
+ int *xpoints;
+ const unsigned int **ypoints;
+ int *xapoints, *yapoints;
+ int xup_yup;
+ };
+}
+
QT_END_NAMESPACE
#endif
diff --git a/src/gui/painting/qimagescale_sse4.cpp b/src/gui/painting/qimagescale_sse4.cpp
new file mode 100644
index 0000000000..565ea4daa1
--- /dev/null
+++ b/src/gui/painting/qimagescale_sse4.cpp
@@ -0,0 +1,247 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qimagescale_p.h"
+#include "qimage.h"
+#include <private/qsimd_p.h>
+
+#if defined(QT_COMPILER_SUPPORTS_SSE4_1)
+
+QT_BEGIN_NAMESPACE
+
+using namespace QImageScale;
+
+inline static __m128i qt_qimageScaleAARGBA_helper_x(const unsigned int *pix, int xap, int Cx, const __m128i vxap, const __m128i vCx)
+{
+ __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ __m128i vx = _mm_mullo_epi32(vpix, vxap);
+ int i;
+ for (i = (1 << 14) - xap; i > Cx; i -= Cx) {
+ pix++;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCx));
+ }
+ pix++;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
+ return vx;
+}
+
+inline static __m128i qt_qimageScaleAARGBA_helper_y(const unsigned int *pix, int yap, int Cy, int sow, const __m128i vyap, const __m128i vCy)
+{
+ __m128i vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ __m128i vx = _mm_mullo_epi32(vpix, vyap);
+ int i;
+ for (i = (1 << 14) - yap; i > Cy; i -= Cy) {
+ pix += sow;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, vCy));
+ }
+ pix += sow;
+ vpix = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(*pix));
+ vx = _mm_add_epi32(vx, _mm_mullo_epi32(vpix, _mm_set1_epi32(i)));
+ return vx;
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ const __m128i v256 = _mm_set1_epi32(256);
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+ const __m128i vCy = _mm_set1_epi32(Cy);
+ const __m128i vyap = _mm_set1_epi32(yap);
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_y(sptr, yap, Cy, sow, vyap, vCy);
+
+ int xap = xapoints[x];
+ if (xap > 0) {
+ const __m128i vxap = _mm_set1_epi32(xap);
+ const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
+ __m128i vr = qt_qimageScaleAARGBA_helper_y(sptr + 1, yap, Cy, sow, vyap, vCy);
+
+ vx = _mm_mullo_epi32(vx, vinvxap);
+ vr = _mm_mullo_epi32(vr, vxap);
+ vx = _mm_add_epi32(vx, vr);
+ vx = _mm_srli_epi32(vx, 8);
+ }
+ vx = _mm_srli_epi32(vx, 14);
+ vx = _mm_packus_epi32(vx, _mm_setzero_si128());
+ vx = _mm_packus_epi16(vx, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vx);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ int end = dxx + dw;
+
+ const __m128i v256 = _mm_set1_epi32(256);
+
+ /* go through every scanline in the output buffer */
+ for (int y = 0; y < dh; y++) {
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ for (int x = dxx; x < end; x++) {
+ int Cx = xapoints[x] >> 16;
+ int xap = xapoints[x] & 0xffff;
+ const __m128i vCx = _mm_set1_epi32(Cx);
+ const __m128i vxap = _mm_set1_epi32(xap);
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+
+ int yap = yapoints[dyy + y];
+ if (yap > 0) {
+ const __m128i vyap = _mm_set1_epi32(yap);
+ const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
+ __m128i vr = qt_qimageScaleAARGBA_helper_x(sptr + sow, xap, Cx, vxap, vCx);
+
+ vx = _mm_mullo_epi32(vx, vinvyap);
+ vr = _mm_mullo_epi32(vr, vyap);
+ vx = _mm_add_epi32(vx, vr);
+ vx = _mm_srli_epi32(vx, 8);
+ }
+ vx = _mm_srli_epi32(vx, 14);
+ vx = _mm_packus_epi32(vx, _mm_setzero_si128());
+ vx = _mm_packus_epi16(vx, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vx);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template<bool RGB>
+void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow)
+{
+ const unsigned int **ypoints = isi->ypoints;
+ int *xpoints = isi->xpoints;
+ int *xapoints = isi->xapoints;
+ int *yapoints = isi->yapoints;
+
+ for (int y = 0; y < dh; y++) {
+ int Cy = (yapoints[dyy + y]) >> 16;
+ int yap = (yapoints[dyy + y]) & 0xffff;
+ const __m128i vCy = _mm_set1_epi32(Cy);
+ const __m128i vyap = _mm_set1_epi32(yap);
+
+ unsigned int *dptr = dest + dx + ((y + dy) * dow);
+ int end = dxx + dw;
+ for (int x = dxx; x < end; x++) {
+ const int Cx = xapoints[x] >> 16;
+ const int xap = xapoints[x] & 0xffff;
+ const __m128i vCx = _mm_set1_epi32(Cx);
+ const __m128i vxap = _mm_set1_epi32(xap);
+
+ const unsigned int *sptr = ypoints[dyy + y] + xpoints[x];
+ __m128i vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ __m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
+
+ int j;
+ for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
+ sptr += sow;
+ vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy));
+ }
+ sptr += sow;
+ vx = qt_qimageScaleAARGBA_helper_x(sptr, xap, Cx, vxap, vCx);
+ vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
+
+ vr = _mm_srli_epi32(vr, 24);
+ vr = _mm_packus_epi32(vr, _mm_setzero_si128());
+ vr = _mm_packus_epi16(vr, _mm_setzero_si128());
+ *dptr = _mm_cvtsi128_si32(vr);
+ if (RGB)
+ *dptr |= 0xff000000;
+ dptr++;
+ }
+ }
+}
+
+template void qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_up_x_down_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_x_up_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_x_up_y_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_xy_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+template void qt_qimageScaleAARGBA_down_xy_sse4<true>(QImageScaleInfo *isi, unsigned int *dest,
+ int dxx, int dyy, int dx, int dy,
+ int dw, int dh, int dow, int sow);
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index cc1ad02eee..3f2ebb92a0 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -66,12 +66,9 @@ QT_BEGIN_NAMESPACE
inline QPaintEngine::PaintEngineFeatures qt_pdf_decide_features()
{
QPaintEngine::PaintEngineFeatures f = QPaintEngine::AllFeatures;
- f &= ~(QPaintEngine::PorterDuff | QPaintEngine::PerspectiveTransform
+ f &= ~(QPaintEngine::PorterDuff
+ | QPaintEngine::PerspectiveTransform
| QPaintEngine::ObjectBoundingModeGradients
-#ifndef USE_NATIVE_GRADIENTS
- | QPaintEngine::LinearGradientFill
-#endif
- | QPaintEngine::RadialGradientFill
| QPaintEngine::ConicalGradientFill);
return f;
}
@@ -548,189 +545,6 @@ QByteArray QPdf::patternForBrush(const QBrush &b)
return pattern_for_brush[style];
}
-#ifdef USE_NATIVE_GRADIENTS
-static void writeTriangleLine(uchar *&data, int xpos, int ypos, int xoff, int yoff, uint rgb, uchar flag, bool alpha)
-{
- data[0] = flag;
- data[1] = (uchar)(xpos >> 16);
- data[2] = (uchar)(xpos >> 8);
- data[3] = (uchar)(xpos >> 0);
- data[4] = (uchar)(ypos >> 16);
- data[5] = (uchar)(ypos >> 8);
- data[6] = (uchar)(ypos >> 0);
- data += 7;
- if (alpha) {
- *data++ = (uchar)qAlpha(rgb);
- } else {
- *data++ = (uchar)qRed(rgb);
- *data++ = (uchar)qGreen(rgb);
- *data++ = (uchar)qBlue(rgb);
- }
- xpos += xoff;
- ypos += yoff;
- data[0] = flag;
- data[1] = (uchar)(xpos >> 16);
- data[2] = (uchar)(xpos >> 8);
- data[3] = (uchar)(xpos >> 0);
- data[4] = (uchar)(ypos >> 16);
- data[5] = (uchar)(ypos >> 8);
- data[6] = (uchar)(ypos >> 0);
- data += 7;
- if (alpha) {
- *data++ = (uchar)qAlpha(rgb);
- } else {
- *data++ = (uchar)qRed(rgb);
- *data++ = (uchar)qGreen(rgb);
- *data++ = (uchar)qBlue(rgb);
- }
-}
-
-
-QByteArray QPdf::generateLinearGradientShader(const QLinearGradient *gradient, const QPointF *page_rect, bool alpha)
-{
- // generate list of triangles with colors
- QPointF start = gradient->start();
- QPointF stop = gradient->finalStop();
- QGradientStops stops = gradient->stops();
- QPointF offset = stop - start;
- QGradient::Spread spread = gradient->spread();
-
- if (gradient->spread() == QGradient::ReflectSpread) {
- offset *= 2;
- for (int i = stops.size() - 2; i >= 0; --i) {
- QGradientStop stop = stops.at(i);
- stop.first = 2. - stop.first;
- stops.append(stop);
- }
- for (int i = 0 ; i < stops.size(); ++i)
- stops[i].first /= 2.;
- }
-
- QPointF orthogonal(offset.y(), -offset.x());
- qreal length = offset.x()*offset.x() + offset.y()*offset.y();
-
- // find the max and min values in offset and orth direction that are needed to cover
- // the whole page
- int off_min = INT_MAX;
- int off_max = INT_MIN;
- qreal ort_min = INT_MAX;
- qreal ort_max = INT_MIN;
- for (int i = 0; i < 4; ++i) {
- qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length;
- qreal ort = ((page_rect[i].x() - start.x()) * orthogonal.x() + (page_rect[i].y() - start.y()) * orthogonal.y())/length;
- off_min = qMin(off_min, qFloor(off));
- off_max = qMax(off_max, qCeil(off));
- ort_min = qMin(ort_min, ort);
- ort_max = qMax(ort_max, ort);
- }
- ort_min -= 1;
- ort_max += 1;
-
- start += off_min * offset + ort_min * orthogonal;
- orthogonal *= (ort_max - ort_min);
- int num = off_max - off_min;
-
- QPointF gradient_rect[4] = { start,
- start + orthogonal,
- start + num*offset,
- start + num*offset + orthogonal };
- qreal xmin = gradient_rect[0].x();
- qreal xmax = gradient_rect[0].x();
- qreal ymin = gradient_rect[0].y();
- qreal ymax = gradient_rect[0].y();
- for (int i = 1; i < 4; ++i) {
- xmin = qMin(xmin, gradient_rect[i].x());
- xmax = qMax(xmax, gradient_rect[i].x());
- ymin = qMin(ymin, gradient_rect[i].y());
- ymax = qMax(ymax, gradient_rect[i].y());
- }
- xmin -= 1000;
- xmax += 1000;
- ymin -= 1000;
- ymax += 1000;
- start -= QPointF(xmin, ymin);
- qreal factor_x = qreal(1<<24)/(xmax - xmin);
- qreal factor_y = qreal(1<<24)/(ymax - ymin);
- int xoff = (int)(orthogonal.x()*factor_x);
- int yoff = (int)(orthogonal.y()*factor_y);
-
- QByteArray triangles;
- triangles.resize(spread == QGradient::PadSpread ? 20*(stops.size()+2) : 20*num*stops.size());
- uchar *data = (uchar *) triangles.data();
- if (spread == QGradient::PadSpread) {
- if (off_min > 0 || off_max < 1) {
- // linear gradient outside of page
- const QGradientStop &current_stop = off_min > 0 ? stops.at(stops.size()-1) : stops.at(0);
- uint rgb = current_stop.second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 0, alpha);
- start += num*offset;
- xpos = (int)(start.x()*factor_x);
- ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, 1, alpha);
- } else {
- int flag = 0;
- if (off_min < 0) {
- uint rgb = stops.at(0).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- start -= off_min*offset;
- flag = 1;
- }
- for (int s = 0; s < stops.size(); ++s) {
- const QGradientStop &current_stop = stops.at(s);
- uint rgb = current_stop.second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- if (s < stops.size()-1)
- start += offset*(stops.at(s+1).first - stops.at(s).first);
- flag = 1;
- }
- if (off_max > 1) {
- start += (off_max - 1)*offset;
- uint rgb = stops.at(stops.size()-1).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- }
- }
- } else {
- for (int i = 0; i < num; ++i) {
- uchar flag = 0;
- for (int s = 0; s < stops.size(); ++s) {
- uint rgb = stops.at(s).second.rgba();
- int xpos = (int)(start.x()*factor_x);
- int ypos = (int)(start.y()*factor_y);
- writeTriangleLine(data, xpos, ypos, xoff, yoff, rgb, flag, alpha);
- if (s < stops.size()-1)
- start += offset*(stops.at(s+1).first - stops.at(s).first);
- flag = 1;
- }
- }
- }
- triangles.resize((char *)data - triangles.constData());
-
- QByteArray shader;
- QPdf::ByteStream s(&shader);
- s << "<<\n"
- "/ShadingType 4\n"
- "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
- "/AntiAlias true\n"
- "/BitsPerCoordinate 24\n"
- "/BitsPerComponent 8\n"
- "/BitsPerFlag 8\n"
- "/Decode [" << xmin << xmax << ymin << ymax << (alpha ? "0 1]\n" : "0 1 0 1 0 1]\n") <<
- "/AntiAlias true\n"
- "/Length " << triangles.length() << "\n"
- ">>\n"
- "stream\n" << triangles << "endstream\n"
- "endobj\n";
- return shader;
-}
-#endif
static void moveToHook(qfixed x, qfixed y, void *data)
{
@@ -1381,6 +1195,8 @@ void QPdfEngine::setBrush()
bool specifyColor;
int gStateObject = 0;
int patternObject = d->addBrushPattern(d->stroker.matrix, &specifyColor, &gStateObject);
+ if (!patternObject && !specifyColor)
+ return;
*d->currentPage << (patternObject ? "/PCSp cs " : "/CSp cs ");
if (specifyColor) {
@@ -2116,34 +1932,263 @@ int QPdfEnginePrivate::writeImage(const QByteArray &data, int width, int height,
return image;
}
-#ifdef USE_NATIVE_GRADIENTS
-int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject)
+struct QGradientBound {
+ qreal start;
+ qreal stop;
+ int function;
+ bool reverse;
+};
+
+int QPdfEnginePrivate::createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha)
{
- const QGradient *gradient = b.gradient();
- if (!gradient)
- return 0;
+ QGradientStops stops = gradient->stops();
+ if (stops.isEmpty()) {
+ stops << QGradientStop(0, Qt::black);
+ stops << QGradientStop(1, Qt::white);
+ }
+ if (stops.at(0).first > 0)
+ stops.prepend(QGradientStop(0, stops.at(0).second));
+ if (stops.at(stops.size() - 1).first < 1)
+ stops.append(QGradientStop(1, stops.at(stops.size() - 1).second));
+
+ QVector<int> functions;
+ for (int i = 0; i < stops.size() - 1; ++i) {
+ int f = addXrefEntry(-1);
+ QByteArray data;
+ QPdf::ByteStream s(&data);
+ s << "<<\n"
+ "/FunctionType 2\n"
+ "/Domain [0 1]\n"
+ "/N 1\n";
+ if (alpha) {
+ s << "/C0 [" << stops.at(i).second.alphaF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.alphaF() << "]\n";
+ } else {
+ s << "/C0 [" << stops.at(i).second.redF() << stops.at(i).second.greenF() << stops.at(i).second.blueF() << "]\n"
+ "/C1 [" << stops.at(i + 1).second.redF() << stops.at(i + 1).second.greenF() << stops.at(i + 1).second.blueF() << "]\n";
+ }
+ s << ">>\n"
+ "endobj\n";
+ write(data);
+ functions << f;
+ }
+
+ QVector<QGradientBound> gradientBounds;
- QTransform inv = matrix.inverted();
- QPointF page_rect[4] = { inv.map(QPointF(0, 0)),
- inv.map(QPointF(width_, 0)),
- inv.map(QPointF(0, height_)),
- inv.map(QPointF(width_, height_)) };
+ for (int step = from; step < to; ++step) {
+ if (reflect && step % 2) {
+ for (int i = stops.size() - 1; i > 0; --i) {
+ QGradientBound b;
+ b.start = step + 1 - qBound(0., stops.at(i).first, 1.);
+ b.stop = step + 1 - qBound(0., stops.at(i - 1).first, 1.);
+ b.function = functions.at(i - 1);
+ b.reverse = true;
+ gradientBounds << b;
+ }
+ } else {
+ for (int i = 0; i < stops.size() - 1; ++i) {
+ QGradientBound b;
+ b.start = step + qBound(0., stops.at(i).first, 1.);
+ b.stop = step + qBound(0., stops.at(i + 1).first, 1.);
+ b.function = functions.at(i);
+ b.reverse = false;
+ gradientBounds << b;
+ }
+ }
+ }
- bool opaque = b.isOpaque();
+ // normalize bounds to [0..1]
+ qreal bstart = gradientBounds.at(0).start;
+ qreal bend = gradientBounds.at(gradientBounds.size() - 1).stop;
+ qreal norm = 1./(bend - bstart);
+ for (int i = 0; i < gradientBounds.size(); ++i) {
+ gradientBounds[i].start = (gradientBounds[i].start - bstart)*norm;
+ gradientBounds[i].stop = (gradientBounds[i].stop - bstart)*norm;
+ }
- QByteArray shader;
- QByteArray alphaShader;
- if (gradient->type() == QGradient::LinearGradient) {
- const QLinearGradient *lg = static_cast<const QLinearGradient *>(gradient);
- shader = QPdf::generateLinearGradientShader(lg, page_rect);
- if (!opaque)
- alphaShader = QPdf::generateLinearGradientShader(lg, page_rect, true);
+ int function;
+ if (gradientBounds.size() > 1) {
+ function = addXrefEntry(-1);
+ QByteArray data;
+ QPdf::ByteStream s(&data);
+ s << "<<\n"
+ "/FunctionType 3\n"
+ "/Domain [0 1]\n"
+ "/Bounds [";
+ for (int i = 1; i < gradientBounds.size(); ++i)
+ s << gradientBounds.at(i).start;
+ s << "]\n"
+ "/Encode [";
+ for (int i = 0; i < gradientBounds.size(); ++i)
+ s << (gradientBounds.at(i).reverse ? "1 0 " : "0 1 ");
+ s << "]\n"
+ "/Functions [";
+ for (int i = 0; i < gradientBounds.size(); ++i)
+ s << gradientBounds.at(i).function << "0 R ";
+ s << "]\n"
+ ">>\n";
+ write(data);
} else {
- // #############
- return 0;
+ function = functions.at(0);
+ }
+ return function;
+}
+
+int QPdfEnginePrivate::generateLinearGradientShader(const QLinearGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ QPointF start = gradient->start();
+ QPointF stop = gradient->finalStop();
+ QPointF offset = stop - start;
+ Q_ASSERT(gradient->coordinateMode() == QGradient::LogicalMode);
+
+ int from = 0;
+ int to = 1;
+ bool reflect = false;
+ switch (gradient->spread()) {
+ case QGradient::PadSpread:
+ break;
+ case QGradient::ReflectSpread:
+ reflect = true;
+ // fall through
+ case QGradient::RepeatSpread: {
+ // calculate required bounds
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+ QTransform inv = matrix.inverted();
+ QPointF page_rect[4] = { inv.map(pageRect.topLeft()),
+ inv.map(pageRect.topRight()),
+ inv.map(pageRect.bottomLeft()),
+ inv.map(pageRect.bottomRight()) };
+
+ qreal length = offset.x()*offset.x() + offset.y()*offset.y();
+
+ // find the max and min values in offset and orth direction that are needed to cover
+ // the whole page
+ from = INT_MAX;
+ to = INT_MIN;
+ for (int i = 0; i < 4; ++i) {
+ qreal off = ((page_rect[i].x() - start.x()) * offset.x() + (page_rect[i].y() - start.y()) * offset.y())/length;
+ from = qMin(from, qFloor(off));
+ to = qMax(to, qCeil(off));
+ }
+
+ stop = start + to * offset;
+ start = start + from * offset;\
+ break;
+ }
+ }
+
+ int function = createShadingFunction(gradient, from, to, reflect, alpha);
+
+ QByteArray shader;
+ QPdf::ByteStream s(&shader);
+ s << "<<\n"
+ "/ShadingType 2\n"
+ "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
+ "/AntiAlias true\n"
+ "/Coords [" << start.x() << start.y() << stop.x() << stop.y() << "]\n"
+ "/Extend [true true]\n"
+ "/Function " << function << "0 R\n"
+ ">>\n"
+ "endobj\n";
+ int shaderObject = addXrefEntry(-1);
+ write(shader);
+ return shaderObject;
+}
+
+int QPdfEnginePrivate::generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ QPointF p1 = gradient->center();
+ double r1 = gradient->centerRadius();
+ QPointF p0 = gradient->focalPoint();
+ double r0 = gradient->focalRadius();
+
+ Q_ASSERT(gradient->coordinateMode() == QGradient::LogicalMode);
+
+ int from = 0;
+ int to = 1;
+ bool reflect = false;
+ switch (gradient->spread()) {
+ case QGradient::PadSpread:
+ break;
+ case QGradient::ReflectSpread:
+ reflect = true;
+ // fall through
+ case QGradient::RepeatSpread: {
+ Q_ASSERT(qFuzzyIsNull(r0)); // QPainter emulates if this is not 0
+
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+ QTransform inv = matrix.inverted();
+ QPointF page_rect[4] = { inv.map(pageRect.topLeft()),
+ inv.map(pageRect.topRight()),
+ inv.map(pageRect.bottomLeft()),
+ inv.map(pageRect.bottomRight()) };
+
+ // increase to until the whole page fits into it
+ bool done = false;
+ while (!done) {
+ QPointF center = QPointF(p0.x() + to*(p1.x() - p0.x()), p0.y() + to*(p1.y() - p0.y()));
+ double radius = r0 + to*(r1 - r0);
+ double r2 = radius*radius;
+ done = true;
+ for (int i = 0; i < 4; ++i) {
+ QPointF off = page_rect[i] - center;
+ if (off.x()*off.x() + off.y()*off.y() > r2) {
+ ++to;
+ done = false;
+ break;
+ }
+ }
+ }
+ p1 = QPointF(p0.x() + to*(p1.x() - p0.x()), p0.y() + to*(p1.y() - p0.y()));
+ r1 = r0 + to*(r1 - r0);
+ break;
+ }
}
+
+ int function = createShadingFunction(gradient, from, to, reflect, alpha);
+
+ QByteArray shader;
+ QPdf::ByteStream s(&shader);
+ s << "<<\n"
+ "/ShadingType 3\n"
+ "/ColorSpace " << (alpha ? "/DeviceGray\n" : "/DeviceRGB\n") <<
+ "/AntiAlias true\n"
+ "/Domain [0 1]\n"
+ "/Coords [" << p0.x() << p0.y() << r0 << p1.x() << p1.y() << r1 << "]\n"
+ "/Extend [true true]\n"
+ "/Function " << function << "0 R\n"
+ ">>\n"
+ "endobj\n";
int shaderObject = addXrefEntry(-1);
write(shader);
+ return shaderObject;
+}
+
+int QPdfEnginePrivate::generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha)
+{
+ switch (gradient->type()) {
+ case QGradient::LinearGradient:
+ return generateLinearGradientShader(static_cast<const QLinearGradient *>(gradient), matrix, alpha);
+ case QGradient::RadialGradient:
+ return generateRadialGradientShader(static_cast<const QRadialGradient *>(gradient), matrix, alpha);
+ case QGradient::ConicalGradient:
+ default:
+ qWarning() << "Implement me!";
+ }
+ return 0;
+}
+
+int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QTransform &matrix, int *gStateObject)
+{
+ const QGradient *gradient = b.gradient();
+
+ if (!gradient || gradient->coordinateMode() != QGradient::LogicalMode)
+ return 0;
+
+ QRectF pageRect = m_pageLayout.fullRectPixels(resolution);
+
+ QTransform m = b.transform() * matrix;
+ int shaderObject = generateGradientShader(gradient, m);
QByteArray str;
QPdf::ByteStream s(&str);
@@ -2152,12 +2197,12 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
"/PatternType 2\n"
"/Shading " << shaderObject << "0 R\n"
"/Matrix ["
- << matrix.m11()
- << matrix.m12()
- << matrix.m21()
- << matrix.m22()
- << matrix.dx()
- << matrix.dy() << "]\n";
+ << m.m11()
+ << m.m12()
+ << m.m21()
+ << m.m22()
+ << m.dx()
+ << m.dy() << "]\n";
s << ">>\n"
"endobj\n";
@@ -2165,7 +2210,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
write(str);
currentPage->patterns.append(patternObj);
- if (!opaque) {
+ if (!b.isOpaque()) {
bool ca = true;
QGradientStops stops = gradient->stops();
int a = stops.at(0).second.alpha();
@@ -2178,8 +2223,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
if (ca) {
*gStateObject = addConstantAlphaObject(stops.at(0).second.alpha());
} else {
- int alphaShaderObject = addXrefEntry(-1);
- write(alphaShader);
+ int alphaShaderObject = generateGradientShader(gradient, m, true);
QByteArray content;
QPdf::ByteStream c(&content);
@@ -2190,7 +2234,7 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
f << "<<\n"
"/Type /XObject\n"
"/Subtype /Form\n"
- "/BBox [0 0 " << width_ << height_ << "]\n"
+ "/BBox [0 0 " << pageRect.width() << pageRect.height() << "]\n"
"/Group <</S /Transparency >>\n"
"/Resources <<\n"
"/Shading << /Shader" << alphaShaderObject << alphaShaderObject << "0 R >>\n"
@@ -2214,7 +2258,6 @@ int QPdfEnginePrivate::gradientBrush(const QBrush &b, const QMatrix &matrix, int
return patternObj;
}
-#endif
int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
{
@@ -2236,6 +2279,7 @@ int QPdfEnginePrivate::addConstantAlphaObject(int brushAlpha, int penAlpha)
return object;
}
+
int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor, int *gStateObject)
{
int paintType = 2; // Uncolored tiling
@@ -2251,13 +2295,9 @@ int QPdfEnginePrivate::addBrushPattern(const QTransform &m, bool *specifyColor,
//qDebug() << brushOrigin << matrix;
Qt::BrushStyle style = brush.style();
- if (style == Qt::LinearGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
-#ifdef USE_NATIVE_GRADIENTS
+ if (style == Qt::LinearGradientPattern || style == Qt::RadialGradientPattern) {// && style <= Qt::ConicalGradientPattern) {
*specifyColor = false;
- return gradientBrush(b, matrix, gStateObject);
-#else
- return 0;
-#endif
+ return gradientBrush(brush, matrix, gStateObject);
}
if ((!brush.isOpaque() && brush.style() < Qt::LinearGradientPattern) || opacity != 1.0)
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index e7ff09cd3b..94e74f30b9 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -58,8 +58,6 @@
#include "private/qfontsubset_p.h"
#include "qpagelayout.h"
-// #define USE_NATIVE_GRADIENTS
-
QT_BEGIN_NAMESPACE
const char *qt_real_to_string(qreal val, char *buf);
@@ -116,9 +114,6 @@ namespace QPdf {
QByteArray generateMatrix(const QTransform &matrix);
QByteArray generateDashes(const QPen &pen);
QByteArray patternForBrush(const QBrush &b);
-#ifdef USE_NATIVE_GRADIENTS
- QByteArray generateLinearGradientShader(const QLinearGradient *lg, const QPointF *page_rect, bool alpha = false);
-#endif
struct Stroker {
Stroker();
@@ -276,9 +271,11 @@ public:
QPageLayout m_pageLayout;
private:
-#ifdef USE_NATIVE_GRADIENTS
- int gradientBrush(const QBrush &b, const QMatrix &matrix, int *gStateObject);
-#endif
+ int gradientBrush(const QBrush &b, const QTransform &matrix, int *gStateObject);
+ int generateGradientShader(const QGradient *gradient, const QTransform &matrix, bool alpha = false);
+ int generateLinearGradientShader(const QLinearGradient *lg, const QTransform &matrix, bool alpha);
+ int generateRadialGradientShader(const QRadialGradient *gradient, const QTransform &matrix, bool alpha);
+ int createShadingFunction(const QGradient *gradient, int from, int to, bool reflect, bool alpha);
void writeInfo();
void writePageRoot();
diff --git a/src/gui/painting/qrgb.h b/src/gui/painting/qrgb.h
index f7f2185bef..05b3a76bce 100644
--- a/src/gui/painting/qrgb.h
+++ b/src/gui/painting/qrgb.h
@@ -36,6 +36,11 @@
#include <QtCore/qglobal.h>
#include <QtCore/qprocessordetection.h>
+#if defined(__SSE4_1__)
+#include <smmintrin.h>
+#elif defined(__SSE2__)
+#include <emmintrin.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -87,19 +92,45 @@ inline Q_DECL_RELAXED_CONSTEXPR QRgb qPremultiply(QRgb x)
Q_GUI_EXPORT extern const uint qt_inv_premul_factor[];
+#if defined(__SSE2__)
+inline QRgb qUnpremultiply(QRgb p)
+{
+ const uint alpha = qAlpha(p);
+ if (alpha == 255 || alpha == 0)
+ return p;
+ const uint invAlpha = qt_inv_premul_factor[alpha];
+ const __m128i via = _mm_set1_epi32(invAlpha);
+ const __m128i vr = _mm_set1_epi32(0x8000);
+#ifdef __SSE4_1__
+ __m128i vl = _mm_cvtepu8_epi32(_mm_cvtsi32_si128(p));
+ vl = _mm_mullo_epi32(vl, via);
+#else
+ __m128i vl = _mm_unpacklo_epi8(_mm_cvtsi32_si128(p), _mm_setzero_si128());
+ vl = _mm_unpacklo_epi16(vl, vl);
+ __m128i vll = _mm_mullo_epi16(vl, via);
+ __m128i vlh = _mm_mulhi_epu16(vl, via);
+ vl = _mm_add_epi32(vll, _mm_slli_epi32(vlh, 16));
+#endif
+ vl = _mm_add_epi32(vl, vr);
+ vl = _mm_srli_epi32(vl, 16);
+ vl = _mm_packs_epi32(vl, _mm_setzero_si128());
+ vl = _mm_insert_epi16(vl, alpha, 3);
+ vl = _mm_packus_epi16(vl, _mm_setzero_si128());
+ return _mm_cvtsi128_si32(vl);
+}
+#else
inline QRgb qUnpremultiply(QRgb p)
{
const uint alpha = qAlpha(p);
// Alpha 255 and 0 are the two most common values, which makes them beneficial to short-cut.
- if (alpha == 255)
+ if (alpha == 255 || alpha == 0)
return p;
- if (alpha == 0)
- return 0;
// (p*(0x00ff00ff/alpha)) >> 16 == (p*255)/alpha for all p and alpha <= 256.
const uint invAlpha = qt_inv_premul_factor[alpha];
// We add 0x8000 to get even rounding. The rounding also ensures that qPremultiply(qUnpremultiply(p)) == p for all p.
return qRgba((qRed(p)*invAlpha + 0x8000)>>16, (qGreen(p)*invAlpha + 0x8000)>>16, (qBlue(p)*invAlpha + 0x8000)>>16, alpha);
}
+#endif
QT_END_NAMESPACE
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index 1a71042648..0f3cb21c70 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -356,7 +356,6 @@ struct QtFontFamily
populated(false),
fixedPitch(false),
name(n), count(0), foundries(0)
- , bogusWritingSystems(false)
, askedForFallback(false)
{
memset(writingSystems, 0, sizeof(writingSystems));
@@ -375,7 +374,6 @@ struct QtFontFamily
int count;
QtFontFoundry **foundries;
- bool bogusWritingSystems;
QStringList fallbackFamilies;
bool askedForFallback;
unsigned char writingSystems[QFontDatabase::WritingSystemsCount];
diff --git a/src/gui/text/qtextcursor.cpp b/src/gui/text/qtextcursor.cpp
index a151c515a3..eb51447105 100644
--- a/src/gui/text/qtextcursor.cpp
+++ b/src/gui/text/qtextcursor.cpp
@@ -424,9 +424,9 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
// skip if already at word start
QTextEngine *engine = layout->engine();
- engine->attributes();
+ const QCharAttributes *attributes = engine->attributes();
if ((relativePos == blockIt.length() - 1)
- && (engine->atSpace(relativePos - 1) || engine->atWordSeparator(relativePos - 1)))
+ && (attributes[relativePos - 1].whiteSpace || engine->atWordSeparator(relativePos - 1)))
return false;
if (relativePos < blockIt.length()-1)
@@ -499,7 +499,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
}
case QTextCursor::EndOfWord: {
QTextEngine *engine = layout->engine();
- engine->attributes();
+ const QCharAttributes *attributes = engine->attributes();
const int len = blockIt.length() - 1;
if (relativePos >= len)
return false;
@@ -508,7 +508,7 @@ bool QTextCursorPrivate::movePosition(QTextCursor::MoveOperation op, QTextCursor
while (relativePos < len && engine->atWordSeparator(relativePos))
++relativePos;
} else {
- while (relativePos < len && !engine->atSpace(relativePos) && !engine->atWordSeparator(relativePos))
+ while (relativePos < len && !attributes[relativePos].whiteSpace && !engine->atWordSeparator(relativePos))
++relativePos;
}
newPosition = blockIt.position() + relativePos;
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index e8dd663354..d3b70aaf26 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -1142,6 +1142,9 @@ void QTextDocument::setMetaInformation(MetaInformation info, const QString &stri
Returns the plain text contained in the document. If you want
formatting information use a QTextCursor instead.
+ \note Embedded objects, such as images, are represented by a
+ Unicode value U+FFFC (OBJECT REPLACEMENT CHARACTER).
+
\sa toHtml()
*/
QString QTextDocument::toPlainText() const
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 10a61d3c84..67a19804a3 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -2549,21 +2549,6 @@ bool QTextEngine::atWordSeparator(int position) const
return false;
}
-bool QTextEngine::atSpace(int position) const
-{
- const QChar c = layoutData->string.at(position);
- switch (c.unicode()) {
- case QChar::Tabulation:
- case QChar::Space:
- case QChar::Nbsp:
- case QChar::LineSeparator:
- return true;
- default:
- break;
- }
- return false;
-}
-
void QTextEngine::setPreeditArea(int position, const QString &preeditText)
{
if (preeditText.isEmpty()) {
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index 8037fd5f6d..39b9e0cb5a 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -592,7 +592,6 @@ private:
public:
bool atWordSeparator(int position) const;
- bool atSpace(int position) const;
QString elidedText(Qt::TextElideMode mode, const QFixed &width, int flags = 0, int from = 0, int count = -1) const;
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index a477aa2c99..d4eb1a4b0b 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -3027,8 +3027,8 @@ QTextTableFormat::QTextTableFormat(const QTextFormat &fmt)
\ingroup richtext-processing
\ingroup shared
- Inline images are represented by an object replacement character
- (0xFFFC in Unicode) which has an associated QTextImageFormat. The
+ Inline images are represented by a Unicode value U+FFFC (OBJECT
+ REPLACEMENT CHARACTER) which has an associated QTextImageFormat. The
image format specifies a name with setName() that is used to
locate the image. The size of the rectangle that the image will
occupy is specified using setWidth() and setHeight().
diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp
index cab9f6ae61..7da3e84041 100644
--- a/src/gui/text/qtextlayout.cpp
+++ b/src/gui/text/qtextlayout.cpp
@@ -648,10 +648,10 @@ int QTextLayout::nextCursorPosition(int oldPos, CursorMode mode) const
while (oldPos < len && d->atWordSeparator(oldPos))
oldPos++;
} else {
- while (oldPos < len && !d->atSpace(oldPos) && !d->atWordSeparator(oldPos))
+ while (oldPos < len && !attributes[oldPos].whiteSpace && !d->atWordSeparator(oldPos))
oldPos++;
}
- while (oldPos < len && d->atSpace(oldPos))
+ while (oldPos < len && attributes[oldPos].whiteSpace)
oldPos++;
}
@@ -679,7 +679,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
while (oldPos && !attributes[oldPos].graphemeBoundary)
oldPos--;
} else {
- while (oldPos && d->atSpace(oldPos-1))
+ while (oldPos > 0 && attributes[oldPos - 1].whiteSpace)
oldPos--;
if (oldPos && d->atWordSeparator(oldPos-1)) {
@@ -687,7 +687,7 @@ int QTextLayout::previousCursorPosition(int oldPos, CursorMode mode) const
while (oldPos && d->atWordSeparator(oldPos-1))
oldPos--;
} else {
- while (oldPos && !d->atSpace(oldPos-1) && !d->atWordSeparator(oldPos-1))
+ while (oldPos > 0 && !attributes[oldPos - 1].whiteSpace && !d->atWordSeparator(oldPos-1))
oldPos--;
}
}
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index 425126d474..df7c8b9c71 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -1561,7 +1561,7 @@ QTextBlock QTextBlock::next() const
Returns the text block in the document before this block, or an empty text
block if this is the first one.
- Note that the next block may be in a different frame or table to this block.
+ Note that the previous block may be in a different frame or table to this block.
\sa next(), begin(), end()
*/
diff --git a/src/gui/util/qvalidator.cpp b/src/gui/util/qvalidator.cpp
index 6b1e20c844..31dfd20d1a 100644
--- a/src/gui/util/qvalidator.cpp
+++ b/src/gui/util/qvalidator.cpp
@@ -448,6 +448,8 @@ void QIntValidator::fixup(QString &input) const
input = locale().toString(entered);
}
+// FIXME: Qt 6: Make QIntValidator::setRange() non-virtual
+
/*!
Sets the range of the validator to only accept integers between \a
bottom and \a top inclusive.
@@ -696,6 +698,7 @@ QValidator::State QDoubleValidatorPrivate::validateWithLocale(QString &input, QL
return QValidator::Intermediate;
}
+// FIXME: Qt 6: Make QDoubleValidator::setRange() non-virtual
/*!
Sets the validator to accept doubles from \a minimum to \a maximum
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 445b2c9743..321352e045 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -382,7 +382,8 @@ bool QNetworkAccessBackend::start()
const QString host = reply->url.host();
if (host == QLatin1String("localhost") ||
- QHostAddress(host).isLoopback()) {
+ QHostAddress(host).isLoopback() ||
+ reply->url.isLocalFile()) {
// Don't need an open session for localhost access.
} else {
// need to wait for session to be opened
diff --git a/src/network/access/qnetworkreplynsurlconnectionimpl.mm b/src/network/access/qnetworkreplynsurlconnectionimpl.mm
index 2c9ef0ac56..f4f494560c 100644
--- a/src/network/access/qnetworkreplynsurlconnectionimpl.mm
+++ b/src/network/access/qnetworkreplynsurlconnectionimpl.mm
@@ -287,7 +287,7 @@ void QNetworkReplyNSURLConnectionImpl::readyReadOutgoingData()
if ([response expectedContentLength] != NSURLResponseUnknownLength) {
QMetaObject::invokeMethod(replyprivate->q_func(), "downloadProgress", Qt::QueuedConnection,
- Q_ARG(qint64, qint64([responseData length])),
+ Q_ARG(qint64, qint64([responseData length] + replyprivate->bytesRead)),
Q_ARG(qint64, qint64([response expectedContentLength])));
}
@@ -418,9 +418,7 @@ qint64 QNetworkReplyNSURLConnectionImpl::bytesAvailable() const
{
Q_D(const QNetworkReplyNSURLConnectionImpl);
qint64 available = QNetworkReply::bytesAvailable() +
- [[d->urlConnectionDelegate responseData] length] -
- d->bytesRead;
-
+ [[d->urlConnectionDelegate responseData] length];
return available;
}
@@ -432,7 +430,7 @@ bool QNetworkReplyNSURLConnectionImpl::isSequential() const
qint64 QNetworkReplyNSURLConnectionImpl::size() const
{
Q_D(const QNetworkReplyNSURLConnectionImpl);
- return [[d->urlConnectionDelegate responseData] length];
+ return [[d->urlConnectionDelegate responseData] length] + d->bytesRead;
}
/*!
@@ -442,9 +440,10 @@ qint64 QNetworkReplyNSURLConnectionImpl::readData(char *data, qint64 maxlen)
{
Q_D(QNetworkReplyNSURLConnectionImpl);
qint64 dataSize = [[d->urlConnectionDelegate responseData] length];
- qint64 canRead = qMin(maxlen, dataSize - d->bytesRead);
+ qint64 canRead = qMin(maxlen, dataSize);
const char *sourceBase = static_cast<const char *>([[d->urlConnectionDelegate responseData] bytes]);
- memcpy(data, sourceBase + d->bytesRead, canRead);
+ memcpy(data, sourceBase, canRead);
+ [[d->urlConnectionDelegate responseData] replaceBytesInRange:NSMakeRange(0, canRead) withBytes:NULL length:0];
d->bytesRead += canRead;
return canRead;
}
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
index 3e9d81da5d..33d42370b7 100644
--- a/src/network/bearer/qnetworkconfigmanager_p.cpp
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -276,7 +276,9 @@ bool QNetworkConfigurationManagerPrivate::isOnline() const
{
QMutexLocker locker(&mutex);
- return !onlineConfigurations.isEmpty();
+ // We need allConfigurations since onlineConfigurations is filled with queued connections
+ // and thus is not always (more importantly just after creation) up to date
+ return !allConfigurations(QNetworkConfiguration::Active).isEmpty();
}
QNetworkConfigurationManager::Capabilities QNetworkConfigurationManagerPrivate::capabilities() const
diff --git a/src/network/ssl/qsslsocket.cpp b/src/network/ssl/qsslsocket.cpp
index ea21f1c5ad..513cc51620 100644
--- a/src/network/ssl/qsslsocket.cpp
+++ b/src/network/ssl/qsslsocket.cpp
@@ -790,7 +790,7 @@ void QSslSocket::close()
qCDebug(lcSsl) << "QSslSocket::close()";
#endif
Q_D(QSslSocket);
- if (encryptedBytesToWrite())
+ if (encryptedBytesToWrite() || !d->writeBuffer.isEmpty())
flush();
if (d->plainSocket)
d->plainSocket->close();
diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp
index 4d092a8109..954c11d1f0 100644
--- a/src/network/ssl/qsslsocket_openssl.cpp
+++ b/src/network/ssl/qsslsocket_openssl.cpp
@@ -1392,7 +1392,7 @@ void QSslSocketBackendPrivate::_q_caRootLoaded(QSslCertificate cert, QSslCertifi
if (plainSocket)
plainSocket->resume();
paused = false;
- if (checkSslErrors())
+ if (checkSslErrors() && ssl)
continueHandshake();
}
diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
index accd64f170..d477a63ec7 100644
--- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
+++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h
@@ -96,6 +96,17 @@ public:
{
return QXcbFunctionsHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window);
}
+
+ typedef uint (*VisualId)(QWindow *window);
+ static const QByteArray visualIdIdentifier() { return QByteArrayLiteral("XcbVisualId"); }
+
+ static uint visualId(QWindow *window)
+ {
+ QXcbWindowFunctions::VisualId func = reinterpret_cast<VisualId>(QGuiApplication::platformFunction(visualIdIdentifier()));
+ if (func)
+ return func(window);
+ return UINT_MAX;
+ }
};
diff --git a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
index 200ded760c..1868ff1665 100644
--- a/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformintegration.cpp
@@ -48,7 +48,7 @@
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
-#include <QtPlatformSupport/private/qevdevtouch_p.h>
+#include <QtPlatformSupport/private/qevdevtouchmanager_p.h>
#endif
#if !defined(QT_NO_TSLIB) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
@@ -359,7 +359,7 @@ void QEGLPlatformIntegration::createInputHandlers()
new QTsLibMouseHandler(QLatin1String("TsLib"), QString() /* spec */);
else
#endif // QT_NO_TSLIB
- new QEvdevTouchScreenHandlerThread(QString() /* spec */, this);
+ new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this);
#endif
}
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 99f54237bc..be70092010 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -276,7 +276,7 @@ static void getFontDescription(CTFontDescriptorRef font, FontDescription *fd)
uint length = 128;
QVarLengthArray<uchar, 128> os2Table(length);
if (QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length) && length >= 86) {
- if (length > os2Table.length()) {
+ if (length > uint(os2Table.length())) {
os2Table.resize(length);
if (!QCoreTextFontEngine::ct_getSfntTable(userData, tag, os2Table.data(), &length))
Q_UNREACHABLE();
diff --git a/src/platformsupport/input/evdevtouch/evdevtouch.pri b/src/platformsupport/input/evdevtouch/evdevtouch.pri
index ffbb05d61d..c2edc13143 100644
--- a/src/platformsupport/input/evdevtouch/evdevtouch.pri
+++ b/src/platformsupport/input/evdevtouch/evdevtouch.pri
@@ -1,8 +1,10 @@
HEADERS += \
- $$PWD/qevdevtouch_p.h
+ $$PWD/qevdevtouchhandler_p.h \
+ $$PWD/qevdevtouchmanager_p.h
SOURCES += \
- $$PWD/qevdevtouch.cpp
+ $$PWD/qevdevtouchhandler.cpp \
+ $$PWD/qevdevtouchmanager.cpp
contains(QT_CONFIG, libudev) {
LIBS_PRIVATE += $$QMAKE_LIBS_LIBUDEV
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
index 5c28dfb082..885326e512 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouch.cpp
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler.cpp
@@ -31,16 +31,14 @@
**
****************************************************************************/
-#include "qevdevtouch_p.h"
+#include "qevdevtouchhandler_p.h"
#include <QStringList>
#include <QHash>
#include <QSocketNotifier>
#include <QGuiApplication>
#include <QLoggingCategory>
#include <QtCore/private/qcore_unix_p.h>
-#include <QtPlatformSupport/private/qdevicediscovery_p.h>
#include <QtGui/private/qguiapplication_p.h>
-#include <QtGui/private/qinputdevicemanager_p_p.h>
#include <linux/input.h>
#if !defined(QT_NO_MTDEV)
@@ -148,12 +146,6 @@ void QEvdevTouchScreenData::registerDevice()
m_device->setCapabilities(m_device->capabilities() | QTouchDevice::Pressure);
QWindowSystemInterface::registerTouchDevice(m_device);
-
- // No monitoring of added/removed devices is done here, so for now just
- // increase the number of touch devices.
- QInputDeviceManager *imgr = QGuiApplicationPrivate::inputDeviceManager();
- QInputDeviceManagerPrivate::get(imgr)->setDeviceCount(QInputDeviceManager::DeviceTypeTouch,
- imgr->deviceCount(QInputDeviceManager::DeviceTypeTouch) + 1);
}
#define LONG_BITS (sizeof(long) << 3)
@@ -166,7 +158,7 @@ static inline bool testBit(long bit, const long *array)
}
#endif
-QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification, QObject *parent)
+QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &device, const QString &spec, QObject *parent)
: QObject(parent), m_notify(0), m_fd(-1), d(0)
#if !defined(QT_NO_MTDEV)
, m_mtdev(0)
@@ -174,25 +166,12 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
{
setObjectName(QLatin1String("Evdev Touch Handler"));
- if (qEnvironmentVariableIsSet("QT_QPA_EVDEV_DEBUG"))
- const_cast<QLoggingCategory &>(qLcEvdevTouch()).setEnabled(QtDebugMsg, true);
-
- // only the first device argument is used for now
- QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS"));
-
- if (spec.isEmpty())
- spec = specification;
-
- QStringList args = spec.split(QLatin1Char(':'));
-
- QString dev;
+ const QStringList args = spec.split(QLatin1Char(':'));
int rotationAngle = 0;
bool invertx = false;
bool inverty = false;
for (int i = 0; i < args.count(); ++i) {
- if (args.at(i).startsWith(QLatin1String("/dev/")) && dev.isEmpty()) {
- dev = args.at(i);
- } else if (args.at(i).startsWith(QLatin1String("rotate"))) {
+ if (args.at(i).startsWith(QLatin1String("rotate"))) {
QString rotateArg = args.at(i).section(QLatin1Char('='), 1, 1);
bool ok;
uint argValue = rotateArg.toUInt(&ok);
@@ -213,32 +192,15 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
}
}
- if (dev.isEmpty()) {
- // try to let udev scan for already connected devices
- QScopedPointer<QDeviceDiscovery> deviceDiscovery(QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this));
- if (deviceDiscovery) {
- QStringList devices = deviceDiscovery->scanConnectedDevices();
-
- // only the first device found is used for now
- if (devices.size() > 0)
- dev = devices[0];
- }
- }
-
- if (dev.isEmpty()) {
- qCDebug(qLcEvdevTouch, "evdevtouch: No touch devices found");
- return;
- }
-
- qCDebug(qLcEvdevTouch, "evdevtouch: Using device %s", qPrintable(dev));
+ qCDebug(qLcEvdevTouch, "evdevtouch: Using device %s", qPrintable(device));
- m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
+ m_fd = QT_OPEN(device.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0);
if (m_fd >= 0) {
m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notify, SIGNAL(activated(int)), this, SLOT(readData()));
} else {
- qErrnoWarning(errno, "evdevtouch: Cannot open input device %s", qPrintable(dev));
+ qErrnoWarning(errno, "evdevtouch: Cannot open input device %s", qPrintable(device));
return;
}
@@ -266,32 +228,35 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
}
#endif
- qCDebug(qLcEvdevTouch, "evdevtouch: Protocol type %c %s (%s)", d->m_typeB ? 'B' : 'A',
- mtdevStr, d->m_singleTouch ? "single" : "multi");
+ qCDebug(qLcEvdevTouch, "evdevtouch: %s: Protocol type %c %s (%s)", qPrintable(device),
+ d->m_typeB ? 'B' : 'A', mtdevStr, d->m_singleTouch ? "single" : "multi");
input_absinfo absInfo;
memset(&absInfo, 0, sizeof(input_absinfo));
bool has_x_range = false, has_y_range = false;
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_X : ABS_MT_POSITION_X)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: min X: %d max X: %d", absInfo.minimum, absInfo.maximum);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %s: min X: %d max X: %d", qPrintable(device),
+ absInfo.minimum, absInfo.maximum);
d->hw_range_x_min = absInfo.minimum;
d->hw_range_x_max = absInfo.maximum;
has_x_range = true;
}
if (ioctl(m_fd, EVIOCGABS((d->m_singleTouch ? ABS_Y : ABS_MT_POSITION_Y)), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: min Y: %d max Y: %d", absInfo.minimum, absInfo.maximum);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %s: min Y: %d max Y: %d", qPrintable(device),
+ absInfo.minimum, absInfo.maximum);
d->hw_range_y_min = absInfo.minimum;
d->hw_range_y_max = absInfo.maximum;
has_y_range = true;
}
if (!has_x_range || !has_y_range)
- qWarning("evdevtouch: Invalid ABS limits, behavior unspecified");
+ qWarning("evdevtouch: %s: Invalid ABS limits, behavior unspecified", qPrintable(device));
if (ioctl(m_fd, EVIOCGABS(ABS_PRESSURE), &absInfo) >= 0) {
- qCDebug(qLcEvdevTouch, "evdevtouch: min pressure: %d max pressure: %d", absInfo.minimum, absInfo.maximum);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %s: min pressure: %d max pressure: %d", qPrintable(device),
+ absInfo.minimum, absInfo.maximum);
if (absInfo.maximum > absInfo.minimum) {
d->hw_pressure_min = absInfo.minimum;
d->hw_pressure_max = absInfo.maximum;
@@ -301,7 +266,7 @@ QEvdevTouchScreenHandler::QEvdevTouchScreenHandler(const QString &specification,
char name[1024];
if (ioctl(m_fd, EVIOCGNAME(sizeof(name) - 1), name) >= 0) {
d->hw_name = QString::fromLocal8Bit(name);
- qCDebug(qLcEvdevTouch, "evdevtouch: device name: %s", name);
+ qCDebug(qLcEvdevTouch, "evdevtouch: %s: device name: %s", qPrintable(device), name);
}
// Fix up the coordinate ranges for am335x in case the kernel driver does not have them fixed.
@@ -676,8 +641,8 @@ void QEvdevTouchScreenData::reportPoints()
}
-QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &spec, QObject *parent)
- : QThread(parent), m_spec(spec), m_handler(0)
+QEvdevTouchScreenHandlerThread::QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent)
+ : QThread(parent), m_device(device), m_spec(spec), m_handler(0)
{
start();
}
@@ -690,7 +655,7 @@ QEvdevTouchScreenHandlerThread::~QEvdevTouchScreenHandlerThread()
void QEvdevTouchScreenHandlerThread::run()
{
- m_handler = new QEvdevTouchScreenHandler(m_spec);
+ m_handler = new QEvdevTouchScreenHandler(m_device, m_spec);
exec();
delete m_handler;
m_handler = 0;
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
index eca1bf465c..a6d3a860f5 100644
--- a/src/platformsupport/input/evdevtouch/qevdevtouch_p.h
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchhandler_p.h
@@ -31,8 +31,8 @@
**
****************************************************************************/
-#ifndef QEVDEVTOUCH_P_H
-#define QEVDEVTOUCH_P_H
+#ifndef QEVDEVTOUCHHANDLER_P_H
+#define QEVDEVTOUCHHANDLER_P_H
//
// W A R N I N G
@@ -65,7 +65,7 @@ class QEvdevTouchScreenHandler : public QObject
Q_OBJECT
public:
- explicit QEvdevTouchScreenHandler(const QString &specification = QString(), QObject *parent = 0);
+ explicit QEvdevTouchScreenHandler(const QString &device, const QString &spec = QString(), QObject *parent = 0);
~QEvdevTouchScreenHandler();
private slots:
@@ -83,12 +83,13 @@ private:
class QEvdevTouchScreenHandlerThread : public QThread
{
public:
- explicit QEvdevTouchScreenHandlerThread(const QString &spec, QObject *parent = 0);
+ explicit QEvdevTouchScreenHandlerThread(const QString &device, const QString &spec, QObject *parent = 0);
~QEvdevTouchScreenHandlerThread();
void run() Q_DECL_OVERRIDE;
QEvdevTouchScreenHandler *handler() { return m_handler; }
private:
+ QString m_device;
QString m_spec;
QEvdevTouchScreenHandler *m_handler;
};
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
new file mode 100644
index 0000000000..98fc83700c
--- /dev/null
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager.cpp
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the plugins module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qevdevtouchmanager_p.h"
+#include "qevdevtouchhandler_p.h"
+
+#include <QStringList>
+#include <QGuiApplication>
+#include <QLoggingCategory>
+#include <QtPlatformSupport/private/qdevicediscovery_p.h>
+#include <private/qguiapplication_p.h>
+#include <private/qinputdevicemanager_p_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_DECLARE_LOGGING_CATEGORY(qLcEvdevTouch)
+
+QEvdevTouchManager::QEvdevTouchManager(const QString &key, const QString &specification, QObject *parent)
+ : QObject(parent)
+{
+ Q_UNUSED(key);
+
+ if (qEnvironmentVariableIsSet("QT_QPA_EVDEV_DEBUG"))
+ const_cast<QLoggingCategory &>(qLcEvdevTouch()).setEnabled(QtDebugMsg, true);
+
+ QString spec = QString::fromLocal8Bit(qgetenv("QT_QPA_EVDEV_TOUCHSCREEN_PARAMETERS"));
+
+ if (spec.isEmpty())
+ spec = specification;
+
+ QStringList args = spec.split(QLatin1Char(':'));
+ QStringList devices;
+
+ foreach (const QString &arg, args) {
+ if (arg.startsWith(QLatin1String("/dev/"))) {
+ devices.append(arg);
+ args.removeAll(arg);
+ }
+ }
+
+ // build new specification without /dev/ elements
+ m_spec = args.join(QLatin1Char(':'));
+
+ foreach (const QString &device, devices)
+ addDevice(device);
+
+ // when no devices specified, use device discovery to scan and monitor
+ if (devices.isEmpty()) {
+ qCDebug(qLcEvdevTouch) << "evdevtouch: Using device discovery";
+ m_deviceDiscovery = QDeviceDiscovery::create(QDeviceDiscovery::Device_Touchpad | QDeviceDiscovery::Device_Touchscreen, this);
+ if (m_deviceDiscovery) {
+ QStringList devices = m_deviceDiscovery->scanConnectedDevices();
+ foreach (const QString &device, devices)
+ addDevice(device);
+ connect(m_deviceDiscovery, SIGNAL(deviceDetected(QString)), this, SLOT(addDevice(QString)));
+ connect(m_deviceDiscovery, SIGNAL(deviceRemoved(QString)), this, SLOT(removeDevice(QString)));
+ }
+ }
+}
+
+QEvdevTouchManager::~QEvdevTouchManager()
+{
+ qDeleteAll(m_activeDevices);
+}
+
+void QEvdevTouchManager::addDevice(const QString &deviceNode)
+{
+ qCDebug(qLcEvdevTouch) << "Adding device at" << deviceNode;
+ QEvdevTouchScreenHandlerThread *handler;
+ handler = new QEvdevTouchScreenHandlerThread(deviceNode, m_spec);
+ if (handler) {
+ m_activeDevices.insert(deviceNode, handler);
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count());
+ } else {
+ qWarning("evdevtouch: Failed to open touch device %s", qPrintable(deviceNode));
+ }
+}
+
+void QEvdevTouchManager::removeDevice(const QString &deviceNode)
+{
+ if (m_activeDevices.contains(deviceNode)) {
+ qCDebug(qLcEvdevTouch) << "Removing device at" << deviceNode;
+ QEvdevTouchScreenHandlerThread *handler = m_activeDevices.value(deviceNode);
+ m_activeDevices.remove(deviceNode);
+ QInputDeviceManagerPrivate::get(QGuiApplicationPrivate::inputDeviceManager())->setDeviceCount(
+ QInputDeviceManager::DeviceTypeTouch, m_activeDevices.count());
+ delete handler;
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
new file mode 100644
index 0000000000..bf484fd88b
--- /dev/null
+++ b/src/platformsupport/input/evdevtouch/qevdevtouchmanager_p.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2015 The Qt Company Ltd.
+** Contact: http://www.qt.io/licensing/
+**
+** This file is part of the QtGui module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL21$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see http://www.qt.io/terms-conditions. For further
+** information use the contact form at http://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 or version 3 as published by the Free
+** Software Foundation and appearing in the file LICENSE.LGPLv21 and
+** LICENSE.LGPLv3 included in the packaging of this file. Please review the
+** following information to ensure the GNU Lesser General Public License
+** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** As a special exception, The Qt Company gives you certain additional
+** rights. These rights are described in The Qt Company LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QEVDEVTOUCHMANAGER_P_H
+#define QEVDEVTOUCHMANAGER_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QObject>
+#include <QHash>
+#include <QSocketNotifier>
+
+QT_BEGIN_NAMESPACE
+
+class QDeviceDiscovery;
+class QEvdevTouchScreenHandlerThread;
+
+class QEvdevTouchManager : public QObject
+{
+ Q_OBJECT
+public:
+ QEvdevTouchManager(const QString &key, const QString &spec, QObject *parent = 0);
+ ~QEvdevTouchManager();
+
+private slots:
+ void addDevice(const QString &deviceNode);
+ void removeDevice(const QString &deviceNode);
+
+private:
+ QString m_spec;
+ QDeviceDiscovery *m_deviceDiscovery;
+ QHash<QString, QEvdevTouchScreenHandlerThread *> m_activeDevices;
+};
+
+QT_END_NAMESPACE
+
+#endif // QEVDEVTOUCHMANAGER_P_H
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
index 843387e679..e662d5f2d3 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -79,10 +79,14 @@ QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent)
connect(ofonoWatcher, SIGNAL(serviceUnregistered(QString)),
this, SLOT(ofonoUnRegistered(QString)));
- if (QDBusConnection::systemBus().interface()->isServiceRegistered("org.ofono"))
+ QDBusConnectionInterface *interface = QDBusConnection::systemBus().interface();
+
+ if (!interface) return;
+
+ if (interface->isServiceRegistered("org.ofono"))
QMetaObject::invokeMethod(this, "ofonoRegistered", Qt::QueuedConnection);
- if (QDBusConnection::systemBus().interface()->isServiceRegistered(NM_DBUS_SERVICE))
+ if (interface->isServiceRegistered(NM_DBUS_SERVICE))
QMetaObject::invokeMethod(this, "nmRegistered", Qt::QueuedConnection);
}
diff --git a/src/plugins/generic/evdevtouch/main.cpp b/src/plugins/generic/evdevtouch/main.cpp
index d9aebfbe4c..ef6774b0a0 100644
--- a/src/plugins/generic/evdevtouch/main.cpp
+++ b/src/plugins/generic/evdevtouch/main.cpp
@@ -32,7 +32,7 @@
****************************************************************************/
#include <QtGui/qgenericplugin.h>
-#include <QtPlatformSupport/private/qevdevtouch_p.h>
+#include <QtPlatformSupport/private/qevdevtouchmanager_p.h>
QT_BEGIN_NAMESPACE
@@ -55,7 +55,7 @@ QObject* QEvdevTouchScreenPlugin::create(const QString &key,
const QString &spec)
{
if (!key.compare(QLatin1String("EvdevTouch"), Qt::CaseInsensitive))
- return new QEvdevTouchScreenHandlerThread(spec);
+ return new QEvdevTouchManager(key, spec);
return 0;
}
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index dca5fe871e..ad9877eb25 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -554,6 +554,10 @@ void TableGenerator::parseKeySequence(char *line)
if (!composeValueEnd)
return;
+ // if composed value is a quotation mark adjust the end pointer
+ if (composeValueEnd[1] == '"')
+ ++composeValueEnd;
+
if (*composeValue == '\\' && composeValue[1] >= '0' && composeValue[1] <= '9') {
// handle octal and hex code values
char detectBase = composeValue[2];
@@ -568,7 +572,7 @@ void TableGenerator::parseKeySequence(char *line)
// handle direct text encoded in the locale
if (*composeValue == '\\')
++composeValue;
- elem.value = QString::fromLocal8Bit(composeValue).at(0).unicode();
+ elem.value = QString::fromLocal8Bit(composeValue, composeValueEnd - composeValue).at(0).unicode();
++composeValue;
}
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
index 49fa32004e..d1bea9af23 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.cpp
@@ -80,37 +80,32 @@ static const int composingKeys[] = {
};
QComposeInputContext::QComposeInputContext()
+ : m_tableState(TableGenerator::EmptyTable)
+ , m_compositionTableInitialized(false)
{
- TableGenerator reader;
- m_tableState = reader.tableState();
-
- if ((m_tableState & TableGenerator::NoErrors) == TableGenerator::NoErrors) {
- m_composeTable = reader.composeTable();
- clearComposeBuffer();
- }
+ clearComposeBuffer();
}
bool QComposeInputContext::filterEvent(const QEvent *event)
{
- // if there were errors when generating the compose table input
- // context should not try to filter anything, simply return false
- if ((m_tableState & TableGenerator::NoErrors) != TableGenerator::NoErrors)
- return false;
-
const QKeyEvent *keyEvent = (const QKeyEvent *)event;
// should pass only the key presses
if (keyEvent->type() != QEvent::KeyPress) {
return false;
}
+ // if there were errors when generating the compose table input
+ // context should not try to filter anything, simply return false
+ if (m_compositionTableInitialized && (m_tableState & TableGenerator::NoErrors) != TableGenerator::NoErrors)
+ return false;
+
int keyval = keyEvent->key();
int keysym = 0;
if (ignoreKey(keyval))
return false;
- QString text = keyEvent->text();
- if (!composeKey(keyval) && text.isEmpty())
+ if (!composeKey(keyval) && keyEvent->text().isEmpty())
return false;
keysym = keyEvent->nativeVirtualKey();
@@ -163,6 +158,15 @@ static bool isDuplicate(const QComposeTableElement &lhs, const QComposeTableElem
bool QComposeInputContext::checkComposeTable()
{
+ if (!m_compositionTableInitialized) {
+ TableGenerator reader;
+ m_tableState = reader.tableState();
+
+ if ((m_tableState & TableGenerator::NoErrors) == TableGenerator::NoErrors)
+ m_composeTable = reader.composeTable();
+
+ m_compositionTableInitialized = true;
+ }
QVector<QComposeTableElement>::const_iterator it =
std::lower_bound(m_composeTable.constBegin(), m_composeTable.constEnd(), m_composeBuffer, Compare());
diff --git a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
index 643b93c32d..bdf5a91335 100644
--- a/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
+++ b/src/plugins/platforminputcontexts/compose/qcomposeplatforminputcontext.h
@@ -70,6 +70,7 @@ private:
QVector<QComposeTableElement> m_composeTable;
uint m_composeBuffer[QT_KEYSEQUENCE_MAX_LEN + 1];
TableGenerator::TableState m_tableState;
+ bool m_compositionTableInitialized;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/androidjniinput.cpp b/src/plugins/platforms/android/androidjniinput.cpp
index 14b0c96cb5..8ee3ff88d1 100644
--- a/src/plugins/platforms/android/androidjniinput.cpp
+++ b/src/plugins/platforms/android/androidjniinput.cpp
@@ -663,24 +663,24 @@ namespace QtAndroidInput
return unicode ? QString(QChar(unicode)) : QString();
}
- static void keyDown(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier)
+ static void keyDown(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier, jboolean autoRepeat)
{
QWindowSystemInterface::handleKeyEvent(0,
QEvent::KeyPress,
mapAndroidKey(key),
mapAndroidModifiers(modifier),
toString(unicode),
- false);
+ autoRepeat);
}
- static void keyUp(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier)
+ static void keyUp(JNIEnv */*env*/, jobject /*thiz*/, jint key, jint unicode, jint modifier, jboolean autoRepeat)
{
QWindowSystemInterface::handleKeyEvent(0,
QEvent::KeyRelease,
mapAndroidKey(key),
mapAndroidModifiers(modifier),
toString(unicode),
- false);
+ autoRepeat);
}
static void keyboardVisibilityChanged(JNIEnv */*env*/, jobject /*thiz*/, jboolean visibility)
@@ -702,8 +702,8 @@ namespace QtAndroidInput
{"mouseUp", "(III)V", (void *)mouseUp},
{"mouseMove", "(III)V", (void *)mouseMove},
{"longPress", "(III)V", (void *)longPress},
- {"keyDown", "(III)V", (void *)keyDown},
- {"keyUp", "(III)V", (void *)keyUp},
+ {"keyDown", "(IIIZ)V", (void *)keyDown},
+ {"keyUp", "(IIIZ)V", (void *)keyUp},
{"keyboardVisibilityChanged", "(Z)V", (void *)keyboardVisibilityChanged}
};
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h
index dc9140d990..ee42a83446 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.h
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.h
@@ -138,6 +138,8 @@ public:
QCocoaWindow *popPopupWindow();
QCocoaWindow *activePopupWindow() const;
QList<QCocoaWindow *> *popupWindowStack();
+
+ void setApplicationIcon(const QIcon &icon) const;
private:
static QCocoaIntegration *mInstance;
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index aa33cfd8bc..c8f6dd05db 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -420,6 +420,7 @@ bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
case ForeignWindows:
case RasterGLSurface:
case ApplicationState:
+ case ApplicationIcon:
return true;
default:
return QPlatformIntegration::hasCapability(cap);
@@ -569,4 +570,16 @@ QList<QCocoaWindow *> *QCocoaIntegration::popupWindowStack()
return &m_popupWindowStack;
}
+void QCocoaIntegration::setApplicationIcon(const QIcon &icon) const
+{
+ NSImage *image = nil;
+ if (!icon.isNull()) {
+ NSSize size = [[[NSApplication sharedApplication] dockTile] size];
+ QPixmap pixmap = icon.pixmap(size.width, size.height);
+ image = static_cast<NSImage *>(qt_mac_create_nsimage(pixmap));
+ }
+ [[NSApplication sharedApplication] setApplicationIconImage:image];
+ [image release];
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index bf12c0f2ce..f288ab85c0 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -308,7 +308,6 @@ NSMenuItem *QCocoaMenuItem::sync()
}
[m_native setHidden: !m_isVisible];
- [m_native setEnabled: m_enabled];
[m_native setView:m_itemView];
QString text = mergeText();
@@ -410,7 +409,7 @@ void QCocoaMenuItem::syncModalState(bool modal)
if (modal)
[m_native setEnabled:NO];
else
- [m_native setEnabled:m_enabled];
+ [m_native setEnabled:YES];
}
QPlatformMenuItem::MenuRole QCocoaMenuItem::effectiveRole() const
diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm
index c0c0080f9a..f6389a2096 100644
--- a/src/plugins/platforms/cocoa/qcocoawindow.mm
+++ b/src/plugins/platforms/cocoa/qcocoawindow.mm
@@ -1515,10 +1515,11 @@ void QCocoaWindow::syncWindowState(Qt::WindowState newState)
}
}
+ const bool effMax = m_effectivelyMaximized;
if ((m_synchedWindowState & Qt::WindowMaximized) != (newState & Qt::WindowMaximized) || (m_effectivelyMaximized && newState == Qt::WindowNoState)) {
if ((m_synchedWindowState & Qt::WindowFullScreen) == (newState & Qt::WindowFullScreen)) {
[m_nsWindow zoom : m_nsWindow]; // toggles
- m_effectivelyMaximized = !m_effectivelyMaximized;
+ m_effectivelyMaximized = !effMax;
} else if (!(newState & Qt::WindowMaximized)) {
// it would be nice to change the target geometry that toggleFullScreen will animate toward
// but there is no known way, so the maximized state is not possible at this time
diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h
index c3815ee60a..32bc15d092 100644
--- a/src/plugins/platforms/cocoa/qnsview.h
+++ b/src/plugins/platforms/cocoa/qnsview.h
@@ -59,6 +59,7 @@ Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(QNSViewMouseMoveHelper));
bool m_shouldInvalidateWindowShadow;
QWindow *m_window;
QCocoaWindow *m_platformWindow;
+ NSTrackingArea *m_trackingArea;
Qt::MouseButtons m_buttons;
Qt::MouseButtons m_frameStrutButtons;
QString m_composingText;
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index a27c93e23f..25a92d2868 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -167,6 +167,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
- (void)dealloc
{
CGImageRelease(m_maskImage);
+ [m_trackingArea release];
m_maskImage = 0;
m_window = 0;
m_subscribesForGlobalFrameNotifications = false;
@@ -188,6 +189,7 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
m_window = window;
m_platformWindow = platformWindow;
m_sendKeyEvent = false;
+ m_trackingArea = nil;
#ifdef QT_COCOA_ENABLE_ACCESSIBILITY_INSPECTOR
// prevent rift in space-time continuum, disable
@@ -847,19 +849,11 @@ QT_WARNING_POP
{
[super updateTrackingAreas];
- // [NSView addTrackingArea] is slow, so bail out early if we can:
- if (NSIsEmptyRect([self visibleRect]))
- return;
-
- // Remove current trakcing areas:
QCocoaAutoReleasePool pool;
- if (NSArray *trackingArray = [self trackingAreas]) {
- NSUInteger size = [trackingArray count];
- for (NSUInteger i = 0; i < size; ++i) {
- NSTrackingArea *t = [trackingArray objectAtIndex:i];
- [self removeTrackingArea:t];
- }
- }
+
+ // NSTrackingInVisibleRect keeps care of updating once the tracking is set up, so bail out early
+ if (m_trackingArea && [[self trackingAreas] containsObject:m_trackingArea])
+ return;
// Ideally, we shouldn't have NSTrackingMouseMoved events included below, it should
// only be turned on if mouseTracking, hover is on or a tool tip is set.
@@ -869,12 +863,12 @@ QT_WARNING_POP
// is a performance hit). So it goes.
NSUInteger trackingOptions = NSTrackingMouseEnteredAndExited | NSTrackingActiveInActiveApp
| NSTrackingInVisibleRect | NSTrackingMouseMoved | NSTrackingCursorUpdate;
- NSTrackingArea *ta = [[[NSTrackingArea alloc] initWithRect:[self frame]
- options:trackingOptions
- owner:m_mouseMoveHelper
- userInfo:nil]
- autorelease];
- [self addTrackingArea:ta];
+ [m_trackingArea release];
+ m_trackingArea = [[NSTrackingArea alloc] initWithRect:[self frame]
+ options:trackingOptions
+ owner:m_mouseMoveHelper
+ userInfo:nil];
+ [self addTrackingArea:m_trackingArea];
}
-(void)cursorUpdateImpl:(NSEvent *)theEvent
@@ -1889,6 +1883,48 @@ static QPoint mapWindowCoordinates(QWindow *source, QWindow *target, QPoint poin
response = QWindowSystemInterface::handleDrag(target, &mimeData, mapWindowCoordinates(m_window, target, qt_windowPoint), qtAllowed);
}
+ QCocoaDrag* nativeDrag = QCocoaIntegration::instance()->drag();
+ const QPixmap pixmapCursor = nativeDrag->currentDrag()->dragCursor(response.acceptedAction());
+ NSCursor *nativeCursor = nil;
+
+ if (pixmapCursor.isNull()) {
+ switch (response.acceptedAction()) {
+ case Qt::CopyAction:
+ nativeCursor = [NSCursor dragCopyCursor];
+ break;
+ case Qt::LinkAction:
+ nativeCursor = [NSCursor dragLinkCursor];
+ break;
+ case Qt::IgnoreAction:
+ // Uncomment the next lines if forbiden cursor wanted on non droppable targets.
+ /*nativeCursor = [NSCursor operationNotAllowedCursor];
+ break;*/
+ case Qt::MoveAction:
+ default:
+ nativeCursor = [NSCursor arrowCursor];
+ break;
+ }
+ }
+ else {
+ NSImage *nsimage = qt_mac_create_nsimage(pixmapCursor);
+ nativeCursor = [[NSCursor alloc] initWithImage:nsimage hotSpot:NSZeroPoint];
+ [nsimage release];
+ }
+
+ // change the cursor
+ [nativeCursor set];
+
+ // Make sure the cursor is updated correctly if the mouse does not move and window is under cursor
+ // by creating a fake move event
+ const QPoint mousePos(QCursor::pos());
+ CGEventRef moveEvent(CGEventCreateMouseEvent(
+ NULL, kCGEventMouseMoved,
+ CGPointMake(mousePos.x(), mousePos.y()),
+ kCGMouseButtonLeft // ignored
+ ));
+ CGEventPost(kCGHIDEventTap, moveEvent);
+ CFRelease(moveEvent);
+
return qt_mac_mapDropAction(response.acceptedAction());
}
diff --git a/src/plugins/platforms/ios/qiostextresponder.mm b/src/plugins/platforms/ios/qiostextresponder.mm
index 4f85fb7b55..3d0bac82c8 100644
--- a/src/plugins/platforms/ios/qiostextresponder.mm
+++ b/src/plugins/platforms/ios/qiostextresponder.mm
@@ -218,7 +218,9 @@
else if (hints & Qt::ImhFormattedNumbersOnly)
self.keyboardType = UIKeyboardTypeDecimalPad;
else if (hints & Qt::ImhDialableCharactersOnly)
- self.keyboardType = UIKeyboardTypeNumberPad;
+ self.keyboardType = UIKeyboardTypePhonePad;
+ else if (hints & Qt::ImhLatinOnly)
+ self.keyboardType = UIKeyboardTypeASCIICapable;
else
self.keyboardType = UIKeyboardTypeDefault;
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index 2c61f68e83..ccf86dafb2 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -49,7 +49,7 @@
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
#include <QtPlatformSupport/private/qevdevkeyboardmanager_p.h>
-#include <QtPlatformSupport/private/qevdevtouch_p.h>
+#include <QtPlatformSupport/private/qevdevtouchmanager_p.h>
#endif
#if !defined(QT_NO_TSLIB) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
@@ -139,7 +139,7 @@ void QLinuxFbIntegration::createInputHandlers()
new QTsLibMouseHandler(QLatin1String("TsLib"), QString());
else
#endif // QT_NO_TSLIB
- new QEvdevTouchScreenHandlerThread(QString(), this);
+ new QEvdevTouchManager(QLatin1String("EvdevTouch"), QString() /* spec */, this);
#endif
}
diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.cpp b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
index 96ca531899..ca8d731e66 100644
--- a/src/plugins/platforms/qnx/qqnxfilepicker.cpp
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.cpp
@@ -55,6 +55,8 @@
#define qFilePickerDebug QT_NO_QDEBUG_MACRO
#endif
+QT_BEGIN_NAMESPACE
+
static const char s_filePickerTarget[] = "sys.filepicker.target";
QQnxFilePicker::QQnxFilePicker(QObject *parent)
@@ -316,3 +318,5 @@ QString QQnxFilePicker::modeToString(QQnxFilePicker::Mode mode) const
return QStringLiteral("Picker");
}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxfilepicker.h b/src/plugins/platforms/qnx/qqnxfilepicker.h
index aef8f43abc..7e4f9010cc 100644
--- a/src/plugins/platforms/qnx/qqnxfilepicker.h
+++ b/src/plugins/platforms/qnx/qqnxfilepicker.h
@@ -38,6 +38,8 @@
#include <QObject>
#include <QStringList>
+QT_BEGIN_NAMESPACE
+
struct navigator_invoke_invocation_t;
class QQnxFilePicker : public QObject, public QAbstractNativeEventFilter
@@ -100,4 +102,6 @@ private:
QString m_title;
};
+QT_END_NAMESPACE
+
#endif // QQNXFILEPICKER_H
diff --git a/src/plugins/platforms/qnx/qqnxsystemsettings.h b/src/plugins/platforms/qnx/qqnxsystemsettings.h
index 5535e02dd8..6a99d5a70c 100644
--- a/src/plugins/platforms/qnx/qqnxsystemsettings.h
+++ b/src/plugins/platforms/qnx/qqnxsystemsettings.h
@@ -37,10 +37,10 @@
#include <QtCore/qhash.h>
#include <qpa/qplatformtheme.h>
-class QPlatformFontDatabase;
-
QT_BEGIN_NAMESPACE
+class QPlatformFontDatabase;
+
QHash<QPlatformTheme::Font, QFont *> qt_qnx_createRoleFonts(QPlatformFontDatabase *fontDatabase);
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
index c32a519d97..6bde4c7354 100644
--- a/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
+++ b/src/plugins/platforms/qnx/qqnxvirtualkeyboardpps.h
@@ -86,4 +86,6 @@ private:
static const size_t ms_bufferSize;
};
+QT_END_NAMESPACE
+
#endif // VIRTUALKEYBOARDPPS_H
diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
index eaf44f0f72..99c44c69ef 100644
--- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp
+++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp
@@ -38,7 +38,7 @@
#include <QtPlatformSupport/private/qaccessiblebridgeutils_p.h>
#include <QtGui/qaccessible.h>
#include <QtGui/qclipboard.h>
-#include <QtWidgets/qapplication.h>
+#include <QtGui/qguiapplication.h>
#include <QtCore/qdebug.h>
QT_BEGIN_NAMESPACE
diff --git a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
index 013f1a5b77..8b67f235bb 100644
--- a/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
+++ b/src/plugins/platforms/windows/accessible/qwindowsmsaaaccessible.cpp
@@ -49,10 +49,6 @@
#include <QtGui/qguiapplication.h>
#include <qpa/qplatformnativeinterface.h>
#include <QtGui/qwindow.h>
-#include <QtWidgets/qapplication.h>
-#include <QtWidgets/qgraphicsitem.h>
-#include <QtWidgets/qgraphicsview.h>
-#include <QtWidgets/qmessagebox.h>
//#include <uiautomationcoreapi.h>
#ifndef UiaRootObjectId
diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json
index 0217b79ecf..23607523bd 100644
--- a/src/plugins/platforms/windows/openglblacklists/default.json
+++ b/src/plugins/platforms/windows/openglblacklists/default.json
@@ -4,12 +4,16 @@
"entries": [
{
"id": 1,
- "description": "Desktop OpenGL is unreliable on Intel HD3000/GMA (QTBUG-43263, QTBUG-42240)",
+ "description": "Desktop OpenGL is unreliable on some Intel HD laptops (QTBUG-43263, QTBUG-42240)",
"vendor_id": "0x8086",
"device_id": [ "0x0A16" ],
"os": {
"type": "win"
},
+ "driver_version": {
+ "op": "<=",
+ "value": "10.18.10.3277"
+ },
"features": [
"disable_desktopgl"
]
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp
index 7db6abd8ef..0184877fdd 100644
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp
@@ -366,7 +366,8 @@ QWindowsEGLStaticContext *QWindowsEGLStaticContext::create(QWindowsOpenGLTester:
const EGLint anglePlatformAttributes[][5] = {
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_NONE },
{ EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE, EGL_NONE },
- { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_USE_WARP_ANGLE, EGL_TRUE, EGL_NONE }
+ { EGL_PLATFORM_ANGLE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE,
+ EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, EGL_PLATFORM_ANGLE_DEVICE_TYPE_WARP_ANGLE, EGL_NONE }
};
const EGLint *attributes = 0;
if (preferredType & QWindowsOpenGLTester::AngleRendererD3d11)
diff --git a/src/plugins/platforms/windows/qwindowsglcontext.cpp b/src/plugins/platforms/windows/qwindowsglcontext.cpp
index 7a17942b27..d9eec9f603 100644
--- a/src/plugins/platforms/windows/qwindowsglcontext.cpp
+++ b/src/plugins/platforms/windows/qwindowsglcontext.cpp
@@ -601,6 +601,14 @@ static int choosePixelFormat(HDC hdc,
break;
if (iAttributes[samplesValuePosition] > 1) {
iAttributes[samplesValuePosition] /= 2;
+ } else if (iAttributes[samplesValuePosition] == 1) {
+ // Fallback in case it is unable to initialize with any
+ // samples to avoid falling back to the GDI path
+ // NB: The sample attributes needs to be at the end for this
+ // to work correctly
+ iAttributes[samplesValuePosition - 1] = FALSE;
+ iAttributes[samplesValuePosition] = 0;
+ iAttributes[samplesValuePosition + 1] = 0;
} else {
break;
}
diff --git a/src/plugins/platforms/windows/qwindowsopengltester.cpp b/src/plugins/platforms/windows/qwindowsopengltester.cpp
index f5065a22b8..2e6a43f596 100644
--- a/src/plugins/platforms/windows/qwindowsopengltester.cpp
+++ b/src/plugins/platforms/windows/qwindowsopengltester.cpp
@@ -224,10 +224,7 @@ QWindowsOpenGLTester::Renderers QWindowsOpenGLTester::detectSupportedRenderers(c
#elif defined(Q_OS_WINCE)
return QWindowsOpenGLTester::Gles;
#else
- QOpenGLConfig::Gpu qgpu;
- qgpu.deviceId = gpu.deviceId;
- qgpu.vendorId = gpu.vendorId;
- qgpu.driverVersion = gpu.driverVersion;
+ QOpenGLConfig::Gpu qgpu = QOpenGLConfig::Gpu::fromDevice(gpu.deviceId, gpu.vendorId, gpu.driverVersion);
SupportedRenderersCache *srCache = supportedRenderersCache();
SupportedRenderersCache::const_iterator it = srCache->find(qgpu);
if (it != srCache->cend())
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 6afa4e6591..b19510073a 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -540,13 +540,9 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
}
if (flags & Qt::WindowSystemMenuHint)
style |= WS_SYSMENU;
- else if (dialog) {
- // QTBUG-2027, dialogs without system menu.
- style |= WS_SYSMENU;
- if (!(flags & Qt::FramelessWindowHint)) {
- style |= WS_BORDER;
- exStyle |= WS_EX_DLGMODALFRAME;
- }
+ else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
+ style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
+ exStyle |= WS_EX_DLGMODALFRAME;
}
if (flags & Qt::WindowMinimizeButtonHint)
style |= WS_MINIMIZEBOX;
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
index 299a80b1d7..f0de578db6 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.cpp
@@ -32,6 +32,7 @@
****************************************************************************/
#include "qwinrtinputcontext.h"
+#include "qwinrtscreen.h"
#include <QtGui/QWindow>
#include <wrl.h>
@@ -44,11 +45,6 @@ using namespace ABI::Windows::Foundation;
using namespace ABI::Windows::UI::ViewManagement;
using namespace ABI::Windows::UI::Core;
-#if defined(Q_OS_WINPHONE) && _MSC_VER==1700
-#include <windows.phone.ui.core.h>
-using namespace ABI::Windows::Phone::UI::Core;
-#endif
-
typedef ITypedEventHandler<InputPane*, InputPaneVisibilityEventArgs*> InputPaneVisibilityHandler;
QT_BEGIN_NAMESPACE
@@ -66,8 +62,8 @@ QT_BEGIN_NAMESPACE
Windows Phone, however, supports direct hiding/showing of the keyboard.
*/
-QWinRTInputContext::QWinRTInputContext(ICoreWindow *window)
- : m_window(window)
+QWinRTInputContext::QWinRTInputContext(QWinRTScreen *screen)
+ : m_screen(screen)
{
IInputPaneStatics *statics;
if (FAILED(GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_UI_ViewManagement_InputPane).Get(),
@@ -86,9 +82,7 @@ QWinRTInputContext::QWinRTInputContext(ICoreWindow *window)
inputPane->add_Hiding(Callback<InputPaneVisibilityHandler>(
this, &QWinRTInputContext::onHiding).Get(), &hideToken);
- Rect rect;
- inputPane->get_OccludedRect(&rect);
- m_keyboardRect = QRectF(rect.X, rect.Y, rect.Width, rect.Height);
+ handleVisibilityChange(inputPane);
m_isInputPanelVisible = !m_keyboardRect.isEmpty();
} else {
qWarning(Q_FUNC_INFO ": failed to retrieve InputPane.");
@@ -109,38 +103,31 @@ HRESULT QWinRTInputContext::onShowing(IInputPane *pane, IInputPaneVisibilityEven
{
m_isInputPanelVisible = true;
emitInputPanelVisibleChanged();
-
- Rect rect;
- pane->get_OccludedRect(&rect);
- setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height));
-
- return S_OK;
+ return handleVisibilityChange(pane);
}
HRESULT QWinRTInputContext::onHiding(IInputPane *pane, IInputPaneVisibilityEventArgs *)
{
m_isInputPanelVisible = false;
emitInputPanelVisibleChanged();
+ return handleVisibilityChange(pane);
+}
+HRESULT QWinRTInputContext::handleVisibilityChange(IInputPane *pane)
+{
Rect rect;
pane->get_OccludedRect(&rect);
- setKeyboardRect(QRectF(rect.X, rect.Y, rect.Width, rect.Height));
-
+ const QRectF keyboardRect = QRectF(qRound(rect.X * m_screen->scaleFactor()), qRound(rect.Y * m_screen->scaleFactor()),
+ qRound(rect.Width * m_screen->scaleFactor()), qRound(rect.Height * m_screen->scaleFactor()));
+ if (m_keyboardRect != keyboardRect) {
+ m_keyboardRect = keyboardRect;
+ emitKeyboardRectChanged();
+ }
return S_OK;
}
-void QWinRTInputContext::setKeyboardRect(const QRectF rect)
-{
- if (m_keyboardRect == rect)
- return;
-
- m_keyboardRect = rect;
- emitKeyboardRectChanged();
-}
-
#ifdef Q_OS_WINPHONE
-#if _MSC_VER>1700 // Windows Phone 8.1+
static HRESULT getInputPane(ComPtr<IInputPane2> *inputPane2)
{
ComPtr<IInputPaneStatics> factory;
@@ -165,17 +152,9 @@ static HRESULT getInputPane(ComPtr<IInputPane2> *inputPane2)
}
return hr;
}
-#endif // _MSC_VER>1700
void QWinRTInputContext::showInputPanel()
{
-#if _MSC_VER<=1700 // Windows Phone 8.0
- ICoreWindowKeyboardInput *input;
- if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) {
- input->put_IsKeyboardInputEnabled(true);
- input->Release();
- }
-#else // _MSC_VER<=1700
ComPtr<IInputPane2> inputPane;
HRESULT hr = getInputPane(&inputPane);
if (FAILED(hr))
@@ -185,18 +164,10 @@ void QWinRTInputContext::showInputPanel()
hr = inputPane->TryShow(&success);
if (FAILED(hr))
qErrnoWarning(hr, "Failed to show input panel.");
-#endif // _MSC_VER>1700
}
void QWinRTInputContext::hideInputPanel()
{
-#if _MSC_VER<=1700 // Windows Phone 8.0
- ICoreWindowKeyboardInput *input;
- if (SUCCEEDED(m_window->QueryInterface(IID_PPV_ARGS(&input)))) {
- input->put_IsKeyboardInputEnabled(false);
- input->Release();
- }
-#else // _MSC_VER<=1700
ComPtr<IInputPane2> inputPane;
HRESULT hr = getInputPane(&inputPane);
if (FAILED(hr))
@@ -206,7 +177,6 @@ void QWinRTInputContext::hideInputPanel()
hr = inputPane->TryHide(&success);
if (FAILED(hr))
qErrnoWarning(hr, "Failed to hide input panel.");
-#endif // _MSC_VER>1700
}
#else // Q_OS_WINPHONE
@@ -257,7 +227,7 @@ HRESULT QWinRTInputContext::GetPropertyValue(PROPERTYID idProp, VARIANT *retVal)
break;
case 30020: //UIA_NativeWindowHandlePropertyId
retVal->vt = VT_PTR;
- retVal->punkVal = m_window;
+ retVal->punkVal = m_screen->coreWindow();
break;
}
return S_OK;
@@ -267,7 +237,7 @@ HRESULT QWinRTInputContext::get_HostRawElementProvider(IRawElementProviderSimple
{
// Return the window's element provider
IInspectable *hostProvider;
- HRESULT hr = m_window->get_AutomationHostProvider(&hostProvider);
+ HRESULT hr = m_screen->coreWindow()->get_AutomationHostProvider(&hostProvider);
if (SUCCEEDED(hr)) {
hr = hostProvider->QueryInterface(IID_PPV_ARGS(retVal));
hostProvider->Release();
diff --git a/src/plugins/platforms/winrt/qwinrtinputcontext.h b/src/plugins/platforms/winrt/qwinrtinputcontext.h
index 6b1b66c0a3..761908a9cb 100644
--- a/src/plugins/platforms/winrt/qwinrtinputcontext.h
+++ b/src/plugins/platforms/winrt/qwinrtinputcontext.h
@@ -58,6 +58,7 @@ namespace ABI {
QT_BEGIN_NAMESPACE
+class QWinRTScreen;
class QWinRTInputContext : public QPlatformInputContext
#ifndef Q_OS_WINPHONE
, public Microsoft::WRL::RuntimeClass<
@@ -66,7 +67,7 @@ class QWinRTInputContext : public QPlatformInputContext
#endif // !Q_OS_WINPHONE
{
public:
- explicit QWinRTInputContext(ABI::Windows::UI::Core::ICoreWindow *window);
+ explicit QWinRTInputContext(QWinRTScreen *);
QRectF keyboardRect() const;
@@ -101,9 +102,10 @@ private:
ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *);
HRESULT onHiding(ABI::Windows::UI::ViewManagement::IInputPane *,
ABI::Windows::UI::ViewManagement::IInputPaneVisibilityEventArgs *);
- void setKeyboardRect(const QRectF rect);
- ABI::Windows::UI::Core::ICoreWindow *m_window;
+ HRESULT handleVisibilityChange(ABI::Windows::UI::ViewManagement::IInputPane *);
+
+ QWinRTScreen *m_screen;
QRectF m_keyboardRect;
bool m_isInputPanelVisible;
};
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index d7888194c2..c4512b4d2d 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -497,9 +497,9 @@ QWinRTScreen::QWinRTScreen()
Q_ASSERT_SUCCEEDED(hr);
#ifdef Q_OS_WINPHONE
- d->inputContext.reset(new QWinRTInputContext(d->coreWindow.Get()));
+ d->inputContext.reset(new QWinRTInputContext(this));
#else
- d->inputContext = Make<QWinRTInputContext>(d->coreWindow.Get());
+ d->inputContext = Make<QWinRTInputContext>(this);
#endif
Rect rect;
@@ -580,7 +580,7 @@ QWinRTScreen::QWinRTScreen()
d->orientation = d->nativeOrientation;
onOrientationChanged(Q_NULLPTR, Q_NULLPTR);
- d->eglDisplay = eglGetDisplay(d->displayInformation.Get());
+ d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (d->eglDisplay == EGL_NO_DISPLAY)
qCritical("Failed to initialize EGL display: 0x%x", eglGetError());
@@ -616,14 +616,7 @@ QWinRTScreen::QWinRTScreen()
d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->surfaceFormat);
d->surfaceFormat = q_glFormatFromConfig(d->eglDisplay, d->eglConfig, d->surfaceFormat);
- const QRect bounds = geometry();
- EGLint windowAttributes[] = {
- EGL_FIXED_SIZE_ANGLE, EGL_TRUE,
- EGL_WIDTH, bounds.width(),
- EGL_HEIGHT, bounds.height(),
- EGL_NONE
- };
- d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), windowAttributes);
+ d->eglSurface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, d->coreWindow.Get(), NULL);
if (d->eglSurface == EGL_NO_SURFACE)
qCritical("Failed to create EGL window surface: 0x%x", eglGetError());
}
@@ -680,6 +673,12 @@ QDpi QWinRTScreen::logicalDpi() const
return QDpi(d->logicalDpi, d->logicalDpi);
}
+qreal QWinRTScreen::scaleFactor() const
+{
+ Q_D(const QWinRTScreen);
+ return d->scaleFactor;
+}
+
QWinRTInputContext *QWinRTScreen::inputContext() const
{
Q_D(const QWinRTScreen);
@@ -1081,14 +1080,6 @@ HRESULT QWinRTScreen::onSizeChanged(ICoreWindow *, IWindowSizeChangedEventArgs *
d->logicalSize = logicalSize;
if (d->eglDisplay) {
const QRect newGeometry = geometry();
- int width = newGeometry.width();
- int height = newGeometry.height();
-#ifdef Q_OS_WINPHONE // Windows Phone can pass in a negative size to provide orientation information
- width *= (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::LandscapeOrientation) ? -1 : 1;
- height *= (d->orientation == Qt::InvertedPortraitOrientation || d->orientation == Qt::InvertedLandscapeOrientation) ? -1 : 1;
-#endif
- eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_WIDTH, width);
- eglSurfaceAttrib(d->eglDisplay, d->eglSurface, EGL_HEIGHT, height);
QWindowSystemInterface::handleScreenGeometryChange(screen(), newGeometry, newGeometry);
QPlatformScreen::resizeMaximizedWindows();
handleExpose();
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index 404c8ca04e..cbef9543a9 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -93,6 +93,7 @@ public:
QSurfaceFormat surfaceFormat() const;
QSizeF physicalSize() const Q_DECL_OVERRIDE;
QDpi logicalDpi() const Q_DECL_OVERRIDE;
+ qreal scaleFactor() const;
QWinRTInputContext *inputContext() const;
QPlatformCursor *cursor() const;
Qt::KeyboardModifiers keyboardModifiers() const;
diff --git a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri
index 8c60268e0d..e859865687 100644
--- a/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri
+++ b/src/plugins/platforms/xcb/gl_integrations/gl_integrations_plugin_base.pri
@@ -29,8 +29,8 @@ CONFIG += qpa/genericunixfontdatabase
contains(QT_CONFIG, xcb-qt) {
DEFINES += XCB_USE_RENDER
- XCB_DIR = ../../../3rdparty/xcb
- INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/sysinclude
+ XCB_DIR = $$clean_path($$PWD/../../../../3rdparty/xcb)
+ INCLUDEPATH += $$XCB_DIR/include $$XCB_DIR/include/xcb $$XCB_DIR/sysinclude
LIBS += -lxcb -L$$OUT_PWD/xcb-static -lxcb-static
} else {
LIBS += -lxcb -lxcb-image -lxcb-icccm -lxcb-sync -lxcb-xfixes -lxcb-shm -lxcb-randr -lxcb-shape -lxcb-keysyms
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 706b9c8e48..8500aa1ffa 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -66,6 +66,7 @@
#include <X11/Xlib.h>
#include <X11/Xlib-xcb.h>
#include <X11/Xlibint.h>
+#include <X11/Xutil.h>
#endif
#if defined(XCB_USE_XINPUT2)
@@ -83,6 +84,12 @@ Q_LOGGING_CATEGORY(lcQpaXInput, "qt.qpa.input")
Q_LOGGING_CATEGORY(lcQpaXInputDevices, "qt.qpa.input.devices")
Q_LOGGING_CATEGORY(lcQpaScreen, "qt.qpa.screen")
+// this event type was added in libxcb 1.10,
+// but we support also older version
+#ifndef XCB_GE_GENERIC
+#define XCB_GE_GENERIC 35
+#endif
+
#ifdef XCB_USE_XLIB
static const char * const xcbConnectionErrors[] = {
"No error", /* Error 0 */
@@ -137,7 +144,7 @@ QXcbScreen* QXcbConnection::findScreenForOutput(xcb_window_t rootWindow, xcb_ran
return 0;
}
-QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScreen,
+QXcbScreen* QXcbConnection::createScreen(QXcbVirtualDesktop* virtualDesktop,
xcb_randr_output_t outputId,
xcb_randr_get_output_info_reply_t *output)
{
@@ -150,10 +157,10 @@ QXcbScreen* QXcbConnection::createScreen(int screenNumber, xcb_screen_t* xcbScre
int dotPos = displayName.lastIndexOf('.');
if (dotPos != -1)
displayName.truncate(dotPos);
- name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(screenNumber);
+ name = QString::fromLocal8Bit(displayName) + QLatin1Char('.') + QString::number(virtualDesktop->number());
}
- return new QXcbScreen(this, xcbScreen, outputId, output, name, screenNumber);
+ return new QXcbScreen(this, virtualDesktop, outputId, output, name);
}
bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output)
@@ -173,15 +180,11 @@ bool QXcbConnection::checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_out
return isPrimary;
}
-xcb_screen_t* QXcbConnection::xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber)
+QXcbVirtualDesktop* QXcbConnection::virtualDesktopForRootWindow(xcb_window_t rootWindow)
{
- xcb_screen_iterator_t xcbScreenIter = xcb_setup_roots_iterator(m_setup);
- for (; xcbScreenIter.rem; xcb_screen_next(&xcbScreenIter)) {
- if (xcbScreenIter.data->root == rootWindow) {
- if (xcbScreenNumber)
- *xcbScreenNumber = xcb_setup_roots_length(m_setup) - xcbScreenIter.rem;
- return xcbScreenIter.data;
- }
+ foreach (QXcbVirtualDesktop *virtualDesktop, m_virtualDesktops) {
+ if (virtualDesktop->screen()->root == rootWindow)
+ return virtualDesktop;
}
return 0;
@@ -194,8 +197,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
{
if (event->subCode == XCB_RANDR_NOTIFY_CRTC_CHANGE) {
xcb_randr_crtc_change_t crtc = event->u.cc;
- xcb_screen_t *xcbScreen = xcbScreenForRootWindow(crtc.window);
- if (!xcbScreen)
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(crtc.window);
+ if (!virtualDesktop)
// Not for us
return;
@@ -212,9 +215,8 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
} else if (event->subCode == XCB_RANDR_NOTIFY_OUTPUT_CHANGE) {
xcb_randr_output_change_t output = event->u.oc;
- int xcbScreenNumber = 0;
- xcb_screen_t *xcbScreen = xcbScreenForRootWindow(output.window, &xcbScreenNumber);
- if (!xcbScreen)
+ QXcbVirtualDesktop *virtualDesktop = virtualDesktopForRootWindow(output.window);
+ if (!virtualDesktop)
// Not for us
return;
@@ -242,7 +244,7 @@ void QXcbConnection::updateScreens(const xcb_randr_notify_event_t *event)
QScopedPointer<xcb_randr_get_output_info_reply_t, QScopedPointerPodDeleter> outputInfo(
xcb_randr_get_output_info_reply(xcb_connection(), outputInfoCookie, NULL));
- screen = createScreen(xcbScreenNumber, xcbScreen, output.output, outputInfo.data());
+ screen = createScreen(virtualDesktop, output.output, outputInfo.data());
qCDebug(lcQpaScreen) << "output" << screen->name() << "is connected and enabled";
screen->setPrimary(checkOutputIsPrimary(output.window, output.output));
@@ -293,14 +295,15 @@ void QXcbConnection::initializeScreens()
xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup);
int xcbScreenNumber = 0; // screen number in the xcb sense
QXcbScreen* primaryScreen = Q_NULLPTR;
- xcb_screen_t *xcbScreen = Q_NULLPTR;
bool hasOutputs = false;
while (it.rem) {
// Each "screen" in xcb terminology is a virtual desktop,
// potentially a collection of separate juxtaposed monitors.
// But we want a separate QScreen for each output (e.g. DVI-I-1, VGA-1, etc.)
// which will become virtual siblings.
- xcbScreen = it.data;
+ xcb_screen_t *xcbScreen = it.data;
+ QXcbVirtualDesktop *virtualDesktop = new QXcbVirtualDesktop(this, xcbScreen, xcbScreenNumber);
+ m_virtualDesktops.append(virtualDesktop);
QList<QPlatformScreen *> siblings;
int outputCount = 0;
int connectedOutputCount = 0;
@@ -370,7 +373,7 @@ void QXcbConnection::initializeScreens()
continue;
}
- QXcbScreen *screen = createScreen(xcbScreenNumber, xcbScreen, outputs[i], output.data());
+ QXcbScreen *screen = createScreen(virtualDesktop, outputs[i], output.data());
siblings << screen;
++connectedOutputCount;
hasOutputs = true;
@@ -405,8 +408,9 @@ void QXcbConnection::initializeScreens()
// but the dimensions are known anyway, and we don't already have any lingering
// (possibly disconnected) screens, then showing windows should be possible,
// so create one screen. (QTBUG-31389)
- if (xcbScreen && !hasOutputs && xcbScreen->width_in_pixels > 0 && xcbScreen->height_in_pixels > 0 && m_screens.isEmpty()) {
- QXcbScreen *screen = createScreen(0, xcbScreen, 0, Q_NULLPTR);
+ QXcbVirtualDesktop *virtualDesktop = m_virtualDesktops.value(0);
+ if (virtualDesktop && !hasOutputs && !virtualDesktop->size().isEmpty() && m_screens.isEmpty()) {
+ QXcbScreen *screen = createScreen(virtualDesktop, 0, Q_NULLPTR);
screen->setVirtualSiblings(QList<QPlatformScreen *>() << screen);
m_screens << screen;
primaryScreen = screen;
@@ -434,9 +438,10 @@ void QXcbConnection::initializeScreens()
qCDebug(lcQpaScreen) << "primary output is" << m_screens.first()->name();
}
-QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName)
+QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName)
: m_connection(0)
, m_canGrabServer(canGrabServer)
+ , m_defaultVisualId(defaultVisualId)
, m_primaryScreenNumber(0)
, m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY"))
, m_nativeInterface(nativeInterface)
@@ -577,6 +582,9 @@ QXcbConnection::~QXcbConnection()
while (!m_screens.isEmpty())
integration->destroyScreen(m_screens.takeLast());
+ while (!m_virtualDesktops.isEmpty())
+ delete m_virtualDesktops.takeLast();
+
delete m_glIntegration;
#ifdef XCB_USE_XLIB
@@ -666,6 +674,7 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY);
PRINT_XCB_EVENT(XCB_EXPOSE);
PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE);
+ PRINT_XCB_EVENT(XCB_NO_EXPOSURE);
PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY);
PRINT_XCB_EVENT(XCB_CREATE_NOTIFY);
PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY);
@@ -685,6 +694,8 @@ void printXcbEvent(const char *message, xcb_generic_event_t *event)
PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY);
PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY);
PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE);
+ PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY);
+ PRINT_XCB_EVENT(XCB_GE_GENERIC);
default:
qDebug("QXcbConnection: %s: unknown event - response_type: %d - sequence: %d", message, int(event->response_type & ~0x80), int(event->sequence));
}
@@ -1080,7 +1091,7 @@ void QXcbConnection::handleXcbEvent(xcb_generic_event_t *event)
HANDLE_PLATFORM_WINDOW_EVENT(xcb_property_notify_event_t, window, handlePropertyNotifyEvent);
break;
#if defined(XCB_USE_XINPUT2)
- case GenericEvent:
+ case XCB_GE_GENERIC:
if (m_xi2Enabled)
xi2HandleEvent(reinterpret_cast<xcb_ge_event_t *>(event));
break;
@@ -1342,6 +1353,21 @@ void *QXcbConnection::xlib_display() const
{
return m_xlib_display;
}
+
+void *QXcbConnection::createVisualInfoForDefaultVisualId() const
+{
+ if (m_defaultVisualId == UINT_MAX)
+ return 0;
+ XVisualInfo info;
+ memset(&info, 0, sizeof info);
+ info.visualid = m_defaultVisualId;
+
+ int count = 0;
+ XVisualInfo *retVisual = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &info, &count);
+ Q_ASSERT(count < 2);
+ return retVisual;
+}
+
#endif
void QXcbConnection::processXcbEvents()
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index 1190e7c2b0..466492ce42 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -80,6 +80,7 @@ Q_DECLARE_LOGGING_CATEGORY(lcQpaXInput)
Q_DECLARE_LOGGING_CATEGORY(lcQpaXInputDevices)
Q_DECLARE_LOGGING_CATEGORY(lcQpaScreen)
+class QXcbVirtualDesktop;
class QXcbScreen;
class QXcbWindow;
class QXcbDrag;
@@ -369,7 +370,7 @@ class Q_XCB_EXPORT QXcbConnection : public QObject
{
Q_OBJECT
public:
- QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, const char *displayName = 0);
+ QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGrabServer, xcb_visualid_t defaultVisualId, const char *displayName = 0);
~QXcbConnection();
QXcbConnection *connection() const { return const_cast<QXcbConnection *>(this); }
@@ -399,8 +400,13 @@ public:
QXcbWMSupport *wmSupport() const { return m_wmSupport.data(); }
xcb_window_t rootWindow();
+
+ bool hasDefaultVisualId() const { return m_defaultVisualId != UINT_MAX; }
+ xcb_visualid_t defaultVisualId() const { return m_defaultVisualId; }
+
#ifdef XCB_USE_XLIB
void *xlib_display() const;
+ void *createVisualInfoForDefaultVisualId() const;
#endif
#if defined(XCB_USE_XINPUT2)
@@ -497,12 +503,12 @@ private:
void initializeXShape();
void initializeXKB();
void handleClientMessageEvent(const xcb_client_message_event_t *event);
- QXcbScreen* createScreen(int screenNumber, xcb_screen_t* xcbScreen,
+ QXcbScreen* createScreen(QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId = XCB_NONE,
xcb_randr_get_output_info_reply_t *output = 0);
QXcbScreen* findScreenForCrtc(xcb_window_t rootWindow, xcb_randr_crtc_t crtc);
QXcbScreen* findScreenForOutput(xcb_window_t rootWindow, xcb_randr_output_t output);
- xcb_screen_t* xcbScreenForRootWindow(xcb_window_t rootWindow, int *xcbScreenNumber = 0);
+ QXcbVirtualDesktop* virtualDesktopForRootWindow(xcb_window_t rootWindow);
bool checkOutputIsPrimary(xcb_window_t rootWindow, xcb_randr_output_t output);
void initializeScreens();
void updateScreens(const xcb_randr_notify_event_t *event);
@@ -566,7 +572,9 @@ private:
xcb_connection_t *m_connection;
const xcb_setup_t *m_setup;
bool m_canGrabServer;
+ xcb_visualid_t m_defaultVisualId;
+ QList<QXcbVirtualDesktop *> m_virtualDesktops;
QList<QXcbScreen *> m_screens;
int m_primaryScreenNumber;
@@ -633,6 +641,7 @@ private:
};
#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display()))
+#define CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(object) ((XVisualInfo *)(object->connection()->createVisualInfoForDefaultVisualId()))
template<typename T>
xcb_generic_event_t *QXcbConnection::checkEvent(T &checker)
diff --git a/src/plugins/platforms/xcb/qxcbcursor.cpp b/src/plugins/platforms/xcb/qxcbcursor.cpp
index 8dd27ec9c5..e51ab85e30 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.cpp
+++ b/src/plugins/platforms/xcb/qxcbcursor.cpp
@@ -502,7 +502,7 @@ bool updateCursorTheme(void *dpy, const QByteArray &theme) {
return setTheme;
}
- void QXcbCursor::cursorThemePropertyChanged(QXcbScreen *screen, const QByteArray &name, const QVariant &property, void *handle)
+ void QXcbCursor::cursorThemePropertyChanged(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle)
{
Q_UNUSED(screen);
Q_UNUSED(name);
@@ -633,18 +633,17 @@ void QXcbCursor::queryPointer(QXcbConnection *c, xcb_window_t *rootWin, QPoint *
QPoint QXcbCursor::pos() const
{
- const int dpr = int(m_screen->devicePixelRatio());
QPoint p;
queryPointer(connection(), 0, &p);
- return p / dpr;
+ return m_screen->mapFromNative(p);
}
void QXcbCursor::setPos(const QPoint &pos)
{
- const int dpr = int(m_screen->devicePixelRatio());
+ const QPoint xPos = m_screen->mapToNative(pos);
xcb_window_t root = 0;
queryPointer(connection(), &root, 0);
- xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, pos.x()*dpr, pos.y()*dpr);
+ xcb_warp_pointer(xcb_connection(), XCB_NONE, root, 0, 0, 0, 0, xPos.x(), xPos.y());
xcb_flush(xcb_connection());
}
diff --git a/src/plugins/platforms/xcb/qxcbcursor.h b/src/plugins/platforms/xcb/qxcbcursor.h
index 1280c7e042..7e5cdc6870 100644
--- a/src/plugins/platforms/xcb/qxcbcursor.h
+++ b/src/plugins/platforms/xcb/qxcbcursor.h
@@ -91,7 +91,7 @@ private:
CursorHash m_cursorHash;
#endif
#ifdef XCB_USE_XLIB
- static void cursorThemePropertyChanged(QXcbScreen *screen,
+ static void cursorThemePropertyChanged(QXcbVirtualDesktop *screen,
const QByteArray &name,
const QVariant &property,
void *handle);
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index 2547e537a7..fc06f1a7b0 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -116,6 +116,7 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
: m_services(new QGenericUnixServices)
, m_instanceName(0)
, m_canGrab(true)
+ , m_defaultVisualId(UINT_MAX)
{
m_instance = this;
@@ -143,6 +144,12 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
noGrabArg = true;
else if (arg == "-dograb")
doGrabArg = true;
+ else if (arg == "-visual" && i < argc - 1) {
+ bool ok = false;
+ m_defaultVisualId = QByteArray(argv[++i]).toUInt(&ok, 0);
+ if (!ok)
+ m_defaultVisualId = UINT_MAX;
+ }
else
argv[j++] = argv[i];
}
@@ -167,12 +174,12 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
if (canNotGrabEnv)
m_canGrab = false;
- m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, displayName);
+ m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, displayName);
for (int i = 0; i < parameters.size() - 1; i += 2) {
qCDebug(lcQpaScreen) << "connecting to additional display: " << parameters.at(i) << parameters.at(i+1);
QString display = parameters.at(i) + QLatin1Char(':') + parameters.at(i+1);
- m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, display.toLatin1().constData());
+ m_connections << new QXcbConnection(m_nativeInterface.data(), m_canGrab, m_defaultVisualId, display.toLatin1().constData());
}
m_fontDatabase.reset(new QGenericUnixFontDatabase());
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 4212d53810..4e2a3c2bbd 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -39,6 +39,8 @@
#include "qxcbexport.h"
+#include <xcb/xcb.h>
+
QT_BEGIN_NAMESPACE
class QXcbConnection;
@@ -123,6 +125,7 @@ private:
mutable QByteArray m_wmClass;
const char *m_instanceName;
bool m_canGrab;
+ xcb_visualid_t m_defaultVisualId;
static QXcbIntegration *m_instance;
};
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 6c80c1b30e..5a7c2cef83 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -437,6 +437,7 @@ static const unsigned int KeyTbl[] = {
XF86XK_AudioPrev, Qt::Key_MediaPrevious,
XF86XK_AudioNext, Qt::Key_MediaNext,
XF86XK_AudioRecord, Qt::Key_MediaRecord,
+ XF86XK_AudioPause, Qt::Key_MediaPause,
XF86XK_Mail, Qt::Key_LaunchMail,
XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 6: remap properly
XF86XK_Calculator, Qt::Key_Launch1,
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 75ffaa37bb..1629f3013c 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -361,6 +361,9 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio
if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier())
return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel));
+ if (function == QXcbWindowFunctions::visualIdIdentifier()) {
+ return QFunctionPointer(QXcbWindowFunctions::VisualId(QXcbWindow::visualIdStatic));
+ }
return Q_NULLPTR;
}
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 383adf9734..a0d6d88d11 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -47,11 +47,33 @@
QT_BEGIN_NAMESPACE
-QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
+QXcbVirtualDesktop::QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t *screen, int number)
+ : QXcbObject(connection)
+ , m_screen(screen)
+ , m_number(number)
+ , m_xSettings(Q_NULLPTR)
+{
+}
+
+QXcbVirtualDesktop::~QXcbVirtualDesktop()
+{
+ delete m_xSettings;
+}
+
+QXcbXSettings *QXcbVirtualDesktop::xSettings() const
+{
+ if (!m_xSettings) {
+ QXcbVirtualDesktop *self = const_cast<QXcbVirtualDesktop *>(this);
+ self->m_xSettings = new QXcbXSettings(self);
+ }
+ return m_xSettings;
+}
+
+QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName, int number)
+ QString outputName)
: QXcbObject(connection)
- , m_screen(scr)
+ , m_virtualDesktop(virtualDesktop)
, m_output(outputId)
, m_crtc(output ? output->crtc : 0)
, m_mode(XCB_NONE)
@@ -59,10 +81,9 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
, m_rotation(XCB_RANDR_ROTATION_ROTATE_0)
, m_outputName(outputName)
, m_outputSizeMillimeters(output ? QSize(output->mm_width, output->mm_height) : QSize())
- , m_virtualSize(scr->width_in_pixels, scr->height_in_pixels)
- , m_virtualSizeMillimeters(scr->width_in_millimeters, scr->height_in_millimeters)
+ , m_virtualSize(virtualDesktop->size())
+ , m_virtualSizeMillimeters(virtualDesktop->physicalSize())
, m_orientation(Qt::PrimaryOrientation)
- , m_number(number)
, m_refreshRate(60)
, m_forcedDpi(-1)
, m_devicePixelRatio(1)
@@ -70,7 +91,6 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *scr,
, m_noFontHinting(false)
, m_subpixelType(QFontEngine::SubpixelAntialiasingType(-1))
, m_antialiasingEnabled(-1)
- , m_xSettings(0)
{
if (connection->hasXRandr()) {
xcb_randr_select_input(xcb_connection(), screen()->root, true);
@@ -215,7 +235,7 @@ QXcbScreen::~QXcbScreen()
QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
{
- xcb_window_t root = m_screen->root;
+ xcb_window_t root = screen()->root;
int dpr = int(devicePixelRatio());
int x = p.x() / dpr;
@@ -253,6 +273,31 @@ QWindow *QXcbScreen::topLevelAt(const QPoint &p) const
return 0;
}
+
+QPoint QXcbScreen::mapToNative(const QPoint &pos) const
+{
+ const int dpr = int(devicePixelRatio());
+ return (pos - m_geometry.topLeft()) * dpr + m_nativeGeometry.topLeft();
+}
+
+QPoint QXcbScreen::mapFromNative(const QPoint &pos) const
+{
+ const int dpr = int(devicePixelRatio());
+ return (pos - m_nativeGeometry.topLeft()) / dpr + m_geometry.topLeft();
+}
+
+QRect QXcbScreen::mapToNative(const QRect &rect) const
+{
+ const int dpr = int(devicePixelRatio());
+ return QRect(mapToNative(rect.topLeft()), rect.size() * dpr);
+}
+
+QRect QXcbScreen::mapFromNative(const QRect &rect) const
+{
+ const int dpr = int(devicePixelRatio());
+ return QRect(mapFromNative(rect.topLeft()), rect.size() / dpr);
+}
+
void QXcbScreen::windowShown(QXcbWindow *window)
{
// Freedesktop.org Startup Notification
@@ -310,19 +355,16 @@ QImage::Format QXcbScreen::format() const
QDpi QXcbScreen::logicalDpi() const
{
- int dpr = int(devicePixelRatio());
-
- if (m_forcedDpi > 0)
- return QDpi(m_forcedDpi/dpr, m_forcedDpi/dpr);
+ static const int overrideDpi = qEnvironmentVariableIntValue("QT_FONT_DPI");
+ if (overrideDpi)
+ return QDpi(overrideDpi, overrideDpi);
- static const bool auto_dpr = qgetenv("QT_DEVICE_PIXEL_RATIO").toLower() == "auto";
- if (auto_dpr) {
- return QDpi(Q_MM_PER_INCH * m_geometry.width() / m_sizeMillimeters.width(),
- Q_MM_PER_INCH * m_geometry.height() / m_sizeMillimeters.height());
- } else {
- return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width() / dpr,
- Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height() / dpr);
+ if (m_forcedDpi > 0) {
+ int primaryDpr = int(connection()->screens().at(0)->devicePixelRatio());
+ return QDpi(m_forcedDpi/primaryDpr, m_forcedDpi/primaryDpr);
}
+ return QDpi(Q_MM_PER_INCH * m_virtualSize.width() / m_virtualSizeMillimeters.width(),
+ Q_MM_PER_INCH * m_virtualSize.height() / m_virtualSizeMillimeters.height());
}
@@ -426,6 +468,9 @@ void QXcbScreen::handleScreenChange(xcb_randr_screen_change_notify_event_t *chan
void QXcbScreen::updateGeometry(xcb_timestamp_t timestamp)
{
+ if (!connection()->hasXRandr())
+ return;
+
xcb_randr_get_crtc_info_cookie_t crtcCookie =
xcb_randr_get_crtc_info_unchecked(xcb_connection(), m_crtc, timestamp);
xcb_randr_get_crtc_info_reply_t *crtc =
@@ -482,9 +527,9 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
m_devicePixelRatio = qRound(dpi/96);
const int dpr = int(devicePixelRatio()); // we may override m_devicePixelRatio
- m_geometry = QRect(xGeometry.topLeft()/dpr, xGeometry.size()/dpr);
+ m_geometry = QRect(xGeometry.topLeft(), xGeometry.size()/dpr);
m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
- m_availableGeometry = QRect(xAvailableGeometry.topLeft()/dpr, xAvailableGeometry.size()/dpr);
+ m_availableGeometry = QRect(mapFromNative(xAvailableGeometry.topLeft()), xAvailableGeometry.size()/dpr);
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
}
@@ -499,7 +544,7 @@ void QXcbScreen::updateRefreshRate(xcb_randr_mode_t mode)
// we can safely use get_screen_resources_current here, because in order to
// get here, we must have called get_screen_resources before
xcb_randr_get_screen_resources_current_cookie_t resourcesCookie =
- xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), m_screen->root);
+ xcb_randr_get_screen_resources_current_unchecked(xcb_connection(), screen()->root);
xcb_randr_get_screen_resources_current_reply_t *resources =
xcb_randr_get_screen_resources_current_reply(xcb_connection(), resourcesCookie, NULL);
if (resources) {
@@ -710,11 +755,7 @@ void QXcbScreen::readXResources()
QXcbXSettings *QXcbScreen::xSettings() const
{
- if (!m_xSettings) {
- QXcbScreen *self = const_cast<QXcbScreen *>(this);
- self->m_xSettings = new QXcbXSettings(self);
- }
- return m_xSettings;
+ return m_virtualDesktop->xSettings();
}
static inline void formatRect(QDebug &debug, const QRect r)
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index 3f228465f2..a29efc1e79 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -54,12 +54,32 @@ class QXcbXSettings;
class QDebug;
#endif
+class QXcbVirtualDesktop : public QXcbObject
+{
+public:
+ QXcbVirtualDesktop(QXcbConnection *connection, xcb_screen_t *screen, int number);
+ ~QXcbVirtualDesktop();
+
+ xcb_screen_t *screen() const { return m_screen; }
+ int number() const { return m_number; }
+ QSize size() const { return QSize(m_screen->width_in_pixels, m_screen->height_in_pixels); }
+ QSize physicalSize() const { return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); }
+
+ QXcbXSettings *xSettings() const;
+
+private:
+ xcb_screen_t *m_screen;
+ int m_number;
+
+ QXcbXSettings *m_xSettings;
+};
+
class Q_XCB_EXPORT QXcbScreen : public QXcbObject, public QPlatformScreen
{
public:
- QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen,
+ QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDesktop,
xcb_randr_output_t outputId, xcb_randr_get_output_info_reply_t *output,
- QString outputName, int number);
+ QString outputName);
~QXcbScreen();
QPixmap grabWindow(WId window, int x, int y, int width, int height) const Q_DECL_OVERRIDE;
@@ -69,7 +89,7 @@ public:
QRect geometry() const Q_DECL_OVERRIDE { return m_geometry; }
QRect nativeGeometry() const { return m_nativeGeometry; }
QRect availableGeometry() const Q_DECL_OVERRIDE {return m_availableGeometry;}
- int depth() const Q_DECL_OVERRIDE { return m_screen->root_depth; }
+ int depth() const Q_DECL_OVERRIDE { return screen()->root_depth; }
QImage::Format format() const Q_DECL_OVERRIDE;
QSizeF physicalSize() const Q_DECL_OVERRIDE { return m_sizeMillimeters; }
QSize virtualSize() const { return m_virtualSize; }
@@ -87,10 +107,10 @@ public:
void setPrimary(bool primary) { m_primary = primary; }
bool isPrimary() const { return m_primary; }
- int screenNumber() const { return m_number; }
+ int screenNumber() const { return m_virtualDesktop->number(); }
- xcb_screen_t *screen() const { return m_screen; }
- xcb_window_t root() const { return m_screen->root; }
+ xcb_screen_t *screen() const { return m_virtualDesktop->screen(); }
+ xcb_window_t root() const { return screen()->root; }
xcb_randr_output_t output() const { return m_output; }
xcb_randr_crtc_t crtc() const { return m_crtc; }
xcb_randr_mode_t mode() const { return m_mode; }
@@ -120,13 +140,18 @@ public:
QXcbXSettings *xSettings() const;
+ QPoint mapToNative(const QPoint &pos) const;
+ QPoint mapFromNative(const QPoint &pos) const;
+ QRect mapToNative(const QRect &rect) const;
+ QRect mapFromNative(const QRect &rect) const;
+
private:
static bool xResource(const QByteArray &identifier,
const QByteArray &expectedIdentifier,
QByteArray &stringValue);
void sendStartupMessage(const QByteArray &message) const;
- xcb_screen_t *m_screen;
+ QXcbVirtualDesktop *m_virtualDesktop;
xcb_randr_output_t m_output;
xcb_randr_crtc_t m_crtc;
xcb_randr_mode_t m_mode;
@@ -143,7 +168,6 @@ private:
QSizeF m_virtualSizeMillimeters;
QList<QPlatformScreen *> m_siblings;
Qt::ScreenOrientation m_orientation;
- int m_number;
QString m_windowManagerName;
bool m_syncRequestSupported;
xcb_window_t m_clientLeader;
@@ -157,7 +181,6 @@ private:
bool m_noFontHinting;
QFontEngine::SubpixelAntialiasingType m_subpixelType;
int m_antialiasingEnabled;
- QXcbXSettings *m_xSettings;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index ceb95a1515..076cc1aa80 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -139,7 +139,7 @@ enum QX11EmbedMessageType {
const quint32 XEMBED_VERSION = 0;
-static inline QRect mapToNative(const QRect &qtRect, int dpr)
+static inline QRect mapLocalGeometryToNative(const QRect &qtRect, int dpr)
{
return QRect(qtRect.x() * dpr, qtRect.y() * dpr, qtRect.width() * dpr, qtRect.height() * dpr);
}
@@ -167,11 +167,45 @@ static inline QRect mapExposeFromNative(const QRect &xRect, int dpr)
return QRect(dpr_floor(xRect.topLeft(), dpr), dpr_ceil(xRect.bottomRight(), dpr));
}
-static inline QRect mapGeometryFromNative(const QRect &xRect, int dpr)
+static inline QRect mapLocalGeometryFromNative(const QRect &xRect, int dpr)
{
return QRect(xRect.topLeft() / dpr, dpr_ceil(xRect.size(), dpr));
}
+QXcbScreen *QXcbWindow::parentScreen()
+{
+ return parent() ? static_cast<QXcbWindow*>(parent())->parentScreen() : m_xcbScreen;
+}
+
+QPoint QXcbWindow::mapToNative(const QPoint &pos, const QXcbScreen *screen) const
+{
+ if (parent())
+ return pos * int(screen->devicePixelRatio());
+ else
+ return screen->mapToNative(pos);
+}
+QPoint QXcbWindow::mapFromNative(const QPoint &pos, const QXcbScreen *screen) const
+{
+ if (parent())
+ return pos / int(screen->devicePixelRatio());
+ else
+ return screen->mapFromNative(pos);
+}
+QRect QXcbWindow::mapToNative(const QRect &rect, const QXcbScreen *screen) const
+{
+ if (parent())
+ return mapLocalGeometryToNative(rect, int(screen->devicePixelRatio()));
+ else
+ return screen->mapToNative(rect);
+}
+QRect QXcbWindow::mapFromNative(const QRect &rect, const QXcbScreen *screen) const
+{
+ if (parent())
+ return mapLocalGeometryFromNative(rect, int(screen->devicePixelRatio()));
+ else
+ return screen->mapFromNative(rect);
+}
+
// Returns \c true if we should set WM_TRANSIENT_FOR on \a w
static inline bool isTransient(const QWindow *w)
{
@@ -292,6 +326,7 @@ static const char *wm_window_type_property_id = "_q_xcb_wm_window_type";
QXcbWindow::QXcbWindow(QWindow *window)
: QPlatformWindow(window)
, m_window(0)
+ , m_xcbScreen(0)
, m_syncCounter(0)
, m_gravity(XCB_GRAVITY_STATIC)
, m_mapped(false)
@@ -345,13 +380,25 @@ void QXcbWindow::create()
Qt::WindowType type = window()->type();
- QXcbScreen *platformScreen = xcbScreen();
+ QXcbScreen *currentScreen = xcbScreen();
+ QRect rect = window()->geometry();
+ QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
+ m_xcbScreen = platformScreen;
if (type == Qt::Desktop) {
m_window = platformScreen->root();
m_depth = platformScreen->screen()->root_depth;
m_visualId = platformScreen->screen()->root_visual;
- const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId);
+ const xcb_visualtype_t *visual = 0;
+ if (connection()->hasDefaultVisualId()) {
+ visual = platformScreen->visualForId(connection()->defaultVisualId());
+ if (visual)
+ m_visualId = connection()->defaultVisualId();
+ if (!visual)
+ qWarning() << "Could not use default visual id. Falling back to root_visual for screen.";
+ }
+ if (!visual)
+ visual = platformScreen->visualForId(m_visualId);
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
connection()->addWindowEventListener(m_window, this);
return;
@@ -372,13 +419,10 @@ void QXcbWindow::create()
// Parameters to XCreateWindow() are frame corner + inner size.
// This fits in case position policy is frame inclusive. There is
// currently no way to implement it for frame-exclusive geometries.
- QRect rect = window()->geometry();
QPlatformWindow::setGeometry(rect);
- QXcbScreen *currentScreen = xcbScreen();
- QPlatformScreen *newScreen = screenForGeometry(rect);
- if (newScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ if (platformScreen != currentScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
const int dpr = int(devicePixelRatio());
@@ -408,7 +452,12 @@ void QXcbWindow::create()
#ifdef XCB_USE_XLIB
if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL)) {
- XVisualInfo *visualInfo = static_cast<XVisualInfo *>(createVisual());
+ XVisualInfo *visualInfo = Q_NULLPTR;
+ if (connection()->hasDefaultVisualId())
+ visualInfo = CREATE_VISUALINFO_FROM_DEFAULT_VISUALID(this);
+ if (!visualInfo)
+ visualInfo = static_cast<XVisualInfo *>(createVisual());
+
if (!visualInfo && window()->surfaceType() == QSurface::OpenGLSurface)
qFatal("Could not initialize OpenGL");
@@ -429,7 +478,7 @@ void QXcbWindow::create()
m_visualId = visualInfo->visualid;
- const QRect xRect = mapToNative(rect, dpr);
+ const QRect xRect = mapToNative(rect, platformScreen);
m_window = XCreateWindow(DISPLAY_FROM_XCB(this), xcb_parent_id, xRect.x(), xRect.y(), xRect.width(), xRect.height(),
0, visualInfo->depth, InputOutput, visualInfo->visual,
@@ -443,45 +492,60 @@ void QXcbWindow::create()
if (!m_window)
{
m_window = xcb_generate_id(xcb_connection());
- m_visualId = platformScreen->screen()->root_visual;
+ m_visualId = UINT_MAX;
+ const xcb_visualtype_t *visual = Q_NULLPTR;
m_depth = platformScreen->screen()->root_depth;
uint32_t mask = 0;
uint32_t values[3];
- if (m_format.alphaBufferSize() == 8) {
- xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen());
- while (depthIter.rem) {
- if (depthIter.data->depth == 32) {
- xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data);
- if (visualIter.rem) {
- m_visualId = visualIter.data->visual_id;
- m_depth = 32;
- uint32_t colormap = xcb_generate_id(xcb_connection());
- xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap,
- xcb_parent_id, m_visualId);
- mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
- values[0] = platformScreen->screen()->white_pixel;
- values[1] = platformScreen->screen()->black_pixel;
- values[2] = colormap;
- break;
+ if (connection()->hasDefaultVisualId()) {
+ m_visualId = connection()->defaultVisualId();
+ visual = platformScreen->visualForId(m_visualId);
+ }
+
+ if (!visual) {
+ if (connection()->hasDefaultVisualId())
+ qWarning("Failed to use default visual id. Falling back to using screens root_visual");
+
+ m_visualId = platformScreen->screen()->root_visual;
+
+ if (m_format.alphaBufferSize() == 8) {
+ xcb_depth_iterator_t depthIter = xcb_screen_allowed_depths_iterator(platformScreen->screen());
+ while (depthIter.rem) {
+ if (depthIter.data->depth == 32) {
+ xcb_visualtype_iterator_t visualIter = xcb_depth_visuals_iterator(depthIter.data);
+ if (visualIter.rem) {
+ m_visualId = visualIter.data->visual_id;
+ m_depth = 32;
+ uint32_t colormap = xcb_generate_id(xcb_connection());
+ xcb_create_colormap(xcb_connection(), XCB_COLORMAP_ALLOC_NONE, colormap,
+ xcb_parent_id, m_visualId);
+ mask |= XCB_CW_BACK_PIXEL | XCB_CW_BORDER_PIXEL | XCB_CW_COLORMAP;
+ values[0] = platformScreen->screen()->white_pixel;
+ values[1] = platformScreen->screen()->black_pixel;
+ values[2] = colormap;
+ break;
+ }
}
+ xcb_depth_next(&depthIter);
}
- xcb_depth_next(&depthIter);
}
+
+ visual = platformScreen->visualForId(m_visualId);
}
- const xcb_visualtype_t *visual = platformScreen->visualForId(m_visualId);
m_imageFormat = imageFormatForVisual(m_depth, visual->red_mask, visual->blue_mask, &m_imageRgbSwap);
+ const QRect xRect = mapToNative(rect, platformScreen);
Q_XCB_CALL(xcb_create_window(xcb_connection(),
m_depth,
m_window, // window id
xcb_parent_id, // parent window id
- rect.x(),
- rect.y(),
- rect.width(),
- rect.height(),
+ xRect.x(),
+ xRect.y(),
+ xRect.width(),
+ xRect.height(),
0, // border width
XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class
m_visualId, // visual
@@ -632,7 +696,7 @@ void QXcbWindow::destroy()
void QXcbWindow::maybeSetScreen(QXcbScreen *screen)
{
- if (!window()->screen() && screen->geometry().contains(geometry().topLeft() * int(devicePixelRatio()))) {
+ if (!window()->screen() && screen->geometry().contains(geometry().topLeft())) {
QWindowSystemInterface::handleWindowScreenChanged(window(), static_cast<QPlatformScreen *>(screen)->screen());
QWindowSystemInterface::handleExposeEvent(window(), QRegion(QRect(QPoint(0, 0), window()->size())));
}
@@ -645,16 +709,17 @@ void QXcbWindow::setGeometry(const QRect &rect)
propagateSizeHints();
QXcbScreen *currentScreen = xcbScreen();
- QPlatformScreen *newScreen = screenForGeometry(rect);
+ QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
+
if (!newScreen)
newScreen = currentScreen;
- const QRect xRect = mapToNative(rect, int(newScreen->devicePixelRatio()));
+ m_xcbScreen = newScreen;
+ const QRect xRect = mapToNative(rect, newScreen);
const QRect wmGeometry = windowToWmGeometry(xRect);
-
if (newScreen != currentScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
if (qt_window_private(window())->positionAutomatic) {
const quint32 mask = XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT;
@@ -1161,6 +1226,8 @@ void QXcbWindow::changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two)
event.data.data32[3] = 0;
event.data.data32[4] = 0;
+ if (!xcbScreen())
+ return;
Q_XCB_CALL(xcb_send_event(xcb_connection(), 0, xcbScreen()->root(), XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event));
}
@@ -1567,7 +1634,7 @@ void QXcbWindow::propagateSizeHints()
memset(&hints, 0, sizeof(hints));
const int dpr = int(devicePixelRatio());
- const QRect xRect = mapToNative(windowToWmGeometry(geometry()), dpr);
+ const QRect xRect = windowToWmGeometry(mapToNative(geometry(), xcbScreen()));
QWindow *win = window();
@@ -1660,6 +1727,13 @@ void QXcbWindow::setWindowIconTextStatic(QWindow *window, const QString &text)
static_cast<QXcbWindow *>(window->handle())->setWindowIconText(text);
}
+uint QXcbWindow::visualIdStatic(QWindow *window)
+{
+ if (window && window->handle())
+ return static_cast<QXcbWindow *>(window->handle())->visualId();
+ return UINT_MAX;
+}
+
QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const
{
QXcbWindowFunctions::WmWindowTypes result(0);
@@ -1953,20 +2027,21 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
}
}
-// Temporary workaround for bug in QPlatformScreen::screenForNativeGeometry
+// Temporary workaround for bug in QPlatformScreen::screenForGeometry
// we need the native geometries to detect our screen, but that's not
// available in cross-platform code. Will be fixed properly when highDPI
// support is refactored to expose the native coordinate system.
-QPlatformScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const
+QXcbScreen *QXcbWindow::screenForNativeGeometry(const QRect &newGeometry) const
{
- QXcbScreen *currentScreen = static_cast<QXcbScreen*>(screen());
+ QXcbScreen *currentScreen = xcbScreen();
if (!currentScreen && QGuiApplication::primaryScreen())
currentScreen = static_cast<QXcbScreen*>(QGuiApplication::primaryScreen()->handle());
if (currentScreen && !parent() && !currentScreen->nativeGeometry().intersects(newGeometry)) {
Q_FOREACH (QPlatformScreen* screen, currentScreen->virtualSiblings()) {
- if (static_cast<QXcbScreen*>(screen)->nativeGeometry().intersects(newGeometry))
- return screen;
+ QXcbScreen *xcbScreen = static_cast<QXcbScreen*>(screen);
+ if (xcbScreen->nativeGeometry().intersects(newGeometry))
+ return xcbScreen;
}
}
return currentScreen;
@@ -1988,23 +2063,19 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *
}
}
- const int dpr = devicePixelRatio();
const QRect nativeRect = QRect(pos, QSize(event->width, event->height));
- const QRect rect = mapGeometryFromNative(nativeRect, dpr);
+ QXcbScreen *newScreen = parent() ? parentScreen() : screenForNativeGeometry(nativeRect);
+
+ QXcbScreen *currentScreen = m_xcbScreen;
+ m_xcbScreen = newScreen;
+ if (!newScreen)
+ return;
+ const QRect rect = mapFromNative(nativeRect, newScreen);
QPlatformWindow::setGeometry(rect);
QWindowSystemInterface::handleGeometryChange(window(), rect);
- QPlatformScreen *newScreen = screenForNativeGeometry(nativeRect);
- if (newScreen != screen()) {
- if (newScreen)
- QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
- int newDpr = newScreen->devicePixelRatio();
- if (newDpr != dpr) {
- QRect newRect = mapGeometryFromNative(nativeRect, newDpr);
- QPlatformWindow::setGeometry(newRect);
- QWindowSystemInterface::handleGeometryChange(window(), newRect);
- }
- }
+ if (newScreen != currentScreen)
+ QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->QPlatformScreen::screen());
m_configureNotifyPending = false;
@@ -2045,12 +2116,12 @@ QPoint QXcbWindow::mapToGlobal(const QPoint &pos) const
xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) {
- ret.setX(reply->dst_x / dpr);
- ret.setY(reply->dst_y / dpr);
+ ret.setX(reply->dst_x);
+ ret.setY(reply->dst_y);
free(reply);
}
- return ret;
+ return mapFromNative(ret, xcbScreen());
}
QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
@@ -2060,9 +2131,10 @@ QPoint QXcbWindow::mapFromGlobal(const QPoint &pos) const
const int dpr = int(devicePixelRatio());
QPoint ret;
+ QPoint xPos = mapToNative(pos, xcbScreen());
xcb_translate_coordinates_cookie_t cookie =
xcb_translate_coordinates(xcb_connection(), xcbScreen()->root(), xcb_window(),
- pos.x() *dpr, pos.y() * dpr);
+ xPos.x(), xPos.y());
xcb_translate_coordinates_reply_t *reply =
xcb_translate_coordinates_reply(xcb_connection(), cookie, NULL);
if (reply) {
@@ -2116,7 +2188,7 @@ void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event)
}
const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr);
- QPoint global(event->root_x/dpr, event->root_y/dpr);
+ QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
@@ -2141,7 +2213,7 @@ void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *even
{
const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr);
- QPoint global(event->root_x/dpr, event->root_y/dpr);
+ QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
if (event->detail >= 4 && event->detail <= 7) {
@@ -2156,7 +2228,9 @@ void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event)
{
const int dpr = int(devicePixelRatio());
QPoint local(event->event_x/dpr, event->event_y/dpr);
- QPoint global(event->root_x/dpr, event->root_y/dpr);
+ if (!xcbScreen())
+ return;
+ QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
Qt::KeyboardModifiers modifiers = connection()->keyboard()->translateModifiers(event->state);
handleMouseEvent(event->time, local, global, modifiers);
@@ -2213,7 +2287,9 @@ void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
const int dpr = int(devicePixelRatio());
const QPoint local(event->event_x/dpr, event->event_y/dpr);
- const QPoint global(event->root_x/dpr, event->root_y/dpr);
+ if (!xcbScreen())
+ return;
+ QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
QWindowSystemInterface::handleEnterEvent(window(), local, global);
}
@@ -2231,7 +2307,9 @@ void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event)
if (enterWindow) {
const int dpr = int(devicePixelRatio());
QPoint local(enter->event_x/dpr, enter->event_y/dpr);
- QPoint global(enter->root_x/dpr, enter->root_y/dpr);
+ if (!xcbScreen())
+ return;
+ QPoint global = xcbScreen()->mapFromNative(QPoint(event->root_x, event->root_y));
QWindowSystemInterface::handleEnterLeaveEvent(enterWindow->window(), window(), local, global);
} else {
@@ -2246,6 +2324,8 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
connection()->setTime(event->time);
const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE;
+ if (!xcbScreen())
+ return;
if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) {
if (propertyDeleted)
@@ -2394,7 +2474,6 @@ void QXcbWindow::windowEvent(QEvent *event)
bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
{
- const int dpr = int(devicePixelRatio());
const xcb_atom_t moveResize = connection()->atom(QXcbAtom::_NET_WM_MOVERESIZE);
if (!connection()->wmSupport()->isSupportedByWM(moveResize))
return false;
@@ -2403,7 +2482,7 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner)
xev.type = moveResize;
xev.window = xcb_window();
xev.format = 32;
- const QPoint globalPos = window()->mapToGlobal(pos) * dpr;
+ const QPoint globalPos = mapToNative(window()->mapToGlobal(pos), xcbScreen());
xev.data.data32[0] = globalPos.x();
xev.data.data32[1] = globalPos.y();
const bool bottom = corner == Qt::BottomRightCorner || corner == Qt::BottomLeftCorner;
@@ -2532,7 +2611,7 @@ void QXcbWindow::setMask(const QRegion &region)
const int dpr = devicePixelRatio();
QVector<xcb_rectangle_t> rects;
foreach (const QRect &r, region.rects())
- rects.push_back(qRectToXCBRectangle(mapToNative(r, dpr)));
+ rects.push_back(qRectToXCBRectangle(mapLocalGeometryToNative(r, dpr)));
xcb_shape_rectangles(connection()->xcb_connection(), XCB_SHAPE_SO_SET,
XCB_SHAPE_SK_BOUNDING, XCB_CLIP_ORDERING_UNSORTED,
xcb_window(), 0, 0, rects.size(), &rects[0]);
@@ -2549,6 +2628,11 @@ void QXcbWindow::setAlertState(bool enabled)
changeNetWmState(enabled, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION));
}
+uint QXcbWindow::visualId() const
+{
+ return m_visualId;
+}
+
bool QXcbWindow::needsSync() const
{
return m_syncState == SyncAndConfigureReceived;
@@ -2556,6 +2640,8 @@ bool QXcbWindow::needsSync() const
void QXcbWindow::postSyncWindowRequest()
{
+ if (!xcbScreen())
+ return;
if (!m_pendingSyncRequest) {
QXcbSyncWindowRequest *e = new QXcbSyncWindowRequest(this);
m_pendingSyncRequest = e;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h
index 2442e6c4e3..52e8ac1459 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.h
+++ b/src/plugins/platforms/xcb/qxcbwindow.h
@@ -140,6 +140,7 @@ public:
void updateNetWmUserTime(xcb_timestamp_t timestamp);
static void setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowTypes);
+ static uint visualIdStatic(QWindow *window);
QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const;
void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types);
@@ -154,6 +155,7 @@ public:
static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window);
QRect systemTrayWindowGlobalGeometry() const;
+ uint visualId() const;
bool needsSync() const;
@@ -167,7 +169,7 @@ public:
virtual void create();
virtual void destroy();
void maybeSetScreen(QXcbScreen *screen);
- QPlatformScreen *screenForNativeGeometry(const QRect &newGeometry) const;
+ QXcbScreen *screenForNativeGeometry(const QRect &newGeometry) const;
public Q_SLOTS:
void updateSyncRequestCounter();
@@ -177,6 +179,12 @@ protected:
virtual void *createVisual() { return Q_NULLPTR; }
virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); }
+ QPoint mapToNative(const QPoint &pos, const QXcbScreen *screen) const;
+ QPoint mapFromNative(const QPoint &pos, const QXcbScreen *screen) const;
+ QRect mapToNative(const QRect &rect, const QXcbScreen *screen) const;
+ QRect mapFromNative(const QRect &rect, const QXcbScreen *screen) const;
+ QXcbScreen *parentScreen();
+
void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0);
NetWmStates netWmStates();
void setNetWmStates(NetWmStates);
@@ -204,6 +212,8 @@ protected:
xcb_window_t m_window;
+ QXcbScreen *m_xcbScreen;
+
uint m_depth;
QImage::Format m_imageFormat;
bool m_imageRgbSwap;
diff --git a/src/plugins/platforms/xcb/qxcbwmsupport.cpp b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
index bcdfde2ef9..7d31ac7118 100644
--- a/src/plugins/platforms/xcb/qxcbwmsupport.cpp
+++ b/src/plugins/platforms/xcb/qxcbwmsupport.cpp
@@ -68,7 +68,7 @@ void QXcbWMSupport::updateNetWMAtoms()
remaining = 0;
if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
- int len = xcb_get_property_value_length(reply)/4;
+ int len = xcb_get_property_value_length(reply)/sizeof(xcb_atom_t);
xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);
int s = net_wm_atoms.size();
net_wm_atoms.resize(s + len);
@@ -102,11 +102,11 @@ void QXcbWMSupport::updateVirtualRoots()
remaining = 0;
if (reply->type == XCB_ATOM_ATOM && reply->format == 32) {
- int len = xcb_get_property_value_length(reply)/4;
- xcb_atom_t *atoms = (xcb_atom_t *)xcb_get_property_value(reply);
- int s = net_wm_atoms.size();
- net_wm_atoms.resize(s + len);
- memcpy(net_wm_atoms.data() + s, atoms, len*sizeof(xcb_atom_t));
+ int len = xcb_get_property_value_length(reply)/sizeof(xcb_window_t);
+ xcb_window_t *roots = (xcb_window_t *)xcb_get_property_value(reply);
+ int s = net_virtual_roots.size();
+ net_virtual_roots.resize(s + len);
+ memcpy(net_virtual_roots.data() + s, roots, len*sizeof(xcb_window_t));
remaining = reply->bytes_after;
offset += len;
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.cpp b/src/plugins/platforms/xcb/qxcbxsettings.cpp
index c83edd506d..46cee5d6d0 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.cpp
+++ b/src/plugins/platforms/xcb/qxcbxsettings.cpp
@@ -63,7 +63,7 @@ public:
: last_change_serial(-1)
{}
- void updateValue(QXcbScreen *screen, const QByteArray &name, const QVariant &value, int last_change_serial)
+ void updateValue(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &value, int last_change_serial)
{
if (last_change_serial <= this->last_change_serial)
return;
@@ -92,7 +92,7 @@ public:
class QXcbXSettingsPrivate
{
public:
- QXcbXSettingsPrivate(QXcbScreen *screen)
+ QXcbXSettingsPrivate(QXcbVirtualDesktop *screen)
: screen(screen)
, initialized(false)
{
@@ -217,18 +217,18 @@ public:
}
#endif //XCB_USE_XLIB
- QXcbScreen *screen;
+ QXcbVirtualDesktop *screen;
xcb_window_t x_settings_window;
QMap<QByteArray, QXcbXSettingsPropertyValue> settings;
bool initialized;
};
-QXcbXSettings::QXcbXSettings(QXcbScreen *screen)
+QXcbXSettings::QXcbXSettings(QXcbVirtualDesktop *screen)
: d_ptr(new QXcbXSettingsPrivate(screen))
{
QByteArray settings_atom_for_screen("_XSETTINGS_S");
- settings_atom_for_screen.append(QByteArray::number(screen->screenNumber()));
+ settings_atom_for_screen.append(QByteArray::number(screen->number()));
xcb_intern_atom_cookie_t atom_cookie = xcb_intern_atom(screen->xcb_connection(),
true,
settings_atom_for_screen.length(),
diff --git a/src/plugins/platforms/xcb/qxcbxsettings.h b/src/plugins/platforms/xcb/qxcbxsettings.h
index 4022f0a2c4..3f1d175336 100644
--- a/src/plugins/platforms/xcb/qxcbxsettings.h
+++ b/src/plugins/platforms/xcb/qxcbxsettings.h
@@ -44,13 +44,13 @@ class QXcbXSettings : public QXcbWindowEventListener
{
Q_DECLARE_PRIVATE(QXcbXSettings)
public:
- QXcbXSettings(QXcbScreen *screen);
+ QXcbXSettings(QXcbVirtualDesktop *screen);
~QXcbXSettings();
bool initialized() const;
QVariant setting(const QByteArray &property) const;
- typedef void (*PropertyChangeFunc)(QXcbScreen *screen, const QByteArray &name, const QVariant &property, void *handle);
+ typedef void (*PropertyChangeFunc)(QXcbVirtualDesktop *screen, const QByteArray &name, const QVariant &property, void *handle);
void registerCallbackForProperty(const QByteArray &property, PropertyChangeFunc func, void *handle);
void removeCallbackForHandle(const QByteArray &property, void *handle);
void removeCallbackForHandle(void *handle);
diff --git a/src/printsupport/dialogs/qpagesetupdialog_win.cpp b/src/printsupport/dialogs/qpagesetupdialog_win.cpp
index afe0268e55..8d6fdbd6de 100644
--- a/src/printsupport/dialogs/qpagesetupdialog_win.cpp
+++ b/src/printsupport/dialogs/qpagesetupdialog_win.cpp
@@ -94,7 +94,7 @@ int QPageSetupDialog::exec()
parent = parent ? parent->window() : QApplication::activeWindow();
Q_ASSERT(!parent ||parent->testAttribute(Qt::WA_WState_Created));
- QWindow *parentWindow = parent->windowHandle();
+ QWindow *parentWindow = parent ? parent->windowHandle() : 0;
psd.hwndOwner = parentWindow ? (HWND)QGuiApplication::platformNativeInterface()->nativeResourceForWindow("handle", parentWindow) : 0;
psd.Flags = PSD_MARGINS;
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index f9644dfd8b..1655131de4 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -120,19 +120,22 @@ QT_USE_NAMESPACE
if (dialog->maxPage() < dialog->toPage())
dialog->setFromTo(dialog->fromPage(), dialog->maxPage());
}
- // Keep us in sync with file output
- PMDestinationType dest;
- // If the user selected print to file, the session has been
- // changed behind our back and our d->ep->session object is a
- // dangling pointer. Update it based on the "current" session
+ // Keep us in sync with chosen destination
+ PMDestinationType dest;
PMSessionGetDestinationType(session, settings, &dest);
if (dest == kPMDestinationFile) {
+ // QTBUG-38820
+ // If user selected Print to File, leave OSX to generate the PDF,
+ // otherwise setting PdfFormat would prevent us showing dialog again.
+ // TODO Restore this when QTBUG-36112 is fixed.
+ /*
QCFType<CFURLRef> file;
PMSessionCopyDestinationLocation(session, settings, &file);
UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
+ */
} else {
PMPrinter macPrinter;
PMSessionGetCurrentPrinter(session, &macPrinter);
diff --git a/src/printsupport/kernel/qprintengine_win.cpp b/src/printsupport/kernel/qprintengine_win.cpp
index 910c6c1514..b377401ed9 100644
--- a/src/printsupport/kernel/qprintengine_win.cpp
+++ b/src/printsupport/kernel/qprintengine_win.cpp
@@ -69,7 +69,7 @@ extern QMarginsF qt_convertMargins(const QMarginsF &margins, QPageLayout::Unit f
// #define QT_DEBUG_METRICS
static void draw_text_item_win(const QPointF &_pos, const QTextItemInt &ti, HDC hdc,
- bool convertToText, const QTransform &xform, const QPointF &topLeft);
+ const QTransform &xform, const QPointF &topLeft);
QWin32PrintEngine::QWin32PrintEngine(QPrinter::PrinterMode mode)
: QAlphaPaintEngine(*(new QWin32PrintEnginePrivate),
@@ -309,27 +309,12 @@ void QWin32PrintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem
return ;
}
- // We only want to convert the glyphs to text if the entire string is compatible with ASCII
- // and if we actually have access to the chars.
- bool convertToText = ti.chars != 0;
- for (int i=0; i < ti.num_chars; ++i) {
- if (ti.chars[i].unicode() >= 0x80) {
- convertToText = false;
- break;
- }
-
- if (ti.logClusters[i] != i) {
- convertToText = false;
- break;
- }
- }
-
COLORREF cf = RGB(qRed(brushColor), qGreen(brushColor), qBlue(brushColor));
SelectObject(d->hdc, CreateSolidBrush(cf));
SelectObject(d->hdc, CreatePen(PS_SOLID, 1, cf));
SetTextColor(d->hdc, cf);
- draw_text_item_win(p, ti, d->hdc, convertToText, d->matrix, QPointF(0.0, 0.0));
+ draw_text_item_win(p, ti, d->hdc, d->matrix, QPointF(0.0, 0.0));
DeleteObject(SelectObject(d->hdc,GetStockObject(HOLLOW_BRUSH)));
DeleteObject(SelectObject(d->hdc,GetStockObject(BLACK_PEN)));
}
@@ -399,6 +384,9 @@ int QWin32PrintEngine::metric(QPaintDevice::PaintDeviceMetric m) const
case QPaintDevice::PdmDepth:
val = GetDeviceCaps(d->hdc, PLANES);
break;
+ case QPaintDevice::PdmDevicePixelRatio:
+ val = 1;
+ break;
default:
qWarning("QPrinter::metric: Invalid metric command");
return 0;
@@ -1682,7 +1670,7 @@ void QWin32PrintEnginePrivate::debugMetrics() const
}
static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC hdc,
- bool convertToText, const QTransform &xform, const QPointF &topLeft)
+ const QTransform &xform, const QPointF &topLeft)
{
QPointF baseline_pos = xform.inverted().map(xform.map(pos) - topLeft);
@@ -1692,24 +1680,20 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
const bool has_kerning = ti.f && ti.f->kerning();
HFONT hfont = 0;
- bool ttf = false;
if (ti.fontEngine->type() == QFontEngine::Win) {
const QVariantMap userData = ti.fontEngine->userData().toMap();
const QVariant hfontV = userData.value(QStringLiteral("hFont"));
const QVariant ttfV = userData.value(QStringLiteral("trueType"));
- if (ttfV.type() == QVariant::Bool && hfontV.canConvert<HFONT>()) {
+ if (ttfV.toBool() && hfontV.canConvert<HFONT>())
hfont = hfontV.value<HFONT>();
- ttf = ttfV.toBool();
- }
}
if (!hfont)
hfont = (HFONT)GetStockObject(ANSI_VAR_FONT);
HGDIOBJ old_font = SelectObject(hdc, hfont);
- unsigned int options = (ttf && !convertToText) ? ETO_GLYPH_INDEX : 0;
- wchar_t *convertedGlyphs = (wchar_t *)ti.chars;
+ unsigned int options = ETO_GLYPH_INDEX;
QGlyphLayout glyphs = ti.glyphs;
bool fast = !has_kerning && !(ti.flags & QTextItem::RightToLeft);
@@ -1743,7 +1727,7 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
ExtTextOut(hdc,
qRound(baseline_pos.x() + glyphs.offsets[0].x.toReal()),
qRound(baseline_pos.y() + glyphs.offsets[0].y.toReal()),
- options, 0, convertToText ? convertedGlyphs : g.data(), glyphs.numGlyphs, 0);
+ options, 0, g.constData(), glyphs.numGlyphs, 0);
} else {
QVarLengthArray<QFixedPoint> positions;
QVarLengthArray<glyph_t> _glyphs;
@@ -1756,7 +1740,6 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
return;
}
- convertToText = convertToText && glyphs.numGlyphs == _glyphs.size();
bool outputEntireItem = _glyphs.size() > 0;
if (outputEntireItem) {
@@ -1772,7 +1755,7 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
glyphDistances[(_glyphs.size() - 1) * 2 + 1] = 0;
g[_glyphs.size() - 1] = _glyphs[_glyphs.size() - 1];
ExtTextOut(hdc, qRound(positions[0].x), qRound(positions[0].y), options, 0,
- convertToText ? convertedGlyphs : g.data(), _glyphs.size(),
+ g.constData(), _glyphs.size(),
glyphDistances.data());
} else {
int i = 0;
@@ -1781,7 +1764,7 @@ static void draw_text_item_win(const QPointF &pos, const QTextItemInt &ti, HDC h
ExtTextOut(hdc, qRound(positions[i].x),
qRound(positions[i].y), options, 0,
- convertToText ? convertedGlyphs + i : &g, 1, 0);
+ &g, 1, 0);
++i;
}
}
diff --git a/src/src.pro b/src/src.pro
index 9dad394a06..090ae6872c 100644
--- a/src/src.pro
+++ b/src/src.pro
@@ -81,7 +81,7 @@ src_network.depends = src_corelib
src_testlib.subdir = $$PWD/testlib
src_testlib.target = sub-testlib
-src_testlib.depends = src_corelib # src_gui & src_widgets are not build-depends
+src_testlib.depends = src_corelib # testlib links only to corelib, but see below for the headers
src_3rdparty_pcre.subdir = $$PWD/3rdparty/pcre
src_3rdparty_pcre.target = sub-3rdparty-pcre
@@ -166,10 +166,12 @@ contains(QT_CONFIG, concurrent):SUBDIRS += src_concurrent
SUBDIRS += src_gui src_platformsupport src_platformheaders
contains(QT_CONFIG, opengl(es2)?):SUBDIRS += src_openglextensions
src_plugins.depends += src_gui src_platformsupport src_platformheaders
+ src_testlib.depends += src_gui # if QtGui is enabled, QtTest requires QtGui's headers
!contains(QT_CONFIG, no-widgets) {
SUBDIRS += src_tools_uic src_widgets
TOOLS += src_tools_uic
src_plugins.depends += src_widgets
+ src_testlib.depends += src_widgets # if QtWidgets is enabled, QtTest requires QtWidgets's headers
contains(QT_CONFIG, opengl(es2)?) {
SUBDIRS += src_opengl
src_plugins.depends += src_opengl
diff --git a/src/testlib/qtestblacklist.cpp b/src/testlib/qtestblacklist.cpp
index 52a9977bbf..bfeca08617 100644
--- a/src/testlib/qtestblacklist.cpp
+++ b/src/testlib/qtestblacklist.cpp
@@ -107,6 +107,15 @@ static QSet<QByteArray> keywords()
#endif
#ifdef Q_CC_MSVC
<< "msvc"
+ #ifdef _MSC_VER
+ #if _MSC_VER == 1800
+ << "msvc-2013"
+ #elif _MSC_VER == 1700
+ << "msvc-2012"
+ #elif _MSC_VER == 1600
+ << "msvc-2010"
+ #endif
+ #endif
#endif
#ifdef Q_AUTOTEST_EXPORT
diff --git a/src/testlib/qtestmouse.h b/src/testlib/qtestmouse.h
index 8e1b04e0a0..2cf84a7ea0 100644
--- a/src/testlib/qtestmouse.h
+++ b/src/testlib/qtestmouse.h
@@ -98,7 +98,7 @@ namespace QTest
mouseEvent(MouseRelease, window, button, stateKey, pos);
return;
}
- QTEST_ASSERT(stateKey == 0 || stateKey & Qt::KeyboardModifierMask);
+ QTEST_ASSERT(uint(stateKey) == 0 || stateKey & Qt::KeyboardModifierMask);
stateKey &= static_cast<unsigned int>(Qt::KeyboardModifierMask);
diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro
index 841d913105..52bcdd097b 100644
--- a/src/testlib/testlib.pro
+++ b/src/testlib/testlib.pro
@@ -64,8 +64,7 @@ DEFINES *= QT_NO_CAST_TO_ASCII \
QT_NO_CAST_FROM_ASCII \
QT_NO_DATASTREAM
embedded:QMAKE_CXXFLAGS += -fno-rtti
-wince*::LIBS += libcmt.lib \
- corelibc.lib \
+wince: LIBS += \
ole32.lib \
oleaut32.lib \
uuid.lib \
@@ -97,4 +96,9 @@ mac {
}
}
+# Exclude these headers from the clean check if their dependencies aren't
+# being built
+contains(QT_CONFIG, no-widgets): HEADERSCLEAN_EXCLUDE += qtest_widgets.h
+contains(QT_CONFIG, no-gui): HEADERSCLEAN_EXCLUDE += qtest_gui.h
+
load(qt_module)
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 46acbc608b..8b6a0519c5 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1310,6 +1310,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
}
+ fprintf(out, " Q_UNUSED(_t)\n");
if (needTempVarForGet)
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
@@ -1355,6 +1356,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
}
+ fprintf(out, " Q_UNUSED(_t)\n");
fprintf(out, " void *_v = _a[0];\n");
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
@@ -1408,6 +1410,7 @@ void Generator::generateStaticMetacall()
} else {
fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
}
+ fprintf(out, " Q_UNUSED(_t)\n");
fprintf(out, " switch (_id) {\n");
for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
const PropertyDef &p = cdef->propertyList.at(propindex);
diff --git a/src/tools/qdoc/cppcodeparser.cpp b/src/tools/qdoc/cppcodeparser.cpp
index a2c7a91827..b088031d9d 100644
--- a/src/tools/qdoc/cppcodeparser.cpp
+++ b/src/tools/qdoc/cppcodeparser.cpp
@@ -1329,6 +1329,11 @@ bool CppCodeParser::matchParameter(FunctionNode *func)
QString name;
CodeChunk defaultValue;
+ if (match(Tok_QPrivateSignal)) {
+ func->setPrivateSignal();
+ return true;
+ }
+
if (!matchDataType(&dataType, &name)) {
return false;
}
diff --git a/src/tools/qdoc/generator.cpp b/src/tools/qdoc/generator.cpp
index 22f02327a9..99dec06233 100644
--- a/src/tools/qdoc/generator.cpp
+++ b/src/tools/qdoc/generator.cpp
@@ -213,7 +213,7 @@ void Generator::appendSortedNames(Text& text, const ClassNode* cn, const QList<R
foreach (const QString &className, classNames) {
text << classMap[className];
- text << separator(index++, classNames.count());
+ text << comma(index++, classNames.count());
}
}
@@ -236,7 +236,7 @@ void Generator::appendSortedQmlNames(Text& text, const Node* base, const NodeLis
foreach (const QString &name, names) {
text << classMap[name];
- text << separator(index++, names.count());
+ text << comma(index++, names.count());
}
}
@@ -1245,6 +1245,23 @@ void Generator::generateStatus(const Node *node, CodeMarker *marker)
}
/*!
+ Generates a bold line that says:
+ "The signal is private, not emitted by the user.
+ The function is public so the user can pass it to connect()."
+ */
+void Generator::generatePrivateSignalNote(const Node* node, CodeMarker* marker)
+{
+ Text text;
+ text << Atom::ParaLeft
+ << Atom(Atom::FormattingLeft, ATOM_FORMATTING_BOLD)
+ << "Note: "
+ << Atom(Atom::FormattingRight, ATOM_FORMATTING_BOLD)
+ << "This is a private signal. It can be used in signal connections but cannot be emitted by the user."
+ << Atom::ParaRight;
+ generateText(text, node, marker);
+}
+
+/*!
Generate the documentation for \a relative. i.e. \a relative
is the node that reporesentas the entity where a qdoc comment
was found, and \a text represents the qdoc comment.
diff --git a/src/tools/qdoc/generator.h b/src/tools/qdoc/generator.h
index ba4d5b0a45..8f7e293eb3 100644
--- a/src/tools/qdoc/generator.h
+++ b/src/tools/qdoc/generator.h
@@ -156,6 +156,7 @@ protected:
const QString& tag);
void generateSince(const Node *node, CodeMarker *marker);
void generateStatus(const Node *node, CodeMarker *marker);
+ void generatePrivateSignalNote(const Node* node, CodeMarker* marker);
void generateThreadSafeness(const Node *node, CodeMarker *marker);
QString getMetadataElement(const Aggregate* inner, const QString& t);
QStringList getMetadataElements(const Aggregate* inner, const QString& t);
diff --git a/src/tools/qdoc/htmlgenerator.cpp b/src/tools/qdoc/htmlgenerator.cpp
index 6985d3afee..058fb38c17 100644
--- a/src/tools/qdoc/htmlgenerator.cpp
+++ b/src/tools/qdoc/htmlgenerator.cpp
@@ -2176,7 +2176,7 @@ void HtmlGenerator::generateRequisites(Aggregate *inner, CodeMarker *marker)
else if ((*r).access_ == Node::Private) {
text << " (private)";
}
- text << separator(index++, classe->baseClasses().count());
+ text << comma(index++, classe->baseClasses().count());
}
++r;
}
@@ -3265,6 +3265,7 @@ void HtmlGenerator::generateSectionList(const Section& section,
{
bool alignNames = true;
if (!section.members.isEmpty()) {
+ bool hasPrivateSignals = false;
bool twoColumn = false;
if (style == CodeMarker::Subpage) {
alignNames = false;
@@ -3307,6 +3308,14 @@ void HtmlGenerator::generateSectionList(const Section& section,
prefix = prefix.left(section.keys.at(i).indexOf("::")+1);
}
generateSynopsis(*m, relative, marker, style, alignNames, &prefix);
+ if ((*m)->isFunction()) {
+ const FunctionNode* fn = static_cast<const FunctionNode*>(*m);
+ if (fn->isPrivateSignal()) {
+ hasPrivateSignals = true;
+ if (alignNames)
+ out() << "</td><td class=\"memItemRight bottomAlign\">[see note below]";
+ }
+ }
if (alignNames)
out() << "</td></tr>\n";
else
@@ -3321,6 +3330,9 @@ void HtmlGenerator::generateSectionList(const Section& section,
if (twoColumn)
out() << "</td></tr>\n</table></div>\n";
}
+ if (hasPrivateSignals && alignNames) {
+ generatePrivateSignalNote(relative, marker);
+ }
}
if (style == CodeMarker::Summary && !section.inherited.isEmpty()) {
@@ -4023,6 +4035,11 @@ void HtmlGenerator::generateDetailedMember(const Node *node,
generateSectionList(notifiers, node, marker, CodeMarker::Accessors);
}
}
+ else if (node->isFunction()) {
+ const FunctionNode* fn = static_cast<const FunctionNode*>(node);
+ if (fn->isPrivateSignal())
+ generatePrivateSignalNote(node, marker);
+ }
else if (node->type() == Node::Enum) {
const EnumNode *enume = static_cast<const EnumNode *>(node);
if (enume->flagsType()) {
diff --git a/src/tools/qdoc/node.cpp b/src/tools/qdoc/node.cpp
index 34e5a0aa4e..ec721aee64 100644
--- a/src/tools/qdoc/node.cpp
+++ b/src/tools/qdoc/node.cpp
@@ -1802,6 +1802,7 @@ FunctionNode::FunctionNode(Aggregate *parent, const QString& name)
overload_(false),
reimplemented_(false),
attached_(false),
+ privateSignal_(false),
reimplementedFrom_(0),
associatedProperty_(0)
{
@@ -1822,6 +1823,7 @@ FunctionNode::FunctionNode(NodeType type, Aggregate *parent, const QString& name
overload_(false),
reimplemented_(false),
attached_(attached),
+ privateSignal_(false),
reimplementedFrom_(0),
associatedProperty_(0)
{
diff --git a/src/tools/qdoc/node.h b/src/tools/qdoc/node.h
index 8dcfa1f7be..845b99a4e8 100644
--- a/src/tools/qdoc/node.h
+++ b/src/tools/qdoc/node.h
@@ -404,7 +404,7 @@ public:
void printChildren(const QString& title);
void addChild(Node* child);
void removeChild(Node* child);
- virtual void setOutputSubdirectory(const QString& t);
+ void setOutputSubdirectory(const QString& t) Q_DECL_OVERRIDE;
protected:
Aggregate(NodeType type, Aggregate* parent, const QString& name);
@@ -922,6 +922,8 @@ public:
virtual QString logicalModuleIdentifier() const Q_DECL_OVERRIDE {
return parent()->logicalModuleIdentifier();
}
+ bool isPrivateSignal() const { return privateSignal_; }
+ void setPrivateSignal() { privateSignal_ = true; }
void debug() const;
@@ -940,6 +942,7 @@ private:
bool overload_ : 1;
bool reimplemented_: 1;
bool attached_: 1;
+ bool privateSignal_: 1;
QList<Parameter> parameters_;
const FunctionNode* reimplementedFrom_;
const PropertyNode* associatedProperty_;
diff --git a/src/tools/qdoc/tokenizer.cpp b/src/tools/qdoc/tokenizer.cpp
index 6bfa678bc6..68c6fb7831 100644
--- a/src/tools/qdoc/tokenizer.cpp
+++ b/src/tools/qdoc/tokenizer.cpp
@@ -78,7 +78,8 @@ static const char *kwords[] = {
"QT3_SUPPORT",
"QT3_SUPPORT_CONSTRUCTOR",
"QT3_MOC_SUPPORT",
- "QDOC_PROPERTY"
+ "QDOC_PROPERTY",
+ "QPrivateSignal"
};
static const int KwordHashTableSize = 4096;
diff --git a/src/tools/qdoc/tokenizer.h b/src/tools/qdoc/tokenizer.h
index 5827ce9b7d..2b79320567 100644
--- a/src/tools/qdoc/tokenizer.h
+++ b/src/tools/qdoc/tokenizer.h
@@ -74,8 +74,8 @@ enum { Tok_Eoi, Tok_Ampersand, Tok_Aster, Tok_Caret, Tok_LeftParen,
Tok_Q_DECLARE_FLAGS, Tok_Q_SIGNALS, Tok_Q_SLOTS, Tok_QT_COMPAT,
Tok_QT_COMPAT_CONSTRUCTOR, Tok_QT_DEPRECATED, Tok_QT_MOC_COMPAT,
Tok_QT_MODULE, Tok_QT3_SUPPORT, Tok_QT3_SUPPORT_CONSTRUCTOR,
- Tok_QT3_MOC_SUPPORT, Tok_QDOC_PROPERTY,
- Tok_FirstKeyword = Tok_char, Tok_LastKeyword = Tok_QDOC_PROPERTY };
+ Tok_QT3_MOC_SUPPORT, Tok_QDOC_PROPERTY, Tok_QPrivateSignal,
+ Tok_FirstKeyword = Tok_char, Tok_LastKeyword = Tok_QPrivateSignal };
/*
The Tokenizer class implements lexical analysis of C++ source
diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp
index 6a1374e3ee..9e5548ab4c 100644
--- a/src/widgets/dialogs/qfiledialog.cpp
+++ b/src/widgets/dialogs/qfiledialog.cpp
@@ -331,6 +331,7 @@ QT_BEGIN_INCLUDE_NAMESPACE
#ifdef Q_DEAD_CODE_FROM_QT4_WIN
#include <qwindowsstyle_p.h>
#endif
+#include <QMetaEnum>
#include <qshortcut.h>
#ifdef Q_DEAD_CODE_FROM_QT4_MAC
#include <qmacstyle_mac_p.h>
@@ -385,9 +386,8 @@ QFileDialog::QFileDialog(const QFileDialogArgs &args)
QFileDialog::~QFileDialog()
{
#ifndef QT_NO_SETTINGS
- QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
- settings.beginGroup(QLatin1String("Qt"));
- settings.setValue(QLatin1String("filedialog"), saveState());
+ Q_D(QFileDialog);
+ d->saveSettings();
#endif
}
@@ -503,34 +503,7 @@ bool QFileDialog::restoreState(const QByteArray &state)
if (!d->usingWidgets())
return true;
- if (!d->qFileDialogUi->splitter->restoreState(d->splitterState))
- return false;
- QList<int> list = d->qFileDialogUi->splitter->sizes();
- if (list.count() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
- for (int i = 0; i < list.count(); ++i)
- list[i] = d->qFileDialogUi->splitter->widget(i)->sizeHint().width();
- d->qFileDialogUi->splitter->setSizes(list);
- }
-
- d->qFileDialogUi->sidebar->setUrls(d->sidebarUrls);
- while (history.count() > 5)
- history.pop_front();
- setHistory(history);
- QHeaderView *headerView = d->qFileDialogUi->treeView->header();
- if (!headerView->restoreState(d->headerData))
- return false;
-
- QList<QAction*> actions = headerView->actions();
- QAbstractItemModel *abstractModel = d->model;
-#ifndef QT_NO_PROXYMODEL
- if (d->proxyModel)
- abstractModel = d->proxyModel;
-#endif
- int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
- for (int i = 1; i < total; ++i)
- actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
-
- return true;
+ return d->restoreWidgetState(history, -1);
}
/*!
@@ -2670,6 +2643,104 @@ void QFileDialog::accept()
}
}
+#ifndef QT_NO_SETTINGS
+void QFileDialogPrivate::saveSettings()
+{
+ Q_Q(QFileDialog);
+ QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
+ settings.beginGroup(QLatin1String("FileDialog"));
+
+ if (usingWidgets()) {
+ settings.setValue(QLatin1String("sidebarWidth"), qFileDialogUi->splitter->sizes().first());
+ settings.setValue(QLatin1String("shortcuts"), QUrl::toStringList(qFileDialogUi->sidebar->urls()));
+ settings.setValue(QLatin1String("treeViewHeader"), qFileDialogUi->treeView->header()->saveState());
+ }
+ QStringList historyUrls;
+ foreach (const QString &path, q->history())
+ historyUrls << QUrl::fromLocalFile(path).toString();
+ settings.setValue(QLatin1String("history"), historyUrls);
+ settings.setValue(QLatin1String("lastVisited"), lastVisitedDir()->toString());
+ const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
+ settings.setValue(QLatin1String("viewMode"), QLatin1String(viewModeMeta.key(q->viewMode())));
+ settings.setValue(QLatin1String("qtVersion"), QLatin1String(QT_VERSION_STR));
+}
+
+bool QFileDialogPrivate::restoreFromSettings()
+{
+ Q_Q(QFileDialog);
+ QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
+ if (!settings.childGroups().contains(QLatin1String("FileDialog")))
+ return false;
+ settings.beginGroup(QLatin1String("FileDialog"));
+
+ q->setDirectoryUrl(lastVisitedDir()->isEmpty() ? settings.value(QLatin1String("lastVisited")).toUrl() : *lastVisitedDir());
+
+ QByteArray viewModeStr = settings.value(QLatin1String("viewMode")).toString().toLatin1();
+ const QMetaEnum &viewModeMeta = q->metaObject()->enumerator(q->metaObject()->indexOfEnumerator("ViewMode"));
+ bool ok = false;
+ int viewMode = viewModeMeta.keyToValue(viewModeStr.constData(), &ok);
+ if (!ok)
+ viewMode = QFileDialog::List;
+ q->setViewMode(static_cast<QFileDialog::ViewMode>(viewMode));
+
+ sidebarUrls = QUrl::fromStringList(settings.value(QLatin1String("shortcuts")).toStringList());
+ headerData = settings.value(QLatin1String("treeViewHeader")).toByteArray();
+
+ if (!usingWidgets())
+ return true;
+
+ QStringList history;
+ foreach (const QString &urlStr, settings.value(QLatin1String("history")).toStringList()) {
+ QUrl url(urlStr);
+ if (url.isLocalFile())
+ history << url.toLocalFile();
+ }
+
+ return restoreWidgetState(history, settings.value(QLatin1String("sidebarWidth"), -1).toInt());
+}
+#endif // QT_NO_SETTINGS
+
+bool QFileDialogPrivate::restoreWidgetState(QStringList &history, int splitterPosition)
+{
+ Q_Q(QFileDialog);
+ if (splitterPosition >= 0) {
+ QList<int> splitterSizes;
+ splitterSizes.append(splitterPosition);
+ splitterSizes.append(qFileDialogUi->splitter->widget(1)->sizeHint().width());
+ qFileDialogUi->splitter->setSizes(splitterSizes);
+ } else {
+ if (!qFileDialogUi->splitter->restoreState(splitterState))
+ return false;
+ QList<int> list = qFileDialogUi->splitter->sizes();
+ if (list.count() >= 2 && (list.at(0) == 0 || list.at(1) == 0)) {
+ for (int i = 0; i < list.count(); ++i)
+ list[i] = qFileDialogUi->splitter->widget(i)->sizeHint().width();
+ qFileDialogUi->splitter->setSizes(list);
+ }
+ }
+
+ qFileDialogUi->sidebar->setUrls(sidebarUrls);
+ while (history.count() > 5)
+ history.pop_front();
+ q->setHistory(history);
+
+ QHeaderView *headerView = qFileDialogUi->treeView->header();
+ if (!headerView->restoreState(headerData))
+ return false;
+
+ QList<QAction*> actions = headerView->actions();
+ QAbstractItemModel *abstractModel = model;
+#ifndef QT_NO_PROXYMODEL
+ if (proxyModel)
+ abstractModel = proxyModel;
+#endif
+ int total = qMin(abstractModel->columnCount(QModelIndex()), actions.count() + 1);
+ for (int i = 1; i < total; ++i)
+ actions.at(i - 1)->setChecked(!headerView->isSectionHidden(i));
+
+ return true;
+}
+
/*!
\internal
@@ -2696,8 +2767,12 @@ void QFileDialogPrivate::init(const QUrl &directory, const QString &nameFilter,
q->selectFile(initialSelection(directory));
#ifndef QT_NO_SETTINGS
- const QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
- q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray());
+ // Try to restore from the FileDialog settings group; if it fails, fall back
+ // to the pre-5.5 QByteArray serialized settings.
+ if (!restoreFromSettings()) {
+ const QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
+ q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray());
+ }
#endif
#if defined(Q_EMBEDDED_SMALLSCREEN)
@@ -2845,8 +2920,12 @@ void QFileDialogPrivate::createWidgets()
createMenuActions();
#ifndef QT_NO_SETTINGS
- const QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
- q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray());
+ // Try to restore from the FileDialog settings group; if it fails, fall back
+ // to the pre-5.5 QByteArray serialized settings.
+ if (!restoreFromSettings()) {
+ const QSettings settings(QSettings::UserScope, QLatin1String("QtProject"));
+ q->restoreState(settings.value(QLatin1String("Qt/filedialog")).toByteArray());
+ }
#endif
// Initial widget states from options
diff --git a/src/widgets/dialogs/qfiledialog_p.h b/src/widgets/dialogs/qfiledialog_p.h
index 9eb08f7a3a..8a10896966 100644
--- a/src/widgets/dialogs/qfiledialog_p.h
+++ b/src/widgets/dialogs/qfiledialog_p.h
@@ -181,6 +181,12 @@ public:
#endif
}
+#ifndef QT_NO_SETTINGS
+ void saveSettings();
+ bool restoreFromSettings();
+#endif
+
+ bool restoreWidgetState(QStringList &history, int splitterPosition);
void setLastVisitedDirectory(const QUrl &dir);
void retranslateWindowTitle();
void retranslateStrings();
diff --git a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
index a4609c41cf..c0bb8ef63a 100644
--- a/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
+++ b/src/widgets/graphicsview/qgraphicsanchorlayout_p.h
@@ -251,9 +251,7 @@ struct AnchorVertexPair : public AnchorVertex {
#ifdef QT_DEBUG
inline QString AnchorVertex::toString() const
{
- if (!this) {
- return QLatin1String("NULL");
- } else if (m_type == Pair) {
+ if (m_type == Pair) {
const AnchorVertexPair *vp = static_cast<const AnchorVertexPair *>(this);
return QString::fromLatin1("(%1, %2)").arg(vp->m_first->toString()).arg(vp->m_second->toString());
} else if (!m_item) {
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index eaa5cb99e4..cd30410097 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -11290,7 +11290,7 @@ static void formatGraphicsItemHelper(QDebug debug, const QGraphicsItem *item)
debug << ", pos=";
QtDebugUtils::formatQPoint(debug, item->pos());
if (const qreal z = item->zValue())
- debug << ", z=" << item->zValue();
+ debug << ", z=" << z;
if (item->flags())
debug << ", flags=" << item->flags();
}
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index 00f590ebc2..ed10beddd4 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -1508,6 +1508,7 @@ void QApplicationPrivate::setPalette_helper(const QPalette &palette, const char*
QApplicationPrivate::set_pal = new QPalette(palette);
else
*QApplicationPrivate::set_pal = palette;
+ QCoreApplication::setAttribute(Qt::AA_SetPalette);
}
}
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 1f13a34ac0..b49fd9b3b6 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -2608,6 +2608,8 @@ QString QWidget::styleSheet() const
void QWidget::setStyleSheet(const QString& styleSheet)
{
Q_D(QWidget);
+ if (data->in_destructor)
+ return;
d->createExtra();
QStyleSheetStyle *proxy = qobject_cast<QStyleSheetStyle *>(d->extra->style);
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index f8b8ec5ea3..485cf82078 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -762,6 +762,7 @@ QWidgetBackingStore::~QWidgetBackingStore()
resetWidget(dirtyRenderToTextureWidgets.at(c));
#ifndef QT_NO_OPENGL
+ delete widgetTextures;
delete dirtyOnScreenWidgets;
#endif
dirtyOnScreenWidgets = 0;
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 1efe88acde..5a56c592a6 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -733,9 +733,9 @@ void QToolButtonPrivate::popupTimerDone()
horizontal = false;
#endif
QPoint p;
- QRect screen = QApplication::desktop()->availableGeometry(q);
+ const QRect rect = q->rect(); // Find screen via point in case of QGraphicsProxyWidget.
+ QRect screen = QApplication::desktop()->availableGeometry(q->mapToGlobal(rect.center()));
QSize sh = ((QToolButton*)(QMenu*)actualMenu)->receivers(SIGNAL(aboutToShow()))? QSize() : actualMenu->sizeHint();
- QRect rect = q->rect();
if (horizontal) {
if (q->isRightToLeft()) {
if (q->mapToGlobal(QPoint(0, rect.bottom())).y() + sh.height() <= screen.height()) {