☠☠ backed out by 7b6507f85ef5 ☠ ☠ | |
author | Matt Woodrow <mwoodrow@mozilla.com> |
Thu, 08 Jun 2017 15:26:50 +1200 | |
changeset 362771 | 14ac21b548cf4f8bbec395429f9b941425265e73 |
parent 362770 | 5ea810dbc4affeeffb3694b99609435075a25697 |
child 362772 | 4f29bdedb50c5f60d58e88030cb37c0bec6cfab0 |
push id | 91195 |
push user | mwoodrow@mozilla.com |
push date | Thu, 08 Jun 2017 03:54:38 +0000 |
treeherder | mozilla-inbound@14ac21b548cf [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | mstange |
bugs | 1361970 |
milestone | 55.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/gfx/layers/composite/LayerManagerComposite.cpp +++ b/gfx/layers/composite/LayerManagerComposite.cpp @@ -232,94 +232,66 @@ LayerManagerComposite::BeginTransactionW } mIsCompositorReady = true; mCompositor->SetTargetContext(aTarget, aRect); mTarget = aTarget; mTargetBounds = aRect; } -/** - * Get accumulated transform of from the context creating layer to the - * given layer. - */ -static Matrix4x4 -GetAccTransformIn3DContext(Layer* aLayer) { - Matrix4x4 transform = aLayer->GetLocalTransform(); - for (Layer* layer = aLayer->GetParent(); - layer && layer->Extend3DContext(); - layer = layer->GetParent()) { - transform = transform * layer->GetLocalTransform(); +void +LayerManagerComposite::PostProcessLayers(nsIntRegion& aOpaqueRegion) +{ + RenderTargetIntRect bounds(ViewAs<RenderTargetPixel>(mRenderBounds)); + LayerIntRegion visible; + PostProcessLayers(mRoot, bounds, ParentLayerIntPoint(), aOpaqueRegion, visible, Nothing()); +} + +// We want to skip directly through ContainerLayers that don't have an intermediate +// surface. We compute occlusions for leaves and intermediate surfaces against +// the layer that they actually composite into so that we can use the final (snapped) +// effective transform. +bool ShouldProcessLayer(Layer* aLayer) +{ + if (!aLayer->GetParent() || + !aLayer->AsContainerLayer()) { + return true; } - return transform; + + return aLayer->AsContainerLayer()->UseIntermediateSurface(); } void LayerManagerComposite::PostProcessLayers(Layer* aLayer, + const RenderTargetIntRect& aClipRect, + const ParentLayerIntPoint& aOffset, nsIntRegion& aOpaqueRegion, LayerIntRegion& aVisibleRegion, const Maybe<ParentLayerIntRect>& aClipFromAncestors) { - if (aLayer->Extend3DContext()) { - // For layers participating 3D rendering context, their visible - // region should be empty (invisible), so we pass through them - // without doing anything. - - // Direct children of the establisher may have a clip, becaue the - // item containing it; ex. of nsHTMLScrollFrame, may give it one. - Maybe<ParentLayerIntRect> layerClip = - aLayer->AsHostLayer()->GetShadowClipRect(); - Maybe<ParentLayerIntRect> ancestorClipForChildren = - IntersectMaybeRects(layerClip, aClipFromAncestors); - MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(), - "Only direct children of the establisher could have a clip"); - - for (Layer* child = aLayer->GetLastChild(); - child; - child = child->GetPrevSibling()) { - PostProcessLayers(child, aOpaqueRegion, aVisibleRegion, - ancestorClipForChildren); - } - return; - } - - nsIntRegion localOpaque; - // Treat layers on the path to the root of the 3D rendering context as - // a giant layer if it is a leaf. - Matrix4x4 transform = GetAccTransformIn3DContext(aLayer); - Matrix transform2d; - Maybe<IntPoint> integerTranslation; - // If aLayer has a simple transform (only an integer translation) then we - // can easily convert aOpaqueRegion into pre-transform coordinates and include - // that region. - if (transform.Is2D(&transform2d)) { - if (transform2d.IsIntegerTranslation()) { - integerTranslation = Some(IntPoint::Truncate(transform2d.GetTranslation())); - localOpaque = aOpaqueRegion; - localOpaque.MoveBy(-*integerTranslation); - } - } // Compute a clip that's the combination of our layer clip with the clip // from our ancestors. LayerComposite* composite = static_cast<LayerComposite*>(aLayer->AsHostLayer()); Maybe<ParentLayerIntRect> layerClip = composite->GetShadowClipRect(); MOZ_ASSERT(!layerClip || !aLayer->Combines3DTransformWithAncestors(), "The layer with a clip should not participate " "a 3D rendering context"); Maybe<ParentLayerIntRect> outsideClip = IntersectMaybeRects(layerClip, aClipFromAncestors); + Matrix4x4 localTransform = aLayer->GetLocalTransform(); + // Convert the combined clip into our pre-transform coordinate space, so // that it can later be intersected with our visible region. // If our transform is a perspective, there's no meaningful insideClip rect // we can compute (it would need to be a cone). Maybe<LayerIntRect> insideClip; - if (outsideClip && !transform.HasPerspectiveComponent()) { - Matrix4x4 inverse = transform; + if (outsideClip && !localTransform.HasPerspectiveComponent()) { + Matrix4x4 inverse = localTransform; if (inverse.Invert()) { Maybe<LayerRect> insideClipFloat = UntransformBy(ViewAs<ParentLayerToLayerMatrix4x4>(inverse), ParentLayerRect(*outsideClip), LayerRect::MaxIntRect()); if (insideClipFloat) { insideClipFloat->RoundOut(); LayerIntRect insideClipInt; @@ -331,28 +303,72 @@ LayerManagerComposite::PostProcessLayers } Maybe<ParentLayerIntRect> ancestorClipForChildren; if (insideClip) { ancestorClipForChildren = Some(ViewAs<ParentLayerPixel>(*insideClip, PixelCastJustification::MovingDownToChildren)); } + if (!ShouldProcessLayer(aLayer)) { + MOZ_ASSERT(!aLayer->AsContainerLayer() || !aLayer->AsContainerLayer()->UseIntermediateSurface()); + // For layers participating 3D rendering context, their visible + // region should be empty (invisible), so we pass through them + // without doing anything. + for (Layer* child = aLayer->GetLastChild(); + child; + child = child->GetPrevSibling()) { + RenderTargetIntRect clipRect = child->CalculateScissorRect(aClipRect); + PostProcessLayers(child, clipRect, aOffset, aOpaqueRegion, aVisibleRegion, + ancestorClipForChildren); + } + return; + } + + nsIntRegion localOpaque; + // Treat layers on the path to the root of the 3D rendering context as + // a giant layer if it is a leaf. + Matrix4x4 transform = aLayer->GetEffectiveTransform(); + Matrix transform2d; + Maybe<IntPoint> integerTranslation; + // If aLayer has a simple transform (only an integer translation) then we + // can easily convert aOpaqueRegion into pre-transform coordinates and include + // that region. + if (transform.Is2D(&transform2d)) { + if (transform2d.IsIntegerTranslation()) { + integerTranslation = Some(IntPoint::Truncate(transform2d.GetTranslation())); + localOpaque = aOpaqueRegion; + localOpaque.MoveBy(-*integerTranslation); + } + } + // Save the value of localOpaque, which currently stores the region obscured // by siblings (and uncles and such), before our descendants contribute to it. nsIntRegion obscured = localOpaque; // Recurse on our descendants, in front-to-back order. In this process: // - Occlusions are computed for them, and they contribute to localOpaque. // - They recalculate their visible regions, taking ancestorClipForChildren // into account, and accumulate them into descendantsVisibleRegion. LayerIntRegion descendantsVisibleRegion; + + // CalculateScissorRect calculates rects that are relative to the origin of the + // intermediate surface, not Layer coords. If we create an intermediate surface, + // provide the surface offset to our children so they can move the clip into + // the right coord space. + ParentLayerIntPoint childOffset = aOffset; + if (aLayer->AsContainerLayer() && aLayer->AsContainerLayer()->UseIntermediateSurface()) { + childOffset = ViewAs<ParentLayerPixel>(aLayer->AsContainerLayer()->GetIntermediateSurfaceRect().TopLeft(), + PixelCastJustification::MovingDownToChildren); + } + bool hasPreserve3DChild = false; for (Layer* child = aLayer->GetLastChild(); child; child = child->GetPrevSibling()) { - PostProcessLayers(child, localOpaque, descendantsVisibleRegion, ancestorClipForChildren); + RenderTargetIntRect clipRect = child->CalculateScissorRect(aClipRect); + PostProcessLayers(child, clipRect, childOffset, localOpaque, descendantsVisibleRegion, ancestorClipForChildren); if (child->Extend3DContext()) { hasPreserve3DChild = true; } } // Recalculate our visible region. LayerIntRegion visible = composite->GetShadowVisibleRegion(); @@ -373,34 +389,35 @@ LayerManagerComposite::PostProcessLayers } composite->SetShadowVisibleRegion(visible); // Transform the newly calculated visible region into our parent's space, // apply our clip to it (if any), and accumulate it into |aVisibleRegion| // for the caller to use. ParentLayerIntRegion visibleParentSpace = TransformBy( ViewAs<LayerToParentLayerMatrix4x4>(transform), visible); - if (const Maybe<ParentLayerIntRect>& clipRect = composite->GetShadowClipRect()) { - visibleParentSpace.AndWith(*clipRect); - } + + // Convert the clip from being in RenderTarget coords to Layer coords + // using the offset provided. + ParentLayerIntRect clip = TransformByTranslation(aClipRect, aOffset); + + visibleParentSpace.AndWith(clip); aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace, PixelCastJustification::MovingDownToChildren)); // If we have a simple transform, then we can add our opaque area into // aOpaqueRegion. if (integerTranslation && !aLayer->HasMaskLayers() && aLayer->IsOpaqueForVisibility()) { if (aLayer->IsOpaque()) { localOpaque.OrWith(composite->GetFullyRenderedRegion()); } localOpaque.MoveBy(*integerTranslation); - if (layerClip) { - localOpaque.AndWith(layerClip->ToUnknownRect()); - } + localOpaque.AndWith(clip.ToUnknownRect()); aOpaqueRegion.OrWith(localOpaque); } } void LayerManagerComposite::EndTransaction(const TimeStamp& aTimeStamp, EndTransactionFlags aFlags) { @@ -444,27 +461,24 @@ LayerManagerComposite::EndTransaction(co MOZ_LAYERS_LOG(("]----- EndTransaction")); #endif } void LayerManagerComposite::UpdateAndRender() { nsIntRegion invalid; - bool didEffectiveTransforms = false; + // The results of our drawing always go directly into a pixel buffer, + // so we don't need to pass any global transform here. + mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4()); nsIntRegion opaque; - LayerIntRegion visible; - PostProcessLayers(mRoot, opaque, visible, Nothing()); + PostProcessLayers(opaque); if (mClonedLayerTreeProperties) { - // Effective transforms are needed by ComputeDifferences(). - mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4()); - didEffectiveTransforms = true; - // We need to compute layer tree differences even if we're not going to // immediately use the resulting damage area, since ComputeDifferences // is also responsible for invalidates intermediate surfaces in // ContainerLayers. nsIntRegion changed = mClonedLayerTreeProperties->ComputeDifferences(mRoot, nullptr); if (mTarget) { // Since we're composing to an external target, we're not going to use @@ -497,22 +511,16 @@ LayerManagerComposite::UpdateAndRender() mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot()); return; } // We don't want our debug overlay to cause more frames to happen // so we will invalidate after we've decided if something changed. InvalidateDebugOverlay(invalid, mRenderBounds); - if (!didEffectiveTransforms) { - // The results of our drawing always go directly into a pixel buffer, - // so we don't need to pass any global transform here. - mRoot->ComputeEffectiveTransforms(gfx::Matrix4x4()); - } - Render(invalid, opaque); #if defined(MOZ_WIDGET_ANDROID) RenderToPresentationSurface(); #endif mWindowOverlayChanged = false; // Update cached layer tree information. mClonedLayerTreeProperties = LayerProperties::CloneFrom(GetRoot()); @@ -1104,18 +1112,17 @@ LayerManagerComposite::RenderToPresentat rotation); viewMatrix.Invert(); // unrotate viewMatrix.PostScale(scale, scale); viewMatrix.PostTranslate(offset.x, offset.y); Matrix4x4 matrix = Matrix4x4::From2D(viewMatrix); mRoot->ComputeEffectiveTransforms(matrix); nsIntRegion opaque; - LayerIntRegion visible; - PostProcessLayers(mRoot, opaque, visible, Nothing()); + PostProcessLayers(opaque); nsIntRegion invalid; IntRect bounds = IntRect::Truncate(0, 0, scale * pageWidth, actualHeight); IntRect rect, actualBounds; MOZ_ASSERT(mRoot->GetOpacity() == 1); mCompositor->BeginFrame(invalid, nullptr, bounds, nsIntRegion(), &rect, &actualBounds); // The Java side of Fennec sets a scissor rect that accounts for
--- a/gfx/layers/composite/LayerManagerComposite.h +++ b/gfx/layers/composite/LayerManagerComposite.h @@ -300,17 +300,20 @@ public: * of layers that are covered with opaque content. * |aOpaqueRegion| is the region already known to be covered with opaque * content, in the post-transform coordinate space of aLayer. * * - Recomputes visible regions to account for async transforms. * Each layer accumulates into |aVisibleRegion| its post-transform * (including async transforms) visible region. */ + void PostProcessLayers(nsIntRegion& aOpaqueRegion); void PostProcessLayers(Layer* aLayer, + const RenderTargetIntRect& aClipRect, + const ParentLayerIntPoint& aOffset, nsIntRegion& aOpaqueRegion, LayerIntRegion& aVisibleRegion, const Maybe<ParentLayerIntRect>& aClipFromAncestors); /** * RAII helper class to add a mask effect with the compositable from aMaskLayer * to the EffectChain aEffect and notify the compositable when we are done. */
--- a/layout/base/UnitTransforms.h +++ b/layout/base/UnitTransforms.h @@ -289,11 +289,22 @@ UntransformVector(const gfx::Matrix4x4Ty gfx::Point4DTyped<TargetUnits> projectedAnchor = aTransform.ProjectPoint(aAnchor); gfx::Point4DTyped<TargetUnits> projectedTarget = aTransform.ProjectPoint(aAnchor + aVector); if (!projectedAnchor.HasPositiveWCoord() || !projectedTarget.HasPositiveWCoord()){ return Nothing(); } return Some(projectedTarget.As2DPoint() - projectedAnchor.As2DPoint()); } + +template <typename TargetUnits, typename SourceUnits> +static gfx::IntRectTyped<TargetUnits> +TransformByTranslation(const gfx::IntRectTyped<SourceUnits>& aRect, + const gfx::IntPointTyped<TargetUnits>& aOffset) +{ + nsIntRect rect = aRect.ToUnknownRect(); + rect.MoveBy(aOffset.ToUnknownPoint()); + return ViewAs<TargetUnits>(rect); +} + } // namespace mozilla #endif