Bug 642257. If there are no plugins in the display list skip a potentially expensive compute visibility pass with accurate visible regions to determine plugin geometry because it is not needed. r=roc
authorTimothy Nikkel <tnikkel@gmail.com>
Thu, 18 Oct 2012 00:34:58 -0500
changeset 110766 87df09bc5e8e44547fd1669ae04580326c4c935c
parent 110765 40cca178608aaa7f859c6b607a42a80b63ef3ffe
child 110767 fdd5c75c14f2e5b79e7505d0232d18612e7edaf3
push id93
push usernmatsakis@mozilla.com
push dateWed, 31 Oct 2012 21:26:57 +0000
reviewersroc
bugs642257
milestone19.0a1
Bug 642257. If there are no plugins in the display list skip a potentially expensive compute visibility pass with accurate visible regions to determine plugin geometry because it is not needed. r=roc If there is a plugin in a background tab and a complex scene in a foreground tab the accurate visible regions can cause us to bog down, for no good reason.
layout/base/nsDisplayList.cpp
layout/base/nsDisplayList.h
layout/base/nsPresContext.cpp
layout/generic/nsObjectFrame.h
--- a/layout/base/nsDisplayList.cpp
+++ b/layout/base/nsDisplayList.cpp
@@ -443,17 +443,18 @@ nsDisplayListBuilder::nsDisplayListBuild
       mAllowMergingAndFlattening(true),
       mWillComputePluginGeometry(false),
       mInTransform(false),
       mSyncDecodeImages(false),
       mIsPaintingToWindow(false),
       mHasDisplayPort(false),
       mHasFixedItems(false),
       mIsInFixedPosition(false),
-      mIsCompositingCheap(false)
+      mIsCompositingCheap(false),
+      mContainsPluginItem(false)
 {
   MOZ_COUNT_CTOR(nsDisplayListBuilder);
   PL_InitArenaPool(&mPool, "displayListArena", 1024,
                    NS_MAX(NS_ALIGNMENT_OF(void*),NS_ALIGNMENT_OF(double))-1);
 
   nsPresContext* pc = aReferenceFrame->PresContext();
   nsIPresShell *shell = pc->PresShell();
   if (pc->IsRenderingOnlySelection()) {
--- a/layout/base/nsDisplayList.h
+++ b/layout/base/nsDisplayList.h
@@ -577,16 +577,19 @@ public:
     } else {
       mGlassDisplayItem = aItem;
     }
   }
   bool NeedToForceTransparentSurfaceForItem(nsDisplayItem* aItem) {
     return aItem == mGlassDisplayItem;
   }
 
+  void SetContainsPluginItem() { mContainsPluginItem = true; }
+  bool ContainsPluginItem() { return mContainsPluginItem; }
+
 private:
   void MarkOutOfFlowFrameForDisplay(nsIFrame* aDirtyFrame, nsIFrame* aFrame,
                                     const nsRect& aDirtyRect);
 
   struct PresShellState {
     nsIPresShell* mPresShell;
     nsIFrame*     mCaretFrame;
     uint32_t      mFirstFrameMarkedForDisplay;
@@ -630,16 +633,17 @@ private:
   // under an nsDisplayTransform
   bool                           mInTransform;
   bool                           mSyncDecodeImages;
   bool                           mIsPaintingToWindow;
   bool                           mHasDisplayPort;
   bool                           mHasFixedItems;
   bool                           mIsInFixedPosition;
   bool                           mIsCompositingCheap;
+  bool                           mContainsPluginItem;
 };
 
 class nsDisplayItem;
 class nsDisplayList;
 /**
  * nsDisplayItems are put in singly-linked lists rooted in an nsDisplayList.
  * nsDisplayItemLink holds the link. The lists are linked from lowest to
  * highest in z-order.
--- a/layout/base/nsPresContext.cpp
+++ b/layout/base/nsPresContext.cpp
@@ -2539,31 +2539,30 @@ nsRootPresContext::ComputePluginGeometry
   }
 
   // Initially make the next state for each plugin descendant of aFrame be
   // "hidden". Plugins that are visible will have their next state set to
   // unhidden by nsDisplayPlugin::ComputeVisibility.
   mRegisteredPlugins.EnumerateEntries(SetPluginHidden, aFrame);
 
   nsIFrame* rootFrame = FrameManager()->GetRootFrame();
-  if (!rootFrame) {
-    return;
+
+  if (rootFrame && aBuilder->ContainsPluginItem()) {
+    aBuilder->SetForPluginGeometry();
+    aBuilder->SetAccurateVisibleRegions();
+    // Merging and flattening has already been done and we should not do it
+    // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
+    // again.
+    aBuilder->SetAllowMergingAndFlattening(false);
+    nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
+    // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
+    // widget configuration for the plugin, if it's visible.
+    aList->ComputeVisibilityForRoot(aBuilder, &region);
   }
 
-  aBuilder->SetForPluginGeometry();
-  aBuilder->SetAccurateVisibleRegions();
-  // Merging and flattening has already been done and we should not do it
-  // again. nsDisplayScroll(Info)Layer doesn't support trying to flatten
-  // again.
-  aBuilder->SetAllowMergingAndFlattening(false);
-  nsRegion region = rootFrame->GetVisualOverflowRectRelativeToSelf();
-  // nsDisplayPlugin::ComputeVisibility will automatically set a non-hidden
-  // widget configuration for the plugin, if it's visible.
-  aList->ComputeVisibilityForRoot(aBuilder, &region);
-
   InitApplyPluginGeometryTimer();
 }
 
 static void
 ApplyPluginGeometryUpdatesCallback(nsITimer *aTimer, void *aClosure)
 {
   static_cast<nsRootPresContext*>(aClosure)->ApplyPluginGeometryUpdates();
 }
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -294,16 +294,17 @@ private:
 };
 
 class nsDisplayPlugin : public nsDisplayItem {
 public:
   nsDisplayPlugin(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
     : nsDisplayItem(aBuilder, aFrame)
   {
     MOZ_COUNT_CTOR(nsDisplayPlugin);
+    aBuilder->SetContainsPluginItem();
   }
 #ifdef NS_BUILD_REFCNT_LOGGING
   virtual ~nsDisplayPlugin() {
     MOZ_COUNT_DTOR(nsDisplayPlugin);
   }
 #endif
 
   virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder, bool* aSnap) MOZ_OVERRIDE;