Bug 666446, Part 5/18 - Change nsImageBoxFrame to register corresponding image with nsRefreshDriver to facilitate refresh driver-based animations. [r=roc]
authorScott Johnson <sjohnson@mozilla.com>
Mon, 03 Oct 2011 13:39:05 -0700
changeset 78659 4ec20f190f00c75d58f604cc467350d423657ba5
parent 78658 9d3ac2d3da11c7f8f0159d59fb515abaa3d2b919
child 78660 6cd4f2d8c2f9dbeae404c3248e22c2b7dbf88c7f
push id506
push userclegnitto@mozilla.com
push dateWed, 09 Nov 2011 02:03:18 +0000
treeherdermozilla-aurora@63587fc7bb93 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs666446
milestone10.0a1
Bug 666446, Part 5/18 - Change nsImageBoxFrame to register corresponding image with nsRefreshDriver to facilitate refresh driver-based animations. [r=roc]
layout/xul/base/src/nsImageBoxFrame.cpp
layout/xul/base/src/nsImageBoxFrame.h
--- a/layout/xul/base/src/nsImageBoxFrame.cpp
+++ b/layout/xul/base/src/nsImageBoxFrame.cpp
@@ -67,16 +67,17 @@
 #include "nsIDOMHTMLImageElement.h"
 #include "nsINameSpaceManager.h"
 #include "nsTextFragment.h"
 #include "nsIDOMHTMLMapElement.h"
 #include "nsBoxLayoutState.h"
 #include "nsIDOMDocument.h"
 #include "nsTransform2D.h"
 #include "nsITheme.h"
+#include "nsIImageLoadingContent.h"
 
 #include "nsIServiceManager.h"
 #include "nsIURI.h"
 #include "nsNetUtil.h"
 #include "nsThreadUtils.h"
 #include "nsGUIEvent.h"
 #include "nsEventDispatcher.h"
 #include "nsDisplayList.h"
@@ -173,16 +174,17 @@ nsImageBoxFrame::AttributeChanged(PRInt3
     UpdateLoadFlags();
 
   return rv;
 }
 
 nsImageBoxFrame::nsImageBoxFrame(nsIPresShell* aShell, nsStyleContext* aContext):
   nsLeafBoxFrame(aShell, aContext),
   mIntrinsicSize(0,0),
+  mRequestRegistered(false),
   mLoadFlags(nsIRequest::LOAD_NORMAL),
   mUseSrcAttr(PR_FALSE),
   mSuppressStyleCheck(PR_FALSE)
 {
   MarkIntrinsicWidthsDirty();
 }
 
 nsImageBoxFrame::~nsImageBoxFrame()
@@ -195,19 +197,26 @@ nsImageBoxFrame::MarkIntrinsicWidthsDirt
 {
   SizeNeedsRecalc(mImageSize);
   nsLeafBoxFrame::MarkIntrinsicWidthsDirty();
 }
 
 void
 nsImageBoxFrame::DestroyFrom(nsIFrame* aDestructRoot)
 {
-  // Release image loader first so that it's refcnt can go to zero
-  if (mImageRequest)
+  if (mImageRequest) {
+    nsPresContext* presContext = PresContext();
+    NS_ASSERTION(presContext, "No PresContext");
+    nsLayoutUtils::DeregisterImageRequest(presContext,
+                                          mImageRequest,
+                                          &mRequestRegistered);
+
+    // Release image loader first so that it's refcnt can go to zero
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
+  }
 
   if (mListener)
     reinterpret_cast<nsImageBoxListener*>(mListener.get())->SetFrame(nsnull); // set the frame to null so we don't send messages to a dead object.
 
   nsLeafBoxFrame::DestroyFrom(aDestructRoot);
 }
 
 
@@ -232,17 +241,22 @@ nsImageBoxFrame::Init(nsIContent*      a
   UpdateImage();
 
   return rv;
 }
 
 void
 nsImageBoxFrame::UpdateImage()
 {
+  nsPresContext* presContext = PresContext();
+  NS_ASSERTION(presContext, "No PresContext");
+
   if (mImageRequest) {
+    nsLayoutUtils::DeregisterImageRequest(presContext, mImageRequest,
+                                          &mRequestRegistered);
     mImageRequest->CancelAndForgetObserver(NS_ERROR_FAILURE);
     mImageRequest = nsnull;
   }
 
   // get the new image src
   nsAutoString src;
   mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::src, src);
   mUseSrcAttr = !src.IsEmpty();
@@ -259,16 +273,22 @@ nsImageBoxFrame::UpdateImage()
                                               doc,
                                               baseURI);
 
     if (uri && nsContentUtils::CanLoadImage(uri, mContent, doc,
                                             mContent->NodePrincipal())) {
       nsContentUtils::LoadImage(uri, doc, mContent->NodePrincipal(),
                                 doc->GetDocumentURI(), mListener, mLoadFlags,
                                 getter_AddRefs(mImageRequest));
+
+      // Register our imgIRequest with the refresh driver
+      nsLayoutUtils::RegisterImageRequest(presContext,
+                                          mImageRequest,
+                                          &mRequestRegistered);
+
     }
   } else {
     // Only get the list-style-image if we aren't being drawn
     // by a native theme.
     PRUint8 appearance = GetStyleDisplay()->mAppearance;
     if (!(appearance && nsBox::gTheme && 
           nsBox::gTheme->ThemeSupportsWidget(nsnull, this, appearance))) {
       // get the list-style-image
@@ -583,20 +603,41 @@ NS_IMETHODIMP nsImageBoxFrame::OnStopCon
                                                imgIContainer *image)
 {
   nsBoxLayoutState state(PresContext());
   this->Redraw(state);
 
   return NS_OK;
 }
 
+NS_IMETHODIMP nsImageBoxFrame::OnStartDecode(imgIRequest* aRequest)
+{
+  nsPresContext* presContext = PresContext();
+  NS_ASSERTION(presContext, "No PresContext");
+
+  nsLayoutUtils::RegisterImageRequest(presContext,
+                                      mImageRequest,
+                                      &mRequestRegistered);
+
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsImageBoxFrame::OnStopDecode(imgIRequest *request,
                                             nsresult aStatus,
                                             const PRUnichar *statusArg)
 {
+  // If the imgIRequest does not represent an animated image, then we should
+  // deregister it from our refresh driver.
+  nsPresContext* presContext = PresContext();
+  NS_ASSERTION(presContext, "No PresContext");
+
+  nsLayoutUtils::DeregisterImageRequestIfNotAnimated(presContext,
+                                                     mImageRequest,
+                                                     &mRequestRegistered);
+
   if (NS_SUCCEEDED(aStatus))
     // Fire an onload DOM event.
     FireImageDOMEvent(mContent, NS_LOAD);
   else {
     // Fire an onerror DOM event.
     mIntrinsicSize.SizeTo(0, 0);
     PresContext()->PresShell()->
       FrameNeedsReflow(this, nsIPresShell::eStyleChange, NS_FRAME_IS_DIRTY);
@@ -624,36 +665,45 @@ nsImageBoxListener::nsImageBoxListener()
 nsImageBoxListener::~nsImageBoxListener()
 {
 }
 
 NS_IMETHODIMP nsImageBoxListener::OnStartContainer(imgIRequest *request,
                                                    imgIContainer *image)
 {
   if (!mFrame)
-    return NS_ERROR_FAILURE;
+    return NS_OK;
 
   return mFrame->OnStartContainer(request, image);
 }
 
 NS_IMETHODIMP nsImageBoxListener::OnStopContainer(imgIRequest *request,
                                                   imgIContainer *image)
 {
   if (!mFrame)
-    return NS_ERROR_FAILURE;
+    return NS_OK;
 
   return mFrame->OnStopContainer(request, image);
 }
 
+NS_IMETHODIMP nsImageBoxListener::OnStartDecode(imgIRequest *aRequest)
+{
+  if (!mFrame) {
+    return NS_OK;
+  }
+
+  return mFrame->OnStartDecode(aRequest);
+}
+
 NS_IMETHODIMP nsImageBoxListener::OnStopDecode(imgIRequest *request,
                                                nsresult status,
                                                const PRUnichar *statusArg)
 {
   if (!mFrame)
-    return NS_ERROR_FAILURE;
+    return NS_OK;
 
   return mFrame->OnStopDecode(request, status, statusArg);
 }
 
 NS_IMETHODIMP nsImageBoxListener::FrameChanged(imgIContainer *aContainer,
                                                const nsIntRect *aDirtyRect)
 {
   if (!mFrame)
--- a/layout/xul/base/src/nsImageBoxFrame.h
+++ b/layout/xul/base/src/nsImageBoxFrame.h
@@ -51,16 +51,17 @@ class nsImageBoxListener : public nsStub
 public:
   nsImageBoxListener();
   virtual ~nsImageBoxListener();
 
   NS_DECL_ISUPPORTS
   // imgIDecoderObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
   NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
+  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *request, nsresult status,
                           const PRUnichar *statusArg);
   // imgIContainerObserver (override nsStubImageDecoderObserver)
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   void SetFrame(nsImageBoxFrame *frame) { mFrame = frame; }
 
@@ -114,16 +115,17 @@ public:
   void UpdateLoadFlags();
 
   NS_IMETHOD BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                               const nsRect&           aDirtyRect,
                               const nsDisplayListSet& aLists);
 
   NS_IMETHOD OnStartContainer(imgIRequest *request, imgIContainer *image);
   NS_IMETHOD OnStopContainer(imgIRequest *request, imgIContainer *image);
+  NS_IMETHOD OnStartDecode(imgIRequest *aRequest);
   NS_IMETHOD OnStopDecode(imgIRequest *request,
                           nsresult status,
                           const PRUnichar *statusArg);
   NS_IMETHOD FrameChanged(imgIContainer *aContainer,
                           const nsIntRect *aDirtyRect);
 
   virtual ~nsImageBoxFrame();
 
@@ -137,16 +139,20 @@ protected:
   virtual void GetImageSize();
 
 private:
 
   nsRect mSubRect; ///< If set, indicates that only the portion of the image specified by the rect should be used.
   nsSize mIntrinsicSize;
   nsSize mImageSize;
 
+  // Boolean variable to determine if the current image request has been
+  // registered with the refresh driver.
+  bool mRequestRegistered;
+
   nsCOMPtr<imgIRequest> mImageRequest;
   nsCOMPtr<imgIDecoderObserver> mListener;
 
   PRInt32 mLoadFlags;
 
   bool mUseSrcAttr; ///< Whether or not the image src comes from an attribute.
   bool mSuppressStyleCheck;
 }; // class nsImageBoxFrame