Bug 591687: Create MacIOSurfaceImages for Core Animation plugins. r=roc r=josh a=blocking2.0betaN+
authorMatt Woodrow <mwoodrow@mozilla.com>
Sat, 12 Feb 2011 11:09:03 -0500
changeset 62474 94f0723d8ee6d60710190be05e30fe9afd6dad9c
parent 62473 b0c3b563b2fa0afef993fa4c1fa3c5ae16aee1f8
child 62475 652d012f9dc8f318cd4baccedc982990d3c3c462
push id1
push userroot
push dateTue, 10 Dec 2013 15:46:25 +0000
reviewersroc, josh, blocking2
bugs591687
milestone2.0b12pre
Bug 591687: Create MacIOSurfaceImages for Core Animation plugins. r=roc r=josh a=blocking2.0betaN+
dom/plugins/PluginInstanceParent.cpp
layout/generic/nsObjectFrame.cpp
layout/generic/nsObjectFrame.h
--- a/dom/plugins/PluginInstanceParent.cpp
+++ b/dom/plugins/PluginInstanceParent.cpp
@@ -570,27 +570,47 @@ PluginInstanceParent::GetSurface(gfxASur
       return NS_OK;
     }
     return NS_ERROR_NOT_AVAILABLE;
 }
 
 nsresult
 PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage)
 {
+#ifdef XP_MACOSX
+    if (!mFrontSurface && !mIOSurface)
+#else
     if (!mFrontSurface)
+#endif
         return NS_ERROR_NOT_AVAILABLE;
 
     Image::Format format = Image::CAIRO_SURFACE;
+#ifdef XP_MACOSX
+    if (mIOSurface)
+        format = Image::MAC_IO_SURFACE;
+#endif
 
     nsRefPtr<Image> image;
     image = aContainer->CreateImage(&format, 1);
     if (!image) {
         return NS_ERROR_FAILURE;
     }
 
+#ifdef XP_MACOSX
+    if (mIOSurface) {
+        NS_ASSERTION(image->GetFormat() == Image::MAC_IO_SURFACE, "Wrong format?");
+        MacIOSurfaceImage* ioImage = static_cast<MacIOSurfaceImage*>(image.get());
+        MacIOSurfaceImage::Data ioData;
+        ioData.mIOSurface = mIOSurface;
+        ioImage->SetData(ioData);
+        *aImage = image.forget().get();
+        return NS_OK;
+    }
+#endif
+
     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();
@@ -892,23 +912,25 @@ PluginInstanceParent::NPP_HandleEvent(vo
 
             CGContextRef cgContext = npevent->data.draw.context;
             if (!mShColorSpace) {
                 mShColorSpace = CreateSystemColorSpace();
             }
             if (!mShColorSpace) {
                 PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace."));
                 return false;
-            } 
-            nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface, 
-                                                 mShColorSpace,
-                                                 npevent->data.draw.x,
-                                                 npevent->data.draw.y,
-                                                 npevent->data.draw.width,
-                                                 npevent->data.draw.height);
+            }
+            if (cgContext) {
+                nsCARenderer::DrawSurfaceToCGContext(cgContext, mIOSurface, 
+                                                     mShColorSpace,
+                                                     npevent->data.draw.x,
+                                                     npevent->data.draw.y,
+                                                     npevent->data.draw.width,
+                                                     npevent->data.draw.height);
+            }
             return false;
         } else {
             if (mShWidth == 0 && mShHeight == 0) {
                 PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0."));
                 return false;
             }
             if (!mShSurface.IsReadable()) {
                 PLUGIN_LOG_DEBUG(("Shmem is not readable."));
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -325,16 +325,17 @@ public:
 
   void PrepareToStop(PRBool aDelayedStop);
   
 #ifdef XP_WIN
   void Paint(const RECT& aDirty, HDC aDC);
 #elif defined(XP_MACOSX)
   void Paint(const gfxRect& aDirtyRect, CGContextRef cgContext);  
   void RenderCoreAnimation(CGContextRef aCGContext, int aWidth, int aHeight);
+  void DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext);
 #elif defined(MOZ_X11)
   void Paint(gfxContext* aContext,
              const gfxRect& aFrameRect,
              const gfxRect& aDirtyRect);
 #elif defined(XP_OS2)
   void Paint(const nsRect& aDirtyRect, HPS aHPS);
 #endif
 
@@ -460,17 +461,17 @@ public:
                                      nsIDOMClientRect* position,
                                      nsIDOMClientRect* clip);
 #endif
 
   void NotifyPaintWaiter(nsDisplayListBuilder* aBuilder);
   // Return true if we set image with valid surface
   PRBool SetCurrentImage(ImageContainer* aContainer);
 
-  PRBool UseLayers()
+  PRBool UseAsyncRendering()
   {
     PRBool useAsyncRendering;
     return (mInstance &&
             NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
             useAsyncRendering &&
             (!mPluginWindow ||
              mPluginWindow->type == NPWindowTypeDrawable));
   }
@@ -1152,17 +1153,17 @@ nsObjectFrame::CallSetWindow(PRBool aChe
   nsIntRect intBounds = bounds.ToNearestPixels(appUnitsPerDevPixel);
   window->x = intBounds.x;
   window->y = intBounds.y;
   window->width = intBounds.width;
   window->height = intBounds.height;
 
   // this will call pi->SetWindow and take care of window subclassing
   // if needed, see bug 132759.
-  if (mInstanceOwner->UseLayers()) {
+  if (mInstanceOwner->UseAsyncRendering()) {
     rv = pi->AsyncSetWindow(window);
   }
   else {
     rv = window->CallSetWindow(pi);
   }
 
   mInstanceOwner->ReleasePluginPort(window->window);
   return rv;
@@ -1275,28 +1276,30 @@ nsDisplayPlugin::GetBounds(nsDisplayList
   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;
   }
 
+#ifndef XP_MACOSX
   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
   if (mozilla::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;
 }
 
 void
 nsDisplayPlugin::Paint(nsDisplayListBuilder* aBuilder,
                        nsIRenderingContext* aCtx)
 {
   nsObjectFrame* f = static_cast<nsObjectFrame*>(mFrame);
@@ -1491,17 +1494,17 @@ nsObjectFrame::BuildDisplayList(nsDispla
   if (mWidget && aBuilder->IsInTransform()) {
     // Windowed plugins should not be rendered inside a transform.
     return NS_OK;
   }
 #endif
 
   nsDisplayList replacedContent;
 
-  if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseLayers()) {
+  if (aBuilder->IsForPainting() && mInstanceOwner && mInstanceOwner->UseAsyncRendering()) {
     NPWindow* window = nsnull;
     mInstanceOwner->GetWindow(window);
     PRBool isVisible = window && window->width > 0 && window->height > 0;
     if (isVisible && aBuilder->ShouldSyncDecodeImages()) {
   #ifndef XP_MACOSX
       mInstanceOwner->UpdateWindowVisibility(PR_TRUE);
   #endif
     }
@@ -1812,17 +1815,30 @@ nsPluginInstanceOwner::SetCurrentImage(I
   aContainer->SetCurrentImage(nsnull);
   return PR_FALSE;
 }
 
 mozilla::LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
-  if (!mInstanceOwner || !mInstanceOwner->UseLayers())
+  if (!mInstanceOwner)
+    return mozilla::LAYER_NONE;
+
+#ifdef XP_MACOSX
+  if (aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
+      mInstanceOwner->GetEventModel() == NPEventModelCocoa &&
+      mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics &&
+      mInstanceOwner->IsRemoteDrawingCoreAnimation())
+  {
+    return mozilla::LAYER_ACTIVE;
+  }
+#endif
+
+  if (!mInstanceOwner->UseAsyncRendering())
     return mozilla::LAYER_NONE;
 
   return mozilla::LAYER_ACTIVE;
 }
 
 already_AddRefed<Layer>
 nsObjectFrame::BuildLayer(nsDisplayListBuilder* aBuilder,
                           LayerManager* aManager,
@@ -1842,24 +1858,32 @@ nsObjectFrame::BuildLayer(nsDisplayListB
   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) {
-    mInstanceOwner->NotifyPaintWaiter(aBuilder);
+    if (mInstanceOwner->UseAsyncRendering()) {
+      mInstanceOwner->NotifyPaintWaiter(aBuilder);
+    }
+
     // 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;
@@ -4082,17 +4106,17 @@ void nsPluginInstanceOwner::RenderCoreAn
     FixUpPluginWindow(ePluginPaintDisable);
     FixUpPluginWindow(ePluginPaintEnable);
   }
 
   CGImageRef caImage = NULL;
   nsresult rt = mCARenderer.Render(aWidth, aHeight, &caImage);
   if (rt == NS_OK && mIOSurface) {
     nsCARenderer::DrawSurfaceToCGContext(aCGContext, mIOSurface, CreateSystemColorSpace(),
-                                         0, 0, aWidth, aHeight); 
+                                         0, 0, aWidth, aHeight);
   } else if (rt == NS_OK && caImage != NULL) {
     // Significant speed up by resetting the scaling
     ::CGContextSetInterpolationQuality(aCGContext, kCGInterpolationNone );
     ::CGContextTranslateCTM(aCGContext, 0, aHeight);
     ::CGContextScaleCTM(aCGContext, 1.0, -1.0);
 
     ::CGContextDrawImage(aCGContext, CGRectMake(0,0,aWidth,aHeight), caImage);
   } else {
@@ -5521,31 +5545,36 @@ void nsPluginInstanceOwner::Paint(const 
       InitializeEventRecord(&updateEvent, nsnull);
       updateEvent.what = updateEvt;
       updateEvent.message = UInt32(window);
 
       mInstance->HandleEvent(&updateEvent, nsnull);
     } else if (GetEventModel() == NPEventModelCocoa)
 #endif
     {
-      // The context given here is only valid during the HandleEvent call.
-      NPCocoaEvent updateEvent;
-      InitializeNPCocoaEvent(&updateEvent);
-      updateEvent.type = NPCocoaEventDrawRect;
-      updateEvent.data.draw.context = cgContext;
-      updateEvent.data.draw.x = aDirtyRect.X();
-      updateEvent.data.draw.y = aDirtyRect.Y();
-      updateEvent.data.draw.width = aDirtyRect.Width();
-      updateEvent.data.draw.height = aDirtyRect.Height();
-
-      mInstance->HandleEvent(&updateEvent, nsnull);
+      DoCocoaEventDrawRect(aDirtyRect, cgContext);
     }
     pluginWidget->EndDrawPlugin();
   }
 }
+
+void nsPluginInstanceOwner::DoCocoaEventDrawRect(const gfxRect& aDrawRect, CGContextRef cgContext)
+{
+  // The context given here is only valid during the HandleEvent call.
+  NPCocoaEvent updateEvent;
+  InitializeNPCocoaEvent(&updateEvent);
+  updateEvent.type = NPCocoaEventDrawRect;
+  updateEvent.data.draw.context = cgContext;
+  updateEvent.data.draw.x = aDrawRect.X();
+  updateEvent.data.draw.y = aDrawRect.Y();
+  updateEvent.data.draw.width = aDrawRect.Width();
+  updateEvent.data.draw.height = aDrawRect.Height();
+
+  mInstance->HandleEvent(&updateEvent, nsnull);
+}
 #endif
 
 #ifdef XP_WIN
 void nsPluginInstanceOwner::Paint(const RECT& aDirty, HDC aDC)
 {
   if (!mInstance || !mObjectFrame)
     return;
 
@@ -6546,17 +6575,17 @@ nsPluginInstanceOwner::HidePluginWindow(
 void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(PRBool aSetWindow)
 {
   if (!mPluginWindow)
     return;
 
   // For windowless plugins a non-empty clip rectangle will be
   // passed to the plugin during paint, an additional update
   // of the the clip rectangle here is not required
-  if (aSetWindow && !mWidget && mPluginWindowVisible && !UseLayers())
+  if (aSetWindow && !mWidget && mPluginWindowVisible && !UseAsyncRendering())
     return;
 
   const NPWindow oldWindow = *mPluginWindow;
 
   PRBool windowless = (mPluginWindow->type == NPWindowTypeDrawable);
   nsIntPoint origin = mObjectFrame->GetWindowOriginInPixels(windowless);
 
   mPluginWindow->x = origin.x;
@@ -6587,17 +6616,17 @@ void nsPluginInstanceOwner::UpdateWindow
 }
 
 void
 nsPluginInstanceOwner::CallSetWindow()
 {
   if (!mInstance)
     return;
 
-  if (UseLayers()) {
+  if (UseAsyncRendering()) {
     mInstance->AsyncSetWindow(mPluginWindow);
   } else {
     mInstance->SetWindow(mPluginWindow);
   }
 }
 
 void
 nsPluginInstanceOwner::UpdateWindowVisibility(PRBool aVisible)
--- a/layout/generic/nsObjectFrame.h
+++ b/layout/generic/nsObjectFrame.h
@@ -57,16 +57,17 @@ class nsIAccessible;
 #endif
 
 class nsPluginInstanceOwner;
 class nsIPluginHost;
 class nsIPluginInstance;
 class nsPresContext;
 class nsDisplayPlugin;
 class nsIDOMElement;
+class nsIOSurface;
 
 #define nsObjectFrameSuper nsFrame
 
 class nsObjectFrame : public nsObjectFrameSuper,
                       public nsIObjectFrame,
                       public nsIReflowCallback {
 public:
   typedef mozilla::LayerState LayerState;
@@ -334,17 +335,19 @@ public:
   // If there is no widget associated with the plugin, this
   // simply does nothing.
   void GetWidgetConfiguration(nsDisplayListBuilder* aBuilder,
                               nsTArray<nsIWidget::Configuration>* aConfigurations);
 
   virtual already_AddRefed<Layer> BuildLayer(nsDisplayListBuilder* aBuilder,
                                              LayerManager* aManager)
   {
-    return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder, aManager, this);
+    return static_cast<nsObjectFrame*>(mFrame)->BuildLayer(aBuilder,
+                                                           aManager, 
+                                                           this);
   }
 
   virtual LayerState GetLayerState(nsDisplayListBuilder* aBuilder,
                                    LayerManager* aManager)
   {
     return static_cast<nsObjectFrame*>(mFrame)->GetLayerState(aBuilder, aManager);
   }