diff --git a/dom/ipc/TabChild.cpp b/dom/ipc/TabChild.cpp index 5c33299f5036..30e4d69e0cb0 100644 --- a/dom/ipc/TabChild.cpp +++ b/dom/ipc/TabChild.cpp @@ -74,6 +74,7 @@ #include "nsILoadContext.h" #include "ipc/nsGUIEventIPC.h" #include "mozilla/gfx/Matrix.h" +#include "ClientLayerManager.h" #include "nsColorPickerProxy.h" @@ -106,6 +107,9 @@ static bool sCpowsEnabled = false; static int32_t sActiveDurationMs = 10; static bool sActiveDurationMsSet = false; +typedef nsDataHashtable TabChildMap; +static TabChildMap* sTabChildren; + NS_IMETHODIMP ContentListener::HandleEvent(nsIDOMEvent* aEvent) { @@ -280,6 +284,7 @@ TabChild::TabChild(ContentChild* aManager, const TabContext& aContext, uint32_t , mManager(aManager) , mTabChildGlobal(nullptr) , mChromeFlags(aChromeFlags) + , mLayersId(0) , mOuterRect(0, 0, 0, 0) , mInnerSize(0, 0) , mActivePointerId(-1) @@ -1208,6 +1213,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 @@ -2427,6 +2443,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(); @@ -2629,6 +2652,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 daa1a238f940..5125909244f8 100644 --- a/dom/ipc/TabChild.h +++ b/dom/ipc/TabChild.h @@ -381,6 +381,9 @@ public: } static TabChild* GetFrom(nsIPresShell* aPresShell); + static TabChild* GetFrom(uint64_t aLayersId); + + void DidComposite(); static inline TabChild* GetFrom(nsIDOMWindow* aWindow) @@ -499,6 +502,7 @@ private: nsRefPtr mManager; nsRefPtr mTabChildGlobal; uint32_t mChromeFlags; + uint64_t mLayersId; nsIntRect mOuterRect; ScreenIntSize mInnerSize; // When we're tracking a possible tap gesture, this is the "down" diff --git a/gfx/layers/client/ClientLayerManager.cpp b/gfx/layers/client/ClientLayerManager.cpp index 06939eb83b2f..86cc1e9ab05a 100644 --- a/gfx/layers/client/ClientLayerManager.cpp +++ b/gfx/layers/client/ClientLayerManager.cpp @@ -22,6 +22,7 @@ #include "mozilla/layers/LayerTransactionChild.h" #include "nsAString.h" #include "nsIWidget.h" // for nsIWidget +#include "nsIWidgetListener.h" #include "nsTArray.h" // for AutoInfallibleTArray #include "nsXULAppAPI.h" // for XRE_GetProcessType, etc #ifdef MOZ_WIDGET_ANDROID @@ -264,6 +265,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 6c732fb232fe..8a0fe9ba062b 100644 --- a/gfx/layers/client/ClientLayerManager.h +++ b/gfx/layers/client/ClientLayerManager.h @@ -153,6 +153,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 a721b3be098a..92762942487f 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 045b72fb9614..2a259a695505 100644 --- a/gfx/layers/ipc/CompositorChild.h +++ b/gfx/layers/ipc/CompositorChild.h @@ -57,6 +57,8 @@ public: virtual bool RecvInvalidateAll() MOZ_OVERRIDE; + virtual bool RecvDidComposite(const uint64_t& aId) MOZ_OVERRIDE; + protected: virtual PLayerTransactionChild* AllocPLayerTransactionChild(const nsTArray& aBackendHints, diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index e1fc39e0a89b..371c915e4d65 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -51,6 +51,7 @@ #endif #include "GeckoProfiler.h" #include "mozilla/ipc/ProtocolTypes.h" +#include "mozilla/unused.h" using namespace base; using namespace mozilla; @@ -189,6 +190,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."); @@ -537,6 +539,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 @@ -663,6 +667,11 @@ CompositorParent::CompositeToTarget(DrawTarget* aTarget) mLayerManager->SetDebugOverlayWantsNextFrame(false); mLayerManager->EndEmptyTransaction(); + if (!aTarget && mWantDidCompositeEvent) { + DidComposite(); + mWantDidCompositeEvent = false; + } + if (mLayerManager->DebugOverlayWantsNextFrame()) { ScheduleComposition(); } @@ -689,6 +698,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) { @@ -765,6 +788,7 @@ CompositorParent::ShadowLayersUpdated(LayerTransactionParent* aLayerTree, ScheduleComposition(); } mLayerManager->NotifyShadowTreeTransaction(); + mWantDidCompositeEvent = true; } void diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 84a68c8a057d..e05f26c1754a 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -297,6 +297,8 @@ private: */ bool CanComposite(); + void DidComposite(); + nsRefPtr mLayerManager; nsRefPtr mCompositor; RefPtr mCompositionManager; @@ -325,6 +327,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 3a8f8678b552..831b1fff76ab 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 e00d67f281e5..3244517dc309 100644 --- a/layout/base/nsPresShell.cpp +++ b/layout/base/nsPresShell.cpp @@ -5838,11 +5838,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/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 cbdb324b103d..4a2de01c5c8f 100644 --- a/view/src/nsView.cpp +++ b/view/src/nsView.cpp @@ -16,6 +16,7 @@ #include "nsPresArena.h" #include "nsXULPopupManager.h" #include "nsIWidgetListener.h" +#include "nsContentUtils.h" // for nsAutoScriptBlocker using namespace mozilla; @@ -1054,6 +1055,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() {