Bug 1471221 - Calculate intermediate surface bounds in advanced layers in pre-pass. r=mattwoodrow
Advanced layers was calculating incorrect visible regions for container layers with intermediate surfaces, as it was not taking async transform animations in to account. Rather than recursing the depth of the tree for each layer to calculate this in OnPrepareToRender, do a single pre-pass at the start of the frame. Differential Revision: https://phabricator.services.mozilla.com/D4522
This commit is contained in:
@@ -47,22 +47,6 @@ ContainerLayerMLGPU::OnPrepareToRender(FrameBuilder* aBuilder)
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((!mRenderTarget || mChildrenChanged) &&
|
||||
gfxPrefs::AdvancedLayersEnableContainerResizing())
|
||||
{
|
||||
// Try to compute a more accurate visible region.
|
||||
AL_LOG("Computing new surface size for container %p:\n", GetLayer());
|
||||
|
||||
Maybe<IntRect> bounds = ComputeIntermediateSurfaceBounds();
|
||||
if (bounds) {
|
||||
LayerIntRegion region = std::move(GetShadowVisibleRegion());
|
||||
region.AndWith(LayerIntRect::FromUnknownRect(bounds.value()));
|
||||
AL_LOG(" computed bounds: %s\n", Stringify(bounds.value()).c_str());
|
||||
AL_LOG(" new visible: %s\n", Stringify(region).c_str());
|
||||
|
||||
SetShadowVisibleRegion(std::move(region));
|
||||
}
|
||||
}
|
||||
mChildrenChanged = false;
|
||||
|
||||
mTargetOffset = GetIntermediateSurfaceRect().TopLeft().ToUnknownPoint();
|
||||
@@ -117,41 +101,45 @@ GetTransformedBounds(Layer* aLayer)
|
||||
return bounds;
|
||||
}
|
||||
|
||||
static Maybe<IntRect>
|
||||
FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
|
||||
/* static */ Maybe<IntRect>
|
||||
ContainerLayerMLGPU::FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
|
||||
{
|
||||
AL_LOG(" visiting child %p\n", aLayer);
|
||||
AL_LOG_IF(aClip, " parent clip: %s\n", Stringify(aClip.value()).c_str());
|
||||
|
||||
ContainerLayer* container = aLayer->AsContainerLayer();
|
||||
if (container && !container->UseIntermediateSurface()) {
|
||||
Maybe<IntRect> accumulated = Some(IntRect());
|
||||
if (container) {
|
||||
if (container->UseIntermediateSurface()) {
|
||||
container->AsHostLayer()->AsLayerMLGPU()->AsContainerLayerMLGPU()->ComputeIntermediateSurfaceBounds();
|
||||
} else {
|
||||
Maybe<IntRect> accumulated = Some(IntRect());
|
||||
|
||||
// Traverse children.
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
Maybe<RenderTargetIntRect> clip = aClip;
|
||||
if (const Maybe<ParentLayerIntRect>& childClip = child->AsHostLayer()->GetShadowClipRect()) {
|
||||
RenderTargetIntRect rtChildClip =
|
||||
TransformBy(ViewAs<ParentLayerToRenderTargetMatrix4x4>(
|
||||
aLayer->GetEffectiveTransform(),
|
||||
PixelCastJustification::RenderTargetIsParentLayerForRoot),
|
||||
childClip.value());
|
||||
clip = IntersectMaybeRects(clip, Some(rtChildClip));
|
||||
AL_LOG(" target clip: %s\n", Stringify(rtChildClip).c_str());
|
||||
AL_LOG_IF(clip, " full clip: %s\n", Stringify(clip.value()).c_str());
|
||||
}
|
||||
// Traverse children.
|
||||
for (Layer* child = container->GetFirstChild(); child; child = child->GetNextSibling()) {
|
||||
Maybe<RenderTargetIntRect> clip = aClip;
|
||||
if (const Maybe<ParentLayerIntRect>& childClip = child->AsHostLayer()->GetShadowClipRect()) {
|
||||
RenderTargetIntRect rtChildClip =
|
||||
TransformBy(ViewAs<ParentLayerToRenderTargetMatrix4x4>(
|
||||
aLayer->GetEffectiveTransform(),
|
||||
PixelCastJustification::RenderTargetIsParentLayerForRoot),
|
||||
childClip.value());
|
||||
clip = IntersectMaybeRects(clip, Some(rtChildClip));
|
||||
AL_LOG(" target clip: %s\n", Stringify(rtChildClip).c_str());
|
||||
AL_LOG_IF(clip, " full clip: %s\n", Stringify(clip.value()).c_str());
|
||||
}
|
||||
|
||||
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
|
||||
if (!childBounds) {
|
||||
return Nothing();
|
||||
}
|
||||
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
|
||||
if (!childBounds) {
|
||||
return Nothing();
|
||||
}
|
||||
|
||||
accumulated = accumulated->SafeUnion(childBounds.value());
|
||||
if (!accumulated) {
|
||||
return Nothing();
|
||||
accumulated = accumulated->SafeUnion(childBounds.value());
|
||||
if (!accumulated) {
|
||||
return Nothing();
|
||||
}
|
||||
}
|
||||
return accumulated;
|
||||
}
|
||||
return accumulated;
|
||||
}
|
||||
|
||||
IntRect bounds = GetTransformedBounds(aLayer);
|
||||
@@ -164,7 +152,7 @@ FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip)
|
||||
return Some(bounds);
|
||||
}
|
||||
|
||||
Maybe<IntRect>
|
||||
void
|
||||
ContainerLayerMLGPU::ComputeIntermediateSurfaceBounds()
|
||||
{
|
||||
Maybe<IntRect> bounds = Some(IntRect());
|
||||
@@ -174,15 +162,16 @@ ContainerLayerMLGPU::ComputeIntermediateSurfaceBounds()
|
||||
PixelCastJustification::RenderTargetIsParentLayerForRoot);
|
||||
Maybe<IntRect> childBounds = FindVisibleBounds(child, clip);
|
||||
if (!childBounds) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
|
||||
bounds = bounds->SafeUnion(childBounds.value());
|
||||
if (!bounds) {
|
||||
return Nothing();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return bounds;
|
||||
|
||||
SetShadowVisibleRegion(LayerIntRect::FromUnknownRect(bounds.value()));
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
@@ -69,12 +69,15 @@ public:
|
||||
mView = aView;
|
||||
}
|
||||
|
||||
void ComputeIntermediateSurfaceBounds();
|
||||
|
||||
protected:
|
||||
bool OnPrepareToRender(FrameBuilder* aBuilder) override;
|
||||
void OnLayerManagerChange(LayerManagerMLGPU* aManager) override;
|
||||
Maybe<gfx::IntRect> ComputeIntermediateSurfaceBounds();
|
||||
|
||||
private:
|
||||
static Maybe<gfx::IntRect> FindVisibleBounds(Layer* aLayer, const Maybe<RenderTargetIntRect>& aClip);
|
||||
|
||||
RefPtr<MLGRenderTarget> mRenderTarget;
|
||||
|
||||
// We cache these since occlusion culling can change the visible region.
|
||||
|
||||
@@ -66,6 +66,11 @@ FrameBuilder::Build()
|
||||
|
||||
mWidgetRenderView = new RenderViewMLGPU(this, target, region);
|
||||
|
||||
// Traverse the layer tree and compute visible region for intermediate surfaces
|
||||
if (ContainerLayerMLGPU* root = mRoot->AsLayerMLGPU()->AsContainerLayerMLGPU()) {
|
||||
root->ComputeIntermediateSurfaceBounds();
|
||||
}
|
||||
|
||||
// Traverse the layer tree and assign each layer to tiles.
|
||||
{
|
||||
Maybe<gfx::Polygon> geometry;
|
||||
|
||||
Reference in New Issue
Block a user