зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1361970 - Make PostProcessLayers occlusion culling work against the surface we will draw to rather than the parent layer. r=mstange
This commit is contained in:
Родитель
e4ffc15186
Коммит
80c51057d4
|
@ -237,66 +237,36 @@ LayerManagerComposite::BeginTransactionWithDrawTarget(DrawTarget* aTarget, const
|
|||
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.
|
||||
|
@ -308,13 +278,15 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
|
|||
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),
|
||||
|
@ -336,6 +308,38 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
|
|||
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;
|
||||
|
@ -345,9 +349,21 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
|
|||
// - 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;
|
||||
}
|
||||
|
@ -378,9 +394,12 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
|
|||
// 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 = MoveBy(aClipRect, aOffset);
|
||||
|
||||
visibleParentSpace.AndWith(clip);
|
||||
aVisibleRegion.OrWith(ViewAs<LayerPixel>(visibleParentSpace,
|
||||
PixelCastJustification::MovingDownToChildren));
|
||||
|
||||
|
@ -393,9 +412,7 @@ LayerManagerComposite::PostProcessLayers(Layer* aLayer,
|
|||
localOpaque.OrWith(composite->GetFullyRenderedRegion());
|
||||
}
|
||||
localOpaque.MoveBy(*integerTranslation);
|
||||
if (layerClip) {
|
||||
localOpaque.AndWith(layerClip->ToUnknownRect());
|
||||
}
|
||||
localOpaque.AndWith(clip.ToUnknownRect());
|
||||
aOpaqueRegion.OrWith(localOpaque);
|
||||
}
|
||||
}
|
||||
|
@ -449,17 +466,14 @@ 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
|
||||
|
@ -502,12 +516,6 @@ LayerManagerComposite::UpdateAndRender()
|
|||
// 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();
|
||||
|
@ -1109,8 +1117,7 @@ LayerManagerComposite::RenderToPresentationSurface()
|
|||
|
||||
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);
|
||||
|
|
|
@ -305,7 +305,10 @@ public:
|
|||
* 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);
|
||||
|
|
|
@ -294,6 +294,17 @@ UntransformVector(const gfx::Matrix4x4Typed<SourceUnits, TargetUnits>& aTransfor
|
|||
return Some(projectedTarget.As2DPoint() - projectedAnchor.As2DPoint());
|
||||
}
|
||||
|
||||
|
||||
template <typename TargetUnits, typename SourceUnits>
|
||||
static gfx::IntRectTyped<TargetUnits>
|
||||
MoveBy(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
|
||||
|
|
Загрузка…
Ссылка в новой задаче