author | Tatiana Meshkova <tanya.meshkova@gmail.com> |
Fri, 08 Apr 2011 09:35:16 -0700 | |
changeset 67670 | 288be41b247321bc01af7a584712f2eb5dcc91c9 |
parent 67669 | 48f385ad9f0cf30b7e9913d17c4ea59e891ce43d |
child 67671 | 0f077c086750bdf13fadb05f1efd08a0d18cbdcf |
push id | 19409 |
push user | romaxa@gmail.com |
push date | Fri, 08 Apr 2011 18:58:35 +0000 |
treeherder | mozilla-central@4f957dd3f9f7 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | roc |
bugs | 607417 |
milestone | 2.2a1pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -59,16 +59,17 @@ #include "nsLayoutUtils.h" #include "nsIScrollableFrame.h" #include "nsThemeConstants.h" #include "imgIContainer.h" #include "nsIInterfaceRequestorUtils.h" #include "BasicLayers.h" #include "nsBoxFrame.h" +#include "nsViewportFrame.h" using namespace mozilla; using namespace mozilla::layers; typedef FrameMetrics::ViewID ViewID; nsDisplayListBuilder::nsDisplayListBuilder(nsIFrame* aReferenceFrame, Mode aMode, PRBool aBuildCaret) : mReferenceFrame(aReferenceFrame), @@ -81,31 +82,41 @@ nsDisplayListBuilder::nsDisplayListBuild mHadToIgnoreSuppression(PR_FALSE), mIsAtRootOfPseudoStackingContext(PR_FALSE), mIncludeAllOutOfFlows(PR_FALSE), mSelectedFramesOnly(PR_FALSE), mAccurateVisibleRegions(PR_FALSE), mInTransform(PR_FALSE), mSyncDecodeImages(PR_FALSE), mIsPaintingToWindow(PR_FALSE), - mSnappingEnabled(PR_TRUE) { + mSnappingEnabled(PR_TRUE), + mHasDisplayPort(PR_FALSE), + mHasFixedItems(PR_FALSE) +{ MOZ_COUNT_CTOR(nsDisplayListBuilder); PL_InitArenaPool(&mPool, "displayListArena", 1024, NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1); nsPresContext* pc = aReferenceFrame->PresContext(); nsIPresShell *shell = pc->PresShell(); if (pc->IsRenderingOnlySelection()) { nsCOMPtr<nsISelectionController> selcon(do_QueryInterface(shell)); if (selcon) { selcon->GetSelection(nsISelectionController::SELECTION_NORMAL, getter_AddRefs(mBoundingSelection)); } } + if(mReferenceFrame->GetType() == nsGkAtoms::viewportFrame) { + ViewportFrame* viewportFrame = static_cast<ViewportFrame*>(mReferenceFrame); + if (!viewportFrame->GetChildList(nsGkAtoms::fixedList).IsEmpty()) { + mHasFixedItems = PR_TRUE; + } + } + LayerBuilder()->Init(this); PR_STATIC_ASSERT(nsDisplayItem::TYPE_MAX < (1 << nsDisplayItem::TYPE_BITS)); } static void MarkFrameForDisplay(nsIFrame* aFrame, nsIFrame* aStopAtFrame) { nsFrameManager* frameManager = aFrame->PresContext()->PresShell()->FrameManager(); @@ -116,20 +127,48 @@ static void MarkFrameForDisplay(nsIFrame f->AddStateBits(NS_FRAME_FORCE_DISPLAY_LIST_DESCEND_INTO); if (f == aStopAtFrame) { // we've reached a frame that we know will be painted, so we can stop. break; } } } -static void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, - const nsRect& aDirtyRect) { +static PRBool IsFixedFrame(nsIFrame* aFrame) +{ + return aFrame && aFrame->GetParent() && !aFrame->GetParent()->GetParent(); +} + +static PRBool IsFixedItem(nsDisplayItem *aItem, nsDisplayListBuilder* aBuilder) +{ + nsIFrame* activeScrolledRoot = + nsLayoutUtils::GetActiveScrolledRootFor(aItem, aBuilder); + return activeScrolledRoot && + !nsLayoutUtils::ScrolledByViewportScrolling(activeScrolledRoot, + aBuilder); +} + +static PRBool ForceVisiblityForFixedItem(nsDisplayListBuilder* aBuilder, + nsDisplayItem* aItem) +{ + return aBuilder->GetHasDisplayPort() && aBuilder->GetHasFixedItems() && + IsFixedItem(aItem, aBuilder); +} + +void nsDisplayListBuilder::MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, + nsIFrame* aFrame, + const nsRect& aDirtyRect) +{ nsRect dirty = aDirtyRect - aFrame->GetOffsetTo(aDirtyFrame); nsRect overflowRect = aFrame->GetVisualOverflowRect(); + + if (mHasDisplayPort && IsFixedFrame(aFrame)) { + dirty = overflowRect; + } + if (!dirty.IntersectRect(dirty, overflowRect)) return; aFrame->Properties().Set(nsDisplayListBuilder::OutOfFlowDirtyRectProperty(), new nsRect(dirty)); MarkFrameForDisplay(aFrame, aDirtyFrame); } @@ -425,16 +464,20 @@ nsDisplayList::ComputeVisibilityForSubli } nsRect bounds = item->GetBounds(aBuilder); nsRegion itemVisible; itemVisible.And(*aVisibleRegion, bounds); item->mVisibleRect = itemVisible.GetBounds(); + if (ForceVisiblityForFixedItem(aBuilder, item)) { + item->mVisibleRect = bounds; + } + PRBool containsRootContentDocBG = PR_FALSE; if (item->ComputeVisibility(aBuilder, aVisibleRegion, aAllowVisibleRegionExpansion, containsRootContentDocBG)) { if (containsRootContentDocBG) { aContainsRootContentDocBG = PR_TRUE; } anyVisible = PR_TRUE; PRBool transparentBackground = PR_FALSE; @@ -752,16 +795,20 @@ void nsDisplayList::Sort(nsDisplayListBu PRBool nsDisplayItem::RecomputeVisibility(nsDisplayListBuilder* aBuilder, nsRegion* aVisibleRegion) { nsRect bounds = GetBounds(aBuilder); nsRegion itemVisible; itemVisible.And(*aVisibleRegion, bounds); mVisibleRect = itemVisible.GetBounds(); + if (ForceVisiblityForFixedItem(aBuilder, this)) { + mVisibleRect = bounds; + } + // When we recompute visibility within layers we don't need to // expand the visible region for content behind plugins (the plugin // is not in the layer). PRBool notUsed; if (!ComputeVisibility(aBuilder, aVisibleRegion, nsRect(), notUsed)) return PR_FALSE; PRBool forceTransparentBackground; @@ -814,21 +861,30 @@ nsDisplayBackground::nsDisplayBackground nsIFrame* aFrame) : nsDisplayItem(aBuilder, aFrame), mSnappingEnabled(aBuilder->IsSnappingEnabled() && !aBuilder->IsInTransform()) { MOZ_COUNT_CTOR(nsDisplayBackground); const nsStyleDisplay* disp = mFrame->GetStyleDisplay(); mIsThemed = mFrame->IsThemed(disp, &mThemeTransparency); - // Perform necessary RegisterThemeGeometry - if (mIsThemed && - (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR || - disp->mAppearance == NS_THEME_TOOLBAR)) { - RegisterThemeGeometry(aBuilder, aFrame); + if (mIsThemed) { + // Perform necessary RegisterThemeGeometry + if (disp->mAppearance == NS_THEME_MOZ_MAC_UNIFIED_TOOLBAR || + disp->mAppearance == NS_THEME_TOOLBAR) { + RegisterThemeGeometry(aBuilder, aFrame); + } + } else { + // Set HasFixedItems if we construct a background-attachment:fixed item + nsPresContext* presContext = mFrame->PresContext(); + nsStyleContext* bgSC; + PRBool hasBG = nsCSSRendering::FindBackground(presContext, mFrame, &bgSC); + if (hasBG && bgSC->GetStyleBackground()->HasFixedBackground()) { + aBuilder->SetHasFixedItems(); + } } } // Helper for RoundedRectIntersectsRect. static PRBool CheckCorner(nscoord aXOffset, nscoord aYOffset, nscoord aXRadius, nscoord aYRadius) {
--- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -288,16 +288,30 @@ public: PRBool IsInTransform() { return mInTransform; } /** * Indicate whether or not we're directly or indirectly under and * nsDisplayTransform or SVG foreignObject. */ void SetInTransform(PRBool aInTransform) { mInTransform = aInTransform; } /** + * Call this if using display port for scrolling. + */ + void SetHasDisplayPort() { mHasDisplayPort = PR_TRUE; } + PRBool GetHasDisplayPort() { return mHasDisplayPort; } + + /** + * Call this if ReferenceFrame() is a viewport frame with fixed-position + * children, or when we construct an item which will return true from + * ShouldFixToViewport() + */ + void SetHasFixedItems() { mHasFixedItems = PR_TRUE; } + PRBool GetHasFixedItems() { return mHasFixedItems; } + + /** * Returns true if snapping is enabled for the final drawing context. * The default is true. */ PRBool IsSnappingEnabled() { return mSnappingEnabled; } /** * Set if snapping is enabled for the final drawing context. */ void SetSnappingEnabled(PRBool aSnappingEnabled) { mSnappingEnabled = aSnappingEnabled; } @@ -451,16 +465,19 @@ public: NS_DECLARE_FRAME_PROPERTY(OutOfFlowDirtyRectProperty, nsIFrame::DestroyRect) nsPresContext* CurrentPresContext() { return CurrentPresShellState()->mPresShell->GetPresContext(); } private: + void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame, + const nsRect& aDirtyRect); + struct PresShellState { nsIPresShell* mPresShell; nsIFrame* mCaretFrame; PRUint32 mFirstFrameMarkedForDisplay; PRPackedBool mIsBackgroundOnly; }; PresShellState* CurrentPresShellState() { NS_ASSERTION(mPresShellStates.Length() > 0, @@ -487,16 +504,18 @@ private: PRPackedBool mSelectedFramesOnly; PRPackedBool mAccurateVisibleRegions; // True when we're building a display list that's directly or indirectly // under an nsDisplayTransform PRPackedBool mInTransform; PRPackedBool mSyncDecodeImages; PRPackedBool mIsPaintingToWindow; PRPackedBool mSnappingEnabled; + PRPackedBool mHasDisplayPort; + PRPackedBool mHasFixedItems; }; class nsDisplayItem; class nsDisplayList; /** * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList. * nsDisplayItemLink holds the link. The lists are linked from lowest to * highest in z-order.
--- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1446,16 +1446,20 @@ nsLayoutUtils::PaintFrame(nsIRenderingCo // If we're going to display something different from what we'd normally // paint in a window then we will flush out any retained layer trees before // *and after* we draw. PRBool willFlushRetainedLayers = (aFlags & PAINT_HIDE_CARET) != 0; nsDisplayListBuilder builder(aFrame, nsDisplayListBuilder::PAINTING, !(aFlags & PAINT_HIDE_CARET)); + if (usingDisplayPort) { + builder.SetHasDisplayPort(); + } + nsDisplayList list; if (aFlags & PAINT_IN_TRANSFORM) { builder.SetInTransform(PR_TRUE); } if (aFlags & PAINT_SYNC_DECODE_IMAGES) { builder.SetSyncDecodeImages(PR_TRUE); } if (aFlags & (PAINT_WIDGET_LAYERS | PAINT_TO_WINDOW)) {