Bug 626602, part 8: Dig a tunnel from nsObjectFrame to PluginInstanceParent for background copying. r=bsmedberg sr=roc
authorChris Jones <jones.chris.g@gmail.com>
Tue, 08 Feb 2011 18:44:14 -0600
changeset 62206 fd046a4bbb19bf67bfe1157a874a9dc2e559ccd6
parent 62205 580f6ff0b8249874f551545f00867621807e462c
child 62207 9d3141affbe59260de88d44ce9696148a66b6d07
push idunknown
push userunknown
push dateunknown
reviewersbsmedberg, roc
bugs626602
milestone2.0b12pre
Bug 626602, part 8: Dig a tunnel from nsObjectFrame to PluginInstanceParent for background copying. r=bsmedberg sr=roc
dom/plugins/PluginInstanceParent.h
dom/plugins/PluginLibrary.h
dom/plugins/PluginModuleParent.cpp
dom/plugins/PluginModuleParent.h
layout/generic/nsObjectFrame.cpp
modules/plugin/base/public/nsIPluginInstance.idl
modules/plugin/base/src/PluginPRLibrary.cpp
modules/plugin/base/src/PluginPRLibrary.h
modules/plugin/base/src/nsNPAPIPluginInstance.cpp
modules/plugin/base/src/nsNPAPIPluginInstance.h
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -272,16 +272,21 @@ public:
     AnswerPluginFocusChange(const bool& gotFocus);
 
 #if defined(OS_MACOSX)
     void Invalidate();
 #endif // definied(OS_MACOSX)
 
     nsresult AsyncSetWindow(NPWindow* window);
     nsresult GetSurface(gfxASurface** aSurface);
+    nsresult SetBackgroundUnknown() { return NS_OK; }
+    nsresult BeginUpdateBackground(const nsIntRect& aRect,
+                                   gfxContext** aCtx) { return NS_OK; }
+    nsresult EndUpdateBackground(gfxContext* aCtx,
+                                 const nsIntRect& aRect) { return NS_OK; }
 
 private:
     // Quirks mode support for various plugin mime types
     enum PluginQuirks {
         // OSX: Don't use the refresh timer for plug-ins
         // using this quirk. These plug-in most have another
         // way to refresh the window.
         COREANIMATION_REFRESH_TIMER = 1,
--- a/dom/plugins/PluginLibrary.h
+++ b/dom/plugins/PluginLibrary.h
@@ -41,19 +41,21 @@
 
 #include "prlink.h"
 #include "npapi.h"
 #include "npfunctions.h"
 #include "nscore.h"
 #include "nsTArray.h"
 #include "nsPluginError.h"
 
+class gfxASurface;
+class gfxContext;
+class nsCString;
+struct nsIntRect;
 class nsNPAPIPlugin;
-class gfxASurface;
-class nsCString;
 
 namespace mozilla {
 
 class PluginLibrary
 {
 public:
   virtual ~PluginLibrary() { }
 
@@ -84,14 +86,24 @@ public:
 
   virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                      uint64_t maxAge) = 0;
   virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& aResult) = 0;
 
   virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window) = 0;
   virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface) = 0;
   virtual bool UseAsyncPainting() = 0;
+  /**
+   * The next three methods are the third leg in the trip to
+   * PluginInstanceParent.  They approximately follow the ReadbackSink
+   * API.
+   */
+  virtual nsresult SetBackgroundUnknown(NPP instance) = 0;
+  virtual nsresult BeginUpdateBackground(NPP instance,
+                                         const nsIntRect&, gfxContext**) = 0;
+  virtual nsresult EndUpdateBackground(NPP instance,
+                                       gfxContext*, const nsIntRect&) = 0;
 };
 
 
 } // namespace mozilla
 
 #endif  // ifndef mozilla_PluginLibrary_h
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -677,16 +677,50 @@ PluginModuleParent::GetSurface(NPP insta
 {
     PluginInstanceParent* i = InstCast(instance);
     if (!i)
         return NS_ERROR_FAILURE;
 
     return i->GetSurface(aSurface);
 }
 
+nsresult
+PluginModuleParent::SetBackgroundUnknown(NPP instance)
+{
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NS_ERROR_FAILURE;
+
+    return i->SetBackgroundUnknown();
+}
+
+nsresult
+PluginModuleParent::BeginUpdateBackground(NPP instance,
+                                          const nsIntRect& aRect,
+                                          gfxContext** aCtx)
+{
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NS_ERROR_FAILURE;
+
+    return i->BeginUpdateBackground(aRect, aCtx);
+}
+
+nsresult
+PluginModuleParent::EndUpdateBackground(NPP instance,
+                                        gfxContext* aCtx,
+                                        const nsIntRect& aRect)
+{
+    PluginInstanceParent* i = InstCast(instance);
+    if (!i)
+        return NS_ERROR_FAILURE;
+
+    return i->EndUpdateBackground(aCtx, aRect);
+}
+
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
 nsresult
 PluginModuleParent::NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error)
 {
     PLUGIN_LOG_DEBUG_METHOD;
 
     mNPNIface = bFuncs;
 
--- a/dom/plugins/PluginModuleParent.h
+++ b/dom/plugins/PluginModuleParent.h
@@ -227,16 +227,26 @@ private:
                                 void *value);
     static void NPP_URLRedirectNotify(NPP instance, const char* url,
                                       int32_t status, void* notifyData);
 
     virtual bool HasRequiredFunctions();
     virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
     virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return true; }
+    NS_OVERRIDE
+    virtual nsresult SetBackgroundUnknown(NPP instance);
+    NS_OVERRIDE
+    virtual nsresult BeginUpdateBackground(NPP instance,
+                                           const nsIntRect& aRect,
+                                           gfxContext** aCtx);
+    NS_OVERRIDE
+    virtual nsresult EndUpdateBackground(NPP instance,
+                                         gfxContext* aCtx,
+                                         const nsIntRect& aRect);
 
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPPluginFuncs* pFuncs, NPError* error);
 #else
     virtual nsresult NP_Initialize(NPNetscapeFuncs* bFuncs, NPError* error);
 #endif
     virtual nsresult NP_Shutdown(NPError* error);
     virtual nsresult NP_GetMIMEDescription(const char** mimeDesc);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -462,20 +462,22 @@ 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) {}
+  // Methods to update the background image we send to async plugins.
+  // The eventual target of these operations is PluginInstanceParent,
+  // but it takes several hops to get there.
+  void SetBackgroundUnknown();
+  already_AddRefed<gfxContext> BeginUpdateBackground(const nsIntRect& aRect);
+  void EndUpdateBackground(gfxContext* aContext, const nsIntRect& aRect);
 
   PRBool UseLayers()
   {
     PRBool useAsyncRendering;
     return (mInstance &&
             NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
             useAsyncRendering &&
             (!mPluginWindow ||
@@ -488,16 +490,23 @@ private:
   PRBool IsUpToDate()
   {
     nsRefPtr<gfxASurface> readyToUse;
     return NS_SUCCEEDED(mInstance->GetSurface(getter_AddRefs(readyToUse))) &&
            readyToUse && readyToUse->GetSize() == gfxIntSize(mPluginWindow->width,
                                                              mPluginWindow->height);
   }
 
+  already_AddRefed<nsIPluginInstance_MOZILLA_2_0_BRANCH>
+  GetInstance()
+  {
+    nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = do_QueryInterface(mInstance);
+    return inst.forget();
+  }
+
   void FixUpURLS(const nsString &name, nsAString &value);
 
   nsPluginNativeWindow       *mPluginWindow;
   nsCOMPtr<nsIPluginInstance> mInstance;
   nsObjectFrame              *mObjectFrame; // owns nsPluginInstanceOwner
   nsCOMPtr<nsIContent>        mContent;
   nsCString                   mDocumentBase;
   char                       *mTagText;
@@ -1932,16 +1941,49 @@ nsPluginInstanceOwner::SetCurrentImage(I
   cairoData.mSurface = mLayerSurface.get();
   cairoData.mSize = mLayerSurface->GetSize();
   pluginImage->SetData(cairoData);
   aContainer->SetCurrentImage(image);
 
   return PR_TRUE;
 }
 
+void
+nsPluginInstanceOwner::SetBackgroundUnknown()
+{
+  nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
+  if (inst) {
+    inst->SetBackgroundUnknown();
+  }
+}
+
+already_AddRefed<gfxContext>
+nsPluginInstanceOwner::BeginUpdateBackground(const nsIntRect& aRect)
+{
+  nsIntRect rect = aRect;
+  nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
+  nsRefPtr<gfxContext> ctx;
+  if (inst &&
+      NS_SUCCEEDED(inst->BeginUpdateBackground(&rect, getter_AddRefs(ctx)))) {
+    return ctx.forget();
+  }
+  return nsnull;
+}
+
+void
+nsPluginInstanceOwner::EndUpdateBackground(gfxContext* aContext,
+                                           const nsIntRect& aRect)
+{
+  nsIntRect rect = aRect;
+  nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = GetInstance();
+  if (inst) {
+    inst->EndUpdateBackground(aContext, &rect);
+  }
+}
+
 LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder)
 {
   return mInstanceOwner && mInstanceOwner->UseLayers() ?
       LAYER_ACTIVE : LAYER_NONE;
 }
 
 already_AddRefed<Layer>
--- a/modules/plugin/base/public/nsIPluginInstance.idl
+++ b/modules/plugin/base/public/nsIPluginInstance.idl
@@ -43,23 +43,27 @@ interface nsIOutputStream;
 
 %{C++
 #include "npapi.h"
 #include "nsStringGlue.h"
 #include "gfxASurface.h"
 struct JSContext;
 struct JSObject;
 class gfxASurface;
+class gfxContext;
+struct nsIntRect;
 
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 %}
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native gfxASurfacePtr(gfxASurface);
+[ptr] native gfxContextPtr(gfxContext);
+[ptr] native nsIntRectPtr(nsIntRect);
 
 [uuid(84994340-E120-4051-824F-D4EE8AEF1A3E)]
 interface nsIPluginInstance : nsISupports
 {
     /**
      * Initializes a newly created plugin instance.
      * 
      * @param aOwner - the plugin instance owner
@@ -242,8 +246,23 @@ interface nsIPluginInstance : nsISupport
      */
     void getSurface(out gfxASurfacePtr aSurface);
 
     /**
      * @return true if plugin module supports async rendering
      */
     PRBool useAsyncPainting();
 };
+
+
+// XXX kill me after branching
+[noscript, uuid(324f3c02-4fbd-430b-8afa-db083d3867fc)]
+interface nsIPluginInstance_MOZILLA_2_0_BRANCH : nsIPluginInstance
+{
+    /**
+     * This is the second leg in the trip to PluginInstanceParent.  It
+     * approximately follows the ReadbackSink API.
+     */
+
+    void setBackgroundUnknown();
+    void beginUpdateBackground(in nsIntRectPtr rect, out gfxContextPtr ctx);
+    void endUpdateBackground(in gfxContextPtr ctx, in nsIntRectPtr rect);
+};
--- a/modules/plugin/base/src/PluginPRLibrary.cpp
+++ b/modules/plugin/base/src/PluginPRLibrary.cpp
@@ -250,9 +250,37 @@ nsresult
 PluginPRLibrary::GetSurface(NPP instance, gfxASurface** aSurface)
 {
   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
   *aSurface = nsnull;
   return NS_OK;
 }
 
+nsresult
+PluginPRLibrary::SetBackgroundUnknown(NPP instance)
+{
+  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+  NS_ERROR("Unexpected use of async APIs for in-process plugin.");
+  return NS_ERROR_NOT_IMPLEMENTED;
+}
+
+nsresult
+PluginPRLibrary::BeginUpdateBackground(NPP instance,
+                                       const nsIntRect&, gfxContext** aCtx)
+{
+  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+  NS_ERROR("Unexpected use of async APIs for in-process plugin.");
+  *aCtx = nsnull;
+  return NS_OK;
+}
+
+nsresult
+PluginPRLibrary::EndUpdateBackground(NPP instance,
+                                     gfxContext*, const nsIntRect&)
+{
+  NS_RUNTIMEABORT("This should never be called");
+  return NS_ERROR_NOT_AVAILABLE;
+}
+
 } // namespace mozilla
--- a/modules/plugin/base/src/PluginPRLibrary.h
+++ b/modules/plugin/base/src/PluginPRLibrary.h
@@ -137,16 +137,24 @@ public:
 
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                        uint64_t maxAge);
     virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result);
 
     virtual nsresult AsyncSetWindow(NPP instance, NPWindow* window);
     virtual nsresult GetSurface(NPP instance, gfxASurface** aSurface);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return false; }
+    NS_OVERRIDE
+    virtual nsresult SetBackgroundUnknown(NPP instance);
+    NS_OVERRIDE
+    virtual nsresult BeginUpdateBackground(NPP instance,
+                                           const nsIntRect&, gfxContext** aCtx);
+    NS_OVERRIDE
+    virtual nsresult EndUpdateBackground(NPP instance,
+                                         gfxContext* aCtx, const nsIntRect&);
 
 private:
     NP_InitializeFunc mNP_Initialize;
     NP_ShutdownFunc mNP_Shutdown;
     NP_GetMIMEDescriptionFunc mNP_GetMIMEDescription;
 #if defined(XP_UNIX) && !defined(XP_MACOSX)
     NP_GetValueFunc mNP_GetValue;
 #endif
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -54,23 +54,23 @@
 
 #include "nsIDocument.h"
 #include "nsIScriptGlobalObject.h"
 #include "nsIScriptContext.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsJSNPRuntime.h"
 #include "nsPluginStreamListenerPeer.h"
 
+using namespace mozilla;
 using namespace mozilla::plugins::parent;
-using mozilla::TimeStamp;
 
 static NS_DEFINE_IID(kIOutputStreamIID, NS_IOUTPUTSTREAM_IID);
 static NS_DEFINE_IID(kIPluginStreamListenerIID, NS_IPLUGINSTREAMLISTENER_IID);
 
-NS_IMPL_ISUPPORTS1(nsNPAPIPluginInstance, nsIPluginInstance)
+NS_IMPL_ISUPPORTS2(nsNPAPIPluginInstance, nsIPluginInstance, nsIPluginInstance_MOZILLA_2_0_BRANCH)
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
   :
 #ifdef XP_MACOSX
 #ifdef NP_NO_QUICKDRAW
     mDrawingModel(NPDrawingModelCoreGraphics),
 #else
     mDrawingModel(NPDrawingModelQuickDraw),
@@ -804,46 +804,55 @@ nsNPAPIPluginInstance::ShouldCache(PRBoo
 
 NS_IMETHODIMP
 nsNPAPIPluginInstance::IsWindowless(PRBool* isWindowless)
 {
   *isWindowless = mWindowless;
   return NS_OK;
 }
 
+class NS_STACK_CLASS AutoPluginLibraryCall
+{
+public:
+  AutoPluginLibraryCall(nsNPAPIPluginInstance* aThis)
+    : mThis(aThis), mGuard(aThis), mLibrary(nsnull)
+  {
+    nsNPAPIPlugin* plugin = mThis->GetPlugin();
+    if (plugin)
+      mLibrary = plugin->GetLibrary();
+  }
+  operator bool() { return !!mLibrary; }
+  PluginLibrary* operator->() { return mLibrary; }
+
+private:
+  nsNPAPIPluginInstance* mThis;
+  PluginDestructionGuard mGuard;
+  PluginLibrary* mLibrary;
+};
+
 NS_IMETHODIMP
 nsNPAPIPluginInstance::AsyncSetWindow(NPWindow* window)
 {
   if (RUNNING != mRunning)
     return NS_OK;
 
-  PluginDestructionGuard guard(this);
-
-  if (!mPlugin)
-    return NS_ERROR_FAILURE;
-
-  PluginLibrary* library = mPlugin->GetLibrary();
+  AutoPluginLibraryCall library(this);
   if (!library)
     return NS_ERROR_FAILURE;
 
   return library->AsyncSetWindow(&mNPP, window);
 }
 
 NS_IMETHODIMP
 nsNPAPIPluginInstance::GetSurface(gfxASurface** aSurface)
 {
   if (RUNNING != mRunning)
     return NS_OK;
 
-  PluginDestructionGuard guard(this);
-
-  if (!mPlugin)
-    return NS_ERROR_FAILURE;
-
-  PluginLibrary* library = mPlugin->GetLibrary();
+  AutoPluginLibraryCall library(this);
   if (!library)
     return NS_ERROR_FAILURE;
 
   return library->GetSurface(&mNPP, aSurface);
 }
 
 
 NS_IMETHODIMP
@@ -856,30 +865,66 @@ nsNPAPIPluginInstance::NotifyPainted(voi
 NS_IMETHODIMP
 nsNPAPIPluginInstance::UseAsyncPainting(PRBool* aIsAsync)
 {
   if (!mUsePluginLayersPref) {
     *aIsAsync = mUsePluginLayersPref;
     return NS_OK;
   }
 
-  PluginDestructionGuard guard(this);
-
-  if (!mPlugin)
-    return NS_ERROR_FAILURE;
-
-  PluginLibrary* library = mPlugin->GetLibrary();
+  AutoPluginLibraryCall library(this);
   if (!library)
     return NS_ERROR_FAILURE;
 
   *aIsAsync = library->UseAsyncPainting();
   return NS_OK;
 }
 
 NS_IMETHODIMP
+nsNPAPIPluginInstance::SetBackgroundUnknown()
+{
+  if (RUNNING != mRunning)
+    return NS_OK;
+
+  AutoPluginLibraryCall library(this);
+  if (!library)
+    return NS_ERROR_FAILURE;
+
+  return library->SetBackgroundUnknown(&mNPP);
+}
+
+NS_IMETHODIMP
+nsNPAPIPluginInstance::BeginUpdateBackground(nsIntRect* aRect,
+                                             gfxContext** aContext)
+{
+  if (RUNNING != mRunning)
+    return NS_OK;
+
+  AutoPluginLibraryCall library(this);
+  if (!library)
+    return NS_ERROR_FAILURE;
+
+  return library->BeginUpdateBackground(&mNPP, *aRect, aContext);
+}
+
+NS_IMETHODIMP
+nsNPAPIPluginInstance::EndUpdateBackground(gfxContext* aContext,
+                                           nsIntRect* aRect)
+{
+  if (RUNNING != mRunning)
+    return NS_OK;
+
+  AutoPluginLibraryCall library(this);
+  if (!library)
+    return NS_ERROR_FAILURE;
+
+  return library->EndUpdateBackground(&mNPP, aContext, *aRect);
+}
+
+NS_IMETHODIMP
 nsNPAPIPluginInstance::IsTransparent(PRBool* isTransparent)
 {
   *isTransparent = mTransparent;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNPAPIPluginInstance::GetFormValue(nsAString& aValue)
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.h
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.h
@@ -62,24 +62,25 @@ class nsNPAPITimer
 {
 public:
   NPP npp;
   uint32_t id;
   nsCOMPtr<nsITimer> timer;
   void (*callback)(NPP npp, uint32_t timerID);
 };
 
-class nsNPAPIPluginInstance : public nsIPluginInstance
+class nsNPAPIPluginInstance : public nsIPluginInstance_MOZILLA_2_0_BRANCH
 {
 private:
   typedef mozilla::PluginLibrary PluginLibrary;
 
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIPLUGININSTANCE
+  NS_DECL_NSIPLUGININSTANCE_MOZILLA_2_0_BRANCH
 
   nsNPAPIPlugin* GetPlugin();
 
   nsresult GetNPP(NPP * aNPP);
 
   void SetURI(nsIURI* uri);
   nsIURI* GetURI();