From 0f89a17b16a7a9f4e29a95e517c05080613e6588 Mon Sep 17 00:00:00 2001 From: Markus Stange Date: Wed, 8 Jan 2014 10:30:57 +0100 Subject: [PATCH] Bug 957366 - Skip the temporary surface during filter drawing for DrawTarget-backed gfxContexts. r=roc --- layout/svg/nsSVGFilterInstance.cpp | 42 ++++++++++++++++++------------ layout/svg/nsSVGUtils.cpp | 31 ---------------------- layout/svg/nsSVGUtils.h | 11 -------- 3 files changed, 25 insertions(+), 59 deletions(-) diff --git a/layout/svg/nsSVGFilterInstance.cpp b/layout/svg/nsSVGFilterInstance.cpp index acedc86177cb..c88cde07c9e5 100644 --- a/layout/svg/nsSVGFilterInstance.cpp +++ b/layout/svg/nsSVGFilterInstance.cpp @@ -459,13 +459,15 @@ nsSVGFilterInstance::Render(gfxContext* aContext) } nsIntRect filterRect = mPostFilterDirtyRect.Intersect(mFilterSpaceBounds); + gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); - if (filterRect.IsEmpty()) { + if (filterRect.IsEmpty() || ctm.IsSingular()) { return NS_OK; } + Matrix oldDTMatrix; nsRefPtr resultImage; - RefPtr resultImageDT; + RefPtr dt; if (aContext->IsCairo()) { resultImage = gfxPlatform::GetPlatform()->CreateOffscreenSurface(filterRect.Size(), @@ -474,20 +476,24 @@ nsSVGFilterInstance::Render(gfxContext* aContext) return NS_ERROR_OUT_OF_MEMORY; // Create a Cairo DrawTarget around resultImage. - resultImageDT = - gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( - resultImage, ToIntSize(filterRect.Size())); + dt = gfxPlatform::GetPlatform()->CreateDrawTargetForSurface( + resultImage, ToIntSize(filterRect.Size())); } else { - resultImageDT = gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget( - ToIntSize(filterRect.Size()), FORMAT_B8G8R8A8); + // When we have a DrawTarget-backed context, we can call DrawFilter + // directly on the target DrawTarget and don't need a temporary DT. + dt = aContext->GetDrawTarget(); + oldDTMatrix = dt->GetTransform(); + Matrix matrix = ToMatrix(ctm); + matrix.Translate(filterRect.x, filterRect.y); + dt->SetTransform(matrix * oldDTMatrix); } ComputeNeededBoxes(); - rv = BuildSourceImage(resultImage, resultImageDT); + rv = BuildSourceImage(resultImage, dt); if (NS_FAILED(rv)) return rv; - rv = BuildSourcePaints(resultImage, resultImageDT); + rv = BuildSourcePaints(resultImage, dt); if (NS_FAILED(rv)) return rv; @@ -495,21 +501,23 @@ nsSVGFilterInstance::Render(gfxContext* aContext) FilterDescription filter(mPrimitiveDescriptions, filterSpaceBounds); FilterSupport::RenderFilterDescription( - resultImageDT, filter, ToRect(filterRect), + dt, filter, ToRect(filterRect), mSourceGraphic.mSourceSurface, mSourceGraphic.mSurfaceRect, mFillPaint.mSourceSurface, mFillPaint.mSurfaceRect, mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect, mInputImages); - RefPtr resultImageSource; - if (!resultImage) { - resultImageSource = resultImageDT->Snapshot(); + if (resultImage) { + aContext->Save(); + aContext->Multiply(ctm); + aContext->Translate(filterRect.TopLeft()); + aContext->SetSource(resultImage); + aContext->Paint(); + aContext->Restore(); + } else { + dt->SetTransform(oldDTMatrix); } - gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform(); - nsSVGUtils::CompositeSurfaceMatrix(aContext, resultImage, resultImageSource, - filterRect.TopLeft(), ctm); - return NS_OK; } diff --git a/layout/svg/nsSVGUtils.cpp b/layout/svg/nsSVGUtils.cpp index 9c0a363a3b10..aa0a6fe59c5f 100644 --- a/layout/svg/nsSVGUtils.cpp +++ b/layout/svg/nsSVGUtils.cpp @@ -841,37 +841,6 @@ nsSVGUtils::GetClipRectForFrame(nsIFrame *aFrame, return gfxRect(aX, aY, aWidth, aHeight); } -void -nsSVGUtils::CompositeSurfaceMatrix(gfxContext *aContext, - gfxASurface *aSurface, - SourceSurface *aSourceSurface, - const gfxPoint &aSurfaceOffset, - const gfxMatrix &aCTM) -{ - if (aCTM.IsSingular()) - return; - - if (aSurface) { - aContext->Save(); - aContext->Multiply(aCTM); - aContext->Translate(aSurfaceOffset); - aContext->SetSource(aSurface); - aContext->Paint(); - aContext->Restore(); - } else { - DrawTarget *destDT = aContext->GetDrawTarget(); - Matrix oldMat = destDT->GetTransform(); - destDT->SetTransform(ToMatrix(aCTM) * oldMat); - - IntSize size = aSourceSurface->GetSize(); - Rect sourceRect(Point(0, 0), Size(size.width, size.height)); - Rect drawRect = sourceRect + ToPoint(aSurfaceOffset); - destDT->DrawSurface(aSourceSurface, drawRect, sourceRect); - - destDT->SetTransform(oldMat); - } -} - void nsSVGUtils::SetClipRect(gfxContext *aContext, const gfxMatrix &aCTM, diff --git a/layout/svg/nsSVGUtils.h b/layout/svg/nsSVGUtils.h index b660cf4395a5..8c298f39f5ea 100644 --- a/layout/svg/nsSVGUtils.h +++ b/layout/svg/nsSVGUtils.h @@ -413,17 +413,6 @@ public: GetClipRectForFrame(nsIFrame *aFrame, float aX, float aY, float aWidth, float aHeight); - /** - * Composites a surface into a context with a given surface offset and an - * additional transform. Supports both Thebes and DrawTarget drawing. - * If aSurface is null, aSourceSurface will be used instead. - */ - static void CompositeSurfaceMatrix(gfxContext *aContext, - gfxASurface *aSurface, - mozilla::gfx::SourceSurface *aSourceSurface, - const gfxPoint &aSurfaceOffset, - const gfxMatrix &aCTM); - static void SetClipRect(gfxContext *aContext, const gfxMatrix &aCTM, const gfxRect &aRect);