diff options
Diffstat (limited to 'gfx/layers/mlgpu/MLGDevice.h')
-rw-r--r-- | gfx/layers/mlgpu/MLGDevice.h | 481 |
1 files changed, 481 insertions, 0 deletions
diff --git a/gfx/layers/mlgpu/MLGDevice.h b/gfx/layers/mlgpu/MLGDevice.h new file mode 100644 index 0000000000..a8e49add2c --- /dev/null +++ b/gfx/layers/mlgpu/MLGDevice.h @@ -0,0 +1,481 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_gfx_layers_mlgpu_MLGDevice_h +#define mozilla_gfx_layers_mlgpu_MLGDevice_h + +#include "mozilla/Assertions.h" // for MOZ_ASSERT, etc +#include "mozilla/EnumeratedArray.h" +#include "mozilla/RefPtr.h" // for already_AddRefed, RefCounted +#include "mozilla/TypedEnumBits.h" +#include "mozilla/WidgetUtils.h" +#include "mozilla/gfx/Types.h" +#include "mozilla/layers/CompositorTypes.h" +#include "mozilla/layers/LayersTypes.h" +#include "ImageTypes.h" +#include "MLGDeviceTypes.h" +#include "nsISupportsImpl.h" +#include "nsString.h" +#include "nsPrintfCString.h" + +namespace mozilla { + +namespace widget { +class CompositorWidget; +} // namespace widget +namespace gfx { +class DrawTarget; +} // namespace gfx + +namespace layers { + +struct GPUStats; +class BufferCache; +class ConstantBufferSection; +class DataTextureSource; +class MLGBufferD3D11; +class MLGDeviceD3D11; +class MLGRenderTargetD3D11; +class MLGResourceD3D11; +class MLGTexture; +class MLGTextureD3D11; +class SharedVertexBuffer; +class SharedConstantBuffer; +class TextureSource; +class VertexBufferSection; +struct ClearRegionHelper; + +class MLGRenderTarget { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGRenderTarget) + + virtual gfx::IntSize GetSize() const = 0; + virtual MLGRenderTargetD3D11* AsD3D11() { return nullptr; } + + // Returns the underlying texture of the render target. + virtual MLGTexture* GetTexture() = 0; + + bool HasDepthBuffer() const { + return (mFlags & MLGRenderTargetFlags::ZBuffer) == + MLGRenderTargetFlags::ZBuffer; + } + + int32_t GetLastDepthStart() const { return mLastDepthStart; } + void SetLastDepthStart(int32_t aDepthStart) { mLastDepthStart = aDepthStart; } + + protected: + explicit MLGRenderTarget(MLGRenderTargetFlags aFlags); + virtual ~MLGRenderTarget() = default; + + protected: + MLGRenderTargetFlags mFlags; + + // When using a depth buffer, callers can track the range of depth values + // that were last used. + int32_t mLastDepthStart; +}; + +class MLGSwapChain { + protected: + virtual ~MLGSwapChain() = default; + + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGSwapChain) + + virtual RefPtr<MLGRenderTarget> AcquireBackBuffer() = 0; + virtual bool ResizeBuffers(const gfx::IntSize& aSize) = 0; + virtual gfx::IntSize GetSize() const = 0; + + // Present to the screen. + virtual void Present() = 0; + + // Force a present without waiting for the previous frame's present to + // complete. + virtual void ForcePresent() = 0; + + // Copy an area of the backbuffer to a draw target. + virtual void CopyBackbuffer(gfx::DrawTarget* aTarget, + const gfx::IntRect& aBounds) = 0; + + // Free any internal resources. + virtual void Destroy() = 0; + + // Give the new invalid region to the swap chain in preparation for + // acquiring the backbuffer. If the new invalid region is empty, + // this returns false and no composite is required. + // + // The extra rect is used for the debug overlay, which is factored in + // separately to avoid causing unnecessary composites. + bool ApplyNewInvalidRegion(nsIntRegion&& aRegion, + const Maybe<gfx::IntRect>& aExtraRect); + + const nsIntRegion& GetBackBufferInvalidRegion() const { + return mBackBufferInvalid; + } + + protected: + MLGSwapChain(); + + protected: + gfx::IntSize mLastPresentSize; + // The swap chain tracks the invalid region of its buffers. After presenting, + // the invalid region for the backbuffer is cleared. If using double + // buffering, it is set to the area of the non-presented buffer that was not + // painted this frame. The initial invalid region each frame comes from + // LayerManagerMLGPU, and is combined with the back buffer's invalid region + // before frame building begins. + nsIntRegion mBackBufferInvalid; + nsIntRegion mFrontBufferInvalid; + bool mIsDoubleBuffered; +}; + +class MLGResource { + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGResource) + + public: + enum class Type { Buffer, Texture }; + + virtual Type GetType() const = 0; + virtual MLGResourceD3D11* AsResourceD3D11() { return nullptr; } + + protected: + virtual ~MLGResource() = default; +}; + +// A buffer for use as a shader input. +class MLGBuffer : public MLGResource { + public: + Type GetType() const override { return Type::Buffer; } + virtual MLGBufferD3D11* AsD3D11() { return nullptr; } + virtual size_t GetSize() const = 0; + + protected: + virtual ~MLGBuffer() = default; +}; + +// This is a lower-level resource than a TextureSource. It wraps +// a 2D texture. +class MLGTexture : public MLGResource { + public: + Type GetType() const override { return Type::Texture; } + virtual MLGTextureD3D11* AsD3D11() { return nullptr; } + const gfx::IntSize& GetSize() const { return mSize; } + + protected: + gfx::IntSize mSize; +}; + +enum class VertexShaderID { + TexturedQuad, + TexturedVertex, + ColoredQuad, + ColoredVertex, + BlendVertex, + Clear, + MaskCombiner, + DiagnosticText, + MaxShaders +}; + +enum class PixelShaderID { + ColoredQuad, + ColoredVertex, + TexturedQuadRGB, + TexturedQuadRGBA, + TexturedVertexRGB, + TexturedVertexRGBA, + TexturedQuadIMC4, + TexturedQuadIdentityIMC4, + TexturedQuadNV12, + TexturedVertexIMC4, + TexturedVertexIdentityIMC4, + TexturedVertexNV12, + ComponentAlphaQuad, + ComponentAlphaVertex, + BlendMultiply, + BlendScreen, + BlendOverlay, + BlendDarken, + BlendLighten, + BlendColorDodge, + BlendColorBurn, + BlendHardLight, + BlendSoftLight, + BlendDifference, + BlendExclusion, + BlendHue, + BlendSaturation, + BlendColor, + BlendLuminosity, + Clear, + MaskCombiner, + DiagnosticText, + MaxShaders +}; + +class MLGDevice { + public: + NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MLGDevice) + + MLGDevice(); + + virtual bool Initialize(); + + virtual TextureFactoryIdentifier GetTextureFactoryIdentifier( + widget::CompositorWidget* aWidget) const = 0; + virtual int32_t GetMaxTextureSize() const = 0; + virtual LayersBackend GetLayersBackend() const = 0; + + virtual RefPtr<MLGSwapChain> CreateSwapChainForWidget( + widget::CompositorWidget* aWidget) = 0; + + // Markers for when we start and finish issuing "normal" (i.e., non- + // diagnostic) draw commands for the frame. + virtual void StartDiagnostics(uint32_t aInvalidPixels) = 0; + virtual void EndDiagnostics() = 0; + virtual void GetDiagnostics(GPUStats* aStats) = 0; + + // Layers interaction. + virtual RefPtr<DataTextureSource> CreateDataTextureSource( + TextureFlags aFlags) = 0; + + // Resource access + virtual bool Map(MLGResource* aResource, MLGMapType aType, + MLGMappedResource* aMap) = 0; + virtual void Unmap(MLGResource* aResource) = 0; + virtual void UpdatePartialResource(MLGResource* aResource, + const gfx::IntRect* aRect, void* aData, + uint32_t aStride) = 0; + virtual void CopyTexture(MLGTexture* aDest, const gfx::IntPoint& aTarget, + MLGTexture* aSource, const gfx::IntRect& aRect) = 0; + + // Begin a frame. This clears and resets all shared buffers. + virtual void BeginFrame(); + virtual void EndFrame(); + + // State setup commands. + virtual void SetRenderTarget(MLGRenderTarget* aRT) = 0; + virtual MLGRenderTarget* GetRenderTarget() = 0; + virtual void SetViewport(const gfx::IntRect& aRT) = 0; + virtual void SetScissorRect(const Maybe<gfx::IntRect>& aScissorRect) = 0; + virtual void SetVertexShader(VertexShaderID aVertexShader) = 0; + virtual void SetPixelShader(PixelShaderID aPixelShader) = 0; + virtual void SetSamplerMode(uint32_t aIndex, SamplerMode aSamplerMode) = 0; + virtual void SetBlendState(MLGBlendState aBlendState) = 0; + virtual void SetVertexBuffer(uint32_t aSlot, MLGBuffer* aBuffer, + uint32_t aStride, uint32_t aOffset = 0) = 0; + virtual void SetVSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer) = 0; + virtual void SetPSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer) = 0; + virtual void SetPSTextures(uint32_t aSlot, uint32_t aNumTextures, + TextureSource* const* aTextures) = 0; + virtual void SetPSTexture(uint32_t aSlot, MLGTexture* aTexture) = 0; + virtual void SetDepthTestMode(MLGDepthTestMode aMode) = 0; + + // If supported, bind constant buffers at a particular offset. These can only + // be used if CanUseConstantBufferOffsetBinding returns true. + virtual void SetVSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer, + uint32_t aFirstConstant, + uint32_t aNumConstants) = 0; + virtual void SetPSConstantBuffer(uint32_t aSlot, MLGBuffer* aBuffer, + uint32_t aFirstConstant, + uint32_t aNumConstants) = 0; + + // Set the topology. No API call is made if the topology has not changed. + // The UnitQuad topology implicity binds a unit quad triangle strip as + // vertex buffer #0. + void SetTopology(MLGPrimitiveTopology aTopology); + + // Set textures that have special binding logic, and bind to multiple slots. + virtual void SetPSTexturesNV12(uint32_t aSlot, TextureSource* aTexture) = 0; + void SetPSTexturesYUV(uint32_t aSlot, TextureSource* aTexture); + + virtual RefPtr<MLGBuffer> CreateBuffer( + MLGBufferType aType, uint32_t aSize, MLGUsage aUsage, + const void* aInitialData = nullptr) = 0; + + virtual RefPtr<MLGTexture> CreateTexture(const gfx::IntSize& aSize, + gfx::SurfaceFormat aFormat, + MLGUsage aUsage, + MLGTextureFlags aFlags) = 0; + + // Unwrap the underlying GPU texture in the given TextureSource, and re-wrap + // it in an MLGTexture structure. + virtual RefPtr<MLGTexture> CreateTexture(TextureSource* aSource) = 0; + + virtual RefPtr<MLGRenderTarget> CreateRenderTarget( + const gfx::IntSize& aSize, + MLGRenderTargetFlags aFlags = MLGRenderTargetFlags::Default) = 0; + + // Clear a render target to the given color, or clear a depth buffer. + virtual void Clear(MLGRenderTarget* aRT, const gfx::DeviceColor& aColor) = 0; + virtual void ClearDepthBuffer(MLGRenderTarget* aRT) = 0; + + // This is only available if CanUseClearView() returns true. + virtual void ClearView(MLGRenderTarget* aRT, const gfx::DeviceColor& aColor, + const gfx::IntRect* aRects, size_t aNumRects) = 0; + + // Drawing Commands + virtual void Draw(uint32_t aVertexCount, uint32_t aOffset) = 0; + virtual void DrawInstanced(uint32_t aVertexCountPerInstance, + uint32_t aInstanceCount, uint32_t aVertexOffset, + uint32_t aInstanceOffset) = 0; + virtual void Flush() = 0; + + // This unlocks any textures that were implicitly locked during drawing. + virtual void UnlockAllTextures() = 0; + + virtual MLGDeviceD3D11* AsD3D11() { return nullptr; } + + // Helpers. + void SetVertexBuffer(uint32_t aSlot, const VertexBufferSection* aSection); + void SetPSConstantBuffer(uint32_t aSlot, + const ConstantBufferSection* aSection); + void SetVSConstantBuffer(uint32_t aSlot, + const ConstantBufferSection* aSection); + void SetPSTexture(uint32_t aSlot, TextureSource* aSource); + void SetSamplerMode(uint32_t aIndex, gfx::SamplingFilter aFilter); + + // This creates or returns a previously created constant buffer, containing + // a YCbCrShaderConstants instance. + RefPtr<MLGBuffer> GetBufferForColorSpace(gfx::YUVColorSpace aColorSpace); + // This creates or returns a previously created constant buffer, containing + // a YCbCrBitDepthConstants instance. + RefPtr<MLGBuffer> GetBufferForColorDepthCoefficient( + gfx::ColorDepth aColorDepth); + + // A shared buffer that can be used to build VertexBufferSections. + SharedVertexBuffer* GetSharedVertexBuffer() { + return mSharedVertexBuffer.get(); + } + // A shared buffer that can be used to build ConstantBufferSections. Intended + // to be used with vertex shaders. + SharedConstantBuffer* GetSharedVSBuffer() { return mSharedVSBuffer.get(); } + // A shared buffer that can be used to build ConstantBufferSections. Intended + // to be used with pixel shaders. + SharedConstantBuffer* GetSharedPSBuffer() { return mSharedPSBuffer.get(); } + // A cache for constant buffers, used when offset-based binding is not + // supported. + BufferCache* GetConstantBufferCache() { return mConstantBufferCache.get(); } + + // Unmap and upload all shared buffers to the GPU. + void FinishSharedBufferUse(); + + // These are used to detect and report initialization failure. + virtual bool IsValid() const { return mInitialized && mIsValid; } + const nsCString& GetFailureId() const { return mFailureId; } + const nsCString& GetFailureMessage() const { return mFailureMessage; } + + // Prepare a clear-region operation to be run at a later time. + void PrepareClearRegion(ClearRegionHelper* aOut, + nsTArray<gfx::IntRect>&& aRects, + const Maybe<int32_t>& aSortIndex); + + // Execute a clear-region operation. This may change shader state. + void DrawClearRegion(const ClearRegionHelper& aHelper); + + // If supported, synchronize with the SyncObject given to clients. + virtual bool Synchronize(); + + // If this returns true, ClearView() can be called. + bool CanUseClearView() const { return mCanUseClearView; } + + // If this returns true, constant buffers can be bound at specific offsets for + // a given run of bytes. This is only supported on Windows 8+ for Direct3D 11. + bool CanUseConstantBufferOffsetBinding() const { + return mCanUseConstantBufferOffsetBinding; + } + + // Return the maximum number of elements that can be bound to a constant + // buffer. This is different than the maximum size of a buffer (there is + // no such limit on Direct3D 11.1). + // + // The return value must be a power of two. + size_t GetMaxConstantBufferBindSize() const { + return mMaxConstantBufferBindSize; + } + + // Helper function for unbinding textures since SetPSTexture is overloaded. + void UnsetPSTexture(uint32_t aSlot) { + TextureSource* nullTexture = nullptr; + SetPSTexture(aSlot, nullTexture); + } + + // Debugging helper function for dumping an MLGTexture to a file. + void WriteAsPNG(MLGTexture* aTexture, const char* aPath); + + // Debugging helper function for copying a texture for later dumping to a + // file. + RefPtr<MLGTexture> CopyAndCreateReadbackTexture(MLGTexture* aTexture); + + protected: + virtual ~MLGDevice(); + + virtual void SetPrimitiveTopology(MLGPrimitiveTopology aTopology) = 0; + + // Optionally run a runtime test to determine if constant buffer offset + // binding works. + virtual bool VerifyConstantBufferOffsetting() { return true; } + + // Used during initialization to record failure reasons. + bool Fail(const nsCString& aFailureId, const nsCString* aMessage); + + // Used during initialization to record failure reasons. Note: our + // MOZ_FORMAT_PRINTF macro does not work on this function, so we + // disable the warning. +#if defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wformat-security" +#endif + template <typename... T> + bool Fail(const char* aFailureId) { + nsCString failureId(aFailureId); + return Fail(failureId, nullptr); + } + template <typename... T> + bool Fail(const char* aFailureId, const char* aMessage, const T&... args) { + nsCString failureId(aFailureId); + nsPrintfCString message(aMessage, args...); + return Fail(failureId, &message); + } +#if defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + + void UnmapSharedBuffers(); + + private: + MLGPrimitiveTopology mTopology; + UniquePtr<SharedVertexBuffer> mSharedVertexBuffer; + UniquePtr<SharedConstantBuffer> mSharedVSBuffer; + UniquePtr<SharedConstantBuffer> mSharedPSBuffer; + UniquePtr<BufferCache> mConstantBufferCache; + + nsCString mFailureId; + nsCString mFailureMessage; + bool mInitialized; + + typedef EnumeratedArray<gfx::YUVColorSpace, gfx::YUVColorSpace::UNKNOWN, + RefPtr<MLGBuffer>> + ColorSpaceArray; + ColorSpaceArray mColorSpaceBuffers; + typedef EnumeratedArray<gfx::ColorDepth, gfx::ColorDepth::UNKNOWN, + RefPtr<MLGBuffer>> + ColorDepthArray; + ColorDepthArray mColorDepthBuffers; + + protected: + bool mIsValid; + bool mCanUseClearView; + bool mCanUseConstantBufferOffsetBinding; + size_t mMaxConstantBufferBindSize; + + RefPtr<MLGRenderTarget> mCurrentRT; +}; + +} // namespace layers +} // namespace mozilla + +#endif // mozilla_gfx_layers_mlgpu_MLGDevice_h |