author | Markus Stange <mstange@themasta.com> |
Fri, 24 Oct 2014 18:32:17 +0200 | |
changeset 212271 | 853612ddc6861ea705848979a03ed23f35d66f35 |
parent 212259 | 5fcda0c427935b3ead2b8e8cbfab2374efc7562d |
child 212272 | 2d37465635cb60341dc02428d8d67cb514e6b356 |
push id | 27704 |
push user | kwierso@gmail.com |
push date | Sat, 25 Oct 2014 01:25:30 +0000 |
treeherder | mozilla-central@e37231060eb4 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | jrmuizel |
bugs | 1083672 |
milestone | 36.0a1 |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -3849,16 +3849,42 @@ bool CanvasRenderingContext2D::IsPointIn state.miterLimit, state.dash.Length(), state.dash.Elements(), state.dashOffset); 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 // // drawImage(in HTMLImageElement image, in float dx, in float dy); // -- render image from 0,0 at dx,dy top-left coords // drawImage(in HTMLImageElement image, in float dx, in float dy, in float sw, in float sh); // -- render image from 0,0 at dx,dy top-left coords clipping it to sw,sh @@ -3994,20 +4020,29 @@ CanvasRenderingContext2D::DrawImage(cons mgfx::Rect bounds; if (NeedToCalculateBounds()) { bounds = mgfx::Rect(dx, dy, dw, dh); bounds = mTarget->GetTransform().TransformBounds(bounds); } 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 { DrawDirectlyToCanvas(drawInfo, &bounds, mgfx::Rect(dx, dy, dw, dh), mgfx::Rect(sx, sy, sw, sh), imgSize); }