Bug 626602. Part 3: Hook up ReadbackLayers in nsObjectFrame. r=cjones
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 16 Feb 2011 16:43:30 -0600
changeset 62699 bafe55cc0292b4644d40234ecdee2d6ce9d8769d
parent 62698 993a5de16346bfce428a979846fb1feed9f2d836
child 62700 892a2750be5e6a888ff6922f1b4c298b1711d6b3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscjones
bugs626602
milestone2.0b12pre
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 626602. Part 3: Hook up ReadbackLayers in nsObjectFrame. r=cjones
layout/base/nsDisplayItemTypes.h
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/layout/base/nsDisplayItemTypes.h
+++ b/layout/base/nsDisplayItemTypes.h
@@ -73,16 +73,17 @@ enum Type {
   TYPE_LIST_FOCUS,
   TYPE_OPACITY,
   TYPE_OPTION_EVENT_GRABBER,
   TYPE_OUTLINE,
   TYPE_OWN_LAYER,
   TYPE_PAGE_CONTENT,
   TYPE_PAGE_SEQUENCE,
   TYPE_PLUGIN,
+  TYPE_PLUGIN_READBACK,
   TYPE_PRINT_PREVIEW_BACKGROUND,
   TYPE_PRINT_PLUGIN,
   TYPE_REMOTE,
   TYPE_REMOTE_SHADOW,
   TYPE_SCROLL_LAYER,
   TYPE_SELECTION_OVERLAY,
   TYPE_SOLID_COLOR,
   TYPE_TABLE_CELL_BACKGROUND,
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -159,16 +159,17 @@ enum { XKeyPress = KeyPress };
 #ifdef XP_WIN
 #include "gfxWindowsNativeDrawing.h"
 #include "gfxWindowsSurface.h"
 #endif
 
 #include "gfxImageSurface.h"
 #include "gfxUtils.h"
 #include "Layers.h"
+#include "ReadbackLayer.h"
 
 // accessibility support
 #ifdef ACCESSIBILITY
 #include "nsAccessibilityService.h"
 #endif
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG 1 /* Allow logging in the release build */
@@ -233,16 +234,18 @@ using mozilla::DefaultXDisplay;
 #ifdef PR_LOGGING 
 static PRLogModuleInfo *nsObjectFrameLM = PR_NewLogModule("nsObjectFrame");
 #endif /* PR_LOGGING */
 
 #if defined(XP_MACOSX) && !defined(NP_NO_CARBON)
 #define MAC_CARBON_PLUGINS
 #endif
 
+using namespace mozilla;
+using namespace mozilla::plugins;
 using namespace mozilla::layers;
 
 // special class for handeling DOM context menu events because for
 // some reason it starves other mouse events if implemented on the
 // same class
 class nsPluginDOMContextMenuListener : public nsIDOMContextMenuListener
 {
 public:
@@ -462,16 +465,21 @@ public:
                                      nsIDOMClientRect* position,
                                      nsIDOMClientRect* clip);
 #endif
 
   void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
   // Return true if we set image with valid surface
   PRBool SetCurrentImage(ImageContainer* aContainer);
 
+  // Methods to update the background image we send to async plugins
+  void SetBackgroundUnknown() {}
+  already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect) { return nsnull; }
+  void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect) {}
+
   PRBool UseAsyncRendering()
   {
     PRBool useAsyncRendering;
     return (mInstance &&
             NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
             useAsyncRendering &&
             (!mPluginWindow ||
              mPluginWindow->type == NPWindowTypeDrawable));
@@ -619,16 +627,63 @@ private:
   void NativeImageDraw(NPRect* invalidRect = nsnull);
   PRBool UpdateVisibility(PRBool aVisible);
 
 #endif
 
   PRPackedBool          mWaitingForPaint;
 };
 
+class PluginBackgroundSink : public ReadbackSink {
+public:
+  PluginBackgroundSink(nsObjectFrame* aFrame, PRUint64 aStartSequenceNumber)
+    : mLastSequenceNumber(aStartSequenceNumber), mFrame(aFrame) {}
+  ~PluginBackgroundSink()
+  {
+    if (mFrame) {
+      mFrame->mBackgroundSink = nsnull;
+    }
+  }
+
+  virtual void SetUnknown(PRUint64 aSequenceNumber)
+  {
+    if (!AcceptUpdate(aSequenceNumber))
+      return;
+    mFrame->mInstanceOwner->SetBackgroundUnknown();
+  }
+
+  virtual already_AddRefed<gfxContext>
+      BeginUpdate(const nsIntRect& aRect, PRUint64 aSequenceNumber)
+  {
+    if (!AcceptUpdate(aSequenceNumber))
+      return nsnull;
+    return mFrame->mInstanceOwner->BeginUpdateBackground(aRect);
+  }
+
+  virtual void EndUpdate(gfxContext* aContext, const nsIntRect& aRect)
+  {
+    return mFrame->mInstanceOwner->EndUpdateBackground(aContext, aRect);
+  }
+
+  void Destroy() { mFrame = nsnull; }
+
+protected:
+  PRBool AcceptUpdate(PRUint64 aSequenceNumber) {
+    if (aSequenceNumber > mLastSequenceNumber && mFrame &&
+        mFrame->mInstanceOwner) {
+      mLastSequenceNumber = aSequenceNumber;
+      return PR_TRUE;
+    }
+    return PR_FALSE;
+  }
+
+  PRUint64 mLastSequenceNumber;
+  nsObjectFrame* mFrame;
+};
+
   // Mac specific code to fix up port position and clip
 #ifdef XP_MACOSX
 
   enum { ePluginPaintEnable, ePluginPaintDisable };
 
 #endif // XP_MACOSX
 
 nsObjectFrame::nsObjectFrame(nsStyleContext* aContext)
@@ -664,17 +719,16 @@ nsObjectFrame::CreateAccessible()
 NS_IMETHODIMP nsObjectFrame::GetPluginPort(HWND *aPort)
 {
   *aPort = (HWND) mInstanceOwner->GetPluginPortFromWidget();
   return NS_OK;
 }
 #endif
 #endif
 
-
 static NS_DEFINE_CID(kWidgetCID, NS_CHILD_CID);
 
 NS_IMETHODIMP 
 nsObjectFrame::Init(nsIContent*      aContent,
                     nsIFrame*        aParent,
                     nsIFrame*        aPrevInFlow)
 {
   NS_PRECONDITION(aContent, "How did that happen?");
@@ -702,16 +756,20 @@ nsObjectFrame::DestroyFrom(nsIFrame* aDe
 
   // StopPluginInternal might have disowned the widget; if it has,
   // mWidget will be null.
   if (mWidget) {
     mInnerView->DetachWidgetEventHandler(mWidget);
     mWidget->Destroy();
   }
 
+  if (mBackgroundSink) {
+    mBackgroundSink->Destroy();
+  }
+
   nsObjectFrameSuper::DestroyFrom(aDestructRoot);
 }
 
 /* virtual */ void
 nsObjectFrame::DidSetStyleContext(nsStyleContext* aOldStyleContext)
 {
   if (HasView()) {
     nsIView* view = GetView();
@@ -1272,44 +1330,114 @@ nsObjectFrame::PaintPrintPlugin(nsIFrame
                                 const nsRect& aDirtyRect, nsPoint aPt)
 {
   nsPoint pt = aPt + aFrame->GetUsedBorderAndPadding().TopLeft();
   nsIRenderingContext::AutoPushTranslation translate(aCtx, pt.x, pt.y);
   // FIXME - Bug 385435: Doesn't aDirtyRect need translating too?
   static_cast<nsObjectFrame*>(aFrame)->PrintPlugin(*aCtx, aDirtyRect);
 }
 
-nsRect
-nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
-{
-  nsRect r = mFrame->GetContentRect() - mFrame->GetPosition() +
-    ToReferenceFrame();
-  if (aBuilder->IsForPluginGeometry()) {
-    // Return the geometry we want, not the geometry we have (which is based
-    // on the surface the plugin last gave us)
-    return r;
-  }
+class nsDisplayPluginReadback : public nsDisplayItem {
+public:
+  nsDisplayPluginReadback(nsDisplayListBuilder* aBuilder, nsIFrame* aFrame)
+    : nsDisplayItem(aBuilder, aFrame)
+  {
+    MOZ_COUNT_CTOR(nsDisplayPluginReadback);
+  }
+#ifdef NS_BUILD_REFCNT_LOGGING
+  virtual ~nsDisplayPluginReadback() {
+    MOZ_COUNT_DTOR(nsDisplayPluginReadback);
+  }
+#endif
+
+  virtual nsRect GetBounds(nsDisplayListBuilder* aBuilder);
+  virtual PRBool ComputeVisibility(nsDisplayListBuilder* aBuilder,
+                                   nsRegion* aVisibleRegion,
+                                   PRBool& aContainsRootContentDocBG);
+
+  NS_DISPLAY_DECL_NAME("PluginReadback", TYPE_PLUGIN_READBACK)
+
+  virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
+                                             LayerManager* aManager)
+  {
+    return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this);
+  }
+
+  virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
+                                   LayerManager* aManager)
+  {
+    return LAYER_ACTIVE;
+  }
+};
+
+static nsRect
+GetDesiredDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
+{
+  nsRect r = aFrame->GetContentRect() - aFrame->GetPosition() +
+    aItem->ToReferenceFrame();
+  return r;
+}
+
+static nsRect
+GetDrawnDisplayItemBounds(nsDisplayListBuilder* aBuilder, nsDisplayItem* aItem, nsIFrame* aFrame)
+{
+  nsRect r = aFrame->GetContentRect() - aFrame->GetPosition() +
+    aItem->ToReferenceFrame();
 
 #ifndef XP_MACOSX
-  nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
-  if (mozilla::LAYER_ACTIVE == f->GetLayerState(aBuilder, nsnull)) {
+  nsObjectFrame* f = static_cast<nsObjectFrame*>(aFrame);
+  if (LAYER_ACTIVE == f->GetLayerState(aBuilder, nsnull)) {
     ImageContainer* c = f->GetImageContainer();
     if (c) {
       gfxIntSize size = c->GetCurrentSize();
       PRInt32 appUnitsPerDevPixel = f->PresContext()->AppUnitsPerDevPixel();
       nsSize sizeAppUnits(size.width*appUnitsPerDevPixel, size.height*appUnitsPerDevPixel);
       r += nsPoint((r.width - sizeAppUnits.width) / 2,
                    (r.height - sizeAppUnits.height) / 2);
       r.SizeTo(sizeAppUnits);
     }
   }
 #endif
   return r;
 }
 
+nsRect
+nsDisplayPluginReadback::GetBounds(nsDisplayListBuilder* aBuilder)
+{
+  return GetDesiredDisplayItemBounds(aBuilder, this, mFrame);
+}
+
+PRBool
+nsDisplayPluginReadback::ComputeVisibility(nsDisplayListBuilder* aBuilder,
+                                           nsRegion* aVisibleRegion,
+                                           PRBool& aContainsRootContentDocBG)
+{
+  if (!nsDisplayItem::ComputeVisibility(aBuilder, aVisibleRegion, aContainsRootContentDocBG))
+    return PR_FALSE;
+  // *Add* our bounds to the visible region so that stuff underneath us is
+  // likely to be made visible, so we can use it for a background! This is
+  // a bit crazy since we normally only subtract from the visible region.
+  aVisibleRegion->Or(*aVisibleRegion, GetBounds(aBuilder));
+  return PR_TRUE;
+}
+
+nsRect
+nsDisplayPlugin::GetBounds(nsDisplayListBuilder* aBuilder)
+{
+  // We use display lists to notify plugins of visibility.  But we
+  // also need to return the "real" visible bounds, possibly those of
+  // our Image, when actually painting.  Usually those will be the
+  // same, but for the plugin to paint initially, something needs to
+  // notify it that it's visible.  So return whichever the appropriate
+  // rect here.
+  return aBuilder->IsForPluginGeometry() ?
+    GetDesiredDisplayItemBounds(aBuilder, this, mFrame) :
+    GetDrawnDisplayItemBounds(aBuilder, this, mFrame);
+}
+
 void
 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
                        nsIRenderingContext* aCtx)
 {
   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   f->PaintPlugin(aBuilder, *aCtx, mVisibleRect, GetBounds(aBuilder));
 }
 
@@ -1450,47 +1578,61 @@ nsObjectFrame::DidSetWidgetGeometry()
   }
 #endif
 }
 
 PRBool
 nsObjectFrame::IsOpaque() const
 {
 #if defined(XP_MACOSX)
+  // ???
+  return PR_FALSE;
+#else
+  return !IsTransparentMode();
+#endif
+}
+
+PRBool
+nsObjectFrame::IsTransparentMode() const
+{
+#if defined(XP_MACOSX)
+  // ???
   return PR_FALSE;
 #else
   if (!mInstanceOwner)
     return PR_FALSE;
 
   NPWindow *window;
   mInstanceOwner->GetWindow(window);
   if (window->type != NPWindowTypeDrawable)
-    return PR_TRUE;
+    return PR_FALSE;
 
   nsresult rv;
   nsCOMPtr<nsIPluginInstance> pi;
   rv = mInstanceOwner->GetInstance(*getter_AddRefs(pi));
   if (NS_FAILED(rv) || !pi)
     return PR_FALSE;
 
   PRBool transparent = PR_FALSE;
   pi->IsTransparent(&transparent);
-  return !transparent;
+  return transparent;
 #endif
 }
 
 NS_IMETHODIMP
 nsObjectFrame::BuildDisplayList(nsDisplayListBuilder*   aBuilder,
                                 const nsRect&           aDirtyRect,
                                 const nsDisplayListSet& aLists)
 {
+  AddStateBits(NS_OBJECT_NEEDS_SET_IMAGE);
+
   // XXX why are we painting collapsed object frames?
   if (!IsVisibleOrCollapsedForPainting(aBuilder))
     return NS_OK;
-    
+
   nsresult rv = DisplayBorderBackgroundOutline(aBuilder, aLists);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsPresContext::nsPresContextType type = PresContext()->Type();
 
   // If we are painting in Print Preview do nothing....
   if (type == nsPresContext::eContext_PrintPreview)
     return NS_OK;
@@ -1525,16 +1667,24 @@ nsObjectFrame::BuildDisplayList(nsDispla
   }
 
   // determine if we are printing
   if (type == nsPresContext::eContext_Print) {
     rv = replacedContent.AppendNewToTop(new (aBuilder)
         nsDisplayGeneric(aBuilder, this, PaintPrintPlugin, "PrintPlugin",
                          nsDisplayItem::TYPE_PRINT_PLUGIN));
   } else {
+    if (aBuilder->IsPaintingToWindow() &&
+        GetLayerState(aBuilder, nsnull) == LAYER_ACTIVE &&
+        IsTransparentMode()) {
+      rv = replacedContent.AppendNewToTop(new (aBuilder)
+          nsDisplayPluginReadback(aBuilder, this));
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
     rv = replacedContent.AppendNewToTop(new (aBuilder)
         nsDisplayPlugin(aBuilder, this));
   }
   NS_ENSURE_SUCCESS(rv, rv);
 
   WrapReplacedContentForBorderRadius(aBuilder, &replacedContent, aLists);
 
   return NS_OK;
@@ -1826,17 +1976,18 @@ nsPluginInstanceOwner::SetCurrentImage(I
 mozilla::LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
   if (!mInstanceOwner)
     return mozilla::LAYER_NONE;
 
 #ifdef XP_MACOSX
-  if (aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
+  if (aManager &&
+      aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
       mInstanceOwner->GetEventModel() == NPEventModelCocoa &&
       mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics &&
       mInstanceOwner->IsRemoteDrawingCoreAnimation())
   {
     return mozilla::LAYER_ACTIVE;
   }
 #endif
 
@@ -1857,66 +2008,95 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   NPWindow* window = nsnull;
   mInstanceOwner->GetWindow(window);
   if (!window)
     return nsnull;
 
   if (window->width <= 0 || window->height <= 0)
     return nsnull;
 
+  // Create image
+  nsRefPtr<ImageContainer> container = GetImageContainer(aManager);
+  if (!container)
+    return nsnull;
+  if (GetStateBits() & NS_OBJECT_NEEDS_SET_IMAGE) {
+    RemoveStateBits(NS_OBJECT_NEEDS_SET_IMAGE);
+    if (!mInstanceOwner->SetCurrentImage(container)) {
+      return nsnull;
+    }
+  }
+  gfxIntSize size = container->GetCurrentSize();
+
   nsRect area = GetContentRect() + aBuilder->ToReferenceFrame(GetParent());
   gfxRect r = nsLayoutUtils::RectToGfxRect(area, PresContext()->AppUnitsPerDevPixel());
   // to provide crisper and faster drawing.
   r.Round();
   nsRefPtr<Layer> layer =
     (aBuilder->LayerBuilder()->GetLeafLayerFor(aBuilder, aManager, aItem));
 
-  if (!layer) {
-    if (mInstanceOwner->UseAsyncRendering()) {
+  if (aItem->GetType() == nsDisplayItem::TYPE_PLUGIN) {
+    if (!layer) {
       mInstanceOwner->NotifyPaintWaiter(aBuilder);
+      // Initialize ImageLayer
+      layer = aManager->CreateImageLayer();
+      if (!layer)
+        return nsnull;
     }
 
-    // Initialize ImageLayer
-    layer = aManager->CreateImageLayer();
-  }
-
-  if (!layer)
-    return nsnull;
-
 #ifdef XP_MACOSX
-  // Until we get async plugins on mac we need to manually trigger the DrawRect event
-  mInstanceOwner->DoCocoaEventDrawRect(r, nsnull);
-#endif
-
-  NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "ObjectFrame works only with ImageLayer");
-  // Create image
-  nsRefPtr<ImageContainer> container = GetImageContainer(aManager);
-  if (!container)
-    return nsnull;
-
-  if (!mInstanceOwner->SetCurrentImage(container)) {
-    return nsnull;
-  }
-
-  ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
-  imglayer->SetContainer(container);
-  imglayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
-
-  layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
+    // Until we get async plugins on mac we need to manually trigger the DrawRect event
+    mInstanceOwner->DoCocoaEventDrawRect(r, nsnull);
+#endif
+
+    NS_ASSERTION(layer->GetType() == Layer::TYPE_IMAGE, "Bad layer type");
+
+    ImageLayer* imglayer = static_cast<ImageLayer*>(layer.get());
+    imglayer->SetContainer(container);
+    imglayer->SetFilter(nsLayoutUtils::GetGraphicsFilterForFrame(this));
+
+    layer->SetContentFlags(IsOpaque() ? Layer::CONTENT_OPAQUE : 0);
+  } else {
+    NS_ASSERTION(aItem->GetType() == nsDisplayItem::TYPE_PLUGIN_READBACK,
+                 "Unknown item type");
+    NS_ABORT_IF_FALSE(!IsOpaque(), "Opaque plugins don't use backgrounds");
+
+    if (!layer) {
+      layer = aManager->CreateReadbackLayer();
+      if (!layer)
+        return nsnull;
+    }
+    NS_ASSERTION(layer->GetType() == Layer::TYPE_READBACK, "Bad layer type");
+
+    ReadbackLayer* readback = static_cast<ReadbackLayer*>(layer.get());
+    if (readback->GetSize() != nsIntSize(size.width, size.height)) {
+      // This will destroy any old background sink and notify us that the
+      // background is now unknown
+      readback->SetSink(nsnull);
+      NS_ASSERTION(!mBackgroundSink, "Should have been cleared");
+
+      readback->SetSize(nsIntSize(size.width, size.height));
+
+      mBackgroundSink =
+        new PluginBackgroundSink(this,
+                                 readback->AllocateSequenceNumber());
+      readback->SetSink(mBackgroundSink);
+      // The layer has taken ownership of our sink. When either the sink dies
+      // or the frame dies, the connection from the surviving object is nulled out.
+    }
+  }
 
   // Set a transform on the layer to draw the plugin in the right place
   gfxMatrix transform;
   // Center plugin if layer size != frame rect
-  r.pos.x += (r.Width() - container->GetCurrentSize().width) / 2;
-  r.pos.y += (r.Height() - container->GetCurrentSize().height) / 2;
+  r.pos.x += (r.Width() - size.width) / 2;
+  r.pos.y += (r.Height() - size.height) / 2;
   transform.Translate(r.pos);
 
   layer->SetTransform(gfx3DMatrix::From2D(transform));
-  nsRefPtr<Layer> result = layer.forget();
-  return result.forget();
+  return layer.forget();
 }
 
 void
 nsObjectFrame::PaintPlugin(nsDisplayListBuilder* aBuilder,
                            nsIRenderingContext& aRenderingContext,
                            const nsRect& aDirtyRect, const nsRect& aPluginRect)
 {
   // Screen painting code
@@ -2071,17 +2251,17 @@ nsObjectFrame::PaintPlugin(nsDisplayList
 
       gfxWindowsNativeDrawing nativeDraw(ctx, frameGfxRect);
 #ifdef MOZ_IPC
       if (nativeDraw.IsDoublePass()) {
         // OOP plugin specific: let the shim know before we paint if we are doing a
         // double pass render. If this plugin isn't oop, the register window message
         // will be ignored.
         NPEvent pluginEvent;
-        pluginEvent.event = mozilla::plugins::DoublePassRenderingEvent();
+        pluginEvent.event = DoublePassRenderingEvent();
         pluginEvent.wParam = 0;
         pluginEvent.lParam = 0;
         if (pluginEvent.event)
           inst->HandleEvent(&pluginEvent, nsnull);
       }
 #endif
       do {
         HDC hdc = nativeDraw.BeginNativeDrawing();
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -58,19 +58,22 @@ class nsIAccessible;
 
 class nsPluginInstanceOwner;
 class nsIPluginHost;
 class nsIPluginInstance;
 class nsPresContext;
 class nsDisplayPlugin;
 class nsIDOMElement;
 class nsIOSurface;
+class PluginBackgroundSink;
 
 #define nsObjectFrameSuper nsFrame
 
+#define NS_OBJECT_NEEDS_SET_IMAGE NS_FRAME_STATE_BIT(31)
+
 class nsObjectFrame : public nsObjectFrameSuper,
                       public nsIObjectFrame,
                       public nsIReflowCallback {
 public:
   typedef mozilla::LayerState LayerState;
   typedef mozilla::layers::Layer Layer;
   typedef mozilla::layers::LayerManager LayerManager;
   typedef mozilla::layers::ImageContainer ImageContainer;
@@ -172,16 +175,20 @@ public:
   // for a given aRoot, this walks the frame tree looking for the next outFrame
   static nsIObjectFrame* GetNextObjectFrame(nsPresContext* aPresContext,
                                             nsIFrame* aRoot);
 
   // nsIReflowCallback
   virtual PRBool ReflowFinished();
   virtual void ReflowCallbackCanceled();
 
+  /**
+   * Builds either an ImageLayer or a ReadbackLayer, depending on the type
+   * of aItem (TYPE_PLUGIN or TYPE_PLUGIN_READBACK respectively).
+   */
   already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                      LayerManager* aManager,
                                      nsDisplayItem* aItem);
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager);
 
   ImageContainer* GetImageContainer(LayerManager* aManager = nsnull);
@@ -225,16 +232,17 @@ protected:
   nsresult CallSetWindow(PRBool aCheckIsHidden = PR_TRUE);
 
   PRBool IsFocusable(PRInt32 *aTabIndex = nsnull, PRBool aWithMouse = PR_FALSE);
 
   // check attributes and optionally CSS to see if we should display anything
   PRBool IsHidden(PRBool aCheckVisibilityStyle = PR_TRUE) const;
 
   PRBool IsOpaque() const;
+  PRBool IsTransparentMode() const;
 
   void NotifyContentObjectWrapper();
 
   nsIntPoint GetWindowOriginInPixels(PRBool aWindowless);
 
   static void PaintPrintPlugin(nsIFrame* aFrame,
                                nsIRenderingContext* aRenderingContext,
                                const nsRect& aDirtyRect, nsPoint aPt);
@@ -268,16 +276,17 @@ protected:
   nsresult SetAbsoluteScreenPosition(nsIDOMElement* element,
                                      nsIDOMClientRect* position,
                                      nsIDOMClientRect* clip);
 
   void NotifyPluginReflowObservers();
 
   friend class nsPluginInstanceOwner;
   friend class nsDisplayPlugin;
+  friend class PluginBackgroundSink;
 
 private:
   
   class PluginEventNotifier : public nsRunnable {
   public:
     PluginEventNotifier(const nsString &aEventType) : 
       mEventType(aEventType) {}
     
@@ -285,16 +294,21 @@ private:
   private:
     nsString mEventType;
   };
   
   nsRefPtr<nsPluginInstanceOwner> mInstanceOwner;
   nsIView*                        mInnerView;
   nsCOMPtr<nsIWidget>             mWidget;
   nsIntRect                       mWindowlessRect;
+  /**
+   * This is owned by the ReadbackLayer for this nsObjectFrame. It is
+   * automatically cleared if the PluginBackgroundSink is destroyed.
+   */
+  PluginBackgroundSink*           mBackgroundSink;
 
   // For assertions that make it easier to determine if a crash is due
   // to the underlying problem described in bug 136927, and to prevent
   // reentry into instantiation.
   PRBool mPreventInstantiation;
 
   PRPackedBool mReflowCallbackPosted;
 
@@ -343,16 +357,17 @@ public:
     return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder,
                                                            aManager, 
                                                            this);
   }
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager)
   {
-    return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder, aManager);
+    return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder,
+                                                              aManager);
   }
 
 private:
   nsRegion mVisibleRegion;
 };
 
 #endif /* nsObjectFrame_h___ */