mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 790505, part 4: If we're just updating the transform of a prerendered layer, then schedule an empty transaction to skip unnecessary display-list overhead. r=roc
This commit is contained in:
parent
7180e78526
commit
4f1e40ca75
@ -7732,30 +7732,47 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
nsChangeHint(aChange & (nsChangeHint_RepaintFrame |
|
||||
nsChangeHint_SyncFrameView |
|
||||
nsChangeHint_UpdateOpacityLayer)));
|
||||
// This must be set to true if the rendering change needs to
|
||||
// invalidate content. If it's false, a composite-only paint
|
||||
// (empty transaction) will be scheduled.
|
||||
bool needInvalidatingPaint = false;
|
||||
|
||||
// if frame has view, will already be invalidated
|
||||
if (aChange & nsChangeHint_RepaintFrame) {
|
||||
if (aFrame->IsFrameOfType(nsIFrame::eSVG) &&
|
||||
!(aFrame->GetStateBits() & NS_STATE_IS_OUTER_SVG)) {
|
||||
if (aChange & nsChangeHint_UpdateEffects) {
|
||||
needInvalidatingPaint = true;
|
||||
// Invalidate and update our area:
|
||||
nsSVGUtils::InvalidateAndScheduleReflowSVG(aFrame);
|
||||
} else {
|
||||
needInvalidatingPaint = true;
|
||||
// Just invalidate our area:
|
||||
nsSVGUtils::InvalidateBounds(aFrame);
|
||||
}
|
||||
} else {
|
||||
needInvalidatingPaint = true;
|
||||
aFrame->InvalidateFrameSubtree();
|
||||
}
|
||||
}
|
||||
if (aChange & nsChangeHint_UpdateOpacityLayer) {
|
||||
// FIXME/bug 796697: we can get away with empty transactions for
|
||||
// opacity updates in many cases.
|
||||
needInvalidatingPaint = true;
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
|
||||
}
|
||||
|
||||
if (aChange & nsChangeHint_UpdateTransformLayer) {
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
|
||||
// If we're not already going to do an invalidating paint, see
|
||||
// if we can get away with only updating the transform on a
|
||||
// layer for this frame, and not scheduling an invalidating
|
||||
// paint.
|
||||
if (!needInvalidatingPaint) {
|
||||
needInvalidatingPaint |= !aFrame->TryUpdateTransformOnly();
|
||||
}
|
||||
}
|
||||
if (aChange & nsChangeHint_ChildrenOnlyTransform) {
|
||||
needInvalidatingPaint = true;
|
||||
// The long comment in ProcessRestyledFrames that precedes the
|
||||
// |frame->GetContent()->GetPrimaryFrame()| and abort applies here too.
|
||||
nsIFrame *f = aFrame->GetContent()->GetPrimaryFrame();
|
||||
@ -7767,7 +7784,9 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
childFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
|
||||
}
|
||||
}
|
||||
aFrame->SchedulePaint();
|
||||
aFrame->SchedulePaint(needInvalidatingPaint ?
|
||||
nsIFrame::PAINT_DEFAULT :
|
||||
nsIFrame::PAINT_COMPOSITE_ONLY);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3745,6 +3745,12 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
||||
|
||||
AddAnimationsAndTransitionsToLayer(container, aBuilder,
|
||||
this, eCSSProperty_transform);
|
||||
if (ShouldPrerenderTransformedContent(aBuilder, mFrame, false)) {
|
||||
container->SetUserData(nsIFrame::LayerIsPrerenderedDataKey(),
|
||||
/*the value is irrelevant*/nullptr);
|
||||
} else {
|
||||
container->RemoveUserData(nsIFrame::LayerIsPrerenderedDataKey());
|
||||
}
|
||||
return container.forget();
|
||||
}
|
||||
|
||||
|
@ -98,6 +98,7 @@
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/LookAndFeel.h"
|
||||
#include "mozilla/css/ImageLoader.h"
|
||||
#include "mozilla/gfx/Tools.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::layers;
|
||||
@ -4882,7 +4883,48 @@ nsIFrame::InvalidateFrameWithRect(const nsRect& aRect, uint32_t aDisplayItemKey)
|
||||
|
||||
*rect = rect->Union(aRect);
|
||||
}
|
||||
|
||||
|
||||
/*static*/ uint8_t nsIFrame::sLayerIsPrerenderedDataKey;
|
||||
|
||||
bool
|
||||
nsIFrame::TryUpdateTransformOnly()
|
||||
{
|
||||
Layer* layer = FrameLayerBuilder::GetDedicatedLayer(
|
||||
this, nsDisplayItem::TYPE_TRANSFORM);
|
||||
if (!layer || !layer->HasUserData(LayerIsPrerenderedDataKey())) {
|
||||
// This layer isn't prerendered, so we can't correctly optimize to
|
||||
// an empty transaction in general.
|
||||
return false;
|
||||
}
|
||||
|
||||
gfx3DMatrix transform3d;
|
||||
if (!nsLayoutUtils::GetLayerTransformForFrame(this, &transform3d)) {
|
||||
// We're not able to compute a layer transform that we know would
|
||||
// be used at the next layers transaction, so we can't only update
|
||||
// the transform and will need to schedule an invalidating paint.
|
||||
return false;
|
||||
}
|
||||
gfxMatrix transform, previousTransform;
|
||||
// FIXME/bug 796690 and 796705: in general, changes to 3D
|
||||
// transforms, or transform changes to properties other than
|
||||
// translation, may lead us to choose a different rendering
|
||||
// resolution for our layer. So if the transform is 3D or has a
|
||||
// non-translation change, bail and schedule an invalidating paint.
|
||||
// (We can often do better than this, for example for scale-down
|
||||
// changes.)
|
||||
static const gfx::Float kError = 0.0001;
|
||||
if (!transform3d.Is2D(&transform) ||
|
||||
!layer->GetTransform().Is2D(&previousTransform) ||
|
||||
!gfx::FuzzyEqual(transform.xx, previousTransform.xx, kError) ||
|
||||
!gfx::FuzzyEqual(transform.yy, previousTransform.yy, kError) ||
|
||||
!gfx::FuzzyEqual(transform.xy, previousTransform.xy, kError) ||
|
||||
!gfx::FuzzyEqual(transform.yx, previousTransform.yx, kError)) {
|
||||
return false;
|
||||
}
|
||||
layer->SetBaseTransformForNextTransaction(transform3d);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
nsIFrame::IsInvalid(nsRect& aRect)
|
||||
{
|
||||
|
@ -2231,6 +2231,23 @@ public:
|
||||
*/
|
||||
virtual void InvalidateFrameForRemoval() {}
|
||||
|
||||
/**
|
||||
* When HasUserData(frame->LayerIsPrerenderedDataKey()), then the
|
||||
* entire overflow area of this frame has been rendered in its
|
||||
* layer(s).
|
||||
*/
|
||||
static void* LayerIsPrerenderedDataKey() {
|
||||
return &sLayerIsPrerenderedDataKey;
|
||||
}
|
||||
static uint8_t sLayerIsPrerenderedDataKey;
|
||||
|
||||
/**
|
||||
* Try to update this frame's transform without invalidating any
|
||||
* content. Return true iff successful. If unsuccessful, the
|
||||
* caller is responsible for scheduling an invalidating paint.
|
||||
*/
|
||||
bool TryUpdateTransformOnly();
|
||||
|
||||
/**
|
||||
* Checks if a frame has had InvalidateFrame() called on it since the
|
||||
* last paint.
|
||||
|
Loading…
Reference in New Issue
Block a user