mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-09 04:25:38 +00:00
Support component-alpha for intermediate surfaces in Advanced Layers. (bug 1402737 part 2, r=mattwoodrow)
--HG-- extra : rebase_source : dc2121d9f479f8c75237cae8ad4ea9f751f42ab6
This commit is contained in:
parent
2b8bc13b5c
commit
ef626c4458
@ -21,7 +21,8 @@ using namespace gfx;
|
||||
ContainerLayerMLGPU::ContainerLayerMLGPU(LayerManagerMLGPU* aManager)
|
||||
: ContainerLayer(aManager, nullptr),
|
||||
LayerMLGPU(aManager),
|
||||
mInvalidateEntireSurface(false)
|
||||
mInvalidateEntireSurface(false),
|
||||
mSurfaceCopyNeeded(false)
|
||||
{
|
||||
}
|
||||
|
||||
@ -35,6 +36,8 @@ ContainerLayerMLGPU::~ContainerLayerMLGPU()
|
||||
bool
|
||||
ContainerLayerMLGPU::OnPrepareToRender(FrameBuilder* aBuilder)
|
||||
{
|
||||
mView = nullptr;
|
||||
|
||||
if (!UseIntermediateSurface()) {
|
||||
// Set this so we invalidate the entire cached render target (if any)
|
||||
// if our container uses an intermediate surface again later.
|
||||
@ -67,6 +70,19 @@ ContainerLayerMLGPU::OnPrepareToRender(FrameBuilder* aBuilder)
|
||||
mRenderTarget = nullptr;
|
||||
}
|
||||
|
||||
// Note that if a surface copy is needed, we always redraw the
|
||||
// whole surface (on-demand). This is a rare case - the old
|
||||
// Compositor already does this - and it saves us having to
|
||||
// do much more complicated invalidation.
|
||||
bool surfaceCopyNeeded = false;
|
||||
DefaultComputeSupportsComponentAlphaChildren(&surfaceCopyNeeded);
|
||||
if (surfaceCopyNeeded != mSurfaceCopyNeeded ||
|
||||
surfaceCopyNeeded)
|
||||
{
|
||||
mInvalidateEntireSurface = true;
|
||||
}
|
||||
mSurfaceCopyNeeded = surfaceCopyNeeded;
|
||||
|
||||
gfx::IntRect viewport(gfx::IntPoint(0, 0), mTargetSize);
|
||||
if (!mRenderTarget ||
|
||||
!gfxPrefs::AdvancedLayersUseInvalidation() ||
|
||||
|
@ -13,6 +13,7 @@ namespace mozilla {
|
||||
namespace layers {
|
||||
|
||||
class MLGDevice;
|
||||
class RenderViewMLGPU;
|
||||
|
||||
class ContainerLayerMLGPU final : public ContainerLayer
|
||||
, public LayerMLGPU
|
||||
@ -53,6 +54,17 @@ public:
|
||||
mInvalidRect.SetEmpty();
|
||||
}
|
||||
bool IsContentOpaque() override;
|
||||
bool NeedsSurfaceCopy() const {
|
||||
return mSurfaceCopyNeeded;
|
||||
}
|
||||
|
||||
RenderViewMLGPU* GetRenderView() const {
|
||||
return mView;
|
||||
}
|
||||
void SetRenderView(RenderViewMLGPU* aView) {
|
||||
MOZ_ASSERT(!mView);
|
||||
mView = aView;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool OnPrepareToRender(FrameBuilder* aBuilder) override;
|
||||
@ -71,6 +83,11 @@ private:
|
||||
// is in layer coordinates.
|
||||
gfx::IntRect mInvalidRect;
|
||||
bool mInvalidateEntireSurface;
|
||||
bool mSurfaceCopyNeeded;
|
||||
|
||||
// This is only valid for intermediate surfaces while an instance of
|
||||
// FrameBuilder is live.
|
||||
RenderViewMLGPU* mView;
|
||||
};
|
||||
|
||||
} // namespace layers
|
||||
|
@ -305,6 +305,11 @@ ShaderRenderPass::ExecuteRendering()
|
||||
return;
|
||||
}
|
||||
|
||||
// Change the blend state if needed.
|
||||
if (Maybe<MLGBlendState> blendState = GetBlendState()) {
|
||||
mDevice->SetBlendState(blendState.value());
|
||||
}
|
||||
|
||||
mDevice->SetPSConstantBuffer(0, &mPSBuffer0);
|
||||
if (MaskOperation* mask = GetMask()) {
|
||||
mDevice->SetPSTexture(kMaskLayerTextureSlot, mask->GetTexture());
|
||||
@ -994,5 +999,48 @@ RenderViewPass::SetupPipeline()
|
||||
mDevice->SetSamplerMode(kDefaultSamplerSlot, SamplerMode::LinearClamp);
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewPass::ExecuteRendering()
|
||||
{
|
||||
if (mAssignedLayer->NeedsSurfaceCopy()) {
|
||||
RenderWithBackdropCopy();
|
||||
return;
|
||||
}
|
||||
|
||||
TexturedRenderPass::ExecuteRendering();
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewPass::RenderWithBackdropCopy()
|
||||
{
|
||||
MOZ_ASSERT(mAssignedLayer->NeedsSurfaceCopy());
|
||||
|
||||
DebugOnly<Matrix> transform2d;
|
||||
const Matrix4x4& transform = mAssignedLayer->GetEffectiveTransform();
|
||||
MOZ_ASSERT(transform.Is2D(&transform2d) &&
|
||||
!gfx::ThebesMatrix(transform2d).HasNonIntegerTranslation());
|
||||
|
||||
IntRect visible = mAssignedLayer->GetShadowVisibleRegion().GetBounds().ToUnknownRect();
|
||||
visible += IntPoint::Truncate(transform._41, transform._42);
|
||||
visible -= mParentView->GetTargetOffset();
|
||||
|
||||
RefPtr<MLGTexture> dest = mAssignedLayer->GetRenderTarget()->GetTexture();
|
||||
RefPtr<MLGTexture> source = mParentView->GetRenderTarget()->GetTexture();
|
||||
|
||||
// Clamp the rect so that we don't read pixels outside the source texture, or
|
||||
// write pixels outside the destination texture.
|
||||
visible = visible.Intersect(IntRect(IntPoint(0, 0), source->GetSize()));
|
||||
visible = visible.Intersect(IntRect(visible.TopLeft(), dest->GetSize()));
|
||||
|
||||
mDevice->CopyTexture(dest, IntPoint(0, 0), source, visible);
|
||||
|
||||
RenderViewMLGPU* childView = mAssignedLayer->GetRenderView();
|
||||
childView->RenderAfterBackdropCopy();
|
||||
|
||||
mParentView->RestoreDeviceState();
|
||||
|
||||
TexturedRenderPass::ExecuteRendering();
|
||||
}
|
||||
|
||||
} // namespace layers
|
||||
} // namespace mozilla
|
||||
|
@ -464,8 +464,10 @@ private:
|
||||
bool AddToPass(LayerMLGPU* aItem, ItemInfo& aInfo) override;
|
||||
void SetupPipeline() override;
|
||||
bool OnPrepareBuffers() override;
|
||||
void ExecuteRendering() override;
|
||||
float GetOpacity() const override;
|
||||
bool PrepareBlendState();
|
||||
void RenderWithBackdropCopy();
|
||||
|
||||
private:
|
||||
ConstantBufferSection mBlendConstants;
|
||||
|
@ -62,6 +62,8 @@ RenderViewMLGPU::RenderViewMLGPU(FrameBuilder* aBuilder,
|
||||
this,
|
||||
aContainer->GetLayer(),
|
||||
Stringify(mInvalidBounds).c_str());
|
||||
|
||||
mContainer->SetRenderView(this);
|
||||
}
|
||||
|
||||
RenderViewMLGPU::RenderViewMLGPU(FrameBuilder* aBuilder, RenderViewMLGPU* aParent)
|
||||
@ -72,6 +74,7 @@ RenderViewMLGPU::RenderViewMLGPU(FrameBuilder* aBuilder, RenderViewMLGPU* aParen
|
||||
mFinishedBuilding(false),
|
||||
mCurrentLayerBufferIndex(kInvalidResourceIndex),
|
||||
mCurrentMaskRectBufferIndex(kInvalidResourceIndex),
|
||||
mCurrentDepthMode(MLGDepthTestMode::Disabled),
|
||||
mNextSortIndex(1),
|
||||
mUseDepthBuffer(gfxPrefs::AdvancedLayersEnableDepthBuffer()),
|
||||
mDepthBufferNeedsClear(false)
|
||||
@ -111,11 +114,23 @@ RenderViewMLGPU::AddChild(RenderViewMLGPU* aParent)
|
||||
void
|
||||
RenderViewMLGPU::Render()
|
||||
{
|
||||
// We render tiles front-to-back, depth-first, to minimize render target switching.
|
||||
// We render views depth-first to minimize render target switching.
|
||||
for (const auto& child : mChildren) {
|
||||
child->Render();
|
||||
}
|
||||
|
||||
// If the view requires a surface copy (of its backdrop), then we delay
|
||||
// rendering it until it is added to a batch.
|
||||
if (mContainer && mContainer->NeedsSurfaceCopy()) {
|
||||
return;
|
||||
}
|
||||
ExecuteRendering();
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewMLGPU::RenderAfterBackdropCopy()
|
||||
{
|
||||
MOZ_ASSERT(mContainer && mContainer->NeedsSurfaceCopy());
|
||||
ExecuteRendering();
|
||||
}
|
||||
|
||||
@ -385,26 +400,19 @@ RenderViewMLGPU::ExecuteRendering()
|
||||
if (!mTarget) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Note: we unbind slot 0 (which is where the render target could have been
|
||||
// bound on a previous frame). Otherwise we trigger D3D11_DEVICE_PSSETSHADERRESOURCES_HAZARD.
|
||||
mDevice->UnsetPSTexture(0);
|
||||
mDevice->SetRenderTarget(mTarget);
|
||||
mDevice->SetViewport(IntRect(IntPoint(0, 0), mTarget->GetSize()));
|
||||
mDevice->SetScissorRect(Some(mInvalidBounds));
|
||||
|
||||
if (!mWorldConstants.IsValid()) {
|
||||
gfxWarning() << "Failed to allocate constant buffer for world transform";
|
||||
return;
|
||||
}
|
||||
mDevice->SetVSConstantBuffer(kWorldConstantBufferSlot, &mWorldConstants);
|
||||
|
||||
SetDeviceState();
|
||||
|
||||
// If using the depth buffer, clear it (if needed) and enable writes.
|
||||
if (mUseDepthBuffer) {
|
||||
if (mDepthBufferNeedsClear) {
|
||||
mDevice->ClearDepthBuffer(mTarget);
|
||||
}
|
||||
mDevice->SetDepthTestMode(MLGDepthTestMode::Write);
|
||||
SetDepthTestMode(MLGDepthTestMode::Write);
|
||||
}
|
||||
|
||||
// Opaque items, rendered front-to-back.
|
||||
@ -415,7 +423,7 @@ RenderViewMLGPU::ExecuteRendering()
|
||||
if (mUseDepthBuffer) {
|
||||
// From now on we might be rendering transparent pixels, so we disable
|
||||
// writing to the z-buffer.
|
||||
mDevice->SetDepthTestMode(MLGDepthTestMode::ReadOnly);
|
||||
SetDepthTestMode(MLGDepthTestMode::ReadOnly);
|
||||
}
|
||||
|
||||
// Clear any pixels that are not occluded, and therefore might require
|
||||
@ -466,14 +474,37 @@ RenderViewMLGPU::ExecutePass(RenderPassMLGPU* aPass)
|
||||
mDevice->SetVSConstantBuffer(kMaskBufferSlot, §ion);
|
||||
}
|
||||
|
||||
// Change the blend state if needed.
|
||||
if (Maybe<MLGBlendState> blendState = aPass->GetBlendState()) {
|
||||
mDevice->SetBlendState(blendState.value());
|
||||
}
|
||||
|
||||
aPass->ExecuteRendering();
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewMLGPU::SetDeviceState()
|
||||
{
|
||||
// Note: we unbind slot 0 (which is where the render target could have been
|
||||
// bound on a previous frame). Otherwise we trigger D3D11_DEVICE_PSSETSHADERRESOURCES_HAZARD.
|
||||
mDevice->UnsetPSTexture(0);
|
||||
mDevice->SetRenderTarget(mTarget);
|
||||
mDevice->SetViewport(IntRect(IntPoint(0, 0), mTarget->GetSize()));
|
||||
mDevice->SetScissorRect(Some(mInvalidBounds));
|
||||
mDevice->SetVSConstantBuffer(kWorldConstantBufferSlot, &mWorldConstants);
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewMLGPU::SetDepthTestMode(MLGDepthTestMode aMode)
|
||||
{
|
||||
mDevice->SetDepthTestMode(aMode);
|
||||
mCurrentDepthMode = aMode;
|
||||
}
|
||||
|
||||
void
|
||||
RenderViewMLGPU::RestoreDeviceState()
|
||||
{
|
||||
SetDeviceState();
|
||||
mDevice->SetDepthTestMode(mCurrentDepthMode);
|
||||
mCurrentLayerBufferIndex = kInvalidResourceIndex;
|
||||
mCurrentMaskRectBufferIndex = kInvalidResourceIndex;
|
||||
}
|
||||
|
||||
int32_t
|
||||
RenderViewMLGPU::PrepareDepthBuffer()
|
||||
{
|
||||
@ -514,6 +545,11 @@ RenderViewMLGPU::PrepareDepthBuffer()
|
||||
void
|
||||
RenderViewMLGPU::PrepareClears()
|
||||
{
|
||||
// We don't do any clearing if we're copying from a source backdrop.
|
||||
if (mContainer && mContainer->NeedsSurfaceCopy()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the list of rects to clear. If using the depth buffer, we don't
|
||||
// care if it's accurate since the GPU will do occlusion testing for us.
|
||||
// If not using the depth buffer, we subtract out the occluded region.
|
||||
|
@ -52,6 +52,11 @@ public:
|
||||
return mUseDepthBuffer;
|
||||
}
|
||||
|
||||
// Render after having previously delayed rendering due to the view
|
||||
// requiring a backdrop copy.
|
||||
void RenderAfterBackdropCopy();
|
||||
void RestoreDeviceState();
|
||||
|
||||
// The size and render target cannot be read until the view has finished
|
||||
// building, since we try to right-size the render target to the visible
|
||||
// region.
|
||||
@ -72,6 +77,8 @@ private:
|
||||
void AddItemBackToFront(LayerMLGPU* aLayer, ItemInfo& aItem);
|
||||
|
||||
void PrepareClears();
|
||||
void SetDeviceState();
|
||||
void SetDepthTestMode(MLGDepthTestMode aMode);
|
||||
|
||||
void ExecutePass(RenderPassMLGPU* aPass);
|
||||
|
||||
@ -124,6 +131,9 @@ private:
|
||||
size_t mCurrentLayerBufferIndex;
|
||||
size_t mCurrentMaskRectBufferIndex;
|
||||
|
||||
// This state is saved locally so it can be restored in RestoreDeviceState.
|
||||
MLGDepthTestMode mCurrentDepthMode;
|
||||
|
||||
// Depth-buffer tracking.
|
||||
int32_t mNextSortIndex;
|
||||
bool mUseDepthBuffer;
|
||||
|
Loading…
x
Reference in New Issue
Block a user