From 41dbdc53f7635e37c1856c4854c9dd7f7c10d5e9 Mon Sep 17 00:00:00 2001 From: David Zbarsky Date: Mon, 27 May 2013 16:47:45 -0700 Subject: [PATCH] Bug 788549 Part 4: Add the ability to pause and sample animations on compositors at a specified time r=roc --- dom/base/nsDOMWindowUtils.cpp | 15 ++++++++++++--- .../composite/AsyncCompositionManager.cpp | 3 +-- gfx/layers/ipc/CompositorParent.cpp | 17 ++++++++++++++++- gfx/layers/ipc/CompositorParent.h | 11 +++++++++++ 4 files changed, 40 insertions(+), 6 deletions(-) diff --git a/dom/base/nsDOMWindowUtils.cpp b/dom/base/nsDOMWindowUtils.cpp index ff8d6225578..ed6f29cd6d4 100644 --- a/dom/base/nsDOMWindowUtils.cpp +++ b/dom/base/nsDOMWindowUtils.cpp @@ -3,6 +3,7 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "mozilla/layers/CompositorParent.h" #include "nsIDocShell.h" #include "nsPresContext.h" #include "nsDOMClassInfoID.h" @@ -75,6 +76,10 @@ #include "nsIAppShell.h" #include "nsWidgetsCID.h" +#ifdef XP_WIN +#undef GetClassName +#endif + using namespace mozilla; using namespace mozilla::dom; using namespace mozilla::layers; @@ -2000,7 +2005,7 @@ nsDOMWindowUtils::SendContentCommandEvent(const nsAString& aType, msg = NS_CONTENT_COMMAND_PASTE_TRANSFERABLE; else return NS_ERROR_FAILURE; - + nsContentCommandEvent event(true, msg, widget); if (msg == NS_CONTENT_COMMAND_PASTE_TRANSFERABLE) { event.mTransferable = aTransferable; @@ -2371,7 +2376,9 @@ nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds) return NS_ERROR_DOM_SECURITY_ERR; } - GetPresContext()->RefreshDriver()->AdvanceTimeAndRefresh(aMilliseconds); + nsRefreshDriver* driver = GetPresContext()->RefreshDriver(); + driver->AdvanceTimeAndRefresh(aMilliseconds); + CompositorParent::SetTimeAndSampleAnimations(driver->MostRecentRefresh(), true); return NS_OK; } @@ -2383,7 +2390,9 @@ nsDOMWindowUtils::RestoreNormalRefresh() return NS_ERROR_DOM_SECURITY_ERR; } - GetPresContext()->RefreshDriver()->RestoreNormalRefresh(); + nsRefreshDriver* driver = GetPresContext()->RefreshDriver(); + driver->RestoreNormalRefresh(); + CompositorParent::SetTimeAndSampleAnimations(driver->MostRecentRefresh(), false); return NS_OK; } diff --git a/gfx/layers/composite/AsyncCompositionManager.cpp b/gfx/layers/composite/AsyncCompositionManager.cpp index 7462395a9f8..144809786ba 100644 --- a/gfx/layers/composite/AsyncCompositionManager.cpp +++ b/gfx/layers/composite/AsyncCompositionManager.cpp @@ -529,12 +529,11 @@ AsyncCompositionManager::TransformScrollableLayer(Layer* aLayer, const gfx3DMatr bool AsyncCompositionManager::TransformShadowTree(TimeStamp aCurrentFrame) { - bool wantNextFrame = false; Layer* root = mLayerManager->GetRoot(); // NB: we must sample animations *before* sampling pan/zoom // transforms. - wantNextFrame |= SampleAnimations(root, aCurrentFrame); + bool wantNextFrame = SampleAnimations(root, aCurrentFrame); const gfx3DMatrix& rootTransform = root->GetTransform(); diff --git a/gfx/layers/ipc/CompositorParent.cpp b/gfx/layers/ipc/CompositorParent.cpp index ab63420c0f2..dd5eb4b30b9 100644 --- a/gfx/layers/ipc/CompositorParent.cpp +++ b/gfx/layers/ipc/CompositorParent.cpp @@ -134,6 +134,7 @@ CompositorParent::CompositorParent(nsIWidget* aWidget, int aSurfaceWidth, int aSurfaceHeight) : mWidget(aWidget) , mCurrentCompositeTask(NULL) + , mIsTesting(false) , mPaused(false) , mUseExternalSurfaceSize(aUseExternalSurfaceSize) , mEGLSurfaceSize(aSurfaceWidth, aSurfaceHeight) @@ -451,7 +452,8 @@ CompositorParent::Composite() } } - bool requestNextFrame = mCompositionManager->TransformShadowTree(mLastCompose); + TimeStamp time = mIsTesting ? mTestTime : mLastCompose; + bool requestNextFrame = mCompositionManager->TransformShadowTree(time); if (requestNextFrame) { ScheduleComposition(); } @@ -650,6 +652,19 @@ CompositorParent* CompositorParent::RemoveCompositor(uint64_t id) return retval; } +/* static */ void +CompositorParent::SetTimeAndSampleAnimations(TimeStamp aTime, bool aIsTesting) +{ + if (!sCompositorMap) { + return; + } + for (CompositorMap::iterator it = sCompositorMap->begin(); it != sCompositorMap->end(); ++it) { + it->second->mIsTesting = aIsTesting; + it->second->mTestTime = aTime; + it->second->mCompositionManager->TransformShadowTree(aTime); + } +} + typedef map LayerTreeMap; static LayerTreeMap sIndirectLayerTrees; diff --git a/gfx/layers/ipc/CompositorParent.h b/gfx/layers/ipc/CompositorParent.h index 25bfcbbb3a7..cb176353761 100644 --- a/gfx/layers/ipc/CompositorParent.h +++ b/gfx/layers/ipc/CompositorParent.h @@ -163,6 +163,15 @@ public: */ static const LayerTreeState* GetIndirectShadowTree(uint64_t aId); + /** + * Tell all CompositorParents to update their last refresh to aTime and sample + * animations at this time stamp. If aIsTesting is true, the + * CompositorParents will become "paused" and continue sampling animations at + * this time stamp until this function is called again with aIsTesting set to + * false. + */ + static void SetTimeAndSampleAnimations(TimeStamp aTime, bool aIsTesting); + protected: virtual PLayerTransactionParent* AllocPLayerTransaction(const LayersBackend& aBackendHint, @@ -233,6 +242,8 @@ private: nsIWidget* mWidget; CancelableTask *mCurrentCompositeTask; TimeStamp mLastCompose; + TimeStamp mTestTime; + bool mIsTesting; #ifdef COMPOSITOR_PERFORMANCE_WARNING TimeStamp mExpectedComposeTime; #endif