Index: Source/modules/canvas2d/CanvasRenderingContext2D.cpp |
diff --git a/Source/modules/canvas2d/CanvasRenderingContext2D.cpp b/Source/modules/canvas2d/CanvasRenderingContext2D.cpp |
index 022cbf97d6805244fe96430eb2c43c8ebd7b98c7..41d48fe8be8d093508a6b6f92642f749708b670b 100644 |
--- a/Source/modules/canvas2d/CanvasRenderingContext2D.cpp |
+++ b/Source/modules/canvas2d/CanvasRenderingContext2D.cpp |
@@ -879,16 +879,12 @@ void CanvasRenderingContext2D::compositedDraw(const DrawFunc& drawFunc, SkCanvas |
} |
template<typename DrawFunc, typename ContainsFunc> |
-bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc& drawCoversClipBounds, CanvasDeferralMode deferralMode, const SkRect& bounds, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType) |
+bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc& drawCoversClipBounds, const SkRect& bounds, CanvasRenderingContext2DState::PaintType paintType, CanvasRenderingContext2DState::ImageType imageType) |
{ |
if (!state().isTransformInvertible()) |
return false; |
SkIRect clipBounds; |
- // Deliberately not using 'deferralMode' in the call to drawingCanvas below because |
- // a) The call does not write anything so we do not care about the write mode here |
- // b) We want to avoid flushing before the call to checkOverdraw (below), otherwise |
- // we could be supressing an overdraw optimization. |
if (!drawingCanvas()->getClipDeviceBounds(&clipBounds)) |
return false; |
@@ -901,12 +897,12 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc |
} |
if (isFullCanvasCompositeMode(state().globalComposite()) || state().hasFilter()) { |
- compositedDraw(drawFunc, drawingCanvas(deferralMode), paintType, imageType); |
+ compositedDraw(drawFunc, drawingCanvas(), paintType, imageType); |
didDraw(clipBounds); |
} else if (state().globalComposite() == SkXfermode::kSrc_Mode) { |
clearCanvas(); // takes care of checkOvewrdraw() |
const SkPaint* paint = state().getPaint(paintType, DrawForegroundOnly, imageType); |
- drawFunc(drawingCanvas(deferralMode), paint); |
+ drawFunc(drawingCanvas(), paint); |
didDraw(clipBounds); |
} else { |
SkIRect dirtyRect; |
@@ -914,7 +910,7 @@ bool CanvasRenderingContext2D::draw(const DrawFunc& drawFunc, const ContainsFunc |
const SkPaint* paint = state().getPaint(paintType, DrawShadowAndForeground, imageType); |
if (paintType != CanvasRenderingContext2DState::StrokePaintType && drawCoversClipBounds(clipBounds)) |
checkOverdraw(bounds, paint, imageType, ClipFill); |
- drawFunc(drawingCanvas(deferralMode), paint); |
+ drawFunc(drawingCanvas(), paint); |
didDraw(dirtyRect); |
} |
} |
@@ -956,7 +952,7 @@ void CanvasRenderingContext2D::drawPathInternal(const Path& path, CanvasRenderin |
[](const SkIRect& rect) // overdraw test lambda |
{ |
return false; |
- }, AllowDeferredCanvas, bounds, paintType)) { |
+ }, bounds, paintType)) { |
if (isPathExpensive(path)) { |
ImageBuffer* buffer = canvas()->buffer(); |
if (buffer) |
@@ -1013,7 +1009,7 @@ void CanvasRenderingContext2D::fillRect(float x, float y, float width, float hei |
[&rect, this](const SkIRect& clipBounds) // overdraw test lambda |
{ |
return rectContainsTransformedRect(rect, clipBounds); |
- }, AllowDeferredCanvas, rect, CanvasRenderingContext2DState::FillPaintType); |
+ }, rect, CanvasRenderingContext2DState::FillPaintType); |
} |
static void strokeRectOnCanvas(const FloatRect& rect, SkCanvas* canvas, const SkPaint* paint) |
@@ -1050,7 +1046,7 @@ void CanvasRenderingContext2D::strokeRect(float x, float y, float width, float h |
[](const SkIRect& clipBounds) // overdraw test lambda |
{ |
return false; |
- }, AllowDeferredCanvas, bounds, CanvasRenderingContext2DState::StrokePaintType); |
+ }, bounds, CanvasRenderingContext2DState::StrokePaintType); |
} |
void CanvasRenderingContext2D::clipInternal(const Path& path, const String& windingRuleString) |
@@ -1392,7 +1388,13 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
if (srcRect.isEmpty()) |
return; |
- CanvasDeferralMode deferralMode = imageSource->isVideoElement() ? ForceImmediateCanvas : AllowDeferredCanvas; |
+ // FIXME: crbug.com/521001 |
+ // We make the destination canvas fall out of display list mode by forcing |
+ // immediate rendering. This is to prevent run-away memory consumption caused by SkSurface |
+ // copyOnWrite when the source canvas is animated and consumed at a rate higher than the |
+ // presentation frame rate of the destination canvas. |
+ if (imageSource->isVideoElement() || imageSource->isCanvasElement()) |
+ canvas()->disableDeferral(); |
validateStateStack(); |
@@ -1404,7 +1406,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
[this, &dstRect](const SkIRect& clipBounds) // overdraw test lambda |
{ |
return rectContainsTransformedRect(dstRect, clipBounds); |
- }, deferralMode, dstRect, CanvasRenderingContext2DState::ImagePaintType, |
+ }, dstRect, CanvasRenderingContext2DState::ImagePaintType, |
imageSource->isOpaque() ? CanvasRenderingContext2DState::OpaqueImage : CanvasRenderingContext2DState::NonOpaqueImage); |
validateStateStack(); |
@@ -1423,19 +1425,10 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, |
buffer->setHasExpensiveOp(); |
} |
- if (imageSource->isCanvasElement()) { |
- if (static_cast<HTMLCanvasElement*>(imageSource)->is3D()) { |
- // WebGL to 2D canvas: must flush graphics context to prevent a race |
- // FIXME: crbug.com/516331 Fix the underlying synchronization issue so this flush can be eliminated. |
- canvas()->buffer()->flushGpu(); |
- } else { |
- // FIXME: crbug.com/447218 |
- // We make the destination canvas fall out of display list mode by calling |
- // flush. This is to prevent run-away memory consumption caused by SkSurface |
- // copyOnWrite when the source canvas is animated and consumed at a rate higher than the |
- // presentation frame rate of the destination canvas. |
- canvas()->buffer()->flush(); |
- } |
+ if (imageSource->isCanvasElement() && static_cast<HTMLCanvasElement*>(imageSource)->is3D()) { |
+ // WebGL to 2D canvas: must flush graphics context to prevent a race |
+ // FIXME: crbug.com/516331 Fix the underlying synchronization issue so this flush can be eliminated. |
+ canvas()->buffer()->flushGpu(); |
} |
if (canvas()->originClean() && wouldTaintOrigin(imageSource)) |
@@ -1446,8 +1439,9 @@ void CanvasRenderingContext2D::clearCanvas() |
{ |
FloatRect canvasRect(0, 0, canvas()->width(), canvas()->height()); |
checkOverdraw(canvasRect, 0, CanvasRenderingContext2DState::NoImage, ClipFill); |
- if (drawingCanvas()) |
- drawingCanvas()->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); |
+ SkCanvas* c = drawingCanvas(); |
+ if (c) |
+ c->clear(m_hasAlpha ? SK_ColorTRANSPARENT : SK_ColorBLACK); |
} |
bool CanvasRenderingContext2D::rectContainsTransformedRect(const FloatRect& rect, const SkIRect& transformedRect) const |
@@ -1553,11 +1547,11 @@ void CanvasRenderingContext2D::didDraw(const SkIRect& dirtyRect) |
canvas()->didDraw(SkRect::Make(dirtyRect)); |
} |
-SkCanvas* CanvasRenderingContext2D::drawingCanvas(CanvasDeferralMode deferralMode) const |
+SkCanvas* CanvasRenderingContext2D::drawingCanvas() const |
{ |
if (isContextLost()) |
return nullptr; |
- return deferralMode == ForceImmediateCanvas ? canvas()->immediateDrawingCanvas() : canvas()->drawingCanvas(); |
+ return canvas()->drawingCanvas(); |
} |
ImageData* CanvasRenderingContext2D::createImageData(ImageData* imageData) const |
@@ -2020,7 +2014,7 @@ void CanvasRenderingContext2D::drawTextInternal(const String& text, float x, flo |
{ |
return false; |
}, |
- AllowDeferredCanvas, textRunPaintInfo.bounds, paintType); |
+ textRunPaintInfo.bounds, paintType); |
} |
void CanvasRenderingContext2D::inflateStrokeRect(FloatRect& rect) const |