Bug 1152326 - When processing plugin updates only update the visibility of the set of plugins associated with the same compositor. r=aklotz
authorJim Mathies <jmathies@mozilla.com>
Wed, 17 Jun 2015 15:39:09 -0500
changeset 280364 24c16a06692ed48865c887d2cb71cf347002f67a
parent 280363 b812439bc1ff0127a3225360d2615dbb97a70344
child 280365 355d8b0c09ef0fba70a768f79d4fe85e993afafe
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaklotz
bugs1152326
milestone41.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 1152326 - When processing plugin updates only update the visibility of the set of plugins associated with the same compositor. r=aklotz
gfx/layers/ipc/CompositorChild.cpp
gfx/layers/ipc/CompositorChild.h
gfx/layers/ipc/CompositorParent.cpp
gfx/layers/ipc/CompositorParent.h
gfx/layers/ipc/PCompositor.ipdl
widget/nsBaseWidget.cpp
widget/nsIWidget.h
--- a/gfx/layers/ipc/CompositorChild.cpp
+++ b/gfx/layers/ipc/CompositorChild.cpp
@@ -257,24 +257,27 @@ CompositorChild::RecvUpdatePluginConfigu
   // Now that we are on the main thread, update plugin widget config.
   // This should happen a little before we paint to the screen assuming
   // the main thread is running freely.
   DebugOnly<nsresult> rv;
   MOZ_ASSERT(NS_IsMainThread());
 
   // Tracks visible plugins we update, so we can hide any plugins we don't.
   nsTArray<uintptr_t> visiblePluginIds;
-
+  nsIWidget* parent = nullptr;
   for (uint32_t pluginsIdx = 0; pluginsIdx < aPlugins.Length(); pluginsIdx++) {
     nsIWidget* widget =
       nsIWidget::LookupRegisteredPluginWindow(aPlugins[pluginsIdx].windowId());
     if (!widget) {
       NS_WARNING("Unexpected, plugin id not found!");
       continue;
     }
+    if (!parent) {
+      parent = widget->GetParent();
+    }
     bool isVisible = aPlugins[pluginsIdx].visible();
     if (widget && !widget->Destroyed()) {
       gfx::IntRect bounds;
       gfx::IntRect visibleBounds;
       // If the plugin is visible update it's geometry.
       if (isVisible) {
         // bounds (content origin) - don't pass true to Resize, it triggers a
         // sync paint update to the plugin process on Windows, which happens
@@ -316,31 +319,32 @@ CompositorChild::RecvUpdatePluginConfigu
         NS_ASSERTION(NS_SUCCEEDED(rv), "widget call failure");
 #endif
         visiblePluginIds.AppendElement(aPlugins[pluginsIdx].windowId());
       }
     }
   }
   // Any plugins we didn't update need to be hidden, as they are
   // not associated with visible content.
-  nsIWidget::UpdateRegisteredPluginWindowVisibility(visiblePluginIds);
+  nsIWidget::UpdateRegisteredPluginWindowVisibility((uintptr_t)parent, visiblePluginIds);
   return true;
 #endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
 }
 
 bool
-CompositorChild::RecvUpdatePluginVisibility(nsTArray<uintptr_t>&& aVisibleIdList)
+CompositorChild::RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
+                                            nsTArray<uintptr_t>&& aVisibleIdList)
 {
 #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
   NS_NOTREACHED("CompositorChild::RecvUpdatePluginVisibility calls "
                 "unexpected on this platform.");
   return false;
 #else
   MOZ_ASSERT(NS_IsMainThread());
-  nsIWidget::UpdateRegisteredPluginWindowVisibility(aVisibleIdList);
+  nsIWidget::UpdateRegisteredPluginWindowVisibility(aOwnerWidget, aVisibleIdList);
   return true;
 #endif // !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
 }
 
 bool
 CompositorChild::RecvDidComposite(const uint64_t& aId, const uint64_t& aTransactionId)
 {
   if (mLayerManager) {
--- a/gfx/layers/ipc/CompositorChild.h
+++ b/gfx/layers/ipc/CompositorChild.h
@@ -83,17 +83,18 @@ public:
   RecvOverfill(const uint32_t &aOverfill) override;
 
   virtual bool
   RecvUpdatePluginConfigurations(const nsIntPoint& aContentOffset,
                                  const nsIntRegion& aVisibleRegion,
                                  nsTArray<PluginWindowData>&& aPlugins) override;
 
   virtual bool
-  RecvUpdatePluginVisibility(nsTArray<uintptr_t>&& aWindowList) override;
+  RecvUpdatePluginVisibility(const uintptr_t& aOwnerWidget,
+                             nsTArray<uintptr_t>&& aWindowList) override;
 
   /**
    * Request that the parent tell us when graphics are ready on GPU.
    * When we get that message, we bounce it to the TabParent via
    * the TabChild
    * @param tabChild The object to bounce the note to.  Non-NULL.
    */
   void RequestNotifyAfterRemotePaint(TabChild* aTabChild);
--- a/gfx/layers/ipc/CompositorParent.cpp
+++ b/gfx/layers/ipc/CompositorParent.cpp
@@ -1435,22 +1435,19 @@ CompositorParent::InitializeLayerManager
 PLayerTransactionParent*
 CompositorParent::AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
                                                const uint64_t& aId,
                                                TextureFactoryIdentifier* aTextureFactoryIdentifier,
                                                bool *aSuccess)
 {
   MOZ_ASSERT(aId == 0);
 
-  // mWidget doesn't belong to the compositor thread, so it should be set to
-  // nullptr before returning from this method, to avoid accessing it elsewhere.
   gfx::IntRect rect;
   mWidget->GetClientBounds(rect);
   InitializeLayerManager(aBackendHints);
-  mWidget = nullptr;
 
   if (!mLayerManager) {
     NS_WARNING("Failed to initialise Compositor");
     *aSuccess = false;
     LayerTransactionParent* p = new LayerTransactionParent(nullptr, this, 0);
     p->AddIPDLReference();
     return p;
   }
@@ -2032,17 +2029,19 @@ UpdatePluginWindowState(uint64_t aId)
                           !lts.mUpdatedPluginDataAvailable;
   if (shouldComposePlugin) {
     if (!lts.mPluginData.Length()) {
       // We will pass through here in cases where the previous shadow layer
       // tree contained visible plugins and the new tree does not. All we need
       // to do here is hide the plugins for the old tree, so don't waste time
       // calculating clipping.
       nsTArray<uintptr_t> aVisibleIdList;
-      unused << lts.mParent->SendUpdatePluginVisibility(aVisibleIdList);
+      uintptr_t parentWidget = (uintptr_t)lts.mParent->GetWidget();
+      unused << lts.mParent->SendUpdatePluginVisibility(parentWidget,
+                                                        aVisibleIdList);
       lts.mUpdatedPluginDataAvailable = false;
       return;
     }
 
     // Retrieve the offset and visible region of the layer that hosts
     // the plugins, CompositorChild needs these in calculating proper
     // plugin clipping.
     LayerTransactionParent* layerTree = lts.mLayerTree;
--- a/gfx/layers/ipc/CompositorParent.h
+++ b/gfx/layers/ipc/CompositorParent.h
@@ -419,16 +419,18 @@ public:
 
   float ComputeRenderIntegrity();
 
   /**
    * Returns true if the calling thread is the compositor thread.
    */
   static bool IsInCompositorThread();
 
+  nsIWidget* GetWidget() { return mWidget; }
+
 protected:
   // Protected destructor, to discourage deletion outside of Release():
   virtual ~CompositorParent();
 
   void DeferredDestroy();
 
   virtual PLayerTransactionParent*
     AllocPLayerTransactionParent(const nsTArray<LayersBackend>& aBackendHints,
--- a/gfx/layers/ipc/PCompositor.ipdl
+++ b/gfx/layers/ipc/PCompositor.ipdl
@@ -64,17 +64,18 @@ child:
   async UpdatePluginConfigurations(IntPoint aContentOffset,
                                    nsIntRegion aVisibleRegion,
                                    PluginWindowData[] aPlugins);
 
   /**
    * Sets the list of currently visible plugin windows based on a
    * list of plugin window ids.
    */
-  async UpdatePluginVisibility(uintptr_t[] aVisibleIdList);
+  async UpdatePluginVisibility(uintptr_t aOwnerWidget,
+                               uintptr_t[] aVisibleIdList);
 
   /**
    * Drop any buffers that might be retained on the child compositor
    * side.
    */
   async ClearCachedResources(uint64_t id);
 
 parent:
--- a/widget/nsBaseWidget.cpp
+++ b/widget/nsBaseWidget.cpp
@@ -1895,42 +1895,56 @@ nsIWidget::LookupRegisteredPluginWindow(
   nsIWidget* widget = nullptr;
   MOZ_ASSERT(sPluginWidgetList);
   sPluginWidgetList->Get((void*)aWindowID, &widget);
   return widget;
 #endif
 }
 
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
+struct VisEnumContext {
+  uintptr_t parentWidget;
+  const nsTArray<uintptr_t>* list;
+};
+
 static PLDHashOperator
 RegisteredPluginEnumerator(const void* aWindowId, nsIWidget* aWidget, void* aUserArg)
 {
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(aWindowId);
   MOZ_ASSERT(aWidget);
   MOZ_ASSERT(aUserArg);
-  const nsTArray<uintptr_t>* visible = static_cast<const nsTArray<uintptr_t>*>(aUserArg);
-  if (!visible->Contains((uintptr_t)aWindowId) && !aWidget->Destroyed()) {
-    aWidget->Show(false);
+
+  if (!aWidget->Destroyed()) {
+    VisEnumContext* pctx = static_cast<VisEnumContext*>(aUserArg);
+    if ((uintptr_t)aWidget->GetParent() == pctx->parentWidget &&
+        !pctx->list->Contains((uintptr_t)aWindowId)) {
+      aWidget->Show(false);
+    }
   }
   return PLDHashOperator::PL_DHASH_NEXT;
 }
 #endif
 
 // static
 void
-nsIWidget::UpdateRegisteredPluginWindowVisibility(nsTArray<uintptr_t>& aVisibleList)
+nsIWidget::UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
+                                                  nsTArray<uintptr_t>& aVisibleList)
 {
 #if !defined(XP_WIN) && !defined(MOZ_WIDGET_GTK)
   NS_NOTREACHED("nsBaseWidget::UpdateRegisteredPluginWindowVisibility not implemented!");
   return;
 #else
   MOZ_ASSERT(NS_IsMainThread());
   MOZ_ASSERT(sPluginWidgetList);
-  sPluginWidgetList->EnumerateRead(RegisteredPluginEnumerator, static_cast<void*>(&aVisibleList));
+  // Our visible list is associated with a compositor which is associated with
+  // a specific top level window. We hand the parent widget in here so the
+  // enumerator can skip the plugin widgets owned by other top level windows.
+  VisEnumContext ctx = { aOwnerWidget, &aVisibleList };
+  sPluginWidgetList->EnumerateRead(RegisteredPluginEnumerator, static_cast<void*>(&ctx));
 #endif
 }
 
 TemporaryRef<mozilla::gfx::SourceSurface>
 nsIWidget::SnapshotWidgetOnScreen()
 {
   // This is only supported on a widget with a compositor.
   LayerManager* layerManager = GetLayerManager();
--- a/widget/nsIWidget.h
+++ b/widget/nsIWidget.h
@@ -1521,17 +1521,18 @@ class nsIWidget : public nsISupports {
     /**
      * Iterates across the list of registered plugin widgets and updates thier
      * visibility based on which plugins are included in the 'visible' list.
      *
      * The compositor knows little about tabs, but it does know which plugin
      * widgets are currently included in the visible layer tree. It calls this
      * helper to hide widgets it knows nothing about.
      */
-    static void UpdateRegisteredPluginWindowVisibility(nsTArray<uintptr_t>& aVisibleList);
+    static void UpdateRegisteredPluginWindowVisibility(uintptr_t aOwnerWidget,
+                                                       nsTArray<uintptr_t>& aVisibleList);
 
     /**
      * Set the shadow style of the window.
      *
      * Ignored on child widgets and on non-Mac platforms.
      */
     NS_IMETHOD SetWindowShadowStyle(int32_t aStyle) = 0;