Bug 784846 - The ShouldPrerender check for async animations is wrong r=mattwoodrow
authorDavid Zbarsky <dzbarsky@gmail.com>
Thu, 23 Aug 2012 02:05:27 -0400
changeset 103144 2a645c4ea73f4401e30ae3a74fceaa16e1238595
parent 103143 96cd349f463be14d49ed4f2d0a0eadac130d0a96
child 103145 167fdd4db264a8bd9dea4295c6131175262045eb
push id23332
push userryanvm@gmail.com
push dateFri, 24 Aug 2012 02:06:52 +0000
treeherdermozilla-central@e509c7472f30 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs784846
milestone17.0a1
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 784846 - The ShouldPrerender check for async animations is wrong r=mattwoodrow
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -340,17 +340,17 @@ AddAnimationsAndTransitionsToLayer(Layer
     nsAnimationManager::GetAnimationsForCompositor(aContent, aProperty);
 
   if (!ea && !et) {
     return;
   }
 
   // If the frame is not prerendered, bail out.  Layout will still perform the
   // animation.
-  if (!nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder, frame)) {
+  if (!aItem->CanUseAsyncAnimations(aBuilder)) {
     if (nsLayoutUtils::IsAnimationLoggingEnabled()) {
       printf_stderr("Performance warning: Async animation disabled because the frame for element '%s'",
                     nsAtomCString(aContent->Tag()).get());
       nsIAtom* id = aContent->GetID();
       if (id) {
         printf_stderr(" with id '%s'",
                       nsAtomCString(aContent->GetID()).get());
       }
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -905,23 +905,30 @@ public:
    */
   virtual nsRect GetComponentAlphaBounds(nsDisplayListBuilder* aBuilder) { return nsRect(); }
 
   /**
    * Disable usage of component alpha. Currently only relevant for items that have text.
    */
   virtual void DisableComponentAlpha() {}
 
+  /**
+   * Check if we can add async animations to the layer for this display item.
+   */
+  virtual bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
+    return false;
+  }
+
 protected:
   friend class nsDisplayList;
-  
+
   nsDisplayItem() {
     mAbove = nullptr;
   }
-  
+
   nsIFrame* mFrame;
   // Result of ToReferenceFrame(mFrame), if mFrame is non-null
   nsPoint   mToReferenceFrame;
   // This is the rectangle that needs to be painted.
   // nsDisplayList::ComputeVisibility sets this to the visible region
   // of the item by intersecting the current visible region with the bounds
   // of the item. Paint implementations can use this to limit their drawing.
   // Guaranteed to be contained in GetBounds().
@@ -1868,42 +1875,46 @@ public:
 
   nsresult WrapLists(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                      const nsDisplayListSet& aIn, const nsDisplayListSet& aOut);
   nsresult WrapListsInPlace(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                             const nsDisplayListSet& aLists);
 protected:
   nsDisplayWrapper() {}
 };
-                              
+
 /**
  * The standard display item to paint a stacking context with translucency
  * set by the stacking context root frame's 'opacity' style.
  */
 class nsDisplayOpacity : public nsDisplayWrapList {
 public:
   nsDisplayOpacity(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame,
                    nsDisplayList* aList);
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayOpacity();
 #endif
-  
+
   virtual nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                    bool* aSnap);
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager,
                                              const ContainerParameters& aContainerParameters);
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager,
                                    const ContainerParameters& aParameters);
   virtual bool ComputeVisibility(nsDisplayListBuilder* aBuilder,
                                    nsRegion* aVisibleRegion,
                                    const nsRect& aAllowVisibleRegionExpansion);  
   virtual bool TryMerge(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem);
   NS_DISPLAY_DECL_NAME("Opacity", TYPE_OPACITY)
+
+  bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
+    return GetUnderlyingFrame()->AreLayersMarkedActive(nsChangeHint_UpdateOpacityLayer);
+  }
 };
 
 /**
  * A display item that has no purpose but to ensure its contents get
  * their own layer.
  */
 class nsDisplayOwnLayer : public nsDisplayWrapList {
 public:
@@ -2405,16 +2416,20 @@ public:
                                                  nscoord* aChildPerspective = nullptr,
                                                  nsIFrame** aOutAncestor = nullptr);
   /**
    * Return true when we should try to prerender the entire contents of the
    * transformed frame even when it's not completely visible (yet).
    */
   static bool ShouldPrerenderTransformedContent(nsDisplayListBuilder* aBuilder,
                                                 nsIFrame* aFrame);
+  bool CanUseAsyncAnimations(nsDisplayListBuilder* aBuilder) {
+    return nsDisplayTransform::ShouldPrerenderTransformedContent(aBuilder,
+                                                                 GetUnderlyingFrame());
+  }
 
 private:
   nsDisplayWrapList mStoredList;
   gfx3DMatrix mTransform;
   float mCachedAppUnitsPerPixel;
   uint32_t mIndex;
 };