Bug 846901 - Support prerendering elements with animated transforms that are offscreen but only by a small amount. r=mattwoodrow, a=tef+

This commit is contained in:
Robert O'Callahan 2013-03-19 09:08:29 -04:00
Родитель 0d9153a4ac
Коммит 9116e12f6d
4 изменённых файлов: 45 добавлений и 8 удалений

Просмотреть файл

@ -2095,7 +2095,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;
}
@ -2151,7 +2152,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)

Просмотреть файл

@ -565,12 +565,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));
@ -3729,7 +3741,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");
@ -3816,6 +3835,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)

Просмотреть файл

@ -919,6 +919,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.
@ -2406,7 +2412,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;
@ -2655,6 +2662,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;
@ -2775,6 +2783,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 nsIFrame* aFrame,
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 {