diff options
Diffstat (limited to '')
-rw-r--r-- | gfx/layers/d3d11/CompositorD3D11.h | 227 | ||||
-rw-r--r-- | gfx/layers/d3d11/CompositorD3D11.hlsl | 186 |
2 files changed, 413 insertions, 0 deletions
diff --git a/gfx/layers/d3d11/CompositorD3D11.h b/gfx/layers/d3d11/CompositorD3D11.h new file mode 100644 index 0000000000..d8cdd2d2f8 --- /dev/null +++ b/gfx/layers/d3d11/CompositorD3D11.h @@ -0,0 +1,227 @@ +/* -*- 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_COMPOSITORD3D11_H +#define MOZILLA_GFX_COMPOSITORD3D11_H + +#include "mozilla/gfx/2D.h" +#include "gfx2DGlue.h" +#include "mozilla/layers/Compositor.h" +#include "TextureD3D11.h" +#include <d3d11.h> +#include <dxgi1_2.h> +#include "ShaderDefinitionsD3D11.h" + +class nsWidget; + +namespace mozilla { +namespace layers { + +#define LOGD3D11(param) + +class DeviceAttachmentsD3D11; + +class CompositorD3D11 : public Compositor { + public: + explicit CompositorD3D11(widget::CompositorWidget* aWidget); + virtual ~CompositorD3D11(); + + CompositorD3D11* AsCompositorD3D11() override { return this; } + + bool Initialize(nsCString* const out_failureReason) override; + + already_AddRefed<DataTextureSource> CreateDataTextureSource( + TextureFlags aFlags = TextureFlags::NO_FLAGS) override; + + int32_t GetMaxTextureSize() const final; + + already_AddRefed<CompositingRenderTarget> CreateRenderTarget( + const gfx::IntRect& aRect, SurfaceInitMode aInit) override; + + void SetRenderTarget(CompositingRenderTarget* aSurface) override; + already_AddRefed<CompositingRenderTarget> GetCurrentRenderTarget() + const override { + return do_AddRef(mCurrentRT); + } + already_AddRefed<CompositingRenderTarget> GetWindowRenderTarget() + const override; + + bool ReadbackRenderTarget(CompositingRenderTarget* aSource, + AsyncReadbackBuffer* aDest) override; + already_AddRefed<AsyncReadbackBuffer> CreateAsyncReadbackBuffer( + const gfx::IntSize& aSize) override; + + bool BlitRenderTarget(CompositingRenderTarget* aSource, + const gfx::IntSize& aSourceSize, + const gfx::IntSize& aDestSize) override; + + void SetDestinationSurfaceSize(const gfx::IntSize& aSize) override {} + + void ClearRect(const gfx::Rect& aRect); + + void DrawQuad(const gfx::Rect& aRect, const gfx::IntRect& aClipRect, + const EffectChain& aEffectChain, gfx::Float aOpacity, + const gfx::Matrix4x4& aTransform, + const gfx::Rect& aVisibleRect) override; + + /** + * Start a new frame. + */ + Maybe<gfx::IntRect> BeginFrameForWindow( + const nsIntRegion& aInvalidRegion, const Maybe<gfx::IntRect>& aClipRect, + const gfx::IntRect& aRenderBounds, + const nsIntRegion& aOpaqueRegion) override; + + /** + * Flush the current frame to the screen. + */ + void EndFrame() override; + + void CancelFrame(bool aNeedFlush = true) override; + + /** + * Setup the viewport and projection matrix for rendering + * to a window of the given dimensions. + */ + virtual void PrepareViewport(const gfx::IntSize& aSize); + virtual void PrepareViewport(const gfx::IntSize& aSize, + const gfx::Matrix4x4& aProjection, float aZNear, + float aZFar); + +#ifdef MOZ_DUMP_PAINTING + const char* Name() const override { return "Direct3D 11"; } +#endif + + // For TextureSourceProvider. + ID3D11Device* GetD3D11Device() const override { return mDevice; } + + ID3D11Device* GetDevice() { return mDevice; } + + ID3D11DeviceContext* GetDC() { return mContext; } + + virtual void RequestAllowFrameRecording(bool aWillRecord) override { + mAllowFrameRecording = aWillRecord; + } + + void Readback(gfx::DrawTarget* aDrawTarget) { + mTarget = aDrawTarget; + mTargetBounds = gfx::IntRect(); + PaintToTarget(); + mTarget = nullptr; + } + + SyncObjectHost* GetSyncObject(); + + private: + enum Severity { + Recoverable, + DebugAssert, + Critical, + }; + + void HandleError(HRESULT hr, Severity aSeverity = DebugAssert); + + // Same as Failed(), except the severity is critical (with no abort) and + // a string prefix must be provided. + bool Failed(HRESULT hr, const char* aContext); + + // ensure mSize is up to date with respect to mWidget + void EnsureSize(); + bool VerifyBufferSize(); + bool UpdateRenderTarget(); + bool UpdateConstantBuffers(); + void SetSamplerForSamplingFilter(gfx::SamplingFilter aSamplingFilter); + + ID3D11PixelShader* GetPSForEffect(Effect* aEffect); + Maybe<gfx::IntRect> BeginFrame(const nsIntRegion& aInvalidRegion, + const Maybe<gfx::IntRect>& aClipRect, + const gfx::IntRect& aRenderBounds, + const nsIntRegion& aOpaqueRegion); + void PaintToTarget(); + RefPtr<ID3D11Texture2D> CreateTexture(const gfx::IntRect& aRect, + const CompositingRenderTarget* aSource, + const gfx::IntPoint& aSourcePoint); + + void PrepareStaticVertexBuffer(); + + void Draw(const gfx::Rect& aGeometry, const gfx::Rect* aTexCoords); + + void Present(); + + template <typename VertexType> + void SetVertexBuffer(ID3D11Buffer* aBuffer); + + /** + * Whether or not the recorder should be recording frames. + * + * When this returns true, the CompositorD3D11 will allocate and return window + * render targets from |GetWindowRenderTarget|, which otherwise returns + * nullptr. + * + * This will be true when either we are recording a profile with screenshots + * enabled or the |LayerManagerComposite| has requested us to record frames + * for the |CompositionRecorder|. + */ + bool ShouldAllowFrameRecording() const; + + // The DrawTarget from BeginFrameForTarget, which EndFrame needs to copy the + // window contents into. + // Only non-null between BeginFrameForTarget and EndFrame. + RefPtr<gfx::DrawTarget> mTarget; + gfx::IntRect mTargetBounds; + + RefPtr<ID3D11DeviceContext> mContext; + RefPtr<ID3D11Device> mDevice; + RefPtr<IDXGISwapChain> mSwapChain; + RefPtr<CompositingRenderTargetD3D11> mDefaultRT; + RefPtr<CompositingRenderTargetD3D11> mCurrentRT; + mutable RefPtr<CompositingRenderTargetD3D11> mWindowRTCopy; + + RefPtr<ID3D11Query> mQuery; + RefPtr<ID3D11Query> mRecycledQuery; + + RefPtr<DeviceAttachmentsD3D11> mAttachments; + + LayoutDeviceIntSize mSize; + + // The size that we passed to ResizeBuffers to set + // the swapchain buffer size. + LayoutDeviceIntSize mBufferSize; + + HWND mHwnd; + + D3D_FEATURE_LEVEL mFeatureLevel; + + VertexShaderConstants mVSConstants; + PixelShaderConstants mPSConstants; + bool mDisableSequenceForNextFrame; + bool mAllowPartialPresents; + bool mIsDoubleBuffered; + + gfx::IntRegion mFrontBufferInvalid; + gfx::IntRegion mBackBufferInvalid; + // This is the clip rect applied to the default DrawTarget (i.e. the window) + gfx::IntRect mCurrentClip; + + bool mVerifyBuffersFailed; + bool mUseMutexOnPresent; + bool mAllowFrameRecording; +}; + +namespace TexSlot { +static const int RGB = 0; +static const int Y = 1; +static const int Cb = 2; +static const int Cr = 3; +static const int RGBWhite = 4; +static const int Mask = 5; +static const int Backdrop = 6; +} // namespace TexSlot + +} // namespace layers +} // namespace mozilla + +#endif diff --git a/gfx/layers/d3d11/CompositorD3D11.hlsl b/gfx/layers/d3d11/CompositorD3D11.hlsl new file mode 100644 index 0000000000..4e13011782 --- /dev/null +++ b/gfx/layers/d3d11/CompositorD3D11.hlsl @@ -0,0 +1,186 @@ +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- + * 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/. */ + +#include "BlendShaderConstants.h" + +typedef float4 rect; + +float4x4 mLayerTransform : register(vs, c0); +float4x4 mProjection : register(vs, c4); +float4 vRenderTargetOffset : register(vs, c8); +rect vTextureCoords : register(vs, c9); +rect vLayerQuad : register(vs, c10); + +float4 fLayerColor : register(ps, c0); +float fLayerOpacity : register(ps, c1); + +// x = layer type +// y = mask type +// z = blend op +// w = is premultiplied + +float fCoefficient : register(ps, c3); + +row_major float3x3 mYuvColorMatrix : register(ps, c4); + +sampler sSampler : register(ps, s0); + +// The mix-blend mega shader uses all variables, so we have to make sure they +// are assigned fixed slots. +Texture2D tRGB : register(ps, t0); +Texture2D tY : register(ps, t1); +Texture2D tCb : register(ps, t2); +Texture2D tCr : register(ps, t3); + +struct VS_INPUT { + float2 vPosition : POSITION; +}; + +struct VS_TEX_INPUT { + float2 vPosition : POSITION; + float2 vTexCoords : TEXCOORD0; +}; + +struct VS_OUTPUT { + float4 vPosition : SV_Position; + float2 vTexCoords : TEXCOORD0; +}; + +struct PS_OUTPUT { + float4 vSrc; + float4 vAlpha; +}; + +float2 TexCoords(const float2 aPosition) +{ + float2 result; + const float2 size = vTextureCoords.zw; + result.x = vTextureCoords.x + aPosition.x * size.x; + result.y = vTextureCoords.y + aPosition.y * size.y; + + return result; +} + +SamplerState LayerTextureSamplerLinear +{ + Filter = MIN_MAG_MIP_LINEAR; + AddressU = Clamp; + AddressV = Clamp; +}; + +float4 TransformedPosition(float2 aInPosition) +{ + // the current vertex's position on the quad + // [x,y,0,1] is mandated by the CSS Transforms spec as the point value to transform + float4 position = float4(0, 0, 0, 1); + + // We use 4 component floats to uniquely describe a rectangle, by the structure + // of x, y, width, height. This allows us to easily generate the 4 corners + // of any rectangle from the 4 corners of the 0,0-1,1 quad that we use as the + // stream source for our LayerQuad vertex shader. We do this by doing: + // Xout = x + Xin * width + // Yout = y + Yin * height + float2 size = vLayerQuad.zw; + position.x = vLayerQuad.x + aInPosition.x * size.x; + position.y = vLayerQuad.y + aInPosition.y * size.y; + + position = mul(mLayerTransform, position); + + return position; +} + +float4 VertexPosition(float4 aTransformedPosition) +{ + float4 result; + result.w = aTransformedPosition.w; + result.xyz = aTransformedPosition.xyz / aTransformedPosition.w; + result -= vRenderTargetOffset; + result.xyz *= result.w; + + result = mul(mProjection, result); + + return result; +} + +VS_OUTPUT LayerQuadVS(const VS_INPUT aVertex) +{ + VS_OUTPUT outp; + float4 position = TransformedPosition(aVertex.vPosition); + + outp.vPosition = VertexPosition(position); + outp.vTexCoords = TexCoords(aVertex.vPosition.xy); + + return outp; +} + +/* From Rec601: +[R] [1.1643835616438356, 0.0, 1.5960267857142858] [ Y - 16] +[G] = [1.1643835616438358, -0.3917622900949137, -0.8129676472377708] x [Cb - 128] +[B] [1.1643835616438356, 2.017232142857143, 8.862867620416422e-17] [Cr - 128] + +For [0,1] instead of [0,255], and to 5 places: +[R] [1.16438, 0.00000, 1.59603] [ Y - 0.06275] +[G] = [1.16438, -0.39176, -0.81297] x [Cb - 0.50196] +[B] [1.16438, 2.01723, 0.00000] [Cr - 0.50196] + +From Rec709: +[R] [1.1643835616438356, 4.2781193979771426e-17, 1.7927410714285714] [ Y - 16] +[G] = [1.1643835616438358, -0.21324861427372963, -0.532909328559444] x [Cb - 128] +[B] [1.1643835616438356, 2.1124017857142854, 0.0] [Cr - 128] + +For [0,1] instead of [0,255], and to 5 places: +[R] [1.16438, 0.00000, 1.79274] [ Y - 0.06275] +[G] = [1.16438, -0.21325, -0.53291] x [Cb - 0.50196] +[B] [1.16438, 2.11240, 0.00000] [Cr - 0.50196] +*/ +float4 CalculateYCbCrColor(const float2 aTexCoords) +{ + float3 yuv = float3( + tY.Sample(sSampler, aTexCoords).r, + tCb.Sample(sSampler, aTexCoords).r, + tCr.Sample(sSampler, aTexCoords).r); + yuv = yuv * fCoefficient - float3(0.06275, 0.50196, 0.50196); + + return float4(mul(mYuvColorMatrix, yuv), 1.0); +} + +float4 CalculateNV12Color(const float2 aTexCoords) +{ + float3 yuv = float3( + tY.Sample(sSampler, aTexCoords).r, + tCb.Sample(sSampler, aTexCoords).r, + tCb.Sample(sSampler, aTexCoords).g); + yuv = yuv * fCoefficient - float3(0.06275, 0.50196, 0.50196); + + return float4(mul(mYuvColorMatrix, yuv), 1.0); +} + +float4 SolidColorShader(const VS_OUTPUT aVertex) : SV_Target +{ + return fLayerColor; +} + +float4 RGBAShader(const VS_OUTPUT aVertex) : SV_Target +{ + return tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity; +} + +float4 RGBShader(const VS_OUTPUT aVertex) : SV_Target +{ + float4 result; + result = tRGB.Sample(sSampler, aVertex.vTexCoords) * fLayerOpacity; + result.a = fLayerOpacity; + return result; +} + +float4 YCbCrShader(const VS_OUTPUT aVertex) : SV_Target +{ + return CalculateYCbCrColor(aVertex.vTexCoords) * fLayerOpacity; +} + +float4 NV12Shader(const VS_OUTPUT aVertex) : SV_Target +{ + return CalculateNV12Color(aVertex.vTexCoords) * fLayerOpacity; +} |