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 110634 87df09bc5e8e44547fd1669ae04580326c4c935c
parent 110633 40cca178608aaa7f859c6b607a42a80b63ef3ffe
child 110635 fdd5c75c14f2e5b79e7505d0232d18612e7edaf3
push id23704
push useremorley@mozilla.com
push dateThu, 18 Oct 2012 17:12:58 +0000
treeherdermozilla-central@3779eb3f036f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersroc
bugs642257
milestone19.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 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;