Bug 794337 - Properly alias canvas image data when using Quartz compositing. r=jrmuizel

--HG--
extra : rebase_source : fb4c0e1a9bac0ac1cf54ddc23c66756060bbfdab
This commit is contained in:
Benoit Girard 2012-11-02 16:24:37 -04:00
parent a335e4be51
commit a678c602e4
4 changed files with 53 additions and 3 deletions

View File

@ -109,7 +109,7 @@ BasicCanvasLayer::Initialize(const Data& aData)
mNeedsYFlip = true;
} else if (aData.mDrawTarget) {
mDrawTarget = aData.mDrawTarget;
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
mSurface = gfxPlatform::GetPlatform()->CreateThebesSurfaceAliasForDrawTarget_hack(mDrawTarget);
mNeedsYFlip = false;
} else {
NS_ERROR("CanvasLayer created without mSurface, mDrawTarget or mGLContext?");
@ -127,8 +127,14 @@ BasicCanvasLayer::UpdateSurface(gfxASurface* aDestSurface, Layer* aMaskLayer)
if (mDrawTarget) {
mDrawTarget->Flush();
// TODO Fix me before turning accelerated quartz canvas by default
//mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
if (mDrawTarget->GetType() == BACKEND_COREGRAPHICS_ACCELERATED) {
// We have an accelerated CG context which has changed, unlike a bitmap surface
// where we can alias the bits on initializing the mDrawTarget, we need to readback
// and copy the accelerated surface each frame. We want to support this for quick
// thumbnail but if we're going to be doing this every frame it likely is better
// to use a non accelerated (bitmap) canvas.
mSurface = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(mDrawTarget);
}
}
if (!mGLContext && aDestSurface) {

View File

@ -188,6 +188,25 @@ public:
virtual mozilla::TemporaryRef<mozilla::gfx::ScaledFont>
GetScaledFontForFont(mozilla::gfx::DrawTarget* aTarget, gfxFont *aFont);
/*
* Cairo doesn't give us a way to create a surface pointing to a context
* without marking it as copy on write. For canvas we want to create
* a surface that points to what is currently being drawn by a canvas
* without a copy thus we need to create a special case. This works on
* most platforms with GetThebesSurfaceForDrawTarget but fails on Mac
* because when we create the surface we vm_copy the memory and never
* notify the context that the canvas has drawn to it thus we end up
* with a static snapshot.
*
* This function guarantes that the gfxASurface reflects the DrawTarget.
*/
virtual already_AddRefed<gfxASurface>
CreateThebesSurfaceAliasForDrawTarget_hack(mozilla::gfx::DrawTarget *aTarget) {
// Overwrite me on platform where GetThebesSurfaceForDrawTarget returns
// a snapshot of the draw target.
return GetThebesSurfaceForDrawTarget(aTarget);
}
virtual already_AddRefed<gfxASurface>
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);

View File

@ -9,6 +9,7 @@
#include "gfxQuartzSurface.h"
#include "gfxQuartzImageSurface.h"
#include "mozilla/gfx/2D.h"
#include "mozilla/gfx/QuartzSupport.h"
#include "gfxMacPlatformFontList.h"
#include "gfxMacFont.h"
@ -377,6 +378,27 @@ gfxPlatformMac::ReadAntiAliasingThreshold()
return threshold;
}
already_AddRefed<gfxASurface>
gfxPlatformMac::CreateThebesSurfaceAliasForDrawTarget_hack(mozilla::gfx::DrawTarget *aTarget)
{
if (aTarget->GetType() == BACKEND_COREGRAPHICS) {
CGContextRef cg = static_cast<CGContextRef>(aTarget->GetNativeSurface(NATIVE_SURFACE_CGCONTEXT));
unsigned char* data = (unsigned char*)CGBitmapContextGetData(cg);
size_t bpp = CGBitmapContextGetBitsPerPixel(cg);
size_t stride = CGBitmapContextGetBytesPerRow(cg);
gfxIntSize size(aTarget->GetSize().width, aTarget->GetSize().height);
nsRefPtr<gfxImageSurface> imageSurface = new gfxImageSurface(data, size, stride, bpp == 2
? gfxImageFormat::ImageFormatRGB16_565
: gfxImageFormat::ImageFormatARGB32);
// Here we should return a gfxQuartzImageSurface but quartz will assumes that image surfaces
// don't change which wont create a proper alias to the draw target, therefore we have to
// return a plain image surface.
return imageSurface.forget();
} else {
return GetThebesSurfaceForDrawTarget(aTarget);
}
}
already_AddRefed<gfxASurface>
gfxPlatformMac::GetThebesSurfaceForDrawTarget(DrawTarget *aTarget)
{

View File

@ -82,6 +82,9 @@ public:
virtual already_AddRefed<gfxASurface>
GetThebesSurfaceForDrawTarget(mozilla::gfx::DrawTarget *aTarget);
virtual already_AddRefed<gfxASurface>
CreateThebesSurfaceAliasForDrawTarget_hack(mozilla::gfx::DrawTarget *aTarget);
private:
virtual qcms_profile* GetPlatformCMSOutputProfile();