diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 5d0c9bff9143..dd2e8f076111 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -73,6 +73,7 @@ #include "ipc/nsGUIEventIPC.h" #include "mozilla/gfx/Matrix.h" #include "UnitTransforms.h" +#include "ClientLayerManager.h" #include "nsColorPickerProxy.h" @@ -105,6 +106,9 @@ static bool sCpowsEnabled = false; static int32_t sActiveDurationMs = 10; static bool sActiveDurationMsSet = false; +typedef nsDataHashtable TabChildMap; +static TabChildMap* sTabChildren; + TabChildBase::TabChildBase() : mOldViewportWidth(0.0f) , mContentDocumentIsDisplayed(false) @@ -669,6 +673,7 @@ TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t , mRemoteFrame(nullptr) , mManager(aManager) , mChromeFlags(aChromeFlags) + , mLayersId(0) , mOuterRect(0, 0, 0, 0) , mActivePointerId(-1) , mTapHoldTimer(nullptr) @@ -1293,6 +1298,17 @@ TabChild::DestroyWindow() mRemoteFrame->Destroy(); mRemoteFrame = nullptr; } + + + if (mLayersId != 0) { + MOZ_ASSERT(sTabChildren); + sTabChildren->Remove(mLayersId); + if (!sTabChildren->Count()) { + delete sTabChildren; + sTabChildren = nullptr; + } + mLayersId = 0; + } } bool @@ -2387,6 +2403,13 @@ TabChild::InitRenderingState() ImageBridgeChild::IdentifyCompositorTextureHost(mTextureFactoryIdentifier); mRemoteFrame = remoteFrame; + if (id != 0) { + if (!sTabChildren) { + sTabChildren = new TabChildMap; + } + sTabChildren->Put(id, this); + mLayersId = id; + } nsCOMPtr observerService = mozilla::services::GetObserverService(); @@ -2583,6 +2606,26 @@ TabChild::GetFrom(nsIPresShell* aPresShell) return GetFrom(docShell); } +TabChild* +TabChild::GetFrom(uint64_t aLayersId) +{ + if (!sTabChildren) { + return nullptr; + } + return sTabChildren->Get(aLayersId); +} + +void +TabChild::DidComposite() +{ + MOZ_ASSERT(mWidget); + MOZ_ASSERT(mWidget->GetLayerManager()); + MOZ_ASSERT(mWidget->GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_CLIENT); + + ClientLayerManager *manager = static_cast(mWidget->GetLayerManager()); + manager->DidComposite(); +} + NS_IMETHODIMP TabChild::OnShowTooltip(int32_t aXCoords, int32_t aYCoords, const char16_t *aTipText) { diff --git a/dom/ipc/TabChild.h b/dom/ipc/TabChild.h index bdaf2178846a..6d1f4cce5f36 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -430,6 +430,9 @@ public: } static TabChild* GetFrom(nsIPresShell* aPresShell); + static TabChild* GetFrom(uint64_t aLayersId); + + void DidComposite(); static inline TabChild* GetFrom(nsIDOMWindow* aWindow) @@ -514,6 +517,7 @@ private: RenderFrameChild* mRemoteFrame; nsRefPtr mManager; uint32_t mChromeFlags; + uint64_t mLayersId; nsIntRect mOuterRect; // When we're tracking a possible tap gesture, this is the "down" // point of the touchstart. diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 577e13eff208..3ac56c83fba7 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -24,6 +24,7 @@ #include "mozilla/layers/SimpleTextureClientPool.h" // for SimpleTextureClientPool #include "nsAString.h" #include "nsIWidget.h" // for nsIWidget +#include "nsIWidgetListener.h" #include "nsTArray.h" // for AutoInfallibleTArray #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc #include "TiledLayerBuffer.h" @@ -271,6 +272,21 @@ ClientLayerManager::Composite() } } +void +ClientLayerManager::DidComposite() +{ + MOZ_ASSERT(mWidget); + nsIWidgetListener *listener = mWidget->GetWidgetListener(); + if (listener) { + listener->DidCompositeWindow(); + } else { + listener = mWidget->GetAttachedWidgetListener(); + if (listener) { + listener->DidCompositeWindow(); + } + } +} + void ClientLayerManager::MakeSnapshotIfRequired() { diff --git a/gfx/layers/client/ClientLayerManager.h b/gfx/layers/client/ClientLayerManager.h index 7a566e24891a..c7fd0d095467 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -163,6 +163,8 @@ public: virtual void Composite() MOZ_OVERRIDE; + virtual void DidComposite(); + protected: enum TransactionPhase { PHASE_NONE, PHASE_CONSTRUCTION, PHASE_DRAWING, PHASE_FORWARD diff --git a/gfx/layers/ipc/CompositorChild.cpp b/gfx/layers/ipc/CompositorChild.cpp index 049d7061f9e9..22bc308f2773 100644 --- a/gfx/layers/ipc/CompositorChild.cpp +++ b/gfx/layers/ipc/CompositorChild.cpp @@ -20,6 +20,7 @@ #include "nsTArray.h" // for nsTArray, nsTArray_Impl #include "nsXULAppAPI.h" // for XRE_GetIOMessageLoop, etc #include "FrameLayerBuilder.h" +#include "mozilla/dom/TabChild.h" using mozilla::layers::LayerTransactionChild; @@ -120,6 +121,21 @@ CompositorChild::RecvInvalidateAll() return true; } +bool +CompositorChild::RecvDidComposite(const uint64_t& aId) +{ + if (mLayerManager) { + MOZ_ASSERT(aId == 0); + mLayerManager->DidComposite(); + } else if (aId != 0) { + dom::TabChild *child = dom::TabChild::GetFrom(aId); + if (child) { + child->DidComposite(); + } + } + return true; +} + void CompositorChild::ActorDestroy(ActorDestroyReason aWhy) { diff --git a/gfx/layers/ipc/CompositorChild.h b/gfx/layers/ipc/CompositorChild.h index 814bdf1767dc..ce16253052f8 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -56,6 +56,8 @@ public: virtual bool RecvInvalidateAll() MOZ_OVERRIDE; + virtual bool RecvDidComposite(const uint64_t& aId) MOZ_OVERRIDE; + private: // Private destructor, to discourage deletion outside of Release(): virtual ~CompositorChild(); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index f892265153db..1aa3296e8267 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -50,6 +50,7 @@ #endif #include "GeckoProfiler.h" #include "mozilla/ipc/ProtocolTypes.h" +#include "mozilla/unused.h" using namespace base; using namespace mozilla; @@ -188,6 +189,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, , mResumeCompositionMonitor("ResumeCompositionMonitor") , mOverrideComposeReadiness(false) , mForceCompositionTask(nullptr) + , mWantDidCompositeEvent(false) { NS_ABORT_IF_FALSE(sCompositorThread != nullptr || sCompositorThreadID, "The compositor thread must be Initialized before instanciating a COmpositorParent."); @@ -522,6 +524,8 @@ CompositorParent::NotifyShadowTreeTransaction(uint64_t aId, bool aIsFirstPaint, if (aScheduleComposite) { ScheduleComposition(); } + + mWantDidCompositeEvent = true; } // Used when layout.frame_rate is -1. Needs to be kept in sync with @@ -651,6 +655,11 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget) mLayerManager->SetDebugOverlayWantsNextFrame(false); mLayerManager->EndEmptyTransaction(); + if (!aTarget && mWantDidCompositeEvent) { + DidComposite(); + mWantDidCompositeEvent = false; + } + if (mLayerManager->DebugOverlayWantsNextFrame()) { ScheduleComposition(); } @@ -678,6 +687,20 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget) profiler_tracing("Paint", "Composite", TRACING_INTERVAL_END); } +void +CompositorParent::DidComposite() +{ + unused << SendDidComposite(0); + + for (LayerTreeMap::iterator it = sIndirectLayerTrees.begin(); + it != sIndirectLayerTrees.end(); it++) { + LayerTreeState* lts = &it->second; + if (lts->mParent == this && lts->mCrossProcessParent) { + unused << lts->mCrossProcessParent->SendDidComposite(it->first); + } + } +} + void CompositorParent::ForceComposeToTarget(DrawTarget* aTarget) { @@ -766,6 +789,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, } } mLayerManager->NotifyShadowTreeTransaction(); + mWantDidCompositeEvent = true; } void diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index a3dbbd71439d..b0cc866524b7 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -300,6 +300,8 @@ private: */ bool CanComposite(); + void DidComposite(); + nsRefPtr mLayerManager; nsRefPtr mCompositor; RefPtr mCompositionManager; @@ -328,6 +330,8 @@ private: nsRefPtr mApzcTreeManager; + bool mWantDidCompositeEvent; + DISALLOW_EVIL_CONSTRUCTORS(CompositorParent); }; diff --git a/gfx/layers/ipc/PCompositor.ipdl b/gfx/layers/ipc/PCompositor.ipdl index 05d1b33bc9c5..3efb6b7dfd9e 100644 --- a/gfx/layers/ipc/PCompositor.ipdl +++ b/gfx/layers/ipc/PCompositor.ipdl @@ -40,6 +40,11 @@ child: // The child should invalidate everything so that the whole window is redrawn. async InvalidateAll(); + // The compositor completed a layers transaction. id is the layers id + // of the child layer tree that was composited (or 0 when notifying + // the root layer tree). + async DidComposite(uint64_t id); + parent: // The child is about to be destroyed, so perform any necessary cleanup. diff --git a/layout/base/nsPresShell.cpp b/layout/base/nsPresShell.cpp index 8664c0678010..8a5ed5a7fad4 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5824,11 +5824,7 @@ PresShell::Paint(nsView* aViewToPaint, NS_ASSERTION(layerManager, "Must be in paint event"); bool shouldInvalidate = layerManager->NeedsWidgetInvalidation(); - uint32_t didPaintFlags = aFlags; - if (!shouldInvalidate) { - didPaintFlags |= PAINT_COMPOSITE; - } - nsAutoNotifyDidPaint notifyDidPaint(this, didPaintFlags); + nsAutoNotifyDidPaint notifyDidPaint(this, aFlags); AutoUpdateHitRegion updateHitRegion(this, frame); // Whether or not we should set first paint when painting is diff --git a/layout/reftests/forms/input/range/stepDown-unthemed.html b/layout/reftests/forms/input/range/stepDown-unthemed.html index fbddb69ada55..6d4d6708a5e4 100644 --- a/layout/reftests/forms/input/range/stepDown-unthemed.html +++ b/layout/reftests/forms/input/range/stepDown-unthemed.html @@ -9,7 +9,6 @@ document.documentElement.className = ''; } document.addEventListener("MozReftestInvalidate", setValue); - setTimeout(setValue, 2000); // useful when not running under reftest suite diff --git a/layout/reftests/forms/input/range/stepDown.html b/layout/reftests/forms/input/range/stepDown.html index 8e63ea8b9e76..e482af4905dd 100644 --- a/layout/reftests/forms/input/range/stepDown.html +++ b/layout/reftests/forms/input/range/stepDown.html @@ -9,7 +9,6 @@ document.documentElement.className = ''; } document.addEventListener("MozReftestInvalidate", setValue); - setTimeout(setValue, 2000); // useful when not running under reftest suite diff --git a/layout/reftests/forms/input/range/stepUp-unthemed.html b/layout/reftests/forms/input/range/stepUp-unthemed.html index 613049e9ef40..1e4198cc66bb 100644 --- a/layout/reftests/forms/input/range/stepUp-unthemed.html +++ b/layout/reftests/forms/input/range/stepUp-unthemed.html @@ -9,7 +9,6 @@ document.documentElement.className = ''; } document.addEventListener("MozReftestInvalidate", setValue); - setTimeout(setValue, 2000); // useful when not running under reftest suite diff --git a/layout/reftests/forms/input/range/stepUp.html b/layout/reftests/forms/input/range/stepUp.html index 11af00b36cc6..139e6c797caa 100644 --- a/layout/reftests/forms/input/range/stepUp.html +++ b/layout/reftests/forms/input/range/stepUp.html @@ -9,7 +9,6 @@ document.documentElement.className = ''; } document.addEventListener("MozReftestInvalidate", setValue); - setTimeout(setValue, 2000); // useful when not running under reftest suite diff --git a/layout/reftests/printing/745025-1.html b/layout/reftests/printing/745025-1.html index 53fa7de260bc..2ba527131107 100644 --- a/layout/reftests/printing/745025-1.html +++ b/layout/reftests/printing/745025-1.html @@ -12,7 +12,7 @@ }; setTimeout(function() { document.documentElement.className = "reftest-print" - }, 0); + }, 100); }; diff --git a/view/public/nsView.h b/view/public/nsView.h index fdcb52a331d4..6ff3711b0775 100644 --- a/view/public/nsView.h +++ b/view/public/nsView.h @@ -370,6 +370,7 @@ public: virtual void WillPaintWindow(nsIWidget* aWidget) MOZ_OVERRIDE; virtual bool PaintWindow(nsIWidget* aWidget, nsIntRegion aRegion) MOZ_OVERRIDE; virtual void DidPaintWindow() MOZ_OVERRIDE; + virtual void DidCompositeWindow() MOZ_OVERRIDE; virtual void RequestRepaint() MOZ_OVERRIDE; virtual nsEventStatus HandleEvent(mozilla::WidgetGUIEvent* aEvent, bool aUseAttachedEvents) MOZ_OVERRIDE; diff --git a/view/src/nsView.cpp b/view/src/nsView.cpp index 1e2836826919..1f6a745e045d 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -17,6 +17,7 @@ #include "nsPresArena.h" #include "nsXULPopupManager.h" #include "nsIWidgetListener.h" +#include "nsContentUtils.h" // for nsAutoScriptBlocker using namespace mozilla; @@ -1056,6 +1057,16 @@ nsView::DidPaintWindow() vm->DidPaintWindow(); } +void +nsView::DidCompositeWindow() +{ + nsIPresShell* presShell = mViewManager->GetPresShell(); + if (presShell) { + nsAutoScriptBlocker scriptBlocker; + presShell->GetPresContext()->GetDisplayRootPresContext()->GetRootPresContext()->NotifyDidPaintForSubtree(nsIPresShell::PAINT_COMPOSITE); + } +} + void nsView::RequestRepaint() { diff --git a/widget/nsIWidgetListener.h b/widget/nsIWidgetListener.h index c5805acb53c7..4345b80cb46d 100644 --- a/widget/nsIWidgetListener.h +++ b/widget/nsIWidgetListener.h @@ -130,6 +130,8 @@ public: */ virtual void DidPaintWindow(); + virtual void DidCompositeWindow(); + /** * Request that layout schedules a repaint on the next refresh driver tick. */ diff --git a/widget/xpwidgets/nsIWidgetListener.cpp b/widget/xpwidgets/nsIWidgetListener.cpp index a1ad325fc8e8..3c0e56030a05 100644 --- a/widget/xpwidgets/nsIWidgetListener.cpp +++ b/widget/xpwidgets/nsIWidgetListener.cpp @@ -101,6 +101,11 @@ nsIWidgetListener::DidPaintWindow() { } +void +nsIWidgetListener::DidCompositeWindow() +{ +} + void nsIWidgetListener::RequestRepaint() {