From 6455de56ad817b08015ebf25c90ac6bcaee2324f Mon Sep 17 00:00:00 2001 From: Benoit Girard Date: Sat, 25 Jun 2011 15:12:59 -0400 Subject: [PATCH] Enabled Mac Async plugin by default + Fixes. b=663259 r=josh --- dom/plugins/base/nsNPAPIPluginInstance.cpp | 4 +- dom/plugins/base/nsPluginInstanceOwner.cpp | 4 +- dom/plugins/ipc/PluginInstanceChild.cpp | 50 +++++++------ dom/plugins/ipc/PluginInstanceChild.h | 5 ++ dom/plugins/ipc/PluginInstanceParent.cpp | 34 +++++++-- dom/plugins/ipc/PluginInstanceParent.h | 1 + dom/plugins/ipc/PluginUtilsOSX.mm | 3 + dom/plugins/test/mochitest/utils.js | 3 +- .../test/reftest/plugin-background.css | 7 +- dom/plugins/test/reftest/reftest.list | 2 +- gfx/thebes/nsCoreAnimationSupport.h | 4 + gfx/thebes/nsCoreAnimationSupport.mm | 74 ++++++++++++++++++- layout/generic/nsObjectFrame.cpp | 10 +-- 13 files changed, 150 insertions(+), 51 deletions(-) diff --git a/dom/plugins/base/nsNPAPIPluginInstance.cpp b/dom/plugins/base/nsNPAPIPluginInstance.cpp index 98ab48d434c..046f34bd872 100644 --- a/dom/plugins/base/nsNPAPIPluginInstance.cpp +++ b/dom/plugins/base/nsNPAPIPluginInstance.cpp @@ -88,7 +88,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) mMIMEType(nsnull), mOwner(nsnull), mCurrentPluginEvent(nsnull), -#if defined(MOZ_X11) || defined(XP_WIN) +#if defined(MOZ_X11) || defined(XP_WIN) || defined(XP_MACOSX) mUsePluginLayersPref(PR_TRUE) #else mUsePluginLayersPref(PR_FALSE) @@ -104,7 +104,7 @@ nsNPAPIPluginInstance::nsNPAPIPluginInstance(nsNPAPIPlugin* plugin) nsCOMPtr prefs(do_GetService(NS_PREFSERVICE_CONTRACTID)); if (prefs) { PRBool useLayersPref; - nsresult rv = prefs->GetBoolPref("mozilla.plugins.use_layers", &useLayersPref); + nsresult rv = prefs->GetBoolPref("plugins.use_layers", &useLayersPref); if (NS_SUCCEEDED(rv)) mUsePluginLayersPref = useLayersPref; } diff --git a/dom/plugins/base/nsPluginInstanceOwner.cpp b/dom/plugins/base/nsPluginInstanceOwner.cpp index a733d31f084..ee3244f1fa3 100644 --- a/dom/plugins/base/nsPluginInstanceOwner.cpp +++ b/dom/plugins/base/nsPluginInstanceOwner.cpp @@ -263,8 +263,8 @@ nsPluginInstanceOwner::UseAsyncRendering() NS_SUCCEEDED(mInstance->UseAsyncPainting(&useAsyncRendering)) && useAsyncRendering && #ifdef XP_MACOSX - mObjectFrame && mObjectFrame->GetImageContainer().get() && - mObjectFrame->GetImageContainer().get()->GetBackendType() == + container && + container->GetBackendType() == LayerManager::LAYERS_OPENGL #else (!mPluginWindow || diff --git a/dom/plugins/ipc/PluginInstanceChild.cpp b/dom/plugins/ipc/PluginInstanceChild.cpp index d794a427bd7..8aa742b18fe 100644 --- a/dom/plugins/ipc/PluginInstanceChild.cpp +++ b/dom/plugins/ipc/PluginInstanceChild.cpp @@ -2336,17 +2336,12 @@ PluginInstanceChild::DoAsyncSetWindow(const gfxSurfaceType& aSurfaceType, } 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; @@ -2696,6 +2691,8 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow) return; } +#ifndef XP_MACOSX + // Adjusting the window isn't needed for OSX #ifndef XP_WIN // On Windows, we translate the device context, in order for the window // origin to be correct. @@ -2716,6 +2713,7 @@ PluginInstanceChild::UpdateWindowAttributes(bool aForceSetWindow) mWindow.clipRect.right = clipRect.XMost(); mWindow.clipRect.bottom = clipRect.YMost(); } +#endif // XP_MACOSX #ifdef XP_WIN // Windowless plugins on Windows need a WM_WINDOWPOSCHANGED event to update @@ -3016,6 +3014,22 @@ PluginInstanceChild::ShowPluginFrame() AutoRestore pending(mPendingPluginCall); mPendingPluginCall = true; + 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. + ClearCurrentSurface(); + return true; + } + + if (!EnsureCurrentBuffer()) { + return false; + } + #ifdef XP_MACOSX // We can't use the thebes code with CoreAnimation so we will // take a different code path. @@ -3023,8 +3037,8 @@ PluginInstanceChild::ShowPluginFrame() mDrawingModel == NPDrawingModelInvalidatingCoreAnimation || mDrawingModel == NPDrawingModelCoreGraphics) { - if (!EnsureCurrentBuffer()) { - return false; + if (!IsVisible()) { + return true; } // Clear accRect here to be able to pass @@ -3053,6 +3067,8 @@ PluginInstanceChild::ShowPluginFrame() SurfaceDescriptor currSurf; currSurf = IOSurfaceDescriptor(mCurrentIOSurface->GetIOSurfaceID()); + mHasPainted = true; + // Unused SurfaceDescriptor returnSurf; @@ -3067,22 +3083,6 @@ PluginInstanceChild::ShowPluginFrame() } #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. - ClearCurrentSurface(); - return true; - } - - if (!EnsureCurrentBuffer()) { - return false; - } - NS_ASSERTION(mWindow.width == (mWindow.clipRect.right - mWindow.clipRect.left) && mWindow.height == (mWindow.clipRect.bottom - mWindow.clipRect.top), "Clip rect should be same size as window when using layers"); @@ -3566,7 +3566,11 @@ PluginInstanceChild::ClearAllSurfaces() SurfaceDescriptor temp = null_t(); NPRect r = { 0, 0, 1, 1 }; SendShow(r, temp, &temp); + } + if (mCGLayer) { + mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(mCGLayer); + mCGLayer = nsnull; } mCurrentIOSurface = nsnull; diff --git a/dom/plugins/ipc/PluginInstanceChild.h b/dom/plugins/ipc/PluginInstanceChild.h index 7134e55d9e4..874d9b9663f 100644 --- a/dom/plugins/ipc/PluginInstanceChild.h +++ b/dom/plugins/ipc/PluginInstanceChild.h @@ -436,10 +436,15 @@ private: bool CanPaintOnBackground(); bool IsVisible() { +#ifdef XP_MACOSX + return mWindow.clipRect.top != mWindow.clipRect.bottom && + mWindow.clipRect.left != mWindow.clipRect.right; +#else return mWindow.clipRect.top != 0 || mWindow.clipRect.left != 0 || mWindow.clipRect.bottom != 0 || mWindow.clipRect.right != 0; +#endif } // ShowPluginFrame - in general does four things: diff --git a/dom/plugins/ipc/PluginInstanceParent.cpp b/dom/plugins/ipc/PluginInstanceParent.cpp index 47f23980f4d..ec84a9d4baa 100644 --- a/dom/plugins/ipc/PluginInstanceParent.cpp +++ b/dom/plugins/ipc/PluginInstanceParent.cpp @@ -526,7 +526,7 @@ PluginInstanceParent::RecvShow(const NPRect& updatedRect, return false; } - mIOSurface = newIOSurface; + mFrontIOSurface = newIOSurface; RecvNPN_InvalidateRect(updatedRect); @@ -616,7 +616,7 @@ nsresult PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage) { #ifdef XP_MACOSX - if (!mFrontSurface && !mIOSurface) + if (!mFrontSurface && !mFrontIOSurface) #else if (!mFrontSurface) #endif @@ -624,7 +624,7 @@ PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage) Image::Format format = Image::CAIRO_SURFACE; #ifdef XP_MACOSX - if (mIOSurface) { + if (mFrontIOSurface) { format = Image::MAC_IO_SURFACE; if (!aContainer->Manager()) { return NS_ERROR_FAILURE; @@ -639,11 +639,11 @@ PluginInstanceParent::GetImage(ImageContainer* aContainer, Image** aImage) } #ifdef XP_MACOSX - if (mIOSurface) { + if (mFrontIOSurface) { NS_ASSERTION(image->GetFormat() == Image::MAC_IO_SURFACE, "Wrong format?"); MacIOSurfaceImage* ioImage = static_cast(image.get()); MacIOSurfaceImage::Data ioData; - ioData.mIOSurface = mIOSurface; + ioData.mIOSurface = mFrontIOSurface; ioImage->SetData(ioData); *aImage = image.forget().get(); return NS_OK; @@ -671,8 +671,8 @@ PluginInstanceParent::GetImageSize(nsIntSize* aSize) } #ifdef XP_MACOSX - if (mIOSurface) { - *aSize = nsIntSize(mIOSurface->GetWidth(), mIOSurface->GetHeight()); + if (mFrontIOSurface) { + *aSize = nsIntSize(mFrontIOSurface->GetWidth(), mFrontIOSurface->GetHeight()); return NS_OK; } #endif @@ -1167,7 +1167,25 @@ PluginInstanceParent::NPP_HandleEvent(void* event) npevent->data.draw.width, npevent->data.draw.height); } - return false; + return true; + } else if (mFrontIOSurface) { + CGContextRef cgContext = npevent->data.draw.context; + if (!mShColorSpace) { + mShColorSpace = CreateSystemColorSpace(); + } + if (!mShColorSpace) { + PLUGIN_LOG_DEBUG(("Could not allocate ColorSpace.")); + return false; + } + if (cgContext) { + nsCARenderer::DrawSurfaceToCGContext(cgContext, mFrontIOSurface, + mShColorSpace, + npevent->data.draw.x, + npevent->data.draw.y, + npevent->data.draw.width, + npevent->data.draw.height); + } + return true; } else { if (mShWidth == 0 && mShHeight == 0) { PLUGIN_LOG_DEBUG(("NPCocoaEventDrawRect on window of size 0.")); diff --git a/dom/plugins/ipc/PluginInstanceParent.h b/dom/plugins/ipc/PluginInstanceParent.h index cad9dd2aa83..20cb8fbc3e0 100644 --- a/dom/plugins/ipc/PluginInstanceParent.h +++ b/dom/plugins/ipc/PluginInstanceParent.h @@ -355,6 +355,7 @@ private: CGColorSpaceRef mShColorSpace; int16_t mDrawingModel; nsAutoPtr mIOSurface; + nsAutoPtr mFrontIOSurface; #endif // definied(MOZ_WIDGET_COCOA) // ObjectFrame layer wrapper diff --git a/dom/plugins/ipc/PluginUtilsOSX.mm b/dom/plugins/ipc/PluginUtilsOSX.mm index 881f627836d..418e21ec6cb 100644 --- a/dom/plugins/ipc/PluginUtilsOSX.mm +++ b/dom/plugins/ipc/PluginUtilsOSX.mm @@ -97,8 +97,11 @@ void mozilla::plugins::PluginUtilsOSX::ReleaseCGLayer(void *cgLayer) { void mozilla::plugins::PluginUtilsOSX::Repaint(void *caLayer, nsIntRect aRect) { CGBridgeLayer *bridgeLayer = (CGBridgeLayer*)caLayer; + [CATransaction begin]; [bridgeLayer updateRect:aRect]; [bridgeLayer setNeedsDisplay]; + [bridgeLayer displayIfNeeded]; + [CATransaction commit]; } @interface EventProcessor : NSObject { diff --git a/dom/plugins/test/mochitest/utils.js b/dom/plugins/test/mochitest/utils.js index c367a541391..eb0f44354bd 100644 --- a/dom/plugins/test/mochitest/utils.js +++ b/dom/plugins/test/mochitest/utils.js @@ -1,8 +1,7 @@ function paintCountIs(plugin, expected, msg) { var count = plugin.getPaintCount(); var realExpected = expected; - var isAsync = SimpleTest.testPluginIsOOP() && - navigator.platform.indexOf("Mac") < 0; + var isAsync = SimpleTest.testPluginIsOOP(); if (isAsync) { ++realExpected; // extra paint at startup for all async-rendering plugins } else { diff --git a/dom/plugins/test/reftest/plugin-background.css b/dom/plugins/test/reftest/plugin-background.css index 14e37f185a2..f6b251214d3 100644 --- a/dom/plugins/test/reftest/plugin-background.css +++ b/dom/plugins/test/reftest/plugin-background.css @@ -8,7 +8,9 @@ div { #good { left:0px; top:0px; width:220px; height:220px; - background-color: rgba(0,255,0, 0.6); + /* Core Animation alpha blending rounding differs + from the Core Graphics blending, adjust with care */ + background-color: rgba(0,255,0, 0.51); z-index: 0; } @@ -55,4 +57,5 @@ embed#plugin { position: absolute; left:1px; top:1px; z-index: 1; -} \ No newline at end of file +} + diff --git a/dom/plugins/test/reftest/reftest.list b/dom/plugins/test/reftest/reftest.list index ea462f3245b..0c4a8f99557 100644 --- a/dom/plugins/test/reftest/reftest.list +++ b/dom/plugins/test/reftest/reftest.list @@ -8,7 +8,7 @@ random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) = random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == border-padding-2.html border-padding-2-ref.html # bug 629430 random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) skip-if(Android) == border-padding-3.html border-padding-3-ref.html # bug 629430 random-if(cocoaWidget||d2d) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-1.html pluginproblemui-direction-1-ref.html -fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html +random-if(cocoaWidget) fails-if(!haveTestPlugin&&!Android) skip-if(!testPluginIsOOP()) == pluginproblemui-direction-2.html pluginproblemui-direction-2-ref.html fails-if(!haveTestPlugin) == plugin-canvas-alpha-zindex.html div-alpha-zindex.html fails-if(!haveTestPlugin) == plugin-transform-alpha-zindex.html div-alpha-zindex.html random-if(/^Windows\x20NT\x206\.1/.test(http.oscpu)) fails-if(!haveTestPlugin) == plugin-busy-alpha-zindex.html div-alpha-zindex.html diff --git a/gfx/thebes/nsCoreAnimationSupport.h b/gfx/thebes/nsCoreAnimationSupport.h index a850e0b5f9b..e18b33f023e 100644 --- a/gfx/thebes/nsCoreAnimationSupport.h +++ b/gfx/thebes/nsCoreAnimationSupport.h @@ -75,6 +75,10 @@ public: CGColorSpaceRef aColorSpace, int aX, int aY, size_t aWidth, size_t aHeight); + +#ifdef DEBUG + static void SaveToDisk(nsIOSurface *surf); +#endif private: void Destroy(); diff --git a/gfx/thebes/nsCoreAnimationSupport.mm b/gfx/thebes/nsCoreAnimationSupport.mm index 08bb4e0aa0d..1990b862cc5 100644 --- a/gfx/thebes/nsCoreAnimationSupport.mm +++ b/gfx/thebes/nsCoreAnimationSupport.mm @@ -316,10 +316,6 @@ nsIOSurface* nsIOSurface::LookupSurface(IOSurfaceID aIOSurfaceID) { IOSurfacePtr surfaceRef = nsIOSurfaceLib::IOSurfaceLookup(aIOSurfaceID); if (!surfaceRef) return nsnull; - // IOSurfaceLookup does not retain the object for us, - // we want IOSurfacePtr to remain for the lifetime of - // nsIOSurface. - CFRetain(surfaceRef); nsIOSurface* ioSurface = new nsIOSurface(surfaceRef); if (!ioSurface) { @@ -502,10 +498,27 @@ nsresult nsCARenderer::SetupRenderer(void *aCALayer, int aWidth, int aHeight) { Destroy(); return NS_ERROR_FAILURE; } + + // Create a transaction and disable animations + // to make the position update instant. + [CATransaction begin]; + NSMutableDictionary *newActions = [[NSMutableDictionary alloc] initWithObjectsAndKeys:[NSNull null], @"onOrderIn", + [NSNull null], @"onOrderOut", + [NSNull null], @"sublayers", + [NSNull null], @"contents", + [NSNull null], @"position", + [NSNull null], @"bounds", + nil]; + layer.actions = newActions; + [newActions release]; + + [CATransaction setValue: [NSNumber numberWithFloat:0.0f] forKey: kCATransactionAnimationDuration]; + [CATransaction setValue: (id) kCFBooleanTrue forKey: kCATransactionDisableActions]; [layer setBounds:CGRectMake(0, 0, aWidth, aHeight)]; [layer setPosition:CGPointMake(aWidth/2.0, aHeight/2.0)]; caRenderer.layer = layer; caRenderer.bounds = CGRectMake(0, 0, aWidth, aHeight); + [CATransaction commit]; // We either target rendering to a CGImage or IOSurface. if (!mIOSurface) { @@ -680,6 +693,7 @@ nsresult nsCARenderer::Render(int aWidth, int aHeight, ::glClearColor(0.0, 0.0, 0.0, 0.0); ::glClear(GL_COLOR_BUFFER_BIT); + [CATransaction commit]; double caTime = ::CACurrentMediaTime(); [caRenderer beginFrameAtTime:caTime timeStamp:NULL]; [caRenderer addUpdateRect:CGRectMake(0,0, aWidth, aHeight)]; @@ -767,3 +781,55 @@ nsresult nsCARenderer::DrawSurfaceToCGContext(CGContextRef aContext, return NS_OK; } +#ifdef DEBUG + +int sSaveToDiskSequence = 0; +void nsCARenderer::SaveToDisk(nsIOSurface *surf) { + surf->Lock(); + size_t bytesPerRow = surf->GetBytesPerRow(); + size_t ioWidth = surf->GetWidth(); + size_t ioHeight = surf->GetHeight(); + void* ioData = surf->GetBaseAddress(); + CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(ioData, + ioData, ioHeight*(bytesPerRow)*4, + NULL); //No release callback + if (!dataProvider) { + surf->Unlock(); + return; + } + + CGImageRef cgImage = ::CGImageCreate(ioWidth, ioHeight, 8, 32, bytesPerRow, + CreateSystemColorSpace(), kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Host, + dataProvider, NULL, true, kCGRenderingIntentDefault); + ::CGDataProviderRelease(dataProvider); + if (!cgImage) { + surf->Unlock(); + return; + } + + char cstr[1000]; + + sprintf(cstr, "file:///Users/benoitgirard/debug/iosurface_%i.png", ++sSaveToDiskSequence); + + CFStringRef cfStr = ::CFStringCreateWithCString(kCFAllocatorDefault, cstr, kCFStringEncodingMacRoman); + + printf("Exporting: %s\n", cstr); + CFURLRef url = ::CFURLCreateWithString( NULL, cfStr, NULL); + + CFStringRef type = kUTTypePNG; + size_t count = 1; + CFDictionaryRef options = NULL; + CGImageDestinationRef dest = ::CGImageDestinationCreateWithURL(url, type, count, options); + + ::CGImageDestinationAddImage(dest, cgImage, NULL); + + ::CGImageDestinationFinalize(dest); + ::CFRelease(dest); + + surf->Unlock(); + + return; + +} + +#endif diff --git a/layout/generic/nsObjectFrame.cpp b/layout/generic/nsObjectFrame.cpp index cf51939700f..a61ebe0f1db 100644 --- a/layout/generic/nsObjectFrame.cpp +++ b/layout/generic/nsObjectFrame.cpp @@ -1559,13 +1559,9 @@ nsObjectFrame::GetLayerState(nsDisplayListBuilder* aBuilder, return LAYER_NONE; #ifdef XP_MACOSX - if (aManager && - aManager->GetBackendType() == LayerManager::LAYERS_OPENGL && - mInstanceOwner->UseAsyncRendering() && - mInstanceOwner->GetEventModel() == NPEventModelCocoa && - mInstanceOwner->GetDrawingModel() == NPDrawingModelCoreGraphics) - { - return LAYER_ACTIVE; + if (aManager && aManager->GetBackendType() != + LayerManager::LAYERS_OPENGL) { + return LAYER_NONE; } #endif