From 9ce84d590369a6e67c53c8d884fd1cda722b121d Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Wed, 2 Oct 2013 22:12:34 +1300 Subject: [PATCH] Bug 916034 - Use a similar surface rather than an image surface for the canvas background cache when using azure. r=ajones --- layout/generic/nsCanvasFrame.cpp | 48 +++++++++++++++++++------------- layout/generic/nsCanvasFrame.h | 1 + layout/generic/nsFrame.cpp | 6 ++++ layout/generic/nsIFrame.h | 2 ++ 4 files changed, 38 insertions(+), 19 deletions(-) diff --git a/layout/generic/nsCanvasFrame.cpp b/layout/generic/nsCanvasFrame.cpp index f5e046687686..1118606fd086 100644 --- a/layout/generic/nsCanvasFrame.cpp +++ b/layout/generic/nsCanvasFrame.cpp @@ -28,6 +28,7 @@ using namespace mozilla; using namespace mozilla::layout; +using namespace mozilla::gfx; nsIFrame* NS_NewCanvasFrame(nsIPresShell* aPresShell, nsStyleContext* aContext) @@ -198,6 +199,14 @@ static void BlitSurface(gfxContext* aDest, const gfxRect& aRect, gfxASurface* aS aDest->Translate(-gfxPoint(aRect.x, aRect.y)); } +static void BlitSurface(DrawTarget* aDest, const gfxRect& aRect, DrawTarget* aSource) +{ + RefPtr source = aSource->Snapshot(); + aDest->DrawSurface(source, + Rect(aRect.x, aRect.y, aRect.width, aRect.height), + Rect(0, 0, aRect.width, aRect.height)); +} + void nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext* aCtx) @@ -209,6 +218,7 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, nsRenderingContext context; nsRefPtr dest = aCtx->ThebesContext(); nsRefPtr surf; + RefPtr dt; nsRefPtr ctx; gfxRect destRect; #ifndef MOZ_GFX_OPTIMIZE_MOBILE @@ -218,8 +228,8 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, // Snap image rectangle to nearest pixel boundaries. This is the right way // to snap for this context, because we checked HasNonIntegerTranslation above. destRect.Round(); - surf = static_cast(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage())); if (dest->IsCairo()) { + surf = static_cast(Frame()->Properties().Get(nsIFrame::CachedBackgroundImage())); nsRefPtr destSurf = dest->CurrentSurface(); if (surf && surf->GetType() == destSurf->GetType()) { BlitSurface(dest, destRect, surf); @@ -229,24 +239,20 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, GFX_CONTENT_COLOR_ALPHA, gfxIntSize(ceil(destRect.width), ceil(destRect.height))); } else { - if (surf) { - mozilla::gfx::DrawTarget* dt = dest->GetDrawTarget(); - mozilla::RefPtr source = - gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(dt, surf); - if (source) { - // Could be non-integer pixel alignment - dt->DrawSurface(source, - mozilla::gfx::Rect(destRect.x, destRect.y, destRect.width, destRect.height), - mozilla::gfx::Rect(0, 0, destRect.width, destRect.height)); - return; - } + dt = static_cast(Frame()->Properties().Get(nsIFrame::CachedBackgroundImageDT())); + DrawTarget* destDT = dest->GetDrawTarget(); + if (dt) { + BlitSurface(destDT, destRect, dt); + return; } - surf = gfxPlatform::GetPlatform()->CreateOffscreenImageSurface( - gfxIntSize(ceil(destRect.width), ceil(destRect.height)), - GFX_CONTENT_COLOR_ALPHA); + dt = destDT->CreateSimilarDrawTarget(IntSize(ceil(destRect.width), ceil(destRect.height)), FORMAT_B8G8R8A8); } - if (surf) { - ctx = new gfxContext(surf); + if (surf || dt) { + if (surf) { + ctx = new gfxContext(surf); + } else { + ctx = new gfxContext(dt); + } ctx->Translate(-gfxPoint(destRect.x, destRect.y)); context.Init(aCtx->DeviceContext(), ctx); } @@ -254,14 +260,18 @@ nsDisplayCanvasBackgroundImage::Paint(nsDisplayListBuilder* aBuilder, #endif PaintInternal(aBuilder, - surf ? &context : aCtx, - surf ? bgClipRect: mVisibleRect, + (surf || dt) ? &context : aCtx, + (surf || dt) ? bgClipRect: mVisibleRect, &bgClipRect); if (surf) { BlitSurface(dest, destRect, surf); frame->Properties().Set(nsIFrame::CachedBackgroundImage(), surf.forget().get()); } + if (dt) { + BlitSurface(dest->GetDrawTarget(), destRect, dt); + frame->Properties().Set(nsIFrame::CachedBackgroundImageDT(), dt.forget().drop()); + } } void diff --git a/layout/generic/nsCanvasFrame.h b/layout/generic/nsCanvasFrame.h index f8d6830ce466..781f751ee5dd 100644 --- a/layout/generic/nsCanvasFrame.h +++ b/layout/generic/nsCanvasFrame.h @@ -175,6 +175,7 @@ public: virtual void NotifyRenderingChanged() MOZ_OVERRIDE { mFrame->Properties().Delete(nsIFrame::CachedBackgroundImage()); + mFrame->Properties().Delete(nsIFrame::CachedBackgroundImageDT()); } virtual void Paint(nsDisplayListBuilder* aBuilder, diff --git a/layout/generic/nsFrame.cpp b/layout/generic/nsFrame.cpp index 7bfbb582bc82..cac5906b6ed1 100644 --- a/layout/generic/nsFrame.cpp +++ b/layout/generic/nsFrame.cpp @@ -8219,6 +8219,12 @@ nsIFrame::DestroySurface(void* aPropertyValue) } void +nsIFrame::DestroyDT(void* aPropertyValue) +{ + static_cast(aPropertyValue)->Release(); +} + ++void nsIFrame::DestroyRegion(void* aPropertyValue) { delete static_cast(aPropertyValue); diff --git a/layout/generic/nsIFrame.h b/layout/generic/nsIFrame.h index 80ae58105f3f..54166582b130 100644 --- a/layout/generic/nsIFrame.h +++ b/layout/generic/nsIFrame.h @@ -943,6 +943,7 @@ public: } static void DestroySurface(void* aPropertyValue); + static void DestroyDT(void* aPropertyValue); #ifdef _MSC_VER // XXX Workaround MSVC issue by making the static FramePropertyDescriptor @@ -989,6 +990,7 @@ public: NS_DECLARE_FRAME_PROPERTY(LineBaselineOffset, nullptr) NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImage, DestroySurface) + NS_DECLARE_FRAME_PROPERTY(CachedBackgroundImageDT, DestroyDT) NS_DECLARE_FRAME_PROPERTY(InvalidationRect, DestroyRect)