Bug 591687: Add GetImage in order to create mac async plugin images in plugin code instead of nsObjectFrame. r=bsmedberg a=blocking2.0betaN+
authorMatt Woodrow <mwoodrow@mozilla.com>
Sat, 12 Feb 2011 11:07:10 -0500
changeset 62473 b0c3b563b2fa0afef993fa4c1fa3c5ae16aee1f8
parent 62472 3fb968523cbd2607862d4eb1a0c4edbc519d16a4
child 62474 94f0723d8ee6d60710190be05e30fe9afd6dad9c
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, blocking2
bugs591687
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 591687: Add GetImage in order to create mac async plugin images in plugin code instead of nsObjectFrame. r=bsmedberg a=blocking2.0betaN+
dom/plugins/PluginInstanceParent.cpp
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
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -567,16 +567,41 @@ PluginInstanceParent::GetSurface(gfxASur
 {
     if (mFrontSurface) {
       NS_ADDREF(*aSurface = mFrontSurface);
       return NS_OK;
     }
     return NS_ERROR_NOT_AVAILABLE;
 }
 
+nsresult
+PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
+{
+    if (!mFrontSurface)
+        return NS_ERROR_NOT_AVAILABLE;
+
+    Image::Format format = Image::CAIRO_SURFACE;
+
+    nsRefPtr<Image> image;
+    image = aContainer->CreateImage(&format, 1);
+    if (!image) {
+        return NS_ERROR_FAILURE;
+    }
+
+    NS_ASSERTION(image->GetFormat() == Image::CAIRO_SURFACE, "Wrong format?");
+    CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
+    CairoImage::Data cairoData;
+    cairoData.mSurface = mFrontSurface;
+    cairoData.mSize = mFrontSurface->GetSize();
+    pluginImage->SetData(cairoData);
+
+    *aImage = image.forget().get();
+    return NS_OK;
+}
+
 #ifdef XP_MACOSX
 nsresult
 PluginInstanceParent::IsRemoteDrawingCoreAnimation(PRBool *aDrawing)
 {
     *aDrawing = (NPDrawingModelCoreAnimation == (NPDrawingModel)mDrawingModel ||
                  NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel);
     return NS_OK;
 }
--- a/dom/plugins/PluginInstanceParent.h
+++ b/dom/plugins/PluginInstanceParent.h
@@ -48,16 +48,17 @@
 #endif
 
 #include "npfunctions.h"
 #include "nsAutoPtr.h"
 #include "nsDataHashtable.h"
 #include "nsHashKeys.h"
 #include "nsRect.h"
 #include "gfxASurface.h"
+#include "ImageLayers.h"
 #ifdef MOZ_X11
 class gfxXlibSurface;
 #endif
 
 namespace mozilla {
 namespace plugins {
 
 class PBrowserStreamParent;
@@ -272,16 +273,17 @@ public:
     AnswerPluginFocusChange(const bool& gotFocus);
 
 #if defined(OS_MACOSX)
     void Invalidate();
 #endif // definied(OS_MACOSX)
 
     nsresult AsyncSetWindow(NPWindow* window);
     nsresult GetSurface(gfxASurface** aSurface);
+    nsresult GetImage(mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
 #ifdef XP_MACOSX
     nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
 #endif
 
 private:
     // Quirks mode support for various plugin mime types
     enum PluginQuirks {
         // OSX: Don't use the refresh timer for plug-ins
--- a/dom/plugins/PluginLibrary.h
+++ b/dom/plugins/PluginLibrary.h
@@ -46,16 +46,25 @@
 #include "nsTArray.h"
 #include "nsPluginError.h"
 
 class nsNPAPIPlugin;
 class gfxASurface;
 class nsCString;
 
 namespace mozilla {
+namespace layers {
+class Image;
+class ImageContainer;
+}
+}
+
+using namespace mozilla::layers;
+
+namespace mozilla {
 
 class PluginLibrary
 {
 public:
   virtual ~PluginLibrary() { }
 
   /**
    * Inform this library about the nsNPAPIPlugin which owns it. This
@@ -83,16 +92,17 @@ public:
                            NPError* error) = 0;
 
   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 nsresult GetImage(NPP instance, ImageContainer* aContainer, Image** aImage) = 0;
   virtual bool UseAsyncPainting() = 0;
 #if defined(XP_MACOSX)
   virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing) = 0;
 #endif
 };
 
 
 } // namespace mozilla
--- a/dom/plugins/PluginModuleParent.cpp
+++ b/dom/plugins/PluginModuleParent.cpp
@@ -677,16 +677,25 @@ PluginModuleParent::GetSurface(NPP insta
 {
     PluginInstanceParent* i = InstCast(instance);
     if (!i)
         return NS_ERROR_FAILURE;
 
     return i->GetSurface(aSurface);
 }
 
+nsresult
+PluginModuleParent::GetImage(NPP instance,
+                             mozilla::layers::ImageContainer* aContainer,
+                             mozilla::layers::Image** aImage)
+{
+    PluginInstanceParent* i = InstCast(instance);
+    return !i ? NS_ERROR_FAILURE : i->GetImage(aContainer, aImage);
+}
+
 #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
@@ -226,16 +226,17 @@ private:
     static NPError NPP_SetValue(NPP instance, NPNVariable variable,
                                 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);
+    virtual nsresult GetImage(NPP instance, mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return true; }
 
 #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);
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -471,23 +471,39 @@ public:
     return (mInstance &&
             NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
             useAsyncRendering &&
             (!mPluginWindow ||
              mPluginWindow->type == NPWindowTypeDrawable));
   }
 
 private:
+
   // return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
   PRBool IsUpToDate()
   {
-    nsRefPtr<gfxASurface> readyToUse;
-    return NS_SUCCEEDED(mInstance->GetSurface(getter_AddRefs(readyToUse))) &&
-           readyToUse && readyToUse->GetSize() == gfxIntSize(mPluginWindow->width,
-                                                             mPluginWindow->height);
+    nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+    if (!container) {
+      return PR_FALSE;
+    }
+
+    nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = do_QueryInterface(mInstance);
+    if (!inst) {
+      return PR_FALSE;
+    }
+
+    nsRefPtr<Image> image;
+    if (!NS_SUCCEEDED(inst->GetImage(container, getter_AddRefs(image))) || !image)
+      return PR_FALSE;
+
+    container->SetCurrentImage(image);
+
+    if (container->GetCurrentSize() != gfxIntSize(mPluginWindow->width, mPluginWindow->height))
+      return PR_FALSE;
+    return PR_TRUE;
   }
 
   void FixUpURLS(const nsString &name, nsAString &value);
 
   nsPluginNativeWindow       *mPluginWindow;
   nsCOMPtr<nsIPluginInstance> mInstance;
   nsObjectFrame              *mObjectFrame; // owns nsPluginInstanceOwner
   nsCOMPtr<nsIContent>        mContent;
@@ -598,17 +614,16 @@ private:
 
   PRBool SetupXShm();
   void ReleaseXShm();
   void NativeImageDraw(NPRect* invalidRect = nsnull);
   PRBool UpdateVisibility(PRBool aVisible);
 
 #endif
 
-  nsRefPtr<gfxASurface> mLayerSurface;
   PRPackedBool          mWaitingForPaint;
 };
 
   // Mac specific code to fix up port position and clip
 #ifdef XP_MACOSX
 
   enum { ePluginPaintEnable, ePluginPaintDisable };
 
@@ -1780,37 +1795,27 @@ nsPluginInstanceOwner::NotifyPaintWaiter
     // receive it immediately
     mWaitingForPaint = nsContentUtils::AddScriptRunner(event);
   }
 }
 
 PRBool
 nsPluginInstanceOwner::SetCurrentImage(ImageContainer* aContainer)
 {
-  mInstance->GetSurface(getter_AddRefs(mLayerSurface));
-  if (!mLayerSurface) {
-    aContainer->SetCurrentImage(nsnull);
-    return PR_FALSE;
-  }
-
-  Image::Format format = Image::CAIRO_SURFACE;
-  nsRefPtr<Image> image;
-  image = aContainer->CreateImage(&format, 1);
-  if (!image)
-    return PR_FALSE;
-
-  NS_ASSERTION(image->GetFormat() == Image::CAIRO_SURFACE, "Wrong format?");
-  CairoImage* pluginImage = static_cast<CairoImage*>(image.get());
-  CairoImage::Data cairoData;
-  cairoData.mSurface = mLayerSurface.get();
-  cairoData.mSize = mLayerSurface->GetSize();
-  pluginImage->SetData(cairoData);
-  aContainer->SetCurrentImage(image);
-
-  return PR_TRUE;
+  nsCOMPtr<nsIPluginInstance_MOZILLA_2_0_BRANCH> inst = do_QueryInterface(mInstance);
+  if (inst) {
+    nsRefPtr<Image> image;
+    inst->GetImage(aContainer, getter_AddRefs(image));
+    if (image) {
+      aContainer->SetCurrentImage(image);
+      return PR_TRUE;
+    }
+  }
+  aContainer->SetCurrentImage(nsnull);
+  return PR_FALSE;
 }
 
 mozilla::LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
   if (!mInstanceOwner || !mInstanceOwner->UseLayers())
     return mozilla::LAYER_NONE;
@@ -5460,22 +5465,19 @@ nsPluginInstanceOwner::Destroy()
 
 /*
  * Prepare to stop 
  */
 void
 nsPluginInstanceOwner::PrepareToStop(PRBool aDelayedStop)
 {
   // Drop image reference because the child may destroy the surface after we return.
-  if (mLayerSurface) {
-     nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
-     if (container) {
-       container->SetCurrentImage(nsnull);
-     }
-     mLayerSurface = nsnull;
+  nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+  if (container) {
+    container->SetCurrentImage(nsnull);
   }
 
 #if defined(XP_WIN) || defined(MOZ_X11)
   if (aDelayedStop && mWidget) {
     // To delay stopping a plugin we need to reparent the plugin
     // so that we can safely tear down the
     // plugin after its frame (and view) is gone.
 
--- a/modules/plugin/base/public/nsIPluginInstance.idl
+++ b/modules/plugin/base/public/nsIPluginInstance.idl
@@ -40,26 +40,36 @@
 
 interface nsIPluginInstanceOwner;
 interface nsIOutputStream;
 
 %{C++
 #include "npapi.h"
 #include "nsStringGlue.h"
 #include "gfxASurface.h"
+#include "ImageLayers.h"
 struct JSContext;
 struct JSObject;
 class gfxASurface;
 
+namespace mozilla {
+namespace layers {
+class Image;
+class ImageContainer;
+}
+}
+
 #define NPRUNTIME_JSCLASS_NAME "NPObject JS wrapper class"
 %}
 
 [ptr] native JSContextPtr(JSContext);
 [ptr] native JSObjectPtr(JSObject);
 [ptr] native gfxASurfacePtr(gfxASurface);
+[ptr] native ImagePtr(mozilla::layers::Image);
+[ptr] native ImageContainerPtr(mozilla::layers::ImageContainer);
 
 [uuid(84994340-E120-4051-824F-D4EE8AEF1A3E)]
 interface nsIPluginInstance : nsISupports
 {
     /**
      * Initializes a newly created plugin instance.
      * 
      * @param aOwner - the plugin instance owner
@@ -244,13 +254,14 @@ interface nsIPluginInstance : nsISupport
 
     /**
      * @return true if plugin module supports async rendering
      */
     PRBool useAsyncPainting();
 };
 
 // XXX kill me after branching
-[noscript, uuid(c4251cb8-dd2f-4885-a008-2d1b4d21fd33)]
+[noscript, uuid(2b012762-9a55-458b-929e-7ea094812567)]
 interface nsIPluginInstance_MOZILLA_2_0_BRANCH : nsIPluginInstance
 {
     PRBool isRemoteDrawingCoreAnimation();
+    void getImage(in ImageContainerPtr aContainer, out ImagePtr aImage);
 };
--- a/modules/plugin/base/src/PluginPRLibrary.cpp
+++ b/modules/plugin/base/src/PluginPRLibrary.cpp
@@ -250,16 +250,25 @@ 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::GetImage(NPP instance, ImageContainer* aContainer, Image** aImage)
+{
+  nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
+  NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
+  *aImage = nsnull;
+  return NS_OK;
+}
+
 #if defined(XP_MACOSX)
 nsresult
 PluginPRLibrary::IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing)
 {
   nsNPAPIPluginInstance* inst = (nsNPAPIPluginInstance*)instance->ndata;
   NS_ENSURE_TRUE(inst, NS_ERROR_NULL_POINTER);
   *aDrawing = PR_FALSE; 
   return NS_OK;
--- a/modules/plugin/base/src/PluginPRLibrary.h
+++ b/modules/plugin/base/src/PluginPRLibrary.h
@@ -136,16 +136,17 @@ public:
                              NPError* error);
 
     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);
+    virtual nsresult GetImage(NPP instance, ImageContainer* aContainer, Image** aImage);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return false; }
 #if defined(XP_MACOSX)
     virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing);
 #endif
 
 private:
     NP_InitializeFunc mNP_Initialize;
     NP_ShutdownFunc mNP_Shutdown;
--- a/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
+++ b/modules/plugin/base/src/nsNPAPIPluginInstance.cpp
@@ -54,18 +54,18 @@
 
 #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_ISUPPORTS2(nsNPAPIPluginInstance, nsIPluginInstance, nsIPluginInstance_MOZILLA_2_0_BRANCH)
 
 nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin)
   :
@@ -820,16 +820,35 @@ 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);
 
@@ -856,16 +875,25 @@ nsNPAPIPluginInstance::GetSurface(gfxASu
 
   PluginLibrary* library = mPlugin->GetLibrary();
   if (!library)
     return NS_ERROR_FAILURE;
 
   return library->GetSurface(&mNPP, aSurface);
 }
 
+NS_IMETHODIMP
+nsNPAPIPluginInstance::GetImage(ImageContainer* aContainer, Image** aImage)
+{
+  if (RUNNING != mRunning)
+    return NS_OK;
+
+  AutoPluginLibraryCall library(this);
+  return !library ? NS_ERROR_FAILURE : library->GetImage(&mNPP, aContainer, aImage);
+}
 
 NS_IMETHODIMP
 nsNPAPIPluginInstance::NotifyPainted(void)
 {
   NS_NOTREACHED("Dead code, shouldn't be called.");
   return NS_ERROR_NOT_IMPLEMENTED;
 }