diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 4559c42d5f1..a5b2187a65a 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1239,6 +1239,11 @@ public: * root pres shell. */ virtual void DidPaint() = 0; + + /** + * Ensures that the refresh driver is running, and schedules a view + * manager flush on the next tick. + */ virtual void ScheduleViewManagerFlush() = 0; virtual void ClearMouseCaptureOnView(nsIView* aView) = 0; virtual bool IsVisible() = 0; diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 4101365b77e..8d2c7efa5f4 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -4005,8 +4005,11 @@ nsLayoutUtils::GetDisplayRootFrame(nsIFrame* aFrame) // NS_FRAME_IN_POPUP frame bit is set. nsIFrame* f = aFrame; for (;;) { - if (IsPopup(f)) + if (!f->HasAnyStateBits(NS_FRAME_IN_POPUP)) { + f = f->PresContext()->FrameManager()->GetRootFrame(); + } else if (IsPopup(f)) { return f; + } nsIFrame* parent = GetCrossDocParentFrame(f); if (!parent) return f; diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 3f8af98f258..7b70756e268 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -175,6 +175,7 @@ #include "mozilla/css/ImageLoader.h" #include "Layers.h" +#include "LayerTreeInvalidation.h" #include "nsAsyncDOMEvent.h" #define ANCHOR_SCROLL_FLAGS (SCROLL_OVERFLOW_HIDDEN | SCROLL_NO_PARENT_FRAMES) @@ -5235,17 +5236,43 @@ PresShell::Paint(nsIView* aViewToPaint, return; } NS_WARNING("Must complete empty transaction when compositing!"); - } else if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { - layerManager->BeginTransaction(); - if (layerManager->EndEmptyTransaction((aType == PaintType_NoComposite) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT)) { - frame->UpdatePaintCountForPaintedPresShells(); - presContext->NotifyDidPaintForSubtree(); - return; - } } else { layerManager->BeginTransaction(); } + if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { + NotifySubDocInvalidationFunc computeInvalidFunc = + presContext->MayHavePaintEventListenerInSubDocument() ? nsPresContext::NotifySubDocInvalidation : 0; + bool computeInvalidRect = computeInvalidFunc || + (layerManager->GetBackendType() == LAYERS_BASIC); + + nsAutoPtr props(computeInvalidRect ? + LayerProperties::CloneFrom(layerManager->GetRoot()) : + nullptr); + + if (layerManager->EndEmptyTransaction((aType == PaintType_NoComposite) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT)) { + nsIntRect invalid; + if (props) { + invalid = props->ComputeDifferences(layerManager->GetRoot(), computeInvalidFunc); + } + if (!invalid.IsEmpty()) { + if (props) { + nsRect rect(presContext->DevPixelsToAppUnits(invalid.x), + presContext->DevPixelsToAppUnits(invalid.y), + presContext->DevPixelsToAppUnits(invalid.width), + presContext->DevPixelsToAppUnits(invalid.height)); + aViewToPaint->GetViewManager()->InvalidateViewNoSuppression(aViewToPaint, rect); + presContext->NotifyInvalidation(invalid, 0); + } else { + aViewToPaint->GetViewManager()->InvalidateView(aViewToPaint); + } + } + + frame->UpdatePaintCountForPaintedPresShells(); + presContext->NotifyDidPaintForSubtree(); + return; + } + } frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE); } else { layerManager->BeginTransaction(); diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 23b4f0b963b..a353f5ff478 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -4808,18 +4808,21 @@ nsIFrame::IsInvalid() } void -nsIFrame::SchedulePaint() +nsIFrame::SchedulePaint(uint32_t aFlags) { - nsPresContext *pres = PresContext()->GetRootPresContext(); - if (HasAnyStateBits(NS_FRAME_IN_POPUP) || !pres) { - nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this); - NS_ASSERTION(displayRoot, "Need a display root to schedule a paint!"); - if (!displayRoot) { - return; - } - pres = displayRoot->PresContext(); + nsIFrame *displayRoot = nsLayoutUtils::GetDisplayRootFrame(this); + nsPresContext *pres = displayRoot->PresContext()->GetRootPresContext(); + + // No need to schedule a paint for an external document since they aren't + // painted directly. + if (!pres || (pres->Document() && pres->Document()->GetDisplayDocument())) { + return; } + pres->PresShell()->ScheduleViewManagerFlush(); + if (!(aFlags & PAINT_COMPOSITE_ONLY)) { + displayRoot->AddStateBits(NS_FRAME_UPDATE_LAYER_TREE); + } } Layer* @@ -4843,7 +4846,7 @@ nsIFrame::InvalidateLayer(uint32_t aDisplayItemKey, const nsIntRect* aDamageRect layer->SetInvalidRectToVisibleRegion(); } - SchedulePaint(); + SchedulePaint(PAINT_COMPOSITE_ONLY); return layer; } diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 882e2b52d70..2e409107f0c 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -2216,8 +2216,15 @@ public: * The view manager flush will update the layer tree, repaint any * invalid areas in the layer tree and schedule a layer tree * composite operation to display the layer tree. + * + * @param aFlags PAINT_COMPOSITE_ONLY : No changes have been made + * that require a layer tree update, so only schedule a layer + * tree composite. */ - void SchedulePaint(); + enum { + PAINT_COMPOSITE_ONLY + }; + void SchedulePaint(uint32_t aFlags = 0); /** * Checks if the layer tree includes a dedicated layer for this