Bug 618975 Followup: bitrot and remove mDisplayport from nsDisplayScrollLayer r=cjones r=tn a=blocking-fennec

This commit is contained in:
Benjamin Stover 2011-03-09 13:35:27 -08:00
Родитель 1a0ae63ebf
Коммит 30e537ff1a
7 изменённых файлов: 117 добавлений и 114 удалений

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

@ -315,31 +315,27 @@ nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
if (rootScrollFrame) {
if (content == rootScrollFrame->GetContent()) {
// We are setting the root displayport. The pres context needs a special
// flag to be set.
// We are setting a root displayport for a document.
// The pres shell needs a special flag set.
presShell->SetIgnoreViewportScrolling(PR_TRUE);
// The root document currently has a widget, but we might end up
// painting content inside the displayport but outside the widget
// bounds. This ensures the document's view honors invalidations
// within the displayport.
nsPresContext* presContext = GetPresContext();
if (presContext && presContext->IsRoot()) {
nsIFrame* rootFrame = presShell->GetRootFrame();
nsIView* view = rootFrame->GetView();
if (view) {
view->SetInvalidationDimensions(&displayport);
}
}
}
}
// FIXME (Bug 593243 should fix this.)
//
// Invalidated content does not pay any attention to the displayport, so
// invalidating the subdocument's root frame could end up not repainting
// visible content.
//
// For instance, imagine the iframe is located at y=1000. Even though the
// displayport may intersect the iframe's viewport, the visual overflow
// rect of the root content could be (0, 0, 800, 500). Since the dirty region
// does not intersect the visible overflow rect, the display list for the
// iframe will not even be generated.
//
// Here, we find the very top presShell and use its root frame for
// invalidation instead.
//
nsPresContext* rootPresContext = GetPresContext()->GetRootPresContext();
if (rootPresContext) {
nsIPresShell* rootPresShell = rootPresContext->GetPresShell();
nsIFrame* rootFrame = rootPresShell->FrameManager()->GetRootFrame();
if (presShell) {
nsIFrame* rootFrame = presShell->FrameManager()->GetRootFrame();
if (rootFrame) {
rootFrame->InvalidateWithFlags(rootFrame->GetVisualOverflowRectRelativeToSelf(),
nsIFrame::INVALIDATE_NO_THEBES_LAYERS);

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

@ -153,7 +153,7 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
ContainerLayer* aRoot,
nsRect aVisibleRect,
nsRect aViewport,
nsRect aDisplayPort,
nsRect* aDisplayPort,
ViewID aScrollId) {
nsPresContext* presContext = aForFrame->PresContext();
@ -164,11 +164,11 @@ static void RecordFrameMetrics(nsIFrame* aForFrame,
PRInt32 auPerDevPixel = presContext->AppUnitsPerDevPixel();
metrics.mViewport = aViewport.ToNearestPixels(auPerDevPixel);
if (aViewport != aDisplayPort) {
metrics.mDisplayPort = aDisplayPort.ToNearestPixels(auPerDevPixel);
if (aDisplayPort) {
metrics.mDisplayPort = aDisplayPort->ToNearestPixels(auPerDevPixel);
}
nsIScrollableFrame* scrollableFrame = NULL;
nsIScrollableFrame* scrollableFrame = nsnull;
if (aViewportFrame)
scrollableFrame = aViewportFrame->GetScrollTargetFrame();
@ -525,17 +525,17 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder,
: FrameMetrics::NULL_SCROLL_ID;
nsIFrame* rootScrollFrame = presShell->GetRootScrollFrame();
nsRect visibleRect = mVisibleRect;
nsRect displayport;
bool usingDisplayport = false;
if (rootScrollFrame) {
nsIContent* content = rootScrollFrame->GetContent();
if (content) {
// If there is a displayport defined for the root content element,
// it will be stored in visibleRect.
nsLayoutUtils::GetDisplayPort(content, &visibleRect);
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
}
}
RecordFrameMetrics(aForFrame, presShell->GetRootScrollFrame(),
root, mVisibleRect, mVisibleRect, visibleRect, id);
RecordFrameMetrics(aForFrame, rootScrollFrame,
root, mVisibleRect, mVisibleRect,
(usingDisplayport ? &displayport : nsnull), id);
// If the layer manager supports resolution scaling, set that up
if (LayerManager::LAYERS_BASIC == layerManager->GetBackendType()) {
@ -1706,11 +1706,9 @@ nsDisplayOwnLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
nsDisplayScrollLayer::nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder,
nsDisplayList* aList,
nsIFrame* aForFrame,
nsIFrame* aViewportFrame,
const nsRect& aDisplayPort)
nsIFrame* aViewportFrame)
: nsDisplayOwnLayer(aBuilder, aForFrame, aList)
, mViewportFrame(aViewportFrame)
, mDisplayPort(aDisplayPort)
{
#ifdef NS_BUILD_REFCNT_LOGGING
MOZ_COUNT_CTOR(nsDisplayScrollLayer);
@ -1735,8 +1733,13 @@ nsDisplayScrollLayer::BuildLayer(nsDisplayListBuilder* aBuilder,
mViewportFrame->GetPosition() +
aBuilder->ToReferenceFrame(mViewportFrame);
bool usingDisplayport = false;
nsRect displayport;
if (content) {
usingDisplayport = nsLayoutUtils::GetDisplayPort(content, &displayport);
}
RecordFrameMetrics(mFrame, mViewportFrame, layer, mVisibleRect, viewport,
mDisplayPort, scrollId);
(usingDisplayport ? &displayport : nsnull), scrollId);
return layer.forget();
}
@ -1748,17 +1751,13 @@ nsDisplayScrollLayer::ComputeVisibility(nsDisplayListBuilder* aBuilder,
PRBool& aContainsRootContentDocBG)
{
nsPresContext* presContext = mFrame->PresContext();
nsRect viewport = mViewportFrame->GetRect() -
mViewportFrame->GetPosition() +
aBuilder->ToReferenceFrame(mViewportFrame);
if (mDisplayPort != viewport) {
nsRect displayport;
if (nsLayoutUtils::GetDisplayPort(mFrame->GetContent(), &displayport)) {
// The visible region for the children may be much bigger than the hole we
// are viewing the children from, so that the compositor process has enough
// content to asynchronously pan while content is being refreshed.
nsRegion childVisibleRegion = mDisplayPort + aBuilder->ToReferenceFrame(mViewportFrame);
nsRegion childVisibleRegion = displayport + aBuilder->ToReferenceFrame(mViewportFrame);
nsRect boundedRect;
boundedRect.IntersectRect(childVisibleRegion.GetBounds(), mList.GetBounds(aBuilder));

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

@ -1790,12 +1790,9 @@ public:
* @param aForFrame This will determine what the displayport is. It should be
* the root content frame of the scrolled area.
* @param aViewportFrame The viewport frame you see this content through.
* @param aDisplayPort Overrides the visibility of the child items if it
* is not equal to the visible area.
*/
nsDisplayScrollLayer(nsDisplayListBuilder* aBuilder, nsDisplayList* aList,
nsIFrame* aForFrame, nsIFrame* aViewportFrame,
const nsRect& aDisplayPort);
nsIFrame* aForFrame, nsIFrame* aViewportFrame);
NS_DISPLAY_DECL_NAME("ScrollLayer", TYPE_SCROLL_LAYER)
#ifdef NS_BUILD_REFCNT_LOGGING
@ -1819,7 +1816,6 @@ public:
}
private:
nsIFrame* mViewportFrame;
nsRect mDisplayPort;
};
#endif

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

@ -6046,11 +6046,6 @@ void PresShell::SetRenderingState(const RenderingState& aState)
mRenderFlags = aState.mRenderFlags;
mXResolution = aState.mXResolution;
mYResolution = aState.mYResolution;
nsIView* rootView;
if (NS_SUCCEEDED(mViewManager->GetRootView(rootView)) && rootView) {
rootView->SetInvalidationDimensions(&mDisplayPort);
}
}
void PresShell::SynthesizeMouseMove(PRBool aFromScroll)

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

@ -195,12 +195,14 @@ nsHTMLScrollFrame::InvalidateInternal(const nsRect& aDamageRect,
nsRect damage = aDamageRect + nsPoint(aX, aY);
// This is the damage rect that we're going to pass up to our parent.
nsRect parentDamage;
nsIPresShell* presShell = PresContext()->PresShell();
// If we're using a displayport, we might be displaying an area
// different than our scroll port and the damage needs to be
// clipped to that instead.
if (mInner.mIsRoot && presShell->UsingDisplayPort()) {
parentDamage.IntersectRect(damage, presShell->GetDisplayPort());
nsRect displayport;
PRBool usingDisplayport = nsLayoutUtils::GetDisplayPort(GetContent(),
&displayport);
if (usingDisplayport) {
parentDamage.IntersectRect(damage, displayport);
} else {
parentDamage.IntersectRect(damage, mInner.mScrollPort);
}
@ -1112,12 +1114,14 @@ nsXULScrollFrame::InvalidateInternal(const nsRect& aDamageRect,
nsRect damage = aDamageRect + nsPoint(aX, aY);
// This is the damage rect that we're going to pass up to our parent.
nsRect parentDamage;
nsIPresShell* presShell = PresContext()->PresShell();
// If we're using a displayport, we might be displaying an area
// different than our scroll port and the damage needs to be
// clipped to that instead.
if (mInner.mIsRoot && presShell->UsingDisplayPort()) {
parentDamage.IntersectRect(damage, presShell->GetDisplayPort());
nsRect displayport;
PRBool usingDisplayport = nsLayoutUtils::GetDisplayPort(GetContent(),
&displayport);
if (usingDisplayport) {
parentDamage.IntersectRect(damage, displayport);
} else {
parentDamage.IntersectRect(damage, mInner.mScrollPort);
}
@ -1370,33 +1374,36 @@ static ScrollFrameActivityTracker *gScrollFrameActivityTracker = nsnull;
nsGfxScrollFrameInner::nsGfxScrollFrameInner(nsContainerFrame* aOuter,
PRBool aIsRoot)
: mHScrollbarBox(nsnull),
mVScrollbarBox(nsnull),
mScrolledFrame(nsnull),
mScrollCornerBox(nsnull),
mResizerBox(nsnull),
mOuter(aOuter),
mAsyncScroll(nsnull),
mDestination(0, 0),
mScrollPosAtLastPaint(0, 0),
mRestorePos(-1, -1),
mLastPos(-1, -1),
mNeverHasVerticalScrollbar(PR_FALSE),
mNeverHasHorizontalScrollbar(PR_FALSE),
mHasVerticalScrollbar(PR_FALSE),
mHasHorizontalScrollbar(PR_FALSE),
mFrameIsUpdatingScrollbar(PR_FALSE),
mDidHistoryRestore(PR_FALSE),
mIsRoot(aIsRoot),
mSupppressScrollbarUpdate(PR_FALSE),
mSkippedScrollbarLayout(PR_FALSE),
mHadNonInitialReflow(PR_FALSE),
mHorizontalOverflow(PR_FALSE),
mVerticalOverflow(PR_FALSE),
mPostedReflowCallback(PR_FALSE),
mMayHaveDirtyFixedChildren(PR_FALSE),
mUpdateScrollbarAttributes(PR_FALSE),
mCollapsedResizer(PR_FALSE)
: mHScrollbarBox(nsnull)
, mVScrollbarBox(nsnull)
, mScrolledFrame(nsnull)
, mScrollCornerBox(nsnull)
, mResizerBox(nsnull)
, mOuter(aOuter)
, mAsyncScroll(nsnull)
, mDestination(0, 0)
, mScrollPosAtLastPaint(0, 0)
, mRestorePos(-1, -1)
, mLastPos(-1, -1)
, mNeverHasVerticalScrollbar(PR_FALSE)
, mNeverHasHorizontalScrollbar(PR_FALSE)
, mHasVerticalScrollbar(PR_FALSE)
, mHasHorizontalScrollbar(PR_FALSE)
, mFrameIsUpdatingScrollbar(PR_FALSE)
, mDidHistoryRestore(PR_FALSE)
, mIsRoot(aIsRoot)
, mSupppressScrollbarUpdate(PR_FALSE)
, mSkippedScrollbarLayout(PR_FALSE)
, mHadNonInitialReflow(PR_FALSE)
, mHorizontalOverflow(PR_FALSE)
, mVerticalOverflow(PR_FALSE)
, mPostedReflowCallback(PR_FALSE)
, mMayHaveDirtyFixedChildren(PR_FALSE)
, mUpdateScrollbarAttributes(PR_FALSE)
, mCollapsedResizer(PR_FALSE)
#ifdef MOZ_IPC
, mShouldBuildLayer(PR_FALSE)
#endif
{
// lookup if we're allowed to overlap the content from the look&feel object
PRBool canOverlap;
@ -1710,7 +1717,13 @@ void nsGfxScrollFrameInner::ScrollVisual()
if (canScrollWithBlitting) {
MarkActive();
}
mOuter->InvalidateWithFlags(mScrollPort, flags);
nsRect invalidateRect, displayport;
invalidateRect =
(nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &displayport)) ?
displayport : mScrollPort;
mOuter->InvalidateWithFlags(invalidateRect, flags);
if (flags & nsIFrame::INVALIDATE_NO_THEBES_LAYERS) {
nsIFrame* displayRoot = nsLayoutUtils::GetDisplayRootFrame(mOuter);
@ -1835,6 +1848,16 @@ nsGfxScrollFrameInner::AppendScrollPartsTo(nsDisplayListBuilder* aBuild
return rv;
}
PRBool
nsGfxScrollFrameInner::ShouldBuildLayer() const
{
#ifdef MOZ_IPC
return mShouldBuildLayer;
#else
return PR_FALSE;
#endif
}
nsresult
nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
@ -1879,13 +1902,6 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
scrollParts, createLayersForScrollbars);
}
nsRect displayport;
PRBool usingDisplayPort = nsLayoutUtils::GetDisplayPort(mOuter->GetContent(),
&displayport);
if (!usingDisplayPort) {
displayport = mScrollPort;
}
// Overflow clipping can never clip frames outside our subtree, so there
// is no need to worry about whether we are a moving frame that might clip
// non-moving frames.
@ -1897,14 +1913,12 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// dirty rect here.
dirtyRect.IntersectRect(aDirtyRect, mScrollPort);
if (usingDisplayPort) {
dirtyRect = displayport;
}
// Override the dirty rectangle if the displayport has been set.
nsLayoutUtils::GetDisplayPort(mOuter->GetContent(), &dirtyRect);
nsDisplayListCollection set;
nsPresContext* presContext = mOuter->PresContext();
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
#ifdef MOZ_IPC
// Since making new layers is expensive, only use nsDisplayScrollLayer
@ -1916,34 +1930,25 @@ nsGfxScrollFrameInner::BuildDisplayList(nsDisplayListBuilder* aBuilder,
// range of 20 pixels to eliminate many gfx scroll frames from becoming a
// layer.
//
PRInt32 appUnitsPerDevPixel = presContext->AppUnitsPerDevPixel();
nsRect scrollRange = GetScrollRange();
PRBool buildingLayer =
mShouldBuildLayer =
(XRE_GetProcessType() == GeckoProcessType_Content &&
(scrollRange.width >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel) ||
scrollRange.height >= NSIntPixelsToAppUnits(20, appUnitsPerDevPixel))) &&
(!mIsRoot || !mOuter->PresContext()->IsRootContentDocument());
#else
PRBool buildingLayer = false;
#endif
if (buildingLayer) {
if (ShouldBuildLayer()) {
// Note that using StackingContext breaks z order, so the resulting
// rendering can be incorrect for weird edge cases!
nsDisplayList list;
rv = mScrolledFrame->BuildDisplayListForStackingContext(
aBuilder,
dirtyRect + mOuter->GetOffsetTo(mScrolledFrame),
set.Content()
);
aBuilder, dirtyRect + mOuter->GetOffsetTo(mScrolledFrame), &list);
nsDisplayScrollLayer* layerItem = new (aBuilder) nsDisplayScrollLayer(
aBuilder,
set.Content(),
mScrolledFrame,
mOuter,
displayport
);
aBuilder, &list, mScrolledFrame, mOuter);
set.Content()->AppendNewToTop(layerItem);
} else {
rv = mOuter->BuildDisplayListForChild(aBuilder, mScrolledFrame, dirtyRect, set);

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

@ -87,6 +87,8 @@ public:
void PostOverflowEvent();
void Destroy();
PRBool ShouldBuildLayer() const;
nsresult BuildDisplayList(nsDisplayListBuilder* aBuilder,
const nsRect& aDirtyRect,
const nsDisplayListSet& aLists);
@ -237,7 +239,7 @@ public:
nsMargin GetDesiredScrollbarSizes(nsBoxLayoutState* aState);
PRBool IsLTR() const;
PRBool IsScrollbarOnRight() const;
PRBool IsScrollingActive() const { return mScrollingActive; }
PRBool IsScrollingActive() const { return mScrollingActive || ShouldBuildLayer(); }
// adjust the scrollbar rectangle aRect to account for any visible resizer.
// aHasResizer specifies if there is a content resizer, however this method
// will also check if a widget resizer is present as well.
@ -320,6 +322,12 @@ public:
PRPackedBool mScrollbarsCanOverlapContent:1;
// If true, the resizer is collapsed and not displayed
PRPackedBool mCollapsedResizer:1;
#ifdef MOZ_IPC
// If true, the layer should always be active because we always build a layer.
// Used for asynchronous scrolling.
PRPackedBool mShouldBuildLayer:1;
#endif
};
/**

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

@ -181,7 +181,11 @@ ComputeShadowTreeTransform(nsIFrame* aContainerFrame,
aConfig.mScrollOffset.ToNearestPixels(auPerDevPixel);
nsIntPoint metricsScrollOffset = aMetrics->mViewportScrollOffset;
if (aRootFrameLoader->AsyncScrollEnabled()) {
if (aRootFrameLoader->AsyncScrollEnabled() && !aMetrics->mDisplayPort.IsEmpty()) {
// Only use asynchronous scrolling if it is enabled and there is a
// displayport defined. It is useful to have a scroll layer that is
// synchronously scrolled for identifying a scroll area before it is
// being actively scrolled.
nsIntPoint scrollCompensation(
scrollOffset.x * aInverseScaleX - metricsScrollOffset.x * aConfig.mXScale,
scrollOffset.y * aInverseScaleY - metricsScrollOffset.y * aConfig.mYScale);