mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-11 04:15:43 +00:00
Bug 957366 - Skip the temporary surface during filter drawing for DrawTarget-backed gfxContexts. r=roc
This commit is contained in:
parent
77136b7ef2
commit
0f89a17b16
@ -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<gfxASurface> resultImage;
|
||||
RefPtr<DrawTarget> resultImageDT;
|
||||
RefPtr<DrawTarget> 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<SourceSurface> 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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user