Bug 911862 - Make VectorImage use the refresh driver to send out frame change notifications. r=dholbert, a=lsblakk
authorJonathan Watt <jwatt@jwatt.org>
Wed, 04 Sep 2013 11:39:30 +0100
changeset 149281 8d9e7eb92b36f77656faf9dd337547f2c32d3255
parent 149280 5e3bf07e920d2d330e67eeccc082c8c212d21dbb
child 149282 03684770098a0c6521eff6b9822c1cefee5b12d4
push id4223
push userjwatt@jwatt.org
push dateFri, 06 Sep 2013 21:22:53 +0000
treeherdermozilla-aurora@33d447b77903 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdholbert, lsblakk
bugs911862
milestone25.0a2
Bug 911862 - Make VectorImage use the refresh driver to send out frame change notifications. r=dholbert, a=lsblakk
image/src/VectorImage.cpp
image/src/VectorImage.h
--- a/image/src/VectorImage.cpp
+++ b/image/src/VectorImage.cpp
@@ -82,17 +82,17 @@ protected:
       if (!frame || frame->PresContext()->PresShell()->IsDestroying()) {
         // We're being destroyed. Bail out.
         return;
       }
 
       // Ignore further invalidations until we draw.
       mHonoringInvalidations = false;
 
-      mVectorImage->InvalidateObserver();
+      mVectorImage->InvalidateObserversOnNextRefreshDriverTick();
     }
 
     // Our caller might've removed us from rendering-observer list.
     // Add ourselves back!
     if (!mInObserverList) {
       nsSVGEffects::AddRenderingObserver(elem, this);
       mInObserverList = true;
     } 
@@ -306,17 +306,18 @@ NS_IMPL_ISUPPORTS3(VectorImage,
 // Constructor / Destructor
 
 VectorImage::VectorImage(imgStatusTracker* aStatusTracker,
                          nsIURI* aURI /* = nullptr */) :
   ImageResource(aStatusTracker, aURI), // invoke superclass's constructor
   mIsInitialized(false),
   mIsFullyLoaded(false),
   mIsDrawing(false),
-  mHaveAnimations(false)
+  mHaveAnimations(false),
+  mHasPendingInvalidation(false)
 {
 }
 
 VectorImage::~VectorImage()
 {
   CancelAllListeners();
 }
 
@@ -477,16 +478,28 @@ VectorImage::GetWidth(int32_t* aWidth)
 
 //******************************************************************************
 /* [notxpcom] void requestRefresh ([const] in TimeStamp aTime); */
 NS_IMETHODIMP_(void)
 VectorImage::RequestRefresh(const mozilla::TimeStamp& aTime)
 {
   // TODO: Implement for b666446.
   EvaluateAnimation();
+
+  if (mHasPendingInvalidation && mStatusTracker) {
+    // This method is called under the Tick() of an observing document's
+    // refresh driver. We send out the following notifications here rather than
+    // under WillRefresh() (which would be called by our own refresh driver) so
+    // that we only send these notifications if we actually have a document
+    // that is observing us.
+    mStatusTracker->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
+    mStatusTracker->OnStopFrame();
+  }
+
+  mHasPendingInvalidation = false;
 }
 
 //******************************************************************************
 /* readonly attribute int32_t height; */
 NS_IMETHODIMP
 VectorImage::GetHeight(int32_t* aHeight)
 {
   if (mError || !mIsFullyLoaded) {
@@ -992,18 +1005,15 @@ VectorImage::OnDataAvailable(nsIRequest*
   return mSVGDocumentWrapper->OnDataAvailable(aRequest, aCtxt, aInStr,
                                               aSourceOffset, aCount);
 }
 
 // --------------------------
 // Invalidation helper method
 
 void
-VectorImage::InvalidateObserver()
+VectorImage::InvalidateObserversOnNextRefreshDriverTick()
 {
-  if (mStatusTracker) {
-    mStatusTracker->FrameChanged(&nsIntRect::GetMaxSizedIntRect());
-    mStatusTracker->OnStopFrame();
-  }
+  mHasPendingInvalidation = true;
 }
 
 } // namespace image
 } // namespace mozilla
--- a/image/src/VectorImage.h
+++ b/image/src/VectorImage.h
@@ -55,18 +55,25 @@ public:
                                         uint64_t aSourceOffset,
                                         uint32_t aCount) MOZ_OVERRIDE;
   virtual nsresult OnImageDataComplete(nsIRequest* aRequest,
                                        nsISupports* aContext,
                                        nsresult aResult,
                                        bool aLastPart) MOZ_OVERRIDE;
   virtual nsresult OnNewSourceData() MOZ_OVERRIDE;
 
-  // Callback for SVGRootRenderingObserver.
-  void InvalidateObserver();
+  /**
+   * Callback for SVGRootRenderingObserver.
+   *
+   * This just sets a dirty flag that we check in VectorImage::RequestRefresh,
+   * which is called under the ticks of the refresh driver of any observing
+   * documents that we may have. Only then (after all animations in this image
+   * have been updated) do we send out "frame changed" notifications,
+   */
+  void InvalidateObserversOnNextRefreshDriverTick();
 
   // Callback for SVGParseCompleteListener.
   void OnSVGDocumentParsed();
 
   // Callbacks for SVGLoadEventListener.
   void OnSVGDocumentLoaded();
   void OnSVGDocumentError();
 
@@ -85,16 +92,18 @@ private:
   nsRefPtr<SVGLoadEventListener>     mLoadEventListener;
   nsRefPtr<SVGParseCompleteListener> mParseCompleteListener;
 
   bool           mIsInitialized;          // Have we been initalized?
   bool           mIsFullyLoaded;          // Has the SVG document finished loading?
   bool           mIsDrawing;              // Are we currently drawing?
   bool           mHaveAnimations;         // Is our SVG content SMIL-animated?
                                           // (Only set after mIsFullyLoaded.)
+  bool           mHasPendingInvalidation; // Invalidate observers next refresh
+                                          // driver tick.
 
   friend class ImageFactory;
 };
 
 inline NS_IMETHODIMP VectorImage::GetAnimationMode(uint16_t *aAnimationMode) {
   return GetAnimationModeInternal(aAnimationMode);
 }