Bug 1022612. Part 4: Track current dirty rect in nsDisplayListBuilder. r=mattwoodrow

We need this to set the initial visible rect during display list construction.
Eventually we'll also be able to get rid of the dirty rect parameter to
nsIFrame::BuildDisplayList.

--HG--
extra : rebase_source : d846866a6128bb96903e45e6bd08ef67033bf701
This commit is contained in:
Robert O'Callahan 2014-05-20 15:59:14 +12:00
Родитель 763ac99e28
Коммит 01c0570dad
3 изменённых файлов: 45 добавлений и 23 удалений

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

@ -494,7 +494,7 @@ nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame,
mFinalTransparentRegion(nullptr),
mCurrentFrame(aReferenceFrame),
mCurrentReferenceFrame(aReferenceFrame),
mCurrentOffsetToReferenceFrame(0, 0),
mDirtyRect(-1,-1,-1,-1),
mGlassDisplayItem(nullptr),
mMode(aMode),
mCurrentScrollParentId(FrameMetrics::NULL_SCROLL_ID),
@ -887,11 +887,11 @@ void
nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
const nsRect& aDirtyRect) {
PresShellState* state = mPresShellStates.AppendElement();
if (!state)
return;
state->mPresShell = aReferenceFrame->PresContext()->PresShell();
state->mCaretFrame = nullptr;
state->mFirstFrameMarkedForDisplay = mFramesMarkedForDisplay.Length();
state->mPrevDirtyRect = mDirtyRect;
mDirtyRect = aDirtyRect;
state->mPresShell->UpdateCanvasBackground();
@ -935,12 +935,10 @@ nsDisplayListBuilder::EnterPresShell(nsIFrame* aReferenceFrame,
void
nsDisplayListBuilder::LeavePresShell(nsIFrame* aReferenceFrame,
const nsRect& aDirtyRect) {
if (CurrentPresShellState()->mPresShell != aReferenceFrame->PresContext()->PresShell()) {
// Must have not allocated a state for this presshell, presumably due
// to OOM.
return;
}
NS_ASSERTION(CurrentPresShellState()->mPresShell ==
aReferenceFrame->PresContext()->PresShell(),
"Presshell mismatch");
mDirtyRect = CurrentPresShellState()->mPrevDirtyRect;
ResetMarkedFramesForDisplayList();
mPresShellStates.SetLength(mPresShellStates.Length() - 1);
}

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

@ -313,6 +313,14 @@ public:
void SetDescendIntoSubdocuments(bool aDescend) { mDescendIntoSubdocuments = aDescend; }
bool GetDescendIntoSubdocuments() { return mDescendIntoSubdocuments; }
/**
* Get dirty rect relative to current frame (the frame that we're calling
* BuildDisplayList on right now).
*/
const nsRect& GetDirtyRect() { return mDirtyRect; }
const nsIFrame* GetCurrentFrame() { return mCurrentFrame; }
const nsIFrame* GetCurrentReferenceFrame() { return mCurrentReferenceFrame; }
/**
* Returns true if merging and flattening of display lists should be
* performed while computing visibility.
@ -528,20 +536,22 @@ public:
/**
* A helper class to temporarily set the value of
* mIsAtRootOfPseudoStackingContext, and temporarily
* update mCachedOffsetFrame/mCachedOffset from a frame to its child.
* Also saves and restores mClipState.
* set mCurrentFrame and related state. Also temporarily sets mDirtyRect.
* aDirtyRect is relative to aForChild.
*/
class AutoBuildingDisplayList;
friend class AutoBuildingDisplayList;
class AutoBuildingDisplayList {
public:
AutoBuildingDisplayList(nsDisplayListBuilder* aBuilder,
nsIFrame* aForChild, bool aIsRoot)
nsIFrame* aForChild,
const nsRect& aDirtyRect, bool aIsRoot)
: mBuilder(aBuilder),
mPrevFrame(aBuilder->mCurrentFrame),
mPrevReferenceFrame(aBuilder->mCurrentReferenceFrame),
mPrevLayerEventRegions(aBuilder->mLayerEventRegions),
mPrevOffset(aBuilder->mCurrentOffsetToReferenceFrame),
mPrevDirtyRect(aBuilder->mDirtyRect),
mPrevIsAtRootOfPseudoStackingContext(aBuilder->mIsAtRootOfPseudoStackingContext),
mPrevAncestorHasTouchEventHandler(aBuilder->mAncestorHasTouchEventHandler)
{
@ -556,13 +566,18 @@ public:
&aBuilder->mCurrentOffsetToReferenceFrame);
}
aBuilder->mCurrentFrame = aForChild;
aBuilder->mDirtyRect = aDirtyRect;
aBuilder->mIsAtRootOfPseudoStackingContext = aIsRoot;
}
void SetDirtyRect(const nsRect& aRect) {
mBuilder->mDirtyRect = aRect;
}
~AutoBuildingDisplayList() {
mBuilder->mCurrentFrame = mPrevFrame;
mBuilder->mCurrentReferenceFrame = mPrevReferenceFrame;
mBuilder->mLayerEventRegions = mPrevLayerEventRegions;
mBuilder->mCurrentOffsetToReferenceFrame = mPrevOffset;
mBuilder->mDirtyRect = mPrevDirtyRect;
mBuilder->mIsAtRootOfPseudoStackingContext = mPrevIsAtRootOfPseudoStackingContext;
mBuilder->mAncestorHasTouchEventHandler = mPrevAncestorHasTouchEventHandler;
}
@ -572,6 +587,7 @@ public:
const nsIFrame* mPrevReferenceFrame;
nsDisplayLayerEventRegions* mPrevLayerEventRegions;
nsPoint mPrevOffset;
nsRect mPrevDirtyRect;
bool mPrevIsAtRootOfPseudoStackingContext;
bool mPrevAncestorHasTouchEventHandler;
};
@ -736,6 +752,7 @@ private:
struct PresShellState {
nsIPresShell* mPresShell;
nsIFrame* mCaretFrame;
nsRect mPrevDirtyRect;
uint32_t mFirstFrameMarkedForDisplay;
bool mIsBackgroundOnly;
};
@ -763,6 +780,8 @@ private:
const nsIFrame* mCurrentReferenceFrame;
// The offset from mCurrentFrame to mCurrentReferenceFrame.
nsPoint mCurrentOffsetToReferenceFrame;
// Relative to mCurrentFrame.
nsRect mDirtyRect;
nsRegion mExcludedGlassRegion;
// The display item for the Windows window glass background, if any
nsDisplayItem* mGlassDisplayItem;

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

@ -1907,6 +1907,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
AutoSaveRestoreBlendMode autoRestoreBlendMode(*aBuilder);
aBuilder->SetContainsBlendModes(BlendModeSet());
nsPoint offsetToReferenceFrame = aBuilder->ToReferenceFrame(this);
if (isTransformed) {
const nsRect overflow = GetVisualOverflowRectRelativeToSelf();
if (aBuilder->IsForPainting() &&
@ -1917,11 +1919,10 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
return;
}
nsPoint offset = aBuilder->ToReferenceFrame(this);
dirtyRect += offset;
dirtyRect += offsetToReferenceFrame;
nsRect untransformedDirtyRect;
if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this, offset, &untransformedDirtyRect)) {
if (nsDisplayTransform::UntransformRect(dirtyRect, overflow, this,
offsetToReferenceFrame, &untransformedDirtyRect)) {
dirtyRect = untransformedDirtyRect;
} else {
NS_WARNING("Unable to untransform dirty rect!");
@ -1940,6 +1941,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
nsLayoutUtils::SCROLLABLE_SAME_DOC |
nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
nsDisplayListBuilder::AutoBuildingDisplayList
buildingDisplayList(aBuilder, this, dirtyRect, true);
DisplayListClipState::AutoSaveRestore clipState(aBuilder);
if (isTransformed || useOpacity || useBlendMode || usingSVGEffects || useStickyPosition) {
@ -1952,8 +1955,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
}
nsDisplayListCollection set;
{
nsDisplayListBuilder::AutoBuildingDisplayList rootSetter(aBuilder, this, true);
{
DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
nsDisplayListBuilder::AutoInTransformSetter
inTransformSetter(aBuilder, inTransform);
@ -1994,7 +1996,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
set.PositionedDescendants()->DeleteAll();
set.Outlines()->DeleteAll();
}
// This z-order sort also sorts secondarily by content order. We need to do
// this so that boxes produced by the same element are placed together
// in the sort. Consider a position:relative inline element that breaks
@ -2002,7 +2004,7 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
// children should be z-ordered after all the boxes for the position:relative
// element itself.
set.PositionedDescendants()->SortByZOrder(aBuilder, GetContent());
nsDisplayList resultList;
// Now follow the rules of http://www.w3.org/TR/CSS21/zindex.html
// 1,2: backgrounds and borders
@ -2072,8 +2074,8 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
new (aBuilder) nsDisplayStickyPosition(aBuilder, this, &resultList));
}
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
/* If we're going to apply a transformation and don't have preserve-3d set, wrap
* everything in an nsDisplayTransform. If there's nothing in the list, don't add
* anything.
*
* For the preserve-3d case we want to individually wrap every child in the list with
@ -2086,6 +2088,9 @@ nsIFrame::BuildDisplayListForStackingContext(nsDisplayListBuilder* aBuilder,
if (isTransformed && !resultList.IsEmpty()) {
// Restore clip state now so nsDisplayTransform is clipped properly.
clipState.Restore();
// Revert to the dirtyrect coming in from the parent, without our transform
// taken into account.
buildingDisplayList.SetDirtyRect(aDirtyRect + offsetToReferenceFrame);
if (Preserves3DChildren()) {
WrapPreserve3DList(this, aBuilder, &resultList);
@ -2293,7 +2298,7 @@ nsIFrame::BuildDisplayListForChild(nsDisplayListBuilder* aBuilder,
buildingInFixedPos(aBuilder, isInFixedPos);
nsDisplayListBuilder::AutoBuildingDisplayList
buildingForChild(aBuilder, child, pseudoStackingContext);
buildingForChild(aBuilder, child, dirty, pseudoStackingContext);
DisplayListClipState::AutoClipMultiple clipState(aBuilder);
CheckForTouchEventHandler(aBuilder, child);