Bug 973767. Put the compositor into test mode via an IPDL transaction. r=mattwoodrow
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 12 Feb 2014 17:41:57 +1300
changeset 170175 e7349662e30535552cf7573a94bc8b46c5b4eb31
parent 170174 68b905ed5fc48599804d31b106eb91150cf5e6fb
child 170176 e36575f8b202d030e542dda38afd2a2c54eed8fa
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersmattwoodrow
bugs973767
milestone30.0a1
Bug 973767. Put the compositor into test mode via an IPDL transaction. r=mattwoodrow
dom/base/nsDOMWindowUtils.cpp
dom/base/nsDOMWindowUtils.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
--- a/dom/base/nsDOMWindowUtils.cpp
+++ b/dom/base/nsDOMWindowUtils.cpp
@@ -1,20 +1,21 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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 "nsDOMWindowUtils.h"
+
+#include "mozilla/layers/CompositorChild.h"
 #include "mozilla/layers/LayerTransactionChild.h"
 #include "nsPresContext.h"
 #include "nsDOMClassInfoID.h"
 #include "nsError.h"
 #include "nsIDOMEvent.h"
-#include "nsDOMWindowUtils.h"
 #include "nsQueryContentEventResult.h"
 #include "CompositionStringSynthesizer.h"
 #include "nsGlobalWindow.h"
 #include "nsIDocument.h"
 #include "nsFocusManager.h"
 #include "nsEventStateManager.h"
 #include "nsFrameManager.h"
 #include "nsRefreshDriver.h"
@@ -2543,31 +2544,48 @@ NS_IMETHODIMP
 nsDOMWindowUtils::AdvanceTimeAndRefresh(int64_t aMilliseconds)
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
   nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
   driver->AdvanceTimeAndRefresh(aMilliseconds);
-  CompositorParent::SetTimeAndSampleAnimations(driver->MostRecentRefresh(), true);
+
+  nsIWidget* widget = GetWidget();
+  if (widget) {
+    CompositorChild* compositor = widget->GetRemoteRenderer();
+    if (compositor) {
+      compositor->SendSetTestSampleTime(driver->MostRecentRefresh());
+    }
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::RestoreNormalRefresh()
 {
   if (!nsContentUtils::IsCallerChrome()) {
     return NS_ERROR_DOM_SECURITY_ERR;
   }
 
+  // Kick the compositor out of test mode before the refresh driver, so that
+  // the refresh driver doesn't send an update that gets ignored by the
+  // compositor.
+  nsIWidget* widget = GetWidget();
+  if (widget) {
+    CompositorChild* compositor = widget->GetRemoteRenderer();
+    if (compositor) {
+      compositor->SendLeaveTestMode();
+    }
+  }
+
   nsRefreshDriver* driver = GetPresContext()->RefreshDriver();
   driver->RestoreNormalRefresh();
-  CompositorParent::SetTimeAndSampleAnimations(driver->MostRecentRefresh(), false);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDOMWindowUtils::GetIsTestControllingRefreshes(bool *aResult)
 {
   if (!nsContentUtils::IsCallerChrome()) {
--- a/dom/base/nsDOMWindowUtils.h
+++ b/dom/base/nsDOMWindowUtils.h
@@ -5,19 +5,23 @@
 
 #ifndef nsDOMWindowUtils_h_
 #define nsDOMWindowUtils_h_
 
 #include "nsWeakReference.h"
 
 #include "nsIDOMWindowUtils.h"
 #include "mozilla/Attributes.h"
+#include "mozilla/BasicEvents.h"
 
 class nsGlobalWindow;
 class nsIPresShell;
+class nsIWidget;
+class nsPresContext;
+class nsPoint;
 
 class nsDOMWindowUtils MOZ_FINAL : public nsIDOMWindowUtils,
                                    public nsSupportsWeakReference
 {
 public:
   nsDOMWindowUtils(nsGlobalWindow *aWindow);
   ~nsDOMWindowUtils();
   NS_DECL_ISUPPORTS
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -368,16 +368,38 @@ CompositorParent::RecvStopFrameTimeRecor
                                              InfallibleTArray<float>* intervals)
 {
   if (mLayerManager) {
     mLayerManager->StopFrameTimeRecording(aStartIndex, *intervals);
   }
   return true;
 }
 
+bool
+CompositorParent::RecvSetTestSampleTime(const TimeStamp& aTime)
+{
+  if (aTime.IsNull()) {
+    return false;
+  }
+
+  mIsTesting = true;
+  mTestTime = aTime;
+  if (mCompositionManager) {
+    mCompositionManager->TransformShadowTree(aTime);
+  }
+  return true;
+}
+
+bool
+CompositorParent::RecvLeaveTestMode()
+{
+  mIsTesting = false;
+  return true;
+}
+
 void
 CompositorParent::ActorDestroy(ActorDestroyReason why)
 {
   mPaused = true;
   RemoveCompositor(mCompositorID);
 
   if (mLayerManager) {
     mLayerManager->Destroy();
@@ -858,31 +880,16 @@ CompositorParent* CompositorParent::Remo
   if (it == sCompositorMap->end()) {
     return nullptr;
   }
   CompositorParent *retval = it->second;
   sCompositorMap->erase(it);
   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;
-    if (it->second->mCompositionManager) {
-      it->second->mCompositionManager->TransformShadowTree(aTime);
-    }
-  }
-}
-
 bool
 CompositorParent::RecvNotifyChildCreated(const uint64_t& child)
 {
   NotifyChildCreated(child);
   return true;
 }
 
 void
@@ -1008,16 +1015,18 @@ public:
   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                 SurfaceDescriptor* aOutSnapshot)
   { return true; }
   virtual bool RecvFlushRendering() MOZ_OVERRIDE { return true; }
   virtual bool RecvForceComposite() MOZ_OVERRIDE { return true; }
   virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) { return true; }
   virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE { return true; }
   virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) MOZ_OVERRIDE  { return true; }
+  virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) MOZ_OVERRIDE { return true; }
+  virtual bool RecvLeaveTestMode() MOZ_OVERRIDE { return true; }
 
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                  bool *aSuccess) MOZ_OVERRIDE;
 
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -88,16 +88,18 @@ public:
   virtual bool RecvMakeSnapshot(const SurfaceDescriptor& aInSnapshot,
                                 SurfaceDescriptor* aOutSnapshot) MOZ_OVERRIDE;
   virtual bool RecvFlushRendering() MOZ_OVERRIDE;
   virtual bool RecvForceComposite() MOZ_OVERRIDE;
 
   virtual bool RecvNotifyRegionInvalidated(const nsIntRegion& aRegion) MOZ_OVERRIDE;
   virtual bool RecvStartFrameTimeRecording(const int32_t& aBufferSize, uint32_t* aOutStartIndex) MOZ_OVERRIDE;
   virtual bool RecvStopFrameTimeRecording(const uint32_t& aStartIndex, InfallibleTArray<float>* intervals) MOZ_OVERRIDE;
+  virtual bool RecvSetTestSampleTime(const TimeStamp& aTime) MOZ_OVERRIDE;
+  virtual bool RecvLeaveTestMode() MOZ_OVERRIDE;
 
   virtual void ActorDestroy(ActorDestroyReason why) MOZ_OVERRIDE;
 
   virtual void ShadowLayersUpdated(LayerTransactionParent* aLayerTree,
                                    const TargetConfig& aTargetConfig,
                                    bool aIsFirstPaint,
                                    bool aScheduleComposite) MOZ_OVERRIDE;
   virtual AsyncCompositionManager* GetCompositionManager() MOZ_OVERRIDE { return mCompositionManager; }
@@ -218,28 +220,20 @@ public:
    * exists.  Otherwise null is returned.  This must only be called on
    * the compositor thread.
    */
   static const LayerTreeState* GetIndirectShadowTree(uint64_t aId);
 
   float ComputeRenderIntegrity();
 
   /**
-   * 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);
-
-  /**
    * Returns true if the calling thread is the compositor thread.
    */
   static bool IsInCompositorThread();
+
 protected:
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                  const uint64_t& aId,
                                  TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                  bool* aSuccess) MOZ_OVERRIDE;
   virtual bool DeallocPLayerTransactionParent(PLayerTransactionParent* aLayers) MOZ_OVERRIDE;
   virtual void ScheduleTask(CancelableTask*, int);
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -13,16 +13,17 @@ include "nsRegion.h";
 
 using struct mozilla::null_t from "ipc/IPCMessageUtils.h";
 using struct mozilla::layers::TextureFactoryIdentifier from "mozilla/layers/CompositorTypes.h";
 using struct mozilla::layers::FrameMetrics from "FrameMetrics.h";
 using mozilla::layers::FrameMetrics::ViewID from "FrameMetrics.h";
 using mozilla::layers::LayersBackend from "mozilla/layers/LayersTypes.h";
 using mozilla::CrossProcessMutexHandle from "mozilla/ipc/CrossProcessMutex.h";
 using mozilla::ipc::SharedMemoryBasic::Handle from "mozilla/ipc/SharedMemoryBasic.h";
+using class mozilla::TimeStamp from "mozilla/TimeStamp.h";
 
 namespace mozilla {
 namespace layers {
 
 
 /**
  * The PCompositor protocol is used to manage communication between
  * the main thread and the compositor thread context. It's primary
@@ -72,16 +73,22 @@ parent:
   async ForceComposite();
 
   sync StartFrameTimeRecording(int32_t bufferSize)
     returns (uint32_t startIndex);
 
   sync StopFrameTimeRecording(uint32_t startIndex)
     returns (float[] intervals);
 
+  // Enter test mode, set the sample time to sampleTime, and resample animations.
+  // sampleTime must not be null.
+  sync SetTestSampleTime(TimeStamp sampleTime);
+  // Leave test mode and resume normal compositing
+  sync LeaveTestMode();
+
   // layersBackendHints is an ordered list of preffered backends where
   // layersBackendHints[0] is the best backend. If any hints are LayersBackend::LAYERS_NONE
   // that hint is ignored.
   sync PLayerTransaction(LayersBackend[] layersBackendHints, uint64_t id)
     returns (TextureFactoryIdentifier textureFactoryIdentifier, bool success);
 
   // Notify the compositor that a region of the screen has been invalidated.
   async NotifyRegionInvalidated(nsIntRegion region);