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:
Jamie Nicol
2018-08-30 00:26:08 +00:00
parent c9cc9cb27d
commit ddceaa2fe8
3 changed files with 43 additions and 46 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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;