mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-12-12 00:50:40 +00:00
Bug 637852. Part 17: Tighten up AreLayersMarkedActive so we track exactly what properties are changing. Also, clamp resolution to power-of-2 only if the frame's transform has a scale. r=tnikkel
This lets us avoid clamping the scale in more situations. We should only clamp the scale when we think the scale is changing due to a changing transform --- the goal of clamping is to not have to redraw the content too often when the content is zooming in or out.
This commit is contained in:
parent
c944a09c1f
commit
50a8bdee8e
@ -621,7 +621,7 @@ nsHTMLCanvasElement::InvalidateCanvasContent(const gfxRect* damageRect)
|
||||
if (!frame)
|
||||
return;
|
||||
|
||||
frame->MarkLayersActive();
|
||||
frame->MarkLayersActive(nsChangeHint(0));
|
||||
|
||||
nsRect invalRect;
|
||||
nsRect contentArea = frame->GetContentRect();
|
||||
|
@ -1666,14 +1666,16 @@ ChooseScaleAndSetTransform(FrameLayerBuilder* aLayerBuilder,
|
||||
transform.Is2D(&transform2d)) {
|
||||
//Scale factors are normalized to a power of 2 to reduce the number of resolution changes
|
||||
scale = transform2d.ScaleFactors(PR_TRUE);
|
||||
// For frames that aren't marked active (i.e. opacity/transform not
|
||||
// changed recently), let them take their exact resolution. Otherwise
|
||||
// round up to nearest power-of-2 boundary so that we don't keep having to
|
||||
// redraw the content as it scales up and down. Rounding up to nearest
|
||||
// For frames with a changing transform that's not just a translation,
|
||||
// round scale factors up to nearest power-of-2 boundary so that we don't
|
||||
// keep having to redraw the content as it scales up and down. Rounding up to nearest
|
||||
// power-of-2 boundary ensures we never scale up, only down --- avoiding
|
||||
// jaggies. It also ensures we never scale down by more than a factor of 2,
|
||||
// avoiding bad downscaling quality.
|
||||
if (aContainerFrame->AreLayersMarkedActive()) {
|
||||
gfxMatrix frameTransform;
|
||||
if (aContainerFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer) &&
|
||||
aTransform &&
|
||||
(!aTransform->Is2D(&frameTransform) || frameTransform.HasNonTranslationOrFlip())) {
|
||||
scale.width = gfxUtils::ClampToScaleFactor(scale.width);
|
||||
scale.height = gfxUtils::ClampToScaleFactor(scale.height);
|
||||
} else {
|
||||
|
@ -7689,13 +7689,13 @@ DoApplyRenderingChangeToTree(nsIFrame* aFrame,
|
||||
}
|
||||
}
|
||||
if (aChange & nsChangeHint_UpdateOpacityLayer) {
|
||||
aFrame->MarkLayersActive();
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateOpacityLayer);
|
||||
aFrame->InvalidateLayer(aFrame->GetVisualOverflowRectRelativeToSelf(),
|
||||
nsDisplayItem::TYPE_OPACITY);
|
||||
}
|
||||
|
||||
if (aChange & nsChangeHint_UpdateTransformLayer) {
|
||||
aFrame->MarkLayersActive();
|
||||
aFrame->MarkLayersActive(nsChangeHint_UpdateTransformLayer);
|
||||
// Invalidate the old transformed area. The new transformed area
|
||||
// will be invalidated by nsFrame::FinishAndStoreOverflowArea.
|
||||
aFrame->InvalidateTransformLayer();
|
||||
|
@ -1714,7 +1714,7 @@ nsDisplayOpacity::BuildLayer(nsDisplayListBuilder* aBuilder,
|
||||
nsDisplayItem::LayerState
|
||||
nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager) {
|
||||
if (mFrame->AreLayersMarkedActive())
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer))
|
||||
return LAYER_ACTIVE;
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
|
||||
@ -2398,7 +2398,7 @@ already_AddRefed<Layer> nsDisplayTransform::BuildLayer(nsDisplayListBuilder *aBu
|
||||
nsDisplayItem::LayerState
|
||||
nsDisplayTransform::GetLayerState(nsDisplayListBuilder* aBuilder,
|
||||
LayerManager* aManager) {
|
||||
if (mFrame->AreLayersMarkedActive())
|
||||
if (mFrame->AreLayersMarkedActive(nsChangeHint_UpdateTransformLayer))
|
||||
return LAYER_ACTIVE;
|
||||
nsIFrame* activeScrolledRoot =
|
||||
nsLayoutUtils::GetActiveScrolledRootFor(mFrame, nsnull);
|
||||
|
@ -118,6 +118,7 @@
|
||||
#include "nsExpirationTracker.h"
|
||||
#include "nsSVGIntegrationUtils.h"
|
||||
#include "nsSVGEffects.h"
|
||||
#include "nsChangeHint.h"
|
||||
|
||||
#include "gfxContext.h"
|
||||
#include "CSSCalc.h"
|
||||
@ -4099,12 +4100,17 @@ nsIFrame::InvalidateTransformLayer()
|
||||
|
||||
class LayerActivity {
|
||||
public:
|
||||
LayerActivity(nsIFrame* aFrame) : mFrame(aFrame) {}
|
||||
LayerActivity(nsIFrame* aFrame) : mFrame(aFrame), mChangeHint(nsChangeHint(0)) {}
|
||||
~LayerActivity();
|
||||
nsExpirationState* GetExpirationState() { return &mState; }
|
||||
|
||||
nsIFrame* mFrame;
|
||||
nsExpirationState mState;
|
||||
// mChangeHint can be some combination of nsChangeHint_UpdateOpacityLayer and
|
||||
// nsChangeHint_UpdateTransformLayer (or neither)
|
||||
// The presence of those bits indicates whether opacity or transform
|
||||
// changes have been detected.
|
||||
nsChangeHint mChangeHint;
|
||||
};
|
||||
|
||||
class LayerActivityTracker : public nsExpirationTracker<LayerActivity,4> {
|
||||
@ -4149,7 +4155,7 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
|
||||
}
|
||||
|
||||
void
|
||||
nsIFrame::MarkLayersActive()
|
||||
nsIFrame::MarkLayersActive(nsChangeHint aChangeHint)
|
||||
{
|
||||
FrameProperties properties = Properties();
|
||||
LayerActivity* layerActivity =
|
||||
@ -4164,6 +4170,7 @@ nsIFrame::MarkLayersActive()
|
||||
gLayerActivityTracker->AddObject(layerActivity);
|
||||
properties.Set(LayerActivityProperty(), layerActivity);
|
||||
}
|
||||
NS_UpdateHint(layerActivity->mChangeHint, aChangeHint);
|
||||
}
|
||||
|
||||
PRBool
|
||||
@ -4172,6 +4179,14 @@ nsIFrame::AreLayersMarkedActive()
|
||||
return Properties().Get(LayerActivityProperty()) != nsnull;
|
||||
}
|
||||
|
||||
PRBool
|
||||
nsIFrame::AreLayersMarkedActive(nsChangeHint aChangeHint)
|
||||
{
|
||||
LayerActivity* layerActivity =
|
||||
static_cast<LayerActivity*>(Properties().Get(LayerActivityProperty()));
|
||||
return layerActivity && (layerActivity->mChangeHint & aChangeHint);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
nsFrame::ShutdownLayerActivityTimer()
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ nsHTMLCanvasFrame::Init(nsIContent* aContent,
|
||||
// We can fill in the canvas before the canvas frame is created, in
|
||||
// which case we never get around to marking the layer active. Therefore,
|
||||
// we mark it active here when we create the frame.
|
||||
MarkLayersActive();
|
||||
MarkLayersActive(nsChangeHint(0));
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -1997,14 +1997,25 @@ public:
|
||||
* after a short period. This call does no immediate invalidation,
|
||||
* but when the mark times out, we'll invalidate the frame's overflow
|
||||
* area.
|
||||
* @param aChangeHint nsChangeHint_UpdateTransformLayer or
|
||||
* nsChangeHint_UpdateOpacityLayer or 0, depending on whether the change
|
||||
* triggering the activity is a changing transform, changing opacity, or
|
||||
* something else.
|
||||
*/
|
||||
void MarkLayersActive();
|
||||
|
||||
void MarkLayersActive(nsChangeHint aHint);
|
||||
/**
|
||||
* Return true if this frame is marked as needing active layers.
|
||||
*/
|
||||
PRBool AreLayersMarkedActive();
|
||||
|
||||
/**
|
||||
* Return true if this frame is marked as needing active layers.
|
||||
* @param aChangeHint nsChangeHint_UpdateTransformLayer or
|
||||
* nsChangeHint_UpdateOpacityLayer. We return true only if
|
||||
* a change in the transform or opacity has been recorded while layers have
|
||||
* been marked active for this frame.
|
||||
*/
|
||||
PRBool AreLayersMarkedActive(nsChangeHint aChangeHint);
|
||||
|
||||
/**
|
||||
* @param aFlags see InvalidateInternal below
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user