summaryrefslogtreecommitdiffstats
path: root/gfx/layers/mlgpu/MLGDevice.h
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/layers/mlgpu/MLGDevice.h')
-rw-r--r--gfx/layers/mlgpu/MLGDevice.h481
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