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
--- 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)