Asynchronous layer-based plugin painting on Mac b=598425 r=roc,josh
authorBenoit Girard <b56girard@gmail.com>
Thu, 19 May 2011 17:08:14 -0400
changeset 70574 24e35780bd8f8ca2763b4dad8f6c79cc849457d5
parent 70573 52b9e864be0eec472a1a450c95306f037e931beb
child 70576 068197c2a88ec96bf0e40f369dc482b3e62eb63c
push idunknown
push userunknown
push dateunknown
reviewersroc, josh
bugs598425
milestone7.0a1
Asynchronous layer-based plugin painting on Mac b=598425 r=roc,josh
dom/plugins/base/PluginPRLibrary.cpp
dom/plugins/base/PluginPRLibrary.h
dom/plugins/base/nsNPAPIPluginInstance.cpp
dom/plugins/base/nsPluginInstanceOwner.cpp
dom/plugins/base/nsPluginInstanceOwner.h
dom/plugins/ipc/PPluginInstance.ipdl
dom/plugins/ipc/PluginInstanceChild.cpp
dom/plugins/ipc/PluginInstanceChild.h
dom/plugins/ipc/PluginInstanceParent.cpp
dom/plugins/ipc/PluginInstanceParent.h
dom/plugins/ipc/PluginInterposeOSX.h
dom/plugins/ipc/PluginLibrary.h
dom/plugins/ipc/PluginModuleParent.cpp
dom/plugins/ipc/PluginModuleParent.h
dom/plugins/ipc/PluginUtilsOSX.h
dom/plugins/ipc/PluginUtilsOSX.mm
layout/generic/nsObjectFrame.cpp
--- a/dom/plugins/base/PluginPRLibrary.cpp
+++ b/dom/plugins/base/PluginPRLibrary.cpp
@@ -253,27 +253,16 @@ PluginPRLibrary::GetImage(NPP instance, 
 }
 
 nsresult
 PluginPRLibrary::GetImageSize(NPP instance, nsIntSize* aSize)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-#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;
-}
-#endif
-
 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;
 }
--- a/dom/plugins/base/PluginPRLibrary.h
+++ b/dom/plugins/base/PluginPRLibrary.h
@@ -138,19 +138,16 @@ 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 GetImage(NPP instance, ImageContainer* aContainer, Image** aImage);
     virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize);
     NS_OVERRIDE virtual bool UseAsyncPainting() { return false; }
-#if defined(XP_MACOSX)
-    virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing);
-#endif
     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&);
--- a/dom/plugins/base/nsNPAPIPluginInstance.cpp
+++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp
@@ -724,32 +724,16 @@ nsresult nsNPAPIPluginInstance::GetDrawi
 #ifdef XP_MACOSX
   *aModel = (PRInt32)mDrawingModel;
   return NS_OK;
 #else
   return NS_ERROR_FAILURE;
 #endif
 }
 
-nsresult nsNPAPIPluginInstance::IsRemoteDrawingCoreAnimation(PRBool* aDrawing)
-{
-#ifdef XP_MACOSX
-  if (!mPlugin)
-      return NS_ERROR_FAILURE;
-
-  PluginLibrary* library = mPlugin->GetLibrary();
-  if (!library)
-      return NS_ERROR_FAILURE;
-  
-  return library->IsRemoteDrawingCoreAnimation(&mNPP, aDrawing);
-#else
-  return NS_ERROR_FAILURE;
-#endif
-}
-
 nsresult
 nsNPAPIPluginInstance::GetJSObject(JSContext *cx, JSObject** outObject)
 {
   NPObject *npobj = nsnull;
   nsresult rv = GetValueFromPlugin(NPPVpluginScriptableNPObject, &npobj);
   if (NS_FAILED(rv) || !npobj)
     return NS_ERROR_FAILURE;
 
--- a/dom/plugins/base/nsPluginInstanceOwner.cpp
+++ b/dom/plugins/base/nsPluginInstanceOwner.cpp
@@ -246,16 +246,38 @@ nsPluginInstanceOwner::EndUpdateBackgrou
                                            const nsIntRect& aRect)
 {
   nsIntRect rect = aRect;
   if (mInstance) {
     mInstance->EndUpdateBackground(aContext, &rect);
   }
 }
 
+PRBool
+nsPluginInstanceOwner::UseAsyncRendering()
+{
+#ifdef XP_MACOSX
+  nsRefPtr<ImageContainer> container = mObjectFrame->GetImageContainer();
+#endif
+
+  PRBool useAsyncRendering;
+  return (mInstance &&
+          NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
+          useAsyncRendering &&
+#ifdef XP_MACOSX
+          mObjectFrame && mObjectFrame->GetImageContainer().get() &&
+          mObjectFrame->GetImageContainer().get()->GetBackendType() == 
+                  LayerManager::LAYERS_OPENGL
+#else
+          (!mPluginWindow ||
+           mPluginWindow->type == NPWindowTypeDrawable)
+#endif
+          );
+}
+
 nsIntSize
 nsPluginInstanceOwner::GetCurrentImageSize()
 {
   nsIntSize size(0,0);
   if (mInstance) {
     mInstance->GetImageSize(&size);
   }
   return size;
@@ -1333,28 +1355,16 @@ NPDrawingModel nsPluginInstanceOwner::Ge
 
   if (!mInstance)
     return drawingModel;
 
   mInstance->GetDrawingModel((PRInt32*)&drawingModel);
   return drawingModel;
 }
 
-PRBool nsPluginInstanceOwner::IsRemoteDrawingCoreAnimation()
-{
-  if (!mInstance)
-    return PR_FALSE;
-
-  PRBool coreAnimation;
-  if (!NS_SUCCEEDED(mInstance->IsRemoteDrawingCoreAnimation(&coreAnimation)))
-    return PR_FALSE;
-
-  return coreAnimation;
-}
-
 NPEventModel nsPluginInstanceOwner::GetEventModel()
 {
   return mEventModel;
 }
 
 #define DEFAULT_REFRESH_RATE 20 // 50 FPS
 
 nsCOMPtr<nsITimer>                *nsPluginInstanceOwner::sCATimer = NULL;
@@ -3212,31 +3222,31 @@ void* nsPluginInstanceOwner::FixUpPlugin
 
   // if the clip rect changed, call SetWindow()
   // (RealPlayer needs this to draw correctly)
   if (mPluginWindow->clipRect.left    != oldClipRect.left   ||
       mPluginWindow->clipRect.top     != oldClipRect.top    ||
       mPluginWindow->clipRect.right   != oldClipRect.right  ||
       mPluginWindow->clipRect.bottom  != oldClipRect.bottom)
   {
-    mInstance->SetWindow(mPluginWindow);
+    CallSetWindow();
     mPluginPortChanged = PR_FALSE;
 #ifdef MAC_CARBON_PLUGINS
     // if the clipRect is of size 0, make the null timer fire less often
     CancelTimer();
     if (mPluginWindow->clipRect.left == mPluginWindow->clipRect.right ||
         mPluginWindow->clipRect.top == mPluginWindow->clipRect.bottom) {
       StartTimer(PR_FALSE);
     }
     else {
       StartTimer(PR_TRUE);
     }
 #endif
   } else if (mPluginPortChanged) {
-    mInstance->SetWindow(mPluginWindow);
+    CallSetWindow();
     mPluginPortChanged = PR_FALSE;
   }
 
   // After the first NPP_SetWindow call we need to send an initial
   // top-level window focus event.
   if (eventModel == NPEventModelCocoa && !mSentInitialTopLevelWindowEvent) {
     // Set this before calling ProcessEvent to avoid endless recursion.
     mSentInitialTopLevelWindowEvent = PR_TRUE;
@@ -3268,17 +3278,21 @@ nsPluginInstanceOwner::HidePluginWindow(
 {
   if (!mPluginWindow || !mInstance) {
     return;
   }
 
   mPluginWindow->clipRect.bottom = mPluginWindow->clipRect.top;
   mPluginWindow->clipRect.right  = mPluginWindow->clipRect.left;
   mWidgetVisible = PR_FALSE;
-  mInstance->SetWindow(mPluginWindow);
+  if (mAsyncHidePluginWindow) {
+    mInstance->AsyncSetWindow(mPluginWindow);
+  } else {
+    mInstance->SetWindow(mPluginWindow);
+  }
 }
 
 #else // XP_MACOSX
 
 void nsPluginInstanceOwner::UpdateWindowPositionAndClipRect(PRBool aSetWindow)
 {
   if (!mPluginWindow)
     return;
@@ -3317,37 +3331,39 @@ void nsPluginInstanceOwner::UpdateWindow
       mPluginWindow->clipRect.top    != oldWindow.clipRect.top    ||
       mPluginWindow->clipRect.right  != oldWindow.clipRect.right  ||
       mPluginWindow->clipRect.bottom != oldWindow.clipRect.bottom) {
     CallSetWindow();
   }
 }
 
 void
-nsPluginInstanceOwner::CallSetWindow()
-{
-  if (!mInstance)
-    return;
-
-  if (UseAsyncRendering()) {
-    mInstance->AsyncSetWindow(mPluginWindow);
-  } else {
-    mInstance->SetWindow(mPluginWindow);
-  }
-}
-
-void
 nsPluginInstanceOwner::UpdateWindowVisibility(PRBool aVisible)
 {
   mPluginWindowVisible = aVisible;
   UpdateWindowPositionAndClipRect(PR_TRUE);
 }
 
 #endif // XP_MACOSX
 
+void
+nsPluginInstanceOwner::CallSetWindow()
+{
+  if (!mInstance)
+    return;
+
+  if (UseAsyncRendering()) {
+    mAsyncHidePluginWindow = true;
+    mInstance->AsyncSetWindow(mPluginWindow);
+  } else {
+    mAsyncHidePluginWindow = false;
+    mInstance->SetWindow(mPluginWindow);
+  }
+}
+
 // Little helper function to resolve relative URL in
 // |value| for certain inputs of |name|
 void nsPluginInstanceOwner::FixUpURLS(const nsString &name, nsAString &value)
 {
   if (name.LowerCaseEqualsLiteral("pluginurl") ||
       name.LowerCaseEqualsLiteral("pluginspage")) {        
     nsCOMPtr<nsIURI> baseURI = mContent->GetBaseURI();
     nsAutoString newURL;
--- a/dom/plugins/base/nsPluginInstanceOwner.h
+++ b/dom/plugins/base/nsPluginInstanceOwner.h
@@ -174,17 +174,16 @@ public:
   void SetPluginHost(nsIPluginHost* aHost);
   
   nsEventStatus ProcessEvent(const nsGUIEvent & anEvent);
   
 #ifdef XP_MACOSX
   enum { ePluginPaintEnable, ePluginPaintDisable };
   
   NPDrawingModel GetDrawingModel();
-  PRBool IsRemoteDrawingCoreAnimation();
   NPEventModel GetEventModel();
   static void CARefresh(nsITimer *aTimer, void *aClosure);
   static void AddToCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
   static void RemoveFromCARefreshTimer(nsPluginInstanceOwner *aPluginInstance);
   void SetupCARefresh();
   void* FixUpPluginWindow(PRInt32 inPaintState);
   void HidePluginWindow();
   // Set a flag that (if true) indicates the plugin port info has changed and
@@ -202,19 +201,19 @@ public:
   // nsObjectFrame::PaintPlugin().  We need to know this in
   // FixUpPluginWindow() (i.e. we need to know when FixUpPluginWindow() has
   // been called from nsObjectFrame::PaintPlugin() when we're using the
   // CoreGraphics drawing model).
   void BeginCGPaint();
   void EndCGPaint();
 #else // XP_MACOSX
   void UpdateWindowPositionAndClipRect(PRBool aSetWindow);
-  void CallSetWindow();
   void UpdateWindowVisibility(PRBool aVisible);
 #endif // XP_MACOSX
+  void CallSetWindow();
   
   void SetOwner(nsObjectFrame *aOwner)
   {
     mObjectFrame = aOwner;
   }
   nsObjectFrame* GetOwner() {
     return mObjectFrame;
   }
@@ -290,25 +289,17 @@ public:
   
   // 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 UseAsyncRendering()
-  {
-    PRBool useAsyncRendering;
-    return (mInstance &&
-            NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) &&
-            useAsyncRendering &&
-            (!mPluginWindow ||
-             mPluginWindow->type == NPWindowTypeDrawable));
-  }
+  PRBool UseAsyncRendering();
   
 private:
   
   // return FALSE if LayerSurface dirty (newly created and don't have valid plugin content yet)
   PRBool IsUpToDate()
   {
     nsIntSize size;
     return NS_SUCCEEDED(mInstance->GetImageSize(&size)) &&
@@ -334,16 +325,19 @@ private:
   PRInt32                                   mInCGPaintLevel;
   nsIOSurface                              *mIOSurface;
   nsCARenderer                              mCARenderer;
   CGColorSpaceRef                           mColorProfile;
   static nsCOMPtr<nsITimer>                *sCATimer;
   static nsTArray<nsPluginInstanceOwner*>  *sCARefreshListeners;
   PRBool                                    mSentInitialTopLevelWindowEvent;
 #endif
+  // We need to know if async hide window is required since we
+  // can not check UseAsyncRendering when executing StopPlugin
+  PRBool                                    mAsyncHidePluginWindow;
   
   // Initially, the event loop nesting level we were created on, it's updated
   // if we detect the appshell is on a lower level as long as we're not stopped.
   // We delay DoStopPlugin() until the appshell reaches this level or lower.
   PRUint32                    mLastEventloopNestingLevel;
   PRPackedBool                mContentFocused;
   PRPackedBool                mWidgetVisible;    // used on Mac to store our widget's visible state
 #ifdef XP_MACOSX
--- a/dom/plugins/ipc/PPluginInstance.ipdl
+++ b/dom/plugins/ipc/PPluginInstance.ipdl
@@ -64,20 +64,25 @@ namespace mozilla {
 namespace plugins {
 
 struct SurfaceDescriptorX11 {
   int XID;
   int xrenderPictID;
   gfxIntSize size;
 };
 
+struct IOSurfaceDescriptor {
+  uint32_t surfaceId;
+};
+
 union SurfaceDescriptor {
   Shmem;
   SurfaceDescriptorX11;
   PPluginSurface; // used on Windows
+  IOSurfaceDescriptor; // used on OSX 10.5+
   // Descriptor can be null here in case
   // 1) of first Show call (prevSurface is null)
   // 2) when child is going to destroy
   //    and it just want to grab prevSurface
   //     back without giving new surface
   null_t;
 };
 
--- a/dom/plugins/ipc/PluginInstanceChild.cpp
+++ b/dom/plugins/ipc/PluginInstanceChild.cpp
@@ -100,16 +100,17 @@ using mozilla::gfx::SharedDIB;
 // from Chromium's web plugin delegate src. See 'flash msg throttling
 // helpers' section for details.
 const int kFlashWMUSERMessageThrottleDelayMs = 5;
 
 static const TCHAR kPluginIgnoreSubclassProperty[] = TEXT("PluginIgnoreSubclassProperty");
 
 #elif defined(XP_MACOSX)
 #include <ApplicationServices/ApplicationServices.h>
+#include "PluginUtilsOSX.h"
 #endif // defined(XP_MACOSX)
 
 template<>
 struct RunnableMethodTraits<PluginInstanceChild>
 {
     static void RetainCallee(PluginInstanceChild* obj) { }
     static void ReleaseCallee(PluginInstanceChild* obj) { }
 };
@@ -130,16 +131,17 @@ PluginInstanceChild::PluginInstanceChild
     , mAsyncCallMutex("PluginInstanceChild::mAsyncCallMutex")
 #if defined(OS_MACOSX)
 #if defined(__i386__)
     , mEventModel(NPEventModelCarbon)
 #endif
     , mShColorSpace(nsnull)
     , mShContext(nsnull)
     , mDrawingModel(NPDrawingModelCoreGraphics)
+    , mCGLayer(nsnull)
     , mCurrentEvent(nsnull)
 #endif
     , mLayersRendering(false)
 #ifdef XP_WIN
     , mCurrentSurfaceActor(NULL)
     , mBackSurfaceActor(NULL)
 #endif
     , mAccumulatedInvalidRect(0,0,0,0)
@@ -178,16 +180,19 @@ PluginInstanceChild::~PluginInstanceChil
 #endif
 #if defined(OS_MACOSX)
     if (mShColorSpace) {
         ::CGColorSpaceRelease(mShColorSpace);
     }
     if (mShContext) {
         ::CGContextRelease(mShContext);
     }
+    if (mCGLayer) {
+        mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
+    }
 #endif
 }
 
 int
 PluginInstanceChild::GetQuirks()
 {
     return PluginModuleChild::current()->GetQuirks();
 }
@@ -472,29 +477,35 @@ PluginInstanceChild::NPN_SetValue(NPPVar
     case NPPVpluginDrawingModel: {
         NPError rv;
         int drawingModel = (int16) (intptr_t) aValue;
 
         if (!CallNPN_SetValue_NPPVpluginDrawingModel(drawingModel, &rv))
             return NPERR_GENERIC_ERROR;
         mDrawingModel = drawingModel;
 
+        PLUGIN_LOG_DEBUG(("  Plugin requested drawing model id  #%i\n",
+            mDrawingModel));
+
         return rv;
     }
 
     case NPPVpluginEventModel: {
         NPError rv;
         int eventModel = (int16) (intptr_t) aValue;
 
         if (!CallNPN_SetValue_NPPVpluginEventModel(eventModel, &rv))
             return NPERR_GENERIC_ERROR;
 #if defined(__i386__)
         mEventModel = static_cast<NPEventModel>(eventModel);
 #endif
 
+        PLUGIN_LOG_DEBUG(("  Plugin requested event model id # %i\n",
+            eventModel));
+
         return rv;
     }
 #endif
 
     default:
         PR_LOG(gPluginLog, PR_LOG_WARNING,
                ("In PluginInstanceChild::NPN_SetValue: Unhandled NPPVariable %i (%s)",
                 (int) aVar, NPPVariableToString(aVar)));
@@ -773,16 +784,42 @@ PluginInstanceChild::AnswerNPP_HandleEve
 {
     NS_RUNTIMEABORT("not reached.");
     *rtnmem = mem;
     return true;
 }
 #endif
 
 #ifdef XP_MACOSX
+
+void CallCGDraw(CGContextRef ref, void* aPluginInstance, nsIntRect aUpdateRect) {
+  PluginInstanceChild* pluginInstance = (PluginInstanceChild*)aPluginInstance;
+
+  pluginInstance->CGDraw(ref, aUpdateRect);
+}
+
+bool
+PluginInstanceChild::CGDraw(CGContextRef ref, nsIntRect aUpdateRect) {
+
+  NPCocoaEvent drawEvent;
+  drawEvent.type = NPCocoaEventDrawRect;
+  drawEvent.version = 0;
+  drawEvent.data.draw.x = aUpdateRect.x;
+  drawEvent.data.draw.y = aUpdateRect.y;
+  drawEvent.data.draw.width = aUpdateRect.width;
+  drawEvent.data.draw.height = aUpdateRect.height;
+  drawEvent.data.draw.context = ref;
+
+  NPRemoteEvent remoteDrawEvent = {drawEvent};
+
+  int16_t handled;
+  AnswerNPP_HandleEvent(remoteDrawEvent, &handled);
+  return handled == true;
+}
+
 bool
 PluginInstanceChild::AnswerNPP_HandleEvent_IOSurface(const NPRemoteEvent& event,
                                                      const uint32_t &surfaceid,
                                                      int16_t* handled)
 {
     PLUGIN_LOG_DEBUG_FUNCTION;
     AssertPluginThread();
 
@@ -798,23 +835,26 @@ PluginInstanceChild::AnswerNPP_HandleEve
 
     if (evcopy.type == NPCocoaEventDrawRect) {
         mCARenderer.AttachIOSurface(surf);
         if (!mCARenderer.isInit()) {
             void *caLayer = nsnull;
             NPError result = mPluginIface->getvalue(GetNPP(), 
                                      NPPVpluginCoreAnimationLayer,
                                      &caLayer);
+            
             if (result != NPERR_NO_ERROR || !caLayer) {
                 PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
                                   "provide CALayer."));
                 *handled = false;
                 return false;
             }
+
             mCARenderer.SetupRenderer(caLayer, mWindow.width, mWindow.height);
+
             // Flash needs to have the window set again after this step
             if (mPluginIface->setwindow)
                 (void) mPluginIface->setwindow(&mData, &mWindow);
         }
     } else {
         PLUGIN_LOG_DEBUG(("Invalid event type for "
                           "AnswerNNP_HandleEvent_IOSurface."));
         *handled = false;
@@ -2273,22 +2313,27 @@ PluginInstanceChild::DoAsyncSetWindow(co
     if (aIsAsync) {
         if (!mCurrentAsyncSetWindowTask) {
             return;
         }
         mCurrentAsyncSetWindowTask = nsnull;
     }
 
     mWindow.window = NULL;
+#ifdef XP_MACOSX
+    if (mWindow.width != aWindow.width || mWindow.height != aWindow.height) 
+        mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
+#else
     if (mWindow.width != aWindow.width || mWindow.height != aWindow.height ||
         mWindow.clipRect.top != aWindow.clipRect.top ||
         mWindow.clipRect.left != aWindow.clipRect.left ||
         mWindow.clipRect.bottom != aWindow.clipRect.bottom ||
         mWindow.clipRect.right != aWindow.clipRect.right)
         mAccumulatedInvalidRect = nsIntRect(0, 0, aWindow.width, aWindow.height);
+#endif
 
     mWindow.x = aWindow.x;
     mWindow.y = aWindow.y;
     mWindow.width = aWindow.width;
     mWindow.height = aWindow.height;
     mWindow.clipRect = aWindow.clipRect;
     mWindow.type = aWindow.type;
 
@@ -2467,16 +2512,17 @@ PluginInstanceChild::MaybeCreatePlatform
 #endif
 
     return true;
 }
 
 bool
 PluginInstanceChild::EnsureCurrentBuffer(void)
 {
+#ifndef XP_MACOSX
     nsIntRect toInvalidate(0, 0, 0, 0);
     gfxIntSize winSize = gfxIntSize(mWindow.width, mWindow.height);
 
     if (mBackground && mBackground->GetSize() != winSize) {
         // It would be nice to keep the old background here, but doing
         // so can lead to cases in which we permanently keep the old
         // background size.
         mBackground = nsnull;
@@ -2498,30 +2544,89 @@ PluginInstanceChild::EnsureCurrentBuffer
             toInvalidate.UnionRect(toInvalidate,
                                    nsIntRect(0, 0, winSize.width, winSize.height));
         }
     }
 
     mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
 
     if (mCurrentSurface) {
-       return true;
+        return true;
     }
 
     if (!CreateOptSurface()) {
         NS_ERROR("Cannot create optimized surface");
         return false;
     }
 
     if (!MaybeCreatePlatformHelperSurface()) {
         NS_ERROR("Cannot create helper surface");
         return false;
     }
 
     return true;
+#else // XP_MACOSX
+    if (mCurrentIOSurface && 
+        (mCurrentIOSurface->GetWidth() != mWindow.width ||
+         mCurrentIOSurface->GetHeight() != mWindow.height) ) {
+        mCurrentIOSurface = nsnull;
+    }
+
+    if (!mCARenderer.isInit() || !mCurrentIOSurface) {
+        if (!mCurrentIOSurface) {
+            mCurrentIOSurface = nsIOSurface::CreateIOSurface(mWindow.width, mWindow.height);
+
+            nsIntRect toInvalidate(0, 0, mWindow.width, mWindow.height);
+            mAccumulatedInvalidRect.UnionRect(mAccumulatedInvalidRect, toInvalidate);
+        }
+
+        if (!mCurrentIOSurface) {
+            NS_WARNING("Failed to allocate IOSurface");
+            return false;
+        }
+
+        nsIOSurface *rendererSurface = nsIOSurface::LookupSurface(mCurrentIOSurface->GetIOSurfaceID()); 
+        if (!rendererSurface) {
+            NS_WARNING("Failed to lookup IOSurface");
+            return false;
+        }
+        mCARenderer.AttachIOSurface(rendererSurface);
+
+        void *caLayer = nsnull;
+        if (mDrawingModel == NPDrawingModelCoreGraphics) {
+            if (mCGLayer) {
+                mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer);
+                mCGLayer = nsnull;
+            }
+
+            caLayer = mozilla::plugins::PluginUtilsOSX::GetCGLayer(CallCGDraw, this);
+            if (!caLayer) {
+                return false;
+            }
+
+            mCGLayer = caLayer;
+        } else {
+            NPError result = mPluginIface->getvalue(GetNPP(),
+                                     NPPVpluginCoreAnimationLayer,
+                                     &caLayer);
+            if (result != NPERR_NO_ERROR || !caLayer) {
+                PLUGIN_LOG_DEBUG(("Plugin requested CoreAnimation but did not "
+                                  "provide CALayer."));
+                return false;
+            }
+        }
+
+        mCARenderer.SetupRenderer(caLayer, mWindow.width, mWindow.height);
+        // Flash needs to have the window set again after this step
+        if (mPluginIface->setwindow)
+            (void) mPluginIface->setwindow(&mData, &mWindow);
+    }
+
+    return true;
+#endif
 }
 
 void
 PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow)
 {
     nsRefPtr<gfxASurface> curSurface = mHelperSurface ? mHelperSurface : mCurrentSurface;
     bool needWindowUpdate = aForceSetWindow;
 #ifdef MOZ_X11
@@ -2888,16 +2993,67 @@ PluginInstanceChild::ShowPluginFrame()
     // paint.
     if (!mLayersRendering || mPendingPluginCall) {
         return false;
     }
 
     AutoRestore<bool> pending(mPendingPluginCall);
     mPendingPluginCall = true;
 
+#ifdef XP_MACOSX
+    // We can't use the thebes code with CoreAnimation so we will
+    // take a different code path.
+    if (mDrawingModel == NPDrawingModelCoreAnimation ||
+        mDrawingModel == NPDrawingModelInvalidatingCoreAnimation ||
+        mDrawingModel == NPDrawingModelCoreGraphics) {
+
+        if (!EnsureCurrentBuffer()) {
+          return false;
+        }
+
+        // Clear accRect here to be able to pass
+        // test_invalidate_during_plugin_paint  test
+        nsIntRect rect = mAccumulatedInvalidRect;
+        mAccumulatedInvalidRect.SetEmpty();
+
+        // Fix up old invalidations that might have been made when our
+        // surface was a different size
+        rect.IntersectRect(rect,
+                         nsIntRect(0, 0, mCurrentIOSurface->GetWidth(), mCurrentIOSurface->GetHeight()));
+      
+        if (!mCARenderer.isInit()) {
+            NS_ERROR("CARenderer not initialized");
+            return false;
+        }
+
+        if (mDrawingModel == NPDrawingModelCoreGraphics) {
+            mozilla::plugins::PluginUtilsOSX::Repaint(mCGLayer, rect);
+        }
+
+        mCARenderer.Render(mWindow.width, mWindow.height, nsnull);
+
+        NPRect r = { (uint16_t)rect.y, (uint16_t)rect.x,
+                     (uint16_t)rect.YMost(), (uint16_t)rect.XMost() };
+        SurfaceDescriptor currSurf;
+        currSurf = IOSurfaceDescriptor(mCurrentIOSurface->GetIOSurfaceID());
+
+        // Unused
+        SurfaceDescriptor returnSurf;
+
+        if (!SendShow(r, currSurf, &returnSurf)) {
+            return false;
+        }
+
+        return true;
+    } else {
+        NS_ERROR("Unsupported drawing model for async layer rendering");
+        return false;
+    }
+#endif
+
     bool temporarilyMakeVisible = !IsVisible() && !mHasPainted;
     if (temporarilyMakeVisible && mWindow.width && mWindow.height) {
         mWindow.clipRect.right = mWindow.width;
         mWindow.clipRect.bottom = mWindow.height;
     } else if (!IsVisible()) {
         // If we're not visible, don't bother painting a <0,0,0,0>
         // rect.  If we're eventually made visible, the visibility
         // change will invalidate our window.
@@ -3140,16 +3296,17 @@ PluginInstanceChild::InvalidateRect(NPRe
                     aInvalidRect->bottom - aInvalidRect->top);
 
         mAccumulatedInvalidRect.UnionRect(r, mAccumulatedInvalidRect);
         // If we are able to paint and invalidate sent, then reset
         // accumulated rectangle
         AsyncShowPluginFrame();
         return;
     }
+
     // If we were going to use layers rendering but it's not set up
     // yet, and the plugin happens to call this first, we'll forward
     // the invalidation to the browser.  It's unclear whether
     // non-layers plugins need this rect forwarded when their window
     // width or height is 0, which it would be for layers plugins
     // before their first SetWindow().
     SendNPN_InvalidateRect(*aInvalidRect);
 }
@@ -3379,16 +3536,28 @@ PluginInstanceChild::ClearAllSurfaces()
         PPluginSurfaceChild::Send__delete__(mCurrentSurfaceActor);
         mCurrentSurfaceActor = NULL;
     }
     if (mBackSurfaceActor) {
         PPluginSurfaceChild::Send__delete__(mBackSurfaceActor);
         mBackSurfaceActor = NULL;
     }
 #endif
+
+#ifdef XP_MACOSX
+    if (mCurrentIOSurface) {
+        // Get last surface back, and drop it
+        SurfaceDescriptor temp = null_t();
+        NPRect r = { 0, 0, 1, 1 };
+        SendShow(r, temp, &temp);
+
+    }
+
+    mCurrentIOSurface = nsnull;
+#endif
 }
 
 bool
 PluginInstanceChild::AnswerNPP_Destroy(NPError* aResult)
 {
     PLUGIN_LOG_DEBUG_METHOD;
     AssertPluginThread();
 
--- a/dom/plugins/ipc/PluginInstanceChild.h
+++ b/dom/plugins/ipc/PluginInstanceChild.h
@@ -409,21 +409,24 @@ private:
 private:
 #if defined(__i386__)
     NPEventModel          mEventModel;
 #endif
     CGColorSpaceRef       mShColorSpace;
     CGContextRef          mShContext;
     int16_t               mDrawingModel;
     nsCARenderer          mCARenderer;
+    void                 *mCGLayer;
 
 public:
     const NPCocoaEvent* getCurrentEvent() {
         return mCurrentEvent;
     }
+  
+    bool CGDraw(CGContextRef ref, nsIntRect aUpdateRect);
 
 #if defined(__i386__)
     NPEventModel EventModel() { return mEventModel; }
 #endif
 
 private:
     const NPCocoaEvent   *mCurrentEvent;
 #endif
@@ -506,16 +509,22 @@ private:
 
     // Current surface available for rendering
     nsRefPtr<gfxASurface> mCurrentSurface;
 
     // Back surface, just keeping reference to
     // surface which is on ParentProcess side
     nsRefPtr<gfxASurface> mBackSurface;
 
+#ifdef XP_MACOSX
+    // Current IOSurface available for rendering
+    // We can't use thebes gfxASurface like other platforms.
+    nsAutoPtr<nsIOSurface> mCurrentIOSurface; 
+#endif
+
     // (Not to be confused with mBackSurface).  This is a recent copy
     // of the opaque pixels under our object frame, if
     // |mIsTransparent|.  We ask the plugin render directly onto a
     // copy of the background pixels if available, and fall back on
     // alpha recovery otherwise.
     nsRefPtr<gfxASurface> mBackground;
 
 #ifdef XP_WIN
--- a/dom/plugins/ipc/PluginInstanceParent.cpp
+++ b/dom/plugins/ipc/PluginInstanceParent.cpp
@@ -98,17 +98,16 @@ PluginInstanceParent::PluginInstancePare
     , mNestedEventState(false)
 #endif // defined(XP_WIN)
     , mQuirks(0)
 #if defined(XP_MACOSX)
     , mShWidth(0)
     , mShHeight(0)
     , mShColorSpace(nsnull)
     , mDrawingModel(NPDrawingModelCoreGraphics)
-    , mIOSurface(nsnull)
 #endif
 {
     InitQuirksModes(aMimeType);
 }
 
 void
 PluginInstanceParent::InitQuirksModes(const nsCString& aMimeType)
 {
@@ -132,17 +131,16 @@ PluginInstanceParent::~PluginInstancePar
         "Subclass was not reset correctly before the dtor was reached!");
 #endif
 #if defined(OS_MACOSX)
     if (mShWidth != 0 && mShHeight != 0) {
         DeallocShmem(mShSurface);
     }
     if (mShColorSpace)
         ::CGColorSpaceRelease(mShColorSpace);
-    delete mIOSurface;
     if (mDrawingModel == NPDrawingModelCoreAnimation) {
         mParent->RemoveFromRefreshTimer(this);
     }
 #endif
 }
 
 bool
 PluginInstanceParent::Init()
@@ -512,16 +510,39 @@ PluginInstanceParent::RecvShow(const NPR
     nsRefPtr<gfxASurface> surface;
     if (newSurface.type() == SurfaceDescriptor::TShmem) {
         if (!newSurface.get_Shmem().IsReadable()) {
             NS_WARNING("back surface not readable");
             return false;
         }
         surface = gfxSharedImageSurface::Open(newSurface.get_Shmem());
     }
+#ifdef XP_MACOSX
+    else if (newSurface.type() == SurfaceDescriptor::TIOSurfaceDescriptor) {
+        IOSurfaceDescriptor iodesc = newSurface.get_IOSurfaceDescriptor();
+    
+        nsIOSurface *newIOSurface = nsIOSurface::LookupSurface(iodesc.surfaceId());
+
+        if (!newIOSurface) {
+            NS_WARNING("Got bad IOSurfaceDescriptor in RecvShow");
+            return false;
+        }
+      
+        mIOSurface = newIOSurface;
+
+        RecvNPN_InvalidateRect(updatedRect);
+
+        *prevSurface = null_t();
+
+        PLUGIN_LOG_DEBUG(("   (RecvShow invalidated for surface %p)",
+                          mFrontSurface.get()));
+
+        return true;
+    }
+#endif
 #ifdef MOZ_X11
     else if (newSurface.type() == SurfaceDescriptor::TSurfaceDescriptorX11) {
         SurfaceDescriptorX11 xdesc = newSurface.get_SurfaceDescriptorX11();
         XRenderPictFormat pf;
         pf.id = xdesc.xrenderPictID();
         XRenderPictFormat *incFormat =
             XRenderFindFormat(DefaultXDisplay(), PictFormatID, &pf, 0);
         surface =
@@ -654,26 +675,16 @@ PluginInstanceParent::GetImageSize(nsInt
         *aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight());
         return NS_OK;
     }
 #endif
 
     return NS_ERROR_NOT_AVAILABLE;
 }
 
-#ifdef XP_MACOSX
-nsresult
-PluginInstanceParent::IsRemoteDrawingCoreAnimation(PRBool *aDrawing)
-{
-    *aDrawing = (NPDrawingModelCoreAnimation == (NPDrawingModel)mDrawingModel ||
-                 NPDrawingModelInvalidatingCoreAnimation == (NPDrawingModel)mDrawingModel);
-    return NS_OK;
-}
-#endif
-
 nsresult
 PluginInstanceParent::SetBackgroundUnknown()
 {
     PLUGIN_LOG_DEBUG(("[InstanceParent][%p] SetBackgroundUnknown", this));
 
     if (mBackground) {
         DestroyBackground();
         NS_ABORT_IF_FALSE(!mBackground, "Background not destroyed");
@@ -864,17 +875,16 @@ PluginInstanceParent::NPP_SetWindow(cons
     window.clipRect = aWindow->clipRect; // MacOS specific
     window.type = aWindow->type;
 #endif
 
 #if defined(XP_MACOSX)
     if (mShWidth != window.width || mShHeight != window.height) {
         if (mDrawingModel == NPDrawingModelCoreAnimation || 
             mDrawingModel == NPDrawingModelInvalidatingCoreAnimation) {
-            delete mIOSurface;
             mIOSurface = nsIOSurface::CreateIOSurface(window.width, window.height);
         } else if (mShWidth * mShHeight != window.width * window.height) {
             if (mShWidth != 0 && mShHeight != 0) {
                 DeallocShmem(mShSurface);
                 mShWidth = 0;
                 mShHeight = 0;
             }
 
--- a/dom/plugins/ipc/PluginInstanceParent.h
+++ b/dom/plugins/ipc/PluginInstanceParent.h
@@ -277,19 +277,16 @@ public:
 
 #if defined(OS_MACOSX)
     void Invalidate();
 #endif // definied(OS_MACOSX)
 
     nsresult AsyncSetWindow(NPWindow* window);
     nsresult GetImage(mozilla::layers::ImageContainer* aContainer, mozilla::layers::Image** aImage);
     nsresult GetImageSize(nsIntSize* aSize);
-#ifdef XP_MACOSX
-    nsresult IsRemoteDrawingCoreAnimation(PRBool *aDrawing);
-#endif
     nsresult SetBackgroundUnknown();
     nsresult BeginUpdateBackground(const nsIntRect& aRect,
                                    gfxContext** aCtx);
     nsresult EndUpdateBackground(gfxContext* aCtx,
                                  const nsIntRect& aRect);
 
 private:
     // Create an appropriate platform surface for a background of size
@@ -347,22 +344,22 @@ private:
     nsIntRect          mPluginPort;
     nsIntRect          mSharedSize;
     HWND               mPluginHWND;
     WNDPROC            mPluginWndProc;
     bool               mNestedEventState;
 #endif // defined(XP_WIN)
 #if defined(OS_MACOSX)
 private:
-    Shmem              mShSurface; 
-    size_t             mShWidth;
-    size_t             mShHeight;
-    CGColorSpaceRef    mShColorSpace;
-    int16_t            mDrawingModel;
-    nsIOSurface       *mIOSurface;
+    Shmem                  mShSurface; 
+    size_t                 mShWidth;
+    size_t                 mShHeight;
+    CGColorSpaceRef        mShColorSpace;
+    int16_t                mDrawingModel;
+    nsAutoPtr<nsIOSurface> mIOSurface;
 #endif // definied(OS_MACOSX)
 
     // ObjectFrame layer wrapper
     nsRefPtr<gfxASurface>    mFrontSurface;
     // For windowless+transparent instances, this surface contains a
     // "pretty recent" copy of the pixels under its <object> frame.
     // On the plugin side, we use this surface to avoid doing alpha
     // recovery when possible.  This surface is created and owned by
--- a/dom/plugins/ipc/PluginInterposeOSX.h
+++ b/dom/plugins/ipc/PluginInterposeOSX.h
@@ -27,16 +27,18 @@
 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef DOM_PLUGINS_IPC_PLUGININTERPOSEOSX_H
 #define DOM_PLUGINS_IPC_PLUGININTERPOSEOSX_H
 
 #include "base/basictypes.h"
 #include "nsPoint.h"
+#include "npapi.h"
+#include "nsRect.h"
 
 // Make this includable from non-Objective-C code.
 #ifndef __OBJC__
 class NSCursor;
 #else
 #import <Cocoa/Cocoa.h>
 #endif
 
--- a/dom/plugins/ipc/PluginLibrary.h
+++ b/dom/plugins/ipc/PluginLibrary.h
@@ -97,19 +97,16 @@ 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 GetImage(NPP instance, ImageContainer* aContainer, Image** aImage) = 0;
   virtual nsresult GetImageSize(NPP instance, nsIntSize* aSize) = 0;
   virtual bool UseAsyncPainting() = 0;
-#if defined(XP_MACOSX)
-  virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing) = 0;
-#endif
   /**
    * 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;
--- a/dom/plugins/ipc/PluginModuleParent.cpp
+++ b/dom/plugins/ipc/PluginModuleParent.cpp
@@ -34,18 +34,18 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #ifdef MOZ_WIDGET_GTK2
 #include <glib.h>
 #elif XP_MACOSX
+#include "PluginInterposeOSX.h"
 #include "PluginUtilsOSX.h"
-#include "PluginInterposeOSX.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #endif
 #ifdef MOZ_WIDGET_QT
 #include <QtCore/QCoreApplication>
 #include <QtCore/QEventLoop>
 #endif
 
@@ -919,28 +919,16 @@ PluginModuleParent::NPP_GetSitesWithData
         return NS_ERROR_NOT_AVAILABLE;
 
     if (!CallNPP_GetSitesWithData(&result))
         return NS_ERROR_FAILURE;
 
     return NS_OK;
 }
 
-#if defined(XP_MACOSX)
-nsresult
-PluginModuleParent::IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing)
-{
-    PluginInstanceParent* i = InstCast(instance);
-    if (!i)
-        return NS_ERROR_FAILURE;
-
-    return i->IsRemoteDrawingCoreAnimation(aDrawing);
-}
-#endif
-
 bool
 PluginModuleParent::AnswerNPN_GetValue_WithBoolReturn(const NPNVariable& aVariable,
                                                       NPError* aError,
                                                       bool* aBoolVal)
 {
     NPBool boolVal = false;
     *aError = mozilla::plugins::parent::_getvalue(nsnull, aVariable, &boolVal);
     *aBoolVal = boolVal ? true : false;
--- a/dom/plugins/ipc/PluginModuleParent.h
+++ b/dom/plugins/ipc/PluginModuleParent.h
@@ -277,20 +277,16 @@ private:
     virtual nsresult NPP_New(NPMIMEType pluginType, NPP instance,
                              uint16_t mode, int16_t argc, char* argn[],
                              char* argv[], NPSavedData* saved,
                              NPError* error);
     virtual nsresult NPP_ClearSiteData(const char* site, uint64_t flags,
                                        uint64_t maxAge);
     virtual nsresult NPP_GetSitesWithData(InfallibleTArray<nsCString>& result);
 
-#if defined(XP_MACOSX)
-    virtual nsresult IsRemoteDrawingCoreAnimation(NPP instance, PRBool *aDrawing);
-#endif
-
 private:
     void WritePluginExtraDataForMinidump(const nsAString& id);
     void WriteExtraDataForHang();
     void CleanupFromTimeout();
     static int TimeoutChanged(const char* aPref, void* aModule);
     void NotifyPluginCrashed();
 
     nsCString mCrashNotes;
--- a/dom/plugins/ipc/PluginUtilsOSX.h
+++ b/dom/plugins/ipc/PluginUtilsOSX.h
@@ -33,23 +33,32 @@
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the MPL, the GPL or the LGPL.
   *
   * ***** END LICENSE BLOCK ***** */
 
 #include "npapi.h"
+#include "nsRect.h"
 
 namespace mozilla {
 namespace plugins {
 namespace PluginUtilsOSX {
 
-// Need to call back into the browser's to process event.
+// Need to call back into the browser's message loop to process event.
 typedef void (*RemoteProcessEvents) (void*);
 
 NPError ShowCocoaContextMenu(void* aMenu, int aX, int aY, void* pluginModule, RemoteProcessEvents remoteEvent);
 
 void InvokeNativeEventLoop();
 
+// Need to call back and send a cocoa draw event to the plugin.
+typedef void (*DrawPluginFunc) (CGContextRef, void*, nsIntRect aUpdateRect);
+
+void* GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance);
+void ReleaseCGLayer(void* cgLayer);
+void Repaint(void* cgLayer, nsIntRect aRect);
+
+
 } // namespace PluginUtilsOSX
 } // namespace plugins
 } // namespace mozilla
--- a/dom/plugins/ipc/PluginUtilsOSX.mm
+++ b/dom/plugins/ipc/PluginUtilsOSX.mm
@@ -33,23 +33,79 @@
   * decision by deleting the provisions above and replace them with the notice
   * and other provisions required by the GPL or the LGPL. If you do not delete
   * the provisions above, a recipient may use your version of this file under
   * the terms of any one of the MPL, the GPL or the LGPL.
   *
   * ***** END LICENSE BLOCK ***** */
 
 #import <AppKit/AppKit.h>
+#import <QuartzCore/QuartzCore.h>
 #include "PluginUtilsOSX.h"
 
 // Remove definitions for try/catch interfering with ObjCException macros.
 #include "nsObjCExceptions.h"
 
 using namespace mozilla::plugins::PluginUtilsOSX;
 
+@interface CGBridgeLayer : CALayer {
+  DrawPluginFunc mDrawFunc;
+  void* mPluginInstance;
+  nsIntRect mUpdateRect;
+}
+- (void) setDrawFunc: (DrawPluginFunc)aFunc pluginInstance:(void*) aPluginInstance;
+- (void) updateRect: (nsIntRect)aRect;
+
+@end
+
+@implementation CGBridgeLayer
+- (void) updateRect: (nsIntRect)aRect
+{
+   mUpdateRect.UnionRect(mUpdateRect, aRect);
+}
+
+- (void) setDrawFunc: (DrawPluginFunc)aFunc pluginInstance:(void*) aPluginInstance
+{
+  mDrawFunc = aFunc;
+  mPluginInstance = aPluginInstance;
+}
+
+- (void)drawInContext:(CGContextRef)aCGContext
+
+{
+  ::CGContextSaveGState(aCGContext); 
+  ::CGContextTranslateCTM(aCGContext, 0, self.bounds.size.height);
+  ::CGContextScaleCTM(aCGContext, (CGFloat) 1, (CGFloat) -1);
+
+  mDrawFunc(aCGContext, mPluginInstance, mUpdateRect);
+
+  ::CGContextRestoreGState(aCGContext); 
+
+  mUpdateRect.SetEmpty();
+}
+
+@end
+
+void* mozilla::plugins::PluginUtilsOSX::GetCGLayer(DrawPluginFunc aFunc, void* aPluginInstance) {
+  CGBridgeLayer *bridgeLayer = [[CGBridgeLayer alloc] init ];
+  [bridgeLayer setDrawFunc:aFunc pluginInstance:aPluginInstance];
+  return bridgeLayer;
+}
+
+void mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(void *cgLayer) {
+  CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)cgLayer;
+  [bridgeLayer release];
+}
+
+void mozilla::plugins::PluginUtilsOSX::Repaint(void *caLayer, nsIntRect aRect) {
+  CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)caLayer;
+  [bridgeLayer updateRect:aRect];
+  [bridgeLayer setNeedsDisplay];
+}
+
 @interface EventProcessor : NSObject {
   RemoteProcessEvents   aRemoteEvents;
   void                 *aPluginModule;
 }
 - (void)setRemoteEvents:(RemoteProcessEvents) remoteEvents pluginModule:(void*) pluginModule;
 - (void)onTick;
 @end
 
--- a/layout/generic/nsObjectFrame.cpp
+++ b/layout/generic/nsObjectFrame.cpp
@@ -1495,35 +1495,37 @@ nsObjectFrame::GetPaintedRect(nsDisplayP
 void
 nsObjectFrame::UpdateImageLayer(ImageContainer* aContainer, const gfxRect& aRect)
 {
   if (!mInstanceOwner) {
     return;
   }
 
 #ifdef XP_MACOSX
-  mInstanceOwner->DoCocoaEventDrawRect(aRect, nsnull);
+  if (!mInstanceOwner->UseAsyncRendering()) {
+    mInstanceOwner->DoCocoaEventDrawRect(aRect, nsnull);
+  }
 #endif
 
   mInstanceOwner->SetCurrentImage(aContainer);
 }
 
 LayerState
 nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder,
                              LayerManager* aManager)
 {
   if (!mInstanceOwner)
     return LAYER_NONE;
 
 #ifdef XP_MACOSX
   if (aManager &&
       aManager->GetBackendType() == LayerManager::LAYERS_OPENGL &&
+      mInstanceOwner->UseAsyncRendering() &&
       mInstanceOwner->GetEventModel() == NPEventModelCocoa &&
-      mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics &&
-      mInstanceOwner->IsRemoteDrawingCoreAnimation())
+      mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics)
   {
     return LAYER_ACTIVE;
   }
 #endif
 
   if (!mInstanceOwner->UseAsyncRendering())
     return LAYER_NONE;