Bug 637901 - Don't trash our cached ImageContainer unless the retained layer manager has changed. r=tnikkel a=blocking2.0
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 02 Mar 2011 21:53:27 +1300
changeset 63255 01037ab16a65c001367054e5837a6376825c8b7f
parent 63254 919f15d71153a0d7de08928b7184b66edf959591
child 63256 dd542a890eb7c5f37cb36c40594a274be2c44dae
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerstnikkel, blocking2
bugs637901
milestone2.0b13pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 637901 - Don't trash our cached ImageContainer unless the retained layer manager has changed. r=tnikkel a=blocking2.0
content/base/public/nsContentUtils.h
content/base/src/nsContentUtils.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/content/base/public/nsContentUtils.h
+++ b/content/base/public/nsContentUtils.h
@@ -1694,39 +1694,39 @@ public:
                                          nsIDOMNodeList** aReturn);
 
   /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager.
    *
-   * If one can't be found, a BasicLayerManager is created and returned.
-   *
    * @param aDoc the document for which to return a layer manager.
+   * @param aAllowRetaining an outparam that states whether the returned
+   * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
-  LayerManagerForDocument(nsIDocument *aDoc);
+  LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining = nsnull);
 
   /**
    * Returns a layer manager to use for the given document. Basically we
    * look up the document hierarchy for the first document which has
    * a presentation with an associated widget, and use that widget's
    * layer manager. In addition to the normal layer manager lookup this will
    * specifically request a persistent layer manager. This means that the layer
    * manager is expected to remain the layer manager for the document in the
    * forseeable future. This function should be used carefully as it may change
    * the document's layer manager.
    *
-   * If one can't be found, a BasicLayerManager is created and returned.
-   *
    * @param aDoc the document for which to return a layer manager.
+   * @param aAllowRetaining an outparam that states whether the returned
+   * layer manager should be used for retained layers
    */
   static already_AddRefed<mozilla::layers::LayerManager>
-  PersistentLayerManagerForDocument(nsIDocument *aDoc);
+  PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining = nsnull);
 
   /**
    * Determine whether a content node is focused or not,
    *
    * @param aContent the content node to check
    * @return true if the content node is focused, false otherwise.
    */
   static PRBool IsFocusedContent(const nsIContent *aContent);
--- a/content/base/src/nsContentUtils.cpp
+++ b/content/base/src/nsContentUtils.cpp
@@ -6349,17 +6349,18 @@ static nsIView* GetDisplayRootFor(nsIVie
     if (displayRoot->GetFloating() && !displayParent->GetFloating())
       return displayRoot;
     displayRoot = displayParent;
   }
   return nsnull;
 }
 
 static already_AddRefed<LayerManager>
-LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent)
+LayerManagerForDocumentInternal(nsIDocument *aDoc, bool aRequirePersistent,
+                                bool* aAllowRetaining)
 {
   nsIDocument* doc = aDoc;
   nsIDocument* displayDoc = doc->GetDisplayDocument();
   if (displayDoc) {
     doc = displayDoc;
   }
 
   nsIPresShell* shell = doc->GetShell();
@@ -6389,37 +6390,38 @@ LayerManagerForDocumentInternal(nsIDocum
       if (NS_SUCCEEDED(VM->GetRootView(rootView)) && rootView) {
         nsIView* displayRoot = GetDisplayRootFor(rootView);
         if (displayRoot) {
           nsIWidget* widget = displayRoot->GetNearestWidget(nsnull);
           if (widget) {
             nsRefPtr<LayerManager> manager =
               static_cast<nsIWidget_MOZILLA_2_0_BRANCH*>(widget)->
                 GetLayerManager(aRequirePersistent ? nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_PERSISTENT : 
-                                                     nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_CURRENT);
+                                                     nsIWidget_MOZILLA_2_0_BRANCH::LAYER_MANAGER_CURRENT,
+                                aAllowRetaining);
             return manager.forget();
           }
         }
       }
     }
   }
 
   return nsnull;
 }
 
 already_AddRefed<LayerManager>
-nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc)
-{
-  return LayerManagerForDocumentInternal(aDoc, false);
+nsContentUtils::LayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
+{
+  return LayerManagerForDocumentInternal(aDoc, false, aAllowRetaining);
 }
 
 already_AddRefed<LayerManager>
-nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc)
-{
-  return LayerManagerForDocumentInternal(aDoc, true);
+nsContentUtils::PersistentLayerManagerForDocument(nsIDocument *aDoc, bool *aAllowRetaining)
+{
+  return LayerManagerForDocumentInternal(aDoc, true, aAllowRetaining);
 }
 
 bool
 nsContentUtils::AllowXULXBLForPrincipal(nsIPrincipal* aPrincipal)
 {
   if (IsSystemPrincipal(aPrincipal)) {
     return true;
   }
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1637,17 +1637,17 @@ nsObjectFrame::BuildDisplayList(nsDispla
     mInstanceOwner->GetWindow(window);
     PRBool isVisible = window && window->width > 0 && window->height > 0;
     if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
   #ifndef XP_MACOSX
       mInstanceOwner->UpdateWindowVisibility(PR_TRUE);
   #endif
     }
 
-    ImageContainer* container = GetImageContainer();
+    nsRefPtr<ImageContainer> container = GetImageContainer();
     nsRefPtr<Image> currentImage = container ? container->GetCurrentImage() : nsnull;
     if (!currentImage || !isVisible ||
         container->GetCurrentSize() != gfxIntSize(window->width, window->height)) {
       mInstanceOwner->NotifyPaintWaiter(aBuilder);
     }
   }
 
   // determine if we are printing
@@ -1879,41 +1879,53 @@ nsObjectFrame::PrintPlugin(nsIRenderingC
 
   // XXX Nav 4.x always sent a SetWindow call after print. Should we do the same?
   // XXX Calling DidReflow here makes no sense!!!
   nsDidReflowStatus status = NS_FRAME_REFLOW_FINISHED; // should we use a special status?
   frame->DidReflow(presContext,
                    nsnull, status);  // DidReflow will take care of it
 }
 
-ImageContainer*
+already_AddRefed<ImageContainer>
 nsObjectFrame::GetImageContainer(LayerManager* aManager)
 {
   nsRefPtr<LayerManager> manager = aManager;
+  bool retain = false;
 
   if (!manager) {
-    manager = nsContentUtils::LayerManagerForDocument(mContent->GetOwnerDoc());
+    manager = nsContentUtils::LayerManagerForDocument(mContent->GetOwnerDoc(), &retain);
   }
   if (!manager) {
     return nsnull;
   }
+  
+  nsRefPtr<ImageContainer> container;
 
   // XXX - in the future image containers will be manager independent and
   // we can remove the manager equals check and only check the backend type.
   if (mImageContainer) {
     if ((!mImageContainer->Manager() || mImageContainer->Manager() == manager) &&
-        mImageContainer->GetBackendType() == manager->GetBackendType())
-      return mImageContainer;
+        mImageContainer->GetBackendType() == manager->GetBackendType()) {
+      container = mImageContainer;
+      return container.forget();
+    }
+  }
+
+  container = manager->CreateImageContainer();
+
+  if (retain) {
     // Clear current image before we reset mImageContainer. Only mImageContainer
     // is allowed to contain the image for this plugin.
-    mImageContainer->SetCurrentImage(nsnull);
-  }
-
-  mImageContainer = manager->CreateImageContainer();
-  return mImageContainer;
+    if (mImageContainer) {
+      mImageContainer->SetCurrentImage(nsnull);
+    }
+    mImageContainer = container;
+  }
+
+  return container.forget();
 }
 
 nsRect
 nsObjectFrame::GetPaintedRect(nsDisplayPlugin* aItem)
 {
   if (!mInstanceOwner)
     return nsRect();
   nsRect r = GetContentRect() - GetPosition();
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -186,17 +186,17 @@ public:
    */
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem);
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager);
 
-  ImageContainer* GetImageContainer(LayerManager* aManager = nsnull);
+  already_AddRefed<ImageContainer> GetImageContainer(LayerManager* aManager = nsnull);
   /**
    * Get the rectangle (relative to this frame) which it will paint. Normally
    * the frame's content-box but may be smaller if the plugin is rendering
    * asynchronously and has a different-sized image temporarily.
    */
   nsRect GetPaintedRect(nsDisplayPlugin* aItem);
 
   /**