Bug 1334554 - Handle the return value of nsFilterInstance::PaintFilteredFrame r=mstange

MozReview-Commit-ID: 79gddAmRjnp

--HG--
extra : rebase_source : a5652db96f271c5e367aedda1e2e607bec404fe4
This commit is contained in:
cku 2017-01-28 02:54:38 +08:00
parent 61bc2d7d16
commit 08b8ea9a74
4 changed files with 76 additions and 57 deletions

View File

@ -59,7 +59,7 @@ UserSpaceMetricsForFrame(nsIFrame* aFrame)
return MakeUnique<NonSVGFrameUserSpaceMetrics>(aFrame);
}
nsresult
DrawResult
nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame,
DrawTarget* aDrawTarget,
const gfxMatrix& aTransform,
@ -74,8 +74,9 @@ nsFilterInstance::PaintFilteredFrame(nsIFrame *aFilteredFrame,
filterChain, /* InputIsTainted */ true, aPaintCallback,
aTransform, aDirtyArea, nullptr, nullptr, nullptr);
if (!instance.IsInitialized()) {
return NS_OK;
return DrawResult::BAD_IMAGE;
}
return instance.Render(aDrawTarget);
}
@ -230,11 +231,6 @@ nsFilterInstance::nsFilterInstance(nsIFrame *aTargetFrame,
return;
}
if (mPrimitiveDescriptions.IsEmpty()) {
// Nothing should be rendered.
return;
}
// Convert the passed in rects from frame space to filter space:
mPostFilterDirtyRegion = FrameSpaceToFilterSpace(aPostFilterDirtyRegion);
mPreFilterDirtyRegion = FrameSpaceToFilterSpace(aPreFilterDirtyRegion);
@ -365,7 +361,7 @@ nsFilterInstance::ComputeNeededBoxes()
mStrokePaint.mNeededBounds = strokePaintNeededRegion.GetBounds();
}
nsresult
DrawResult
nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
DrawTarget* aTargetDT)
{
@ -376,13 +372,16 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
neededRect.Size(), SurfaceFormat::B8G8R8A8);
if (!offscreenDT || !offscreenDT->IsValid()) {
return NS_ERROR_OUT_OF_MEMORY;
return DrawResult::TEMPORARY_ERROR;
}
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform();
if (!deviceToFilterSpace.Invert()) {
return NS_ERROR_FAILURE;
}
DebugOnly<bool> invertible = deviceToFilterSpace.Invert();
MOZ_ASSERT(invertible,
"The returning matix of GetFilterSpaceToDeviceSpaceTransform must"
"be an invertible matrix(not a singular one), since we already"
"checked it and early return if it's not from the caller side"
"(nsFilterInstance::Render)");
if (!mPaintTransform.IsSingular()) {
RefPtr<gfxContext> gfx = gfxContext::CreateOrNull(offscreenDT);
@ -407,48 +406,52 @@ nsFilterInstance::BuildSourcePaint(SourceInfo *aSource,
aSource->mSourceSurface = offscreenDT->Snapshot();
aSource->mSurfaceRect = neededRect;
return NS_OK;
return DrawResult::SUCCESS;
}
nsresult
DrawResult
nsFilterInstance::BuildSourcePaints(DrawTarget* aTargetDT)
{
nsresult rv = NS_OK;
if (!mFillPaint.mNeededBounds.IsEmpty()) {
rv = BuildSourcePaint(&mFillPaint, aTargetDT);
NS_ENSURE_SUCCESS(rv, rv);
DrawResult result = BuildSourcePaint(&mFillPaint, aTargetDT);
if (result != DrawResult::SUCCESS) {
return result;
}
}
if (!mStrokePaint.mNeededBounds.IsEmpty()) {
rv = BuildSourcePaint(&mStrokePaint, aTargetDT);
NS_ENSURE_SUCCESS(rv, rv);
DrawResult result = BuildSourcePaint(&mStrokePaint, aTargetDT);
if (result != DrawResult::SUCCESS) {
return result;
}
}
return rv;
return DrawResult::SUCCESS;
}
nsresult
DrawResult
nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT)
{
MOZ_ASSERT(mTargetFrame);
nsIntRect neededRect = mSourceGraphic.mNeededBounds;
if (neededRect.IsEmpty()) {
return NS_OK;
return DrawResult::SUCCESS;
}
RefPtr<DrawTarget> offscreenDT =
gfxPlatform::GetPlatform()->CreateOffscreenContentDrawTarget(
neededRect.Size(), SurfaceFormat::B8G8R8A8);
if (!offscreenDT || !offscreenDT->IsValid()) {
return NS_ERROR_OUT_OF_MEMORY;
return DrawResult::TEMPORARY_ERROR;
}
gfxRect r = FilterSpaceToUserSpace(ThebesRect(neededRect));
r.RoundOut();
nsIntRect dirty;
if (!gfxUtils::GfxRectToIntRect(r, &dirty))
return NS_ERROR_FAILURE;
if (!gfxUtils::GfxRectToIntRect(r, &dirty)){
return DrawResult::SUCCESS;
}
// SVG graphics paint to device space, so we need to set an initial device
// space to filter space transform on the gfxContext that SourceGraphic
@ -462,9 +465,13 @@ nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT)
// code more complex while being hard to get right without introducing
// subtle bugs, and in practice it probably makes no real difference.)
gfxMatrix deviceToFilterSpace = GetFilterSpaceToDeviceSpaceTransform();
if (!deviceToFilterSpace.Invert()) {
return NS_ERROR_FAILURE;
}
DebugOnly<bool> invertible = deviceToFilterSpace.Invert();
MOZ_ASSERT(invertible,
"The returning matix of GetFilterSpaceToDeviceSpaceTransform must"
"be an invertible matrix(not a singular one), since we already"
"checked it and early return if it's not from the caller side"
"(nsFilterInstance::Render)");
RefPtr<gfxContext> ctx = gfxContext::CreateOrNull(offscreenDT);
MOZ_ASSERT(ctx); // already checked the draw target above
ctx->SetMatrix(
@ -477,20 +484,25 @@ nsFilterInstance::BuildSourceImage(DrawTarget* aTargetDT)
mSourceGraphic.mSourceSurface = offscreenDT->Snapshot();
mSourceGraphic.mSurfaceRect = neededRect;
return (result == DrawResult::SUCCESS) ? NS_OK : NS_ERROR_FAILURE;
return result;
}
nsresult
DrawResult
nsFilterInstance::Render(DrawTarget* aDrawTarget)
{
MOZ_ASSERT(mTargetFrame, "Need a frame for rendering");
if (mPrimitiveDescriptions.IsEmpty()) {
// An filter without any primitive. Treat it as success and paint nothing.
return DrawResult::SUCCESS;
}
nsIntRect filterRect =
mPostFilterDirtyRegion.GetBounds().Intersect(OutputFilterSpaceBounds());
gfxMatrix ctm = GetFilterSpaceToDeviceSpaceTransform();
if (filterRect.IsEmpty() || ctm.IsSingular()) {
return NS_OK;
return DrawResult::SUCCESS;
}
AutoRestoreTransform autoRestoreTransform(aDrawTarget);
@ -499,13 +511,14 @@ nsFilterInstance::Render(DrawTarget* aDrawTarget)
aDrawTarget->SetTransform(newTM);
ComputeNeededBoxes();
nsresult rv = BuildSourceImage(aDrawTarget);
if (NS_FAILED(rv))
return rv;
rv = BuildSourcePaints(aDrawTarget);
if (NS_FAILED(rv))
return rv;
DrawResult result = BuildSourceImage(aDrawTarget);
if (result != DrawResult::SUCCESS){
return result;
}
result = BuildSourcePaints(aDrawTarget);
if (result != DrawResult::SUCCESS){
return result;
}
FilterSupport::RenderFilterDescription(
aDrawTarget, mFilterDescription, IntRectToRect(filterRect),
@ -514,13 +527,13 @@ nsFilterInstance::Render(DrawTarget* aDrawTarget)
mStrokePaint.mSourceSurface, mStrokePaint.mSurfaceRect,
mInputImages, Point(0, 0));
return NS_OK;
return DrawResult::SUCCESS;
}
nsRegion
nsFilterInstance::ComputePostFilterDirtyRegion()
{
if (mPreFilterDirtyRegion.IsEmpty()) {
if (mPreFilterDirtyRegion.IsEmpty() || mPrimitiveDescriptions.IsEmpty()) {
return nsRegion();
}
@ -533,6 +546,10 @@ nsFilterInstance::ComputePostFilterDirtyRegion()
nsRect
nsFilterInstance::ComputePostFilterExtents()
{
if (mPrimitiveDescriptions.IsEmpty()) {
return nsRect();
}
nsIntRegion postFilterExtents =
FilterSupport::ComputePostFilterExtents(mFilterDescription, mTargetBounds);
return FilterSpaceToFrameSpace(postFilterExtents.GetBounds());

View File

@ -55,7 +55,7 @@ class nsFilterInstance
typedef mozilla::gfx::FilterPrimitiveDescription FilterPrimitiveDescription;
typedef mozilla::gfx::FilterDescription FilterDescription;
typedef mozilla::dom::UserSpaceMetrics UserSpaceMetrics;
typedef mozilla::image::DrawResult DrawResult;
public:
/**
* Create a FilterDescription for the supplied filter. All coordinates in
@ -83,11 +83,11 @@ public:
* frame space (i.e. relative to its origin, the top-left corner of its
* border box).
*/
static nsresult PaintFilteredFrame(nsIFrame *aFilteredFrame,
DrawTarget* aDrawTarget,
const gfxMatrix& aTransform,
nsSVGFilterPaintCallback *aPaintCallback,
const nsRegion* aDirtyArea);
static DrawResult PaintFilteredFrame(nsIFrame *aFilteredFrame,
DrawTarget* aDrawTarget,
const gfxMatrix& aTransform,
nsSVGFilterPaintCallback *aPaintCallback,
const nsRegion* aDirtyArea);
/**
* Returns the post-filter area that could be dirtied when the given
@ -166,7 +166,7 @@ public:
* by passing it as the aPostFilterDirtyRegion argument to the
* nsFilterInstance constructor.
*/
nsresult Render(DrawTarget* aDrawTarget);
DrawResult Render(DrawTarget* aDrawTarget);
const FilterDescription& ExtractDescriptionAndAdditionalImages(nsTArray<RefPtr<SourceSurface>>& aOutAdditionalImages)
{
@ -228,7 +228,7 @@ private:
* Creates a SourceSurface for either the FillPaint or StrokePaint graph
* nodes
*/
nsresult BuildSourcePaint(SourceInfo *aPrimitive,
DrawResult BuildSourcePaint(SourceInfo *aPrimitive,
DrawTarget* aTargetDT);
/**
@ -236,13 +236,13 @@ private:
* nodes, fills its contents and assigns it to mFillPaint.mSourceSurface and
* mStrokePaint.mSourceSurface respectively.
*/
nsresult BuildSourcePaints(DrawTarget* aTargetDT);
DrawResult BuildSourcePaints(DrawTarget* aTargetDT);
/**
* Creates the SourceSurface for the SourceGraphic graph node, paints its
* contents, and assigns it to mSourceGraphic.mSourceSurface.
*/
nsresult BuildSourceImage(DrawTarget* aTargetDT);
DrawResult BuildSourceImage(DrawTarget* aTargetDT);
/**
* Build the list of FilterPrimitiveDescriptions that describes the filter's

View File

@ -1115,14 +1115,15 @@ nsSVGIntegrationUtils::PaintFilter(const PaintFramesParams& aParams)
offsetToUserSpace);
nsRegion dirtyRegion = aParams.dirtyRect - offsetToBoundingBox;
gfxMatrix tm = nsSVGIntegrationUtils::GetCSSPxToDevPxMatrix(frame);
nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(),
tm, &callback, &dirtyRegion);
DrawResult result =
nsFilterInstance::PaintFilteredFrame(frame, context.GetDrawTarget(),
tm, &callback, &dirtyRegion);
if (opacity != 1.0f) {
context.PopGroupAndBlend();
}
return DrawResult::SUCCESS;
return result;
}
gfxMatrix

View File

@ -860,9 +860,10 @@ nsSVGUtils::PaintFrameWithEffects(nsIFrame *aFrame,
dirtyRegion = &tmpDirtyRegion;
}
SVGPaintCallback paintCallback;
nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
aTransform, &paintCallback,
dirtyRegion);
result =
nsFilterInstance::PaintFilteredFrame(aFrame, target->GetDrawTarget(),
aTransform, &paintCallback,
dirtyRegion);
} else {
result = svgChildFrame->PaintSVG(*target, aTransform, aDirtyRect);
}