Bug 1232181 - Add an image layer for plugin frames that represent windowed plugins on platforms that support scroll capture. r=roc draft
authorJim Mathies <jmathies@mozilla.com>
Fri, 26 Feb 2016 08:57:56 -0600
changeset 334923 90f700ab99fe479f110b035a2cce445f953d17cd
parent 334922 3dd84a3fb6804135fc73452392b2a41c7797f1bc
child 334924 fb9c550d86c20531c12c35614e50750520d51e5e
push id11672
push userjmathies@mozilla.com
push dateFri, 26 Feb 2016 14:58:31 +0000
reviewersroc
bugs1232181
milestone47.0a1
Bug 1232181 - Add an image layer for plugin frames that represent windowed plugins on platforms that support scroll capture. r=roc MozReview-Commit-ID: qjBiIrMyAt
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
layout/generic/nsPluginFrame.cpp
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -207,16 +207,31 @@ AttachToContainerAsSurfaceTexture(ImageC
   RefPtr<Image> img = new SurfaceTextureImage(
     surfTex,
     gfx::IntSize(rect.width, rect.height),
     instance->OriginPos());
   *out_image = img;
 }
 #endif
 
+bool
+nsPluginInstanceOwner::NeedsScrollImageLayer()
+{
+#if defined(XP_WIN)
+  // If this is a windowed plugin and we're doing layout in the content
+  // process, force the creation of an image layer for the plugin. We'll
+  // paint to this when scrolling.
+  return XRE_IsContentProcess() &&
+         mPluginWindow &&
+         mPluginWindow->type == NPWindowTypeWindow;
+#else
+  return false;
+#endif
+}
+
 already_AddRefed<ImageContainer>
 nsPluginInstanceOwner::GetImageContainer()
 {
   if (!mInstance)
     return nullptr;
 
   RefPtr<ImageContainer> container;
 
@@ -242,17 +257,25 @@ nsPluginInstanceOwner::GetImageContainer
   if (!img) {
     AttachToContainerAsSurfaceTexture(container, mInstance, r, &img);
   }
 
   if (img) {
     container->SetCurrentImageInTransaction(img);
   }
 #else
-  mInstance->GetImageContainer(getter_AddRefs(container));
+  if (NeedsScrollImageLayer()) {
+    // windowed plugin under e10s
+#if defined(XP_WIN)
+    mInstance->GetScrollCaptureContainer(getter_AddRefs(container));
+#endif
+  } else {
+    // async windowless rendering
+    mInstance->GetImageContainer(getter_AddRefs(container));
+  }
 #endif
 
   return container.forget();
 }
 
 void
 nsPluginInstanceOwner::DidComposite()
 {
@@ -624,24 +647,28 @@ NS_IMETHODIMP nsPluginInstanceOwner::Inv
   // Each time an asynchronously-drawing plugin sends a new surface to display,
   // the image in the ImageContainer is updated and InvalidateRect is called.
   // There are different side effects for (sync) Android plugins.
   RefPtr<ImageContainer> container;
   mInstance->GetImageContainer(getter_AddRefs(container));
 #endif
 
 #ifndef XP_MACOSX
-  // Windowed plugins should not be calling NPN_InvalidateRect, but
-  // Silverlight does and expects it to "work"
+  // Silverlight calls invalidate for windowed plugins so this needs to work.
   if (mWidget) {
     mWidget->Invalidate(
       LayoutDeviceIntRect(invalidRect->left, invalidRect->top,
                           invalidRect->right - invalidRect->left,
                           invalidRect->bottom - invalidRect->top));
-    return NS_OK;
+    // Plugin instances also call invalidate when plugin windows are hidden
+    // during scrolling. In this case fall through so we invalidate the
+    // underlying layer.
+    if (!NeedsScrollImageLayer()) {
+      return NS_OK;
+    }
   }
 #endif
   nsIntRect rect(invalidRect->left,
                  invalidRect->top,
                  invalidRect->right - invalidRect->left,
                  invalidRect->bottom - invalidRect->top);
   // invalidRect is in "display pixels".  In non-HiDPI modes "display pixels"
   // are device pixels.  But in HiDPI modes each display pixel corresponds
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -223,17 +223,19 @@ public:
   {
     return strncmp(GetPluginName(), aPluginName, strlen(aPluginName)) == 0;
   }
   
   void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
 
   // Returns the image container that has our currently displayed image.
   already_AddRefed<mozilla::layers::ImageContainer> GetImageContainer();
-
+  // Returns true if this is windowed plugin that can return static captures
+  // for scroll operations.
+  bool NeedsScrollImageLayer();
   // Notification we receive from nsPluginFrame about scroll state.
   bool UpdateScrollState(bool aIsScrolling);
 
   void DidComposite();
 
   /**
    * Returns the bounds of the current async-rendered surface. This can only
    * change in response to messages received by the event loop (i.e. not during
--- a/layout/generic/nsPluginFrame.cpp
+++ b/layout/generic/nsPluginFrame.cpp
@@ -412,17 +412,18 @@ nsPluginFrame::GetWidgetConfiguration(ns
 
   nsIWidget::Configuration* configuration = aConfigurations->AppendElement();
   configuration->mChild = mWidget;
   configuration->mBounds = mNextConfigurationBounds;
   configuration->mClipRegion = mNextConfigurationClipRegion;
 #if defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
   if (XRE_IsContentProcess()) {
     configuration->mWindowID = (uintptr_t)mWidget->GetNativeData(NS_NATIVE_PLUGIN_PORT);
-    configuration->mVisible = mWidget->IsVisible();
+    configuration->mVisible = mIsHiddenDueToScroll ? false : mWidget->IsVisible();
+
   }
 #endif // defined(XP_WIN) || defined(MOZ_WIDGET_GTK)
 }
 
 void
 nsPluginFrame::GetDesiredSize(nsPresContext* aPresContext,
                               const nsHTMLReflowState& aReflowState,
                               nsHTMLReflowMetrics& aMetrics)
@@ -1116,21 +1117,23 @@ nsPluginFrame::DidSetWidgetGeometry()
       !mNextConfigurationBounds.IsEmpty());
   }
 #endif
 }
 
 bool
 nsPluginFrame::IsOpaque() const
 {
+#if defined(MOZ_WIDGET_GTK)
   // Insure underlying content gets painted when we clip windowed plugins
   // during remote content scroll operations managed by nsGfxScrollFrame.
   if (mIsHiddenDueToScroll) {
     return false;
   }
+#endif
 #if defined(XP_MACOSX)
   return false;
 #elif defined(MOZ_WIDGET_ANDROID)
   // We don't know, so just assume transparent
   return false;
 #else
   return !IsTransparentMode();
 #endif
@@ -1166,21 +1169,23 @@ nsPluginFrame::IsTransparentMode() const
 #endif
 }
 
 void
 nsPluginFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists)
 {
+#if defined(MOZ_WIDGET_GTK)
   // Clip windowed plugin frames from the list during remote content scroll
   // operations managed by nsGfxScrollFrame.
   if (mIsHiddenDueToScroll) {
     return;
   }
+#endif
 
   // XXX why are we painting collapsed object frames?
   if (!IsVisibleOrCollapsedForPainting(aBuilder))
     return;
 
   DisplayBorderBackgroundOutline(aBuilder, aLists);
 
   nsPresContext::nsPresContextType type = PresContext()->Type();
@@ -1392,16 +1397,20 @@ nsPluginFrame::GetLayerState(nsDisplayLi
     return LAYER_NONE;
 
 #ifdef MOZ_WIDGET_ANDROID
   // We always want a layer on Honeycomb and later
   if (AndroidBridge::Bridge()->GetAPIVersion() >= 11)
     return LAYER_ACTIVE;
 #endif
 
+  if (mInstanceOwner->NeedsScrollImageLayer()) {
+    return LAYER_ACTIVE;
+  }
+
   if (!mInstanceOwner->UseAsyncRendering()) {
     return LAYER_NONE;
   }
 
   return LAYER_ACTIVE_FORCE;
 }
 
 class PluginFrameDidCompositeObserver final : public ClientLayerManager::
@@ -1456,20 +1465,23 @@ nsPluginFrame::BuildLayer(nsDisplayListB
   nsRect area = GetContentRectRelativeToSelf() + aItem->ToReferenceFrame();
   gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
   // to provide crisper and faster drawing.
   r.Round();
   RefPtr<Layer> layer =
     (aManager->GetLayerBuilder()->GetLeafLayerFor(aBuilder, aItem));
 
   if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
-    // Create image
-    RefPtr<ImageContainer> container = mInstanceOwner->GetImageContainer();
+    RefPtr<ImageContainer> container;
+    // Image for Windowed plugins that support window capturing for scroll
+    // operations or async windowless rendering.
+    container = mInstanceOwner->GetImageContainer();
     if (!container) {
-      // This can occur if our instance is gone.
+      // This can occur if our instance is gone or if the current plugin
+      // configuration does not require a backing image layer.
       return nullptr;
     }
 
     if (!layer) {
       mInstanceOwner->NotifyPaintWaiter(aBuilder);
       // Initialize ImageLayer
       layer = aManager->CreateImageLayer();
       if (!layer)