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 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)
reviewersbsmedberg, roc
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 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();