mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-30 00:01:50 +00:00
Bug 846901 - Support prerendering elements with animated transforms that are offscreen but only by a small amount. r=mattwoodrow
This commit is contained in:
parent
d26cf75d62
commit
e5a41a4488
@ -2136,7 +2136,8 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
// Note that items without their own layers can't be skipped this
|
||||
// way, since their ThebesLayer may decide it wants to draw them
|
||||
// into its buffer even if they're currently covered.
|
||||
if (itemVisibleRect.IsEmpty() && layerState != LAYER_ACTIVE_EMPTY) {
|
||||
if (itemVisibleRect.IsEmpty() &&
|
||||
!item->ShouldBuildLayerEvenIfInvisible(mBuilder)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -2192,7 +2193,9 @@ ContainerState::ProcessDisplayItems(const nsDisplayList& aList,
|
||||
data->mDrawAboveRegion.SimplifyOutward(4);
|
||||
}
|
||||
itemVisibleRect.MoveBy(mParameters.mOffset);
|
||||
RestrictVisibleRegionForLayer(ownLayer, itemVisibleRect);
|
||||
if (!nsDisplayTransform::IsLayerPrerendered(ownLayer)) {
|
||||
RestrictVisibleRegionForLayer(ownLayer, itemVisibleRect);
|
||||
}
|
||||
|
||||
// rounded rectangle clipping using mask layers
|
||||
// (must be done after visible rect is set on layer)
|
||||
|
@ -570,12 +570,24 @@ void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame,
|
||||
nsRect dirty = aDirtyRect - aFrame->GetOffsetTo(aDirtyFrame);
|
||||
nsRect overflowRect = aFrame->GetVisualOverflowRect();
|
||||
|
||||
if (aFrame->IsTransformed() &&
|
||||
nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
|
||||
eCSSProperty_transform)) {
|
||||
/**
|
||||
* Add a fuzz factor to the overflow rectangle so that elements only just
|
||||
* out of view are pulled into the display list, so they can be
|
||||
* prerendered if necessary.
|
||||
*/
|
||||
overflowRect.Inflate(nsPresContext::CSSPixelsToAppUnits(32));
|
||||
}
|
||||
|
||||
if (mHasDisplayPort && IsFixedFrame(aFrame)) {
|
||||
dirty = overflowRect;
|
||||
}
|
||||
|
||||
if (!dirty.IntersectRect(dirty, overflowRect))
|
||||
return;
|
||||
|
||||
aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDirtyRectProperty(),
|
||||
new nsRect(dirty));
|
||||
|
||||
@ -3891,7 +3903,14 @@ nsDisplayTransform::ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBui
|
||||
nsIFrame* aFrame,
|
||||
bool aLogAnimations)
|
||||
{
|
||||
if (!aFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer)) {
|
||||
// Elements whose transform has been modified recently, or which
|
||||
// have a compositor-animated transform, can be prerendered. An element
|
||||
// might have only just had its transform animated in which case
|
||||
// nsChangeHint_UpdateTransformLayer will not be present yet.
|
||||
if (!aFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
|
||||
(!aFrame->GetContent() ||
|
||||
!nsLayoutUtils::HasAnimationsForCompositor(aFrame->GetContent(),
|
||||
eCSSProperty_transform))) {
|
||||
if (aLogAnimations) {
|
||||
nsCString message;
|
||||
message.AppendLiteral("Performance warning: Async animation disabled because frame was not marked active for transform animation");
|
||||
@ -3978,6 +3997,12 @@ nsDisplayTransform::GetTransform(float aAppUnitsPerPixel)
|
||||
return mTransform;
|
||||
}
|
||||
|
||||
bool
|
||||
nsDisplayTransform::ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
|
||||
{
|
||||
return ShouldPrerenderTransformedContent(aBuilder, mFrame, false);
|
||||
}
|
||||
|
||||
already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBuilder,
|
||||
LayerManager *aManager,
|
||||
const ContainerParameters& aContainerParameters)
|
||||
|
@ -966,6 +966,12 @@ public:
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters)
|
||||
{ return mozilla::LAYER_NONE; }
|
||||
/**
|
||||
* Return true to indicate the layer should be constructed even if it's
|
||||
* completely invisible.
|
||||
*/
|
||||
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder)
|
||||
{ return false; }
|
||||
/**
|
||||
* Actually paint this item to some rendering context.
|
||||
* Content outside mVisibleRect need not be painted.
|
||||
@ -2533,7 +2539,8 @@ public:
|
||||
virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aParameters) MOZ_OVERRIDE;
|
||||
|
||||
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE
|
||||
{ return true; }
|
||||
virtual bool TryMerge(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem* aItem) MOZ_OVERRIDE;
|
||||
|
||||
@ -2789,6 +2796,7 @@ public:
|
||||
virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager,
|
||||
const ContainerParameters& aContainerParameters) MOZ_OVERRIDE;
|
||||
virtual bool ShouldBuildLayerEvenIfInvisible(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
virtual bool ComputeVisibility(nsDisplayListBuilder *aBuilder,
|
||||
nsRegion *aVisibleRegion,
|
||||
const nsRect& aAllowVisibleRegionExpansion) MOZ_OVERRIDE;
|
||||
@ -2940,6 +2948,11 @@ public:
|
||||
bool aLogAnimations = false);
|
||||
bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) MOZ_OVERRIDE;
|
||||
|
||||
static bool IsLayerPrerendered(Layer* aLayer)
|
||||
{
|
||||
return aLayer->HasUserData(nsIFrame::LayerIsPrerenderedDataKey());
|
||||
}
|
||||
|
||||
private:
|
||||
static gfx3DMatrix GetResultingTransformMatrixInternal(const FrameTransformProperties& aProperties,
|
||||
const nsPoint& aOrigin,
|
||||
|
@ -130,10 +130,6 @@ PrintDisplayListTo(nsDisplayListBuilder* aBuilder, const nsDisplayList& aList,
|
||||
}
|
||||
|
||||
for (nsDisplayItem* i = aList.GetBottom(); i != nullptr; i = i->GetAbove()) {
|
||||
#ifdef DEBUG
|
||||
if (aList.DidComputeVisibility() && i->GetVisibleRect().IsEmpty())
|
||||
continue;
|
||||
#endif
|
||||
if (aDumpHtml) {
|
||||
fprintf(aOutput, "<li>");
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user