mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1083672 - Avoid copying more than needed when drawing a canvas onto itself. r=jrmuizel
This commit is contained in:
parent
28bf55dae8
commit
1874a2749b
@ -3854,6 +3854,32 @@ bool CanvasRenderingContext2D::IsPointInStroke(const CanvasPath& mPath, double x
|
||||
return tempPath->StrokeContainsPoint(strokeOptions, Point(x, y), mTarget->GetTransform());
|
||||
}
|
||||
|
||||
// Returns a surface that contains only the part needed to draw aSourceRect.
|
||||
// On entry, aSourceRect is relative to aSurface, and on return aSourceRect is
|
||||
// relative to the returned surface.
|
||||
static TemporaryRef<SourceSurface>
|
||||
ExtractSubrect(SourceSurface* aSurface, mgfx::Rect* aSourceRect, DrawTarget* aTargetDT)
|
||||
{
|
||||
mgfx::Rect roundedOutSourceRect = *aSourceRect;
|
||||
roundedOutSourceRect.RoundOut();
|
||||
mgfx::IntRect roundedOutSourceRectInt;
|
||||
if (!roundedOutSourceRect.ToIntRect(&roundedOutSourceRectInt)) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
RefPtr<DrawTarget> subrectDT =
|
||||
aTargetDT->CreateSimilarDrawTarget(roundedOutSourceRectInt.Size(), SurfaceFormat::B8G8R8A8);
|
||||
|
||||
if (!subrectDT) {
|
||||
return aSurface;
|
||||
}
|
||||
|
||||
*aSourceRect -= roundedOutSourceRect.TopLeft();
|
||||
|
||||
subrectDT->CopySurface(aSurface, roundedOutSourceRectInt, IntPoint());
|
||||
return subrectDT->Snapshot();
|
||||
}
|
||||
|
||||
//
|
||||
// image
|
||||
//
|
||||
@ -3999,10 +4025,19 @@ CanvasRenderingContext2D::DrawImage(const HTMLImageOrCanvasOrVideoElement& image
|
||||
}
|
||||
|
||||
if (srcSurf) {
|
||||
mgfx::Rect sourceRect(sx, sy, sw, sh);
|
||||
if (element == mCanvasElement) {
|
||||
// srcSurf is a snapshot of mTarget. If we draw to mTarget now, we'll
|
||||
// trigger a COW copy of the whole canvas into srcSurf. That's a huge
|
||||
// waste if sourceRect doesn't cover the whole canvas.
|
||||
// We avoid copying the whole canvas by manually copying just the part
|
||||
// that we need.
|
||||
srcSurf = ExtractSubrect(srcSurf, &sourceRect, mTarget);
|
||||
}
|
||||
AdjustedTarget(this, bounds.IsEmpty() ? nullptr : &bounds)->
|
||||
DrawSurface(srcSurf,
|
||||
mgfx::Rect(dx, dy, dw, dh),
|
||||
mgfx::Rect(sx, sy, sw, sh),
|
||||
sourceRect,
|
||||
DrawSurfaceOptions(filter),
|
||||
DrawOptions(CurrentState().globalAlpha, UsedOperation()));
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user