diff --git a/gfx/layers/Layers.h b/gfx/layers/Layers.h index 6436c118f09e..4eb26d16b5c4 100644 --- a/gfx/layers/Layers.h +++ b/gfx/layers/Layers.h @@ -309,6 +309,9 @@ public: void* aCallbackData, EndTransactionFlags aFlags = END_DEFAULT) = 0; + virtual bool HasShadowManagerInternal() const { return false; } + bool HasShadowManager() const { return HasShadowManagerInternal(); } + bool IsSnappingEffectiveTransforms() { return mSnapEffectiveTransforms; } /** diff --git a/gfx/layers/basic/BasicLayers.h b/gfx/layers/basic/BasicLayers.h index 84295eef17f6..3beb55e84978 100644 --- a/gfx/layers/basic/BasicLayers.h +++ b/gfx/layers/basic/BasicLayers.h @@ -148,8 +148,6 @@ public: void PopGroupToSourceWithCachedSurface(gfxContext *aTarget, gfxContext *aPushed); virtual bool IsCompositingCheap() { return false; } - virtual bool HasShadowManagerInternal() const { return false; } - bool HasShadowManager() const { return HasShadowManagerInternal(); } virtual PRInt32 GetMaxTextureSize() const { return PR_INT32_MAX; } protected: diff --git a/gfx/layers/d3d10/LayerManagerD3D10.cpp b/gfx/layers/d3d10/LayerManagerD3D10.cpp index c6ed7271bda6..14b7067b7a88 100644 --- a/gfx/layers/d3d10/LayerManagerD3D10.cpp +++ b/gfx/layers/d3d10/LayerManagerD3D10.cpp @@ -199,7 +199,7 @@ LayerManagerD3D10::Initialize(bool force) mInputLayout = attachments->mInputLayout; } - if (HasShadowManager()) { + if (LayerManager::HasShadowManager()) { reporter.SetSuccessful(); return true; } diff --git a/layout/base/nsDisplayList.cpp b/layout/base/nsDisplayList.cpp index 5748b59915f3..fc7eac16b94c 100644 --- a/layout/base/nsDisplayList.cpp +++ b/layout/base/nsDisplayList.cpp @@ -648,7 +648,7 @@ void nsDisplayList::PaintForFrame(nsDisplayListBuilder* aBuilder, layerManager->SetRoot(root); layerBuilder->WillEndTransaction(layerManager); layerManager->EndTransaction(FrameLayerBuilder::DrawThebesLayer, - aBuilder); + aBuilder, (aFlags & PAINT_NO_COMPOSITE) ? LayerManager::END_NO_COMPOSITE : LayerManager::END_DEFAULT); layerBuilder->DidEndTransaction(layerManager); if (aFlags & PAINT_FLUSH_LAYERS) { diff --git a/layout/base/nsDisplayList.h b/layout/base/nsDisplayList.h index 78944cf0b395..0bcbb366d121 100644 --- a/layout/base/nsDisplayList.h +++ b/layout/base/nsDisplayList.h @@ -25,6 +25,7 @@ #include "FrameLayerBuilder.h" #include "nsThemeConstants.h" #include "ImageLayers.h" +#include "nsLayoutUtils.h" #include "mozilla/StandardInteger.h" @@ -1155,7 +1156,8 @@ public: PAINT_DEFAULT = 0, PAINT_USE_WIDGET_LAYERS = 0x01, PAINT_FLUSH_LAYERS = 0x02, - PAINT_EXISTING_TRANSACTION = 0x04 + PAINT_EXISTING_TRANSACTION = 0x04, + PAINT_NO_COMPOSITE = 0x08 }; void PaintRoot(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx, PRUint32 aFlags) const; diff --git a/layout/base/nsIPresShell.h b/layout/base/nsIPresShell.h index 8aafe07ce1d3..0ab751b52f51 100644 --- a/layout/base/nsIPresShell.h +++ b/layout/base/nsIPresShell.h @@ -1208,9 +1208,12 @@ public: */ virtual void SynthesizeMouseMove(bool aFromScroll) = 0; - virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget, - const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion, - bool aWillSendDidPaint) = 0; + enum PaintType { + PaintType_Composite, + PaintType_NoComposite + }; + virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion, + PaintType aType, bool aWillSendDidPaint) = 0; virtual nsresult HandleEvent(nsIFrame* aFrame, nsGUIEvent* aEvent, bool aDontRetargetEvents, diff --git a/layout/base/nsLayoutUtils.cpp b/layout/base/nsLayoutUtils.cpp index 107db462cbac..0f8eaaff3864 100644 --- a/layout/base/nsLayoutUtils.cpp +++ b/layout/base/nsLayoutUtils.cpp @@ -1783,6 +1783,9 @@ nsLayoutUtils::PaintFrame(nsRenderingContext* aRenderingContext, nsIFrame* aFram if (aFlags & PAINT_EXISTING_TRANSACTION) { flags |= nsDisplayList::PAINT_EXISTING_TRANSACTION; } + if (aFlags & PAINT_NO_COMPOSITE) { + flags |= nsDisplayList::PAINT_NO_COMPOSITE; + } list.PaintRoot(&builder, aRenderingContext, flags); diff --git a/layout/base/nsLayoutUtils.h b/layout/base/nsLayoutUtils.h index 2f3ac071cbf0..10f4621fc900 100644 --- a/layout/base/nsLayoutUtils.h +++ b/layout/base/nsLayoutUtils.h @@ -596,7 +596,8 @@ public: PAINT_HIDE_CARET = 0x20, PAINT_ALL_CONTINUATIONS = 0x40, PAINT_TO_WINDOW = 0x80, - PAINT_EXISTING_TRANSACTION = 0x100 + PAINT_EXISTING_TRANSACTION = 0x100, + PAINT_NO_COMPOSITE = 0x200 }; /** diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index f1f1bab0a7fe..8cf8172f40cf 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5203,9 +5203,8 @@ private: void PresShell::Paint(nsIView* aViewToPaint, - nsIWidget* aWidgetToPaint, const nsRegion& aDirtyRegion, - const nsIntRegion& aIntDirtyRegion, + PaintType aType, bool aWillSendDidPaint) { #ifdef NS_FUNCTION_TIMER @@ -5222,7 +5221,6 @@ PresShell::Paint(nsIView* aViewToPaint, SAMPLE_LABEL("Paint", "PresShell::Paint"); NS_ASSERTION(!mIsDestroying, "painting a destroyed PresShell"); NS_ASSERTION(aViewToPaint, "null view"); - NS_ASSERTION(aWidgetToPaint, "Can't paint without a widget"); nsAutoNotifyDidPaint notifyDidPaint(aWillSendDidPaint); @@ -5233,14 +5231,13 @@ PresShell::Paint(nsIView* aViewToPaint, bool isRetainingManager; LayerManager* layerManager = - aWidgetToPaint->GetLayerManager(&isRetainingManager); + aViewToPaint->GetWidget()->GetLayerManager(&isRetainingManager); NS_ASSERTION(layerManager, "Must be in paint event"); if (mIsFirstPaint) { layerManager->SetIsFirstPaint(); mIsFirstPaint = false; } - layerManager->BeginTransaction(); if (frame && isRetainingManager) { // Try to do an empty transaction, if the frame tree does not @@ -5249,21 +5246,32 @@ PresShell::Paint(nsIView* aViewToPaint, // draws the window title bar on Mac), because a) it won't work // and b) below we don't want to clear NS_FRAME_UPDATE_LAYER_TREE, // that will cause us to forget to update the real layer manager! - if (!(frame->GetStateBits() & NS_FRAME_UPDATE_LAYER_TREE)) { - if (layerManager->EndEmptyTransaction()) { - frame->UpdatePaintCountForPaintedPresShells(); - presContext->NotifyDidPaintForSubtree(); + if (aType == PaintType_Composite) { + if (layerManager->HasShadowManager()) { return; } + layerManager->BeginTransaction(); + if (layerManager->EndEmptyTransaction()) { + return; + } + NS_WARNING("Must complete empty transaction when compositing!"); + } else { + layerManager->BeginTransaction(); } frame->RemoveStateBits(NS_FRAME_UPDATE_LAYER_TREE); + } else { + layerManager->BeginTransaction(); } if (frame) { frame->ClearPresShellsFromLastPaint(); } nscolor bgcolor = ComputeBackstopColor(aViewToPaint); + PRUint32 flags = nsLayoutUtils::PAINT_WIDGET_LAYERS | nsLayoutUtils::PAINT_EXISTING_TRANSACTION; + if (aType == PaintType_NoComposite) { + flags |= nsLayoutUtils::PAINT_NO_COMPOSITE; + } if (frame) { // Defer invalidates that are triggered during painting, and discard @@ -5273,12 +5281,12 @@ PresShell::Paint(nsIView* aViewToPaint, frame->BeginDeferringInvalidatesForDisplayRoot(aDirtyRegion); // We can paint directly into the widget using its layer manager. - nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor, - nsLayoutUtils::PAINT_WIDGET_LAYERS | - nsLayoutUtils::PAINT_EXISTING_TRANSACTION); + nsLayoutUtils::PaintFrame(nsnull, frame, aDirtyRegion, bgcolor, flags); frame->EndDeferringInvalidatesForDisplayRoot(); - presContext->NotifyDidPaintForSubtree(); + if (aType != PaintType_Composite) { + presContext->NotifyDidPaintForSubtree(); + } return; } @@ -5292,9 +5300,13 @@ PresShell::Paint(nsIView* aViewToPaint, root->SetVisibleRegion(bounds); layerManager->SetRoot(root); } - layerManager->EndTransaction(NULL, NULL); + layerManager->EndTransaction(NULL, NULL, aType == PaintType_NoComposite ? + LayerManager::END_NO_COMPOSITE : + LayerManager::END_DEFAULT); - presContext->NotifyDidPaintForSubtree(); + if (aType != PaintType_Composite) { + presContext->NotifyDidPaintForSubtree(); + } } // static diff --git a/layout/base/nsPresShell.h b/layout/base/nsPresShell.h index f8f6cb432088..4b9b78fd0b7c 100644 --- a/layout/base/nsPresShell.h +++ b/layout/base/nsPresShell.h @@ -184,9 +184,8 @@ public: //nsIViewObserver interface - virtual void Paint(nsIView* aViewToPaint, nsIWidget* aWidget, - const nsRegion& aDirtyRegion, const nsIntRegion& aIntDirtyRegion, - bool aWillSendDidPaint); + virtual void Paint(nsIView* aViewToPaint, const nsRegion& aDirtyRegion, + PaintType aType, bool aWillSendDidPaint); virtual nsresult HandleEvent(nsIFrame* aFrame, nsGUIEvent* aEvent, bool aDontRetargetEvents, diff --git a/layout/base/nsRefreshDriver.cpp b/layout/base/nsRefreshDriver.cpp index 26f1c67a17a2..d5a0a1ae8c9f 100644 --- a/layout/base/nsRefreshDriver.cpp +++ b/layout/base/nsRefreshDriver.cpp @@ -411,8 +411,14 @@ nsRefreshDriver::Notify(nsITimer *aTimer) } if (mViewManagerFlushIsPending) { +#ifdef DEBUG_INVALIDATIONS + printf("Starting ProcessPendingUpdates\n"); +#endif mViewManagerFlushIsPending = false; mPresContext->GetPresShell()->GetViewManager()->ProcessPendingUpdates(); +#ifdef DEBUG_INVALIDATIONS + printf("Ending ProcessPendingUpdates\n"); +#endif } if (mThrottled || diff --git a/view/src/nsViewManager.cpp b/view/src/nsViewManager.cpp index c1cccfe567c9..b2472b9af6bc 100644 --- a/view/src/nsViewManager.cpp +++ b/view/src/nsViewManager.cpp @@ -300,11 +300,9 @@ nsIView* nsIViewManager::GetDisplayRootFor(nsIView* aView) aContext may be null, in which case layers should be used for rendering. */ -void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, - const nsIntRegion& aRegion, +void nsViewManager::Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint) { - NS_ASSERTION(aView == nsView::GetViewFor(aWidget), "view widget mismatch"); NS_ASSERTION(aView->GetViewManager() == this, "wrong view manager"); // damageRegion is the damaged area, in twips, relative to the view origin @@ -337,8 +335,14 @@ void nsViewManager::Refresh(nsView *aView, nsIWidget *aWidget, "Widgets that we paint must all be display roots"); if (mPresShell) { - mPresShell->Paint(aView, aWidget, damageRegion, aRegion, +#ifdef DEBUG_INVALIDATIONS + printf("--COMPOSITE-- %p\n", mPresShell); +#endif + mPresShell->Paint(aView, damageRegion, nsIPresShell::PaintType_Composite, aWillSendDidPaint); +#ifdef DEBUG_INVALIDATIONS + printf("--ENDCOMPOSITE--\n"); +#endif mozilla::StartupTimeline::RecordOnce(mozilla::StartupTimeline::FIRST_PAINT); } @@ -374,6 +378,17 @@ void nsViewManager::ProcessPendingUpdatesForView(nsView* aView, // Push out updates after we've processed the children; ensures that // damage is applied based on the final widget geometry if (aFlushDirtyRegion) { + nsIWidget *widget = aView->GetWidget(); + if (widget) { +#ifdef DEBUG_INVALIDATIONS + printf("---- PAINT START ----PresShell(%p), nsView(%p), nsIWidget(%p)\n", mPresShell, aView, widget); +#endif + nsAutoScriptBlocker scriptBlocker; + mPresShell->Paint(aView, nsRegion(), nsIPresShell::PaintType_NoComposite, false); +#ifdef DEBUG_INVALIDATIONS + printf("---- PAINT END ----\n"); +#endif + } FlushDirtyRegionToWidget(aView); } } @@ -767,7 +782,7 @@ NS_IMETHODIMP nsViewManager::DispatchEvent(nsGUIEvent *aEvent, break; // Paint. - Refresh(view, event->widget, event->region, event->willSendDidPaint); + Refresh(view, event->region, event->willSendDidPaint); break; } diff --git a/view/src/nsViewManager.h b/view/src/nsViewManager.h index 70ad2abd4678..cc9230b4a22d 100644 --- a/view/src/nsViewManager.h +++ b/view/src/nsViewManager.h @@ -129,8 +129,7 @@ private: void InvalidateViews(nsView *aView); // aView is the view for aWidget and aRegion is relative to aWidget. - void Refresh(nsView *aView, nsIWidget *aWidget, const nsIntRegion& aRegion, - bool aWillSendDidPaint); + void Refresh(nsView *aView, const nsIntRegion& aRegion, bool aWillSendDidPaint); void InvalidateRectDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut); void InvalidateHorizontalBandDifference(nsView *aView, const nsRect& aRect, const nsRect& aCutOut,