author | Nicolas Silva <nsilva@mozilla.com> |
Fri, 26 Aug 2016 14:31:58 +0200 | |
changeset 311447 | ac16b2ccd7a11e81b8d2fcb84146c6460a188256 |
parent 311446 | bc5a4525f6c291dc0482c750a8addeabdb543ca6 |
child 311448 | ba8f999c0a3fdd0ccc61e3676c564c69dbce248b |
push id | 30610 |
push user | kwierso@gmail.com |
push date | Fri, 26 Aug 2016 23:20:56 +0000 |
treeherder | mozilla-central@f38d60b049f0 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | Bas |
bugs | 1294351 |
milestone | 51.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
|
dom/canvas/CanvasRenderingContext2D.cpp | file | annotate | diff | comparison | revisions | |
dom/canvas/CanvasRenderingContext2D.h | file | annotate | diff | comparison | revisions |
--- a/dom/canvas/CanvasRenderingContext2D.cpp +++ b/dom/canvas/CanvasRenderingContext2D.cpp @@ -1500,16 +1500,43 @@ CanvasRenderingContext2D::OnStableState( return; } ReturnTarget(); mHasPendingStableStateCallback = false; } +void +CanvasRenderingContext2D::RestoreClipsAndTransformToTarget() +{ + // Restore clips and transform. + mTarget->SetTransform(Matrix()); + + if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) { + // Cairo doesn't play well with huge clips. When given a very big clip it + // will try to allocate big mask surface without taking the target + // size into account which can cause OOM. See bug 1034593. + // This limits the clip extents to the size of the canvas. + // A fix in Cairo would probably be preferable, but requires somewhat + // invasive changes. + mTarget->PushClipRect(gfx::Rect(0, 0, mWidth, mHeight)); + } + + for (const auto& style : mStyleStack) { + for (const auto& clipOrTransform : style.clipsAndTransforms) { + if (clipOrTransform.IsClip()) { + mTarget->PushClip(clipOrTransform.clip); + } else { + mTarget->SetTransform(clipOrTransform.transform); + } + } + } +} + CanvasRenderingContext2D::RenderingMode CanvasRenderingContext2D::EnsureTarget(const gfx::Rect* aCoveredRect, RenderingMode aRenderingMode) { if (AlreadyShutDown()) { gfxCriticalError() << "Attempt to render into a Canvas2d after shutdown."; EnsureErrorTarget(); mTarget = sErrorTarget; @@ -1551,17 +1578,23 @@ CanvasRenderingContext2D::EnsureTarget(c // buffer provider. RefPtr<PersistentBufferProvider> oldBufferProvider = mBufferProvider; if (mBufferProvider && mode == mRenderingMode) { auto persistedRect = canDiscardContent ? IntRect() : IntRect(0, 0, mWidth, mHeight); mTarget = mBufferProvider->BorrowDrawTarget(persistedRect); - mode = mRenderingMode; + if (mTarget && !mBufferProvider->PreservesDrawingState()) { + RestoreClipsAndTransformToTarget(); + } + + if (mTarget) { + return mode; + } } mIsSkiaGL = false; // Check that the dimensions are sane IntSize size(mWidth, mHeight); if (!mTarget && size.width <= gfxPrefs::MaxCanvasSize() && @@ -1644,38 +1677,17 @@ CanvasRenderingContext2D::EnsureTarget(c } // Calling Redraw() tells our invalidation machinery that the entire // canvas is already invalid, which can speed up future drawing. Redraw(); } if (mBufferProvider != oldBufferProvider || !mBufferProvider || !mBufferProvider->PreservesDrawingState()) { - // Restore clips and transform. - mTarget->SetTransform(Matrix()); - - if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) { - // Cairo doesn't play well with huge clips. When given a very big clip it - // will try to allocate big mask surface without taking the target - // size into account which can cause OOM. See bug 1034593. - // This limits the clip extents to the size of the canvas. - // A fix in Cairo would probably be preferable, but requires somewhat - // invasive changes. - mTarget->PushClipRect(canvasRect); - } - - for (const auto& style : mStyleStack) { - for (const auto& clipOrTransform : style.clipsAndTransforms) { - if (clipOrTransform.IsClip()) { - mTarget->PushClip(clipOrTransform.clip); - } else { - mTarget->SetTransform(clipOrTransform.transform); - } - } - } + RestoreClipsAndTransformToTarget(); } } else { EnsureErrorTarget(); mTarget = sErrorTarget; mBufferProvider = nullptr; } // Drop a note in the debug builds if we ever use accelerated Skia canvas. @@ -1787,17 +1799,17 @@ CanvasRenderingContext2D::ReturnTarget(b if (clipOrTransform.IsClip()) { mTarget->PopClip(); } } } if (mTarget->GetBackendType() == gfx::BackendType::CAIRO) { // With the cairo backend we pushed an extra clip rect which we have to - // balance out here. See the comment in EnsureDrawTarget. + // balance out here. See the comment in RestoreClipsAndTransformToTarget. mTarget->PopClip(); } } mBufferProvider->ReturnDrawTarget(mTarget.forget()); } }
--- a/dom/canvas/CanvasRenderingContext2D.h +++ b/dom/canvas/CanvasRenderingContext2D.h @@ -638,16 +638,18 @@ protected: * is in turn an error in creating the sErrorTarget then they would both * be null so IsTargetValid() would still return null. * * Returns the actual rendering mode being used by the created target. */ RenderingMode EnsureTarget(const gfx::Rect* aCoveredRect = nullptr, RenderingMode aRenderMode = RenderingMode::DefaultBackendMode); + void RestoreClipsAndTransformToTarget(); + /** * This method is run at the end of the event-loop spin where * ScheduleStableStateCallback was called. * * We use it to unlock resources that need to be locked while drawing. */ void OnStableState();