Bug 876321. Track restyling of top/left/right/bottom and treat such nodes as active scrolled roots. r=mattwoodrow

--HG--
extra : rebase_source : 24e7900efdb476a0533808956b9604d144e4db89
This commit is contained in:
Robert O'Callahan 2013-09-09 17:08:41 -07:00
Родитель cdd20f889b
Коммит 8cf17406d8
7 изменённых файлов: 73 добавлений и 5 удалений

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

@ -38,6 +38,10 @@ public:
switch (aProperty) {
case eCSSProperty_opacity: return mOpacityRestyleCount;
case eCSSProperty_transform: return mTransformRestyleCount;
case eCSSProperty_left: return mLeftRestyleCount;
case eCSSProperty_top: return mTopRestyleCount;
case eCSSProperty_right: return mRightRestyleCount;
case eCSSProperty_bottom: return mBottomRestyleCount;
default: MOZ_ASSERT(false); return mOpacityRestyleCount;
}
}
@ -47,6 +51,10 @@ public:
// Number of restyle operations detected
uint8_t mOpacityRestyleCount;
uint8_t mTransformRestyleCount;
uint8_t mLeftRestyleCount;
uint8_t mTopRestyleCount;
uint8_t mRightRestyleCount;
uint8_t mBottomRestyleCount;
bool mContentActive;
};
@ -78,6 +86,7 @@ static void DestroyLayerActivity(void* aPropertyValue)
delete static_cast<LayerActivity*>(aPropertyValue);
}
// Frames with this property have NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY set
NS_DECLARE_FRAME_PROPERTY(LayerActivityProperty, DestroyLayerActivity)
void
@ -89,12 +98,16 @@ LayerActivityTracker::NotifyExpired(LayerActivity* aObject)
aObject->mFrame = nullptr;
f->SchedulePaint();
f->RemoveStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
f->Properties().Delete(LayerActivityProperty());
}
static LayerActivity*
GetLayerActivity(nsIFrame* aFrame)
{
if (!aFrame->HasAnyStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY)) {
return nullptr;
}
FrameProperties properties = aFrame->Properties();
return static_cast<LayerActivity*>(properties.Get(LayerActivityProperty()));
}
@ -113,17 +126,34 @@ GetLayerActivityForUpdate(nsIFrame* aFrame)
}
layerActivity = new LayerActivity(aFrame);
gLayerActivityTracker->AddObject(layerActivity);
aFrame->AddStateBits(NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY);
properties.Set(LayerActivityProperty(), layerActivity);
}
return layerActivity;
}
static void
IncrementMutationCount(uint8_t* aCount)
{
*aCount = uint8_t(std::min(0xFF, *aCount + 1));
}
/* static */ void
ActiveLayerTracker::NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty)
{
LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
uint8_t& mutationCount = layerActivity->RestyleCountForProperty(aProperty);
mutationCount = uint8_t(std::min(0xFF, mutationCount + 1));
IncrementMutationCount(&mutationCount);
}
/* static */ void
ActiveLayerTracker::NotifyOffsetRestyle(nsIFrame* aFrame)
{
LayerActivity* layerActivity = GetLayerActivityForUpdate(aFrame);
IncrementMutationCount(&layerActivity->mLeftRestyleCount);
IncrementMutationCount(&layerActivity->mTopRestyleCount);
IncrementMutationCount(&layerActivity->mRightRestyleCount);
IncrementMutationCount(&layerActivity->mBottomRestyleCount);
}
/* static */ void
@ -172,6 +202,21 @@ ActiveLayerTracker::IsStyleAnimated(nsIFrame* aFrame, nsCSSProperty aProperty)
return false;
}
/* static */ bool
ActiveLayerTracker::IsOffsetStyleAnimated(nsIFrame* aFrame)
{
LayerActivity* layerActivity = GetLayerActivity(aFrame);
if (layerActivity) {
if (layerActivity->mLeftRestyleCount >= 2 ||
layerActivity->mTopRestyleCount >= 2 ||
layerActivity->mRightRestyleCount >= 2 ||
layerActivity->mBottomRestyleCount >= 2) {
return true;
}
}
return false;
}
/* static */ void
ActiveLayerTracker::NotifyContentChange(nsIFrame* aFrame)
{

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

@ -22,7 +22,10 @@ public:
static void Shutdown();
/*
* We track eCSSProperty_transform and eCSSProperty_opacity style changes
* We track style changes to selected styles:
* eCSSProperty_transform
* eCSSProperty_opacity
* eCSSProperty_left, eCSSProperty_top, eCSSProperty_right, eCSSProperty_bottom
* and use that information to guess whether style changes are animated.
*/
@ -33,6 +36,12 @@ public:
* @param aProperty the property that has changed
*/
static void NotifyRestyle(nsIFrame* aFrame, nsCSSProperty aProperty);
/**
* Notify aFrame's left/top/right/bottom properties as having (maybe)
* changed due to a restyle, and therefore possibly wanting an active layer
* to render that style. Any such marking will time out after a short period.
*/
static void NotifyOffsetRestyle(nsIFrame* aFrame);
/**
* Mark aFrame as being known to have an animation of aProperty.
* Any such marking will time out after a short period.
@ -50,6 +59,11 @@ public:
* for constructing active layers.
*/
static bool IsStyleAnimated(nsIFrame* aFrame, nsCSSProperty aProperty);
/**
* Return true if any of aFrame's offset property styles should be considered
* as being animated for constructing active layers.
*/
static bool IsOffsetStyleAnimated(nsIFrame* aFrame);
/*
* We track modifications to the content of certain frames (i.e. canvas frames)

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

@ -693,6 +693,7 @@ RestyleManager::ProcessRestyledFrames(nsStyleChangeList& aChangeList)
ApplyRenderingChangeToTree(mPresContext, frame, hint);
}
if ((hint & nsChangeHint_RecomputePosition) && !didReflowThisFrame) {
ActiveLayerTracker::NotifyOffsetRestyle(frame);
// It is possible for this to fall back to a reflow
if (!RecomputePosition(frame)) {
didReflowThisFrame = true;

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

@ -71,6 +71,7 @@
#include "nsIFrameInlines.h"
#include "ImageContainer.h"
#include "nsComputedDOMStyle.h"
#include "ActiveLayerTracker.h"
#include "mozilla/Preferences.h"
@ -1206,6 +1207,8 @@ nsLayoutUtils::GetActiveScrolledRootFor(nsIFrame* aFrame,
while (f != aStopAtAncestor) {
if (IsPopup(f))
break;
if (ActiveLayerTracker::IsOffsetStyleAnimated(f))
break;
nsIFrame* parent = GetCrossDocParentFrame(f);
if (!parent)
break;

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

@ -327,6 +327,9 @@ typedef uint64_t nsFrameState;
// <defs> element or an SVG resource element (<mask>, <pattern>, etc.)
#define NS_FRAME_IS_NONDISPLAY NS_FRAME_STATE_BIT(53)
// Frame has a LayerActivityProperty property
#define NS_FRAME_HAS_LAYER_ACTIVITY_PROPERTY NS_FRAME_STATE_BIT(54)
// Box layout bits
#define NS_STATE_IS_HORIZONTAL NS_FRAME_STATE_BIT(22)
#define NS_STATE_IS_DIRECTION_NORMAL NS_FRAME_STATE_BIT(31)

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

@ -1,5 +1,5 @@
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-right-bottom.html move-right-bottom-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,20) == move-top-left.html move-top-left-ref.html # Bug 688545, bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,80) == move-right-bottom.html move-right-bottom-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,80) == move-top-left.html move-top-left-ref.html # Bug 688545, bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,80) == move-right-bottom-table.html move-right-bottom-table-ref.html # Bug 742176
random-if(cocoaWidget) fuzzy-if(d2d,85,80) == move-top-left-table.html move-top-left-table-ref.html # Bug 688545, bug 742176
== percent.html percent-ref.html

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

@ -178,7 +178,9 @@ nsDOMCSSAttributeDeclaration::SetPropertyValue(const nsCSSProperty aPropID,
// Scripted modifications to style.opacity or style.transform
// could immediately force us into the animated state if heuristics suggest
// this is scripted animation.
if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform) {
if (aPropID == eCSSProperty_opacity || aPropID == eCSSProperty_transform ||
aPropID == eCSSProperty_left || aPropID == eCSSProperty_top ||
aPropID == eCSSProperty_right || aPropID == eCSSProperty_bottom) {
nsIFrame* frame = mElement->GetPrimaryFrame();
if (frame) {
ActiveLayerTracker::NotifyInlineStyleRuleModified(frame, aPropID);