Commit ec3bf2dc authored by junov@chromium.org's avatar junov@chromium.org

Reland: 2D canvas: remain in deferred rendering mode with canvas to canvas drawImage

If the source canvas is not animated, no need to exit deferred rendering
because there is no risk of memory bloat due to snapshotting.

Fixed reson for original revert: m_snapshotState was not initialized

BUG=521001, 521732
NOTRY=true

Review URL: https://codereview.chromium.org/1289423003

git-svn-id: svn://svn.chromium.org/blink/trunk@200771 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent 9ffe1ee8
...@@ -441,6 +441,11 @@ bool HTMLCanvasElement::is3D() const ...@@ -441,6 +441,11 @@ bool HTMLCanvasElement::is3D() const
return m_context && m_context->is3d(); return m_context && m_context->is3d();
} }
bool HTMLCanvasElement::isAnimated2D() const
{
return m_context && m_context->is2d() && hasImageBuffer() && m_imageBuffer->wasDrawnToAfterSnapshot();
}
void HTMLCanvasElement::setSurfaceSize(const IntSize& size) void HTMLCanvasElement::setSurfaceSize(const IntSize& size)
{ {
m_size = size; m_size = size;
......
...@@ -138,6 +138,7 @@ public: ...@@ -138,6 +138,7 @@ public:
AffineTransform baseTransform() const; AffineTransform baseTransform() const;
bool is3D() const; bool is3D() const;
bool isAnimated2D() const;
bool hasImageBuffer() const { return m_imageBuffer; } bool hasImageBuffer() const { return m_imageBuffer; }
void discardImageBuffer(); void discardImageBuffer();
......
...@@ -1353,6 +1353,20 @@ void CanvasRenderingContext2D::drawImageInternal(SkCanvas* c, CanvasImageSource* ...@@ -1353,6 +1353,20 @@ void CanvasRenderingContext2D::drawImageInternal(SkCanvas* c, CanvasImageSource*
c->restoreToCount(initialSaveCount); c->restoreToCount(initialSaveCount);
} }
bool shouldDisableDeferral(CanvasImageSource* imageSource)
{
if (imageSource->isVideoElement())
return true;
if (imageSource->isCanvasElement()) {
HTMLCanvasElement* canvas = static_cast<HTMLCanvasElement*>(imageSource);
if (canvas->is3D())
return true;
if (canvas->isAnimated2D())
return true;
}
return false;
}
void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
float sx, float sy, float sw, float sh, float sx, float sy, float sw, float sh,
float dx, float dy, float dw, float dh, ExceptionState& exceptionState) float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
...@@ -1388,12 +1402,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource, ...@@ -1388,12 +1402,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
if (srcRect.isEmpty()) if (srcRect.isEmpty())
return; return;
// FIXME: crbug.com/521001 if (shouldDisableDeferral(imageSource))
// 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(); canvas()->disableDeferral();
validateStateStack(); validateStateStack();
......
...@@ -76,7 +76,8 @@ PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa ...@@ -76,7 +76,8 @@ PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
} }
ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface) ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
: m_surface(surface) : m_snapshotState(InitialSnapshotState)
, m_surface(surface)
, m_client(0) , m_client(0)
{ {
m_surface->setImageBuffer(this); m_surface->setImageBuffer(this);
...@@ -149,6 +150,9 @@ void ImageBuffer::resetCanvas(SkCanvas* canvas) const ...@@ -149,6 +150,9 @@ void ImageBuffer::resetCanvas(SkCanvas* canvas) const
PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const
{ {
if (m_snapshotState == InitialSnapshotState)
m_snapshotState = DidAcquireSnapshot;
if (!isSurfaceValid()) if (!isSurfaceValid())
return nullptr; return nullptr;
return m_surface->newImageSnapshot(); return m_surface->newImageSnapshot();
...@@ -156,14 +160,19 @@ PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const ...@@ -156,14 +160,19 @@ PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const
PassRefPtr<Image> ImageBuffer::newImageSnapshot() const PassRefPtr<Image> ImageBuffer::newImageSnapshot() const
{ {
if (!isSurfaceValid()) RefPtr<SkImage> snapshot = newSkImageSnapshot();
return nullptr;
RefPtr<SkImage> snapshot = m_surface->newImageSnapshot();
if (!snapshot) if (!snapshot)
return nullptr; return nullptr;
return StaticBitmapImage::create(snapshot); return StaticBitmapImage::create(snapshot);
} }
void ImageBuffer::didDraw(const FloatRect& rect) const
{
if (m_snapshotState == DidAcquireSnapshot)
m_snapshotState = DrawnToAfterSnapshot;
m_surface->didDraw(rect);
}
WebLayer* ImageBuffer::platformLayer() const WebLayer* ImageBuffer::platformLayer() const
{ {
return m_surface->layer(); return m_surface->layer();
......
...@@ -82,7 +82,8 @@ public: ...@@ -82,7 +82,8 @@ public:
bool isExpensiveToPaint() const { return m_surface->isExpensiveToPaint(); } bool isExpensiveToPaint() const { return m_surface->isExpensiveToPaint(); }
bool isSurfaceValid() const; bool isSurfaceValid() const;
bool restoreSurface() const; bool restoreSurface() const;
void didDraw(const FloatRect& rect) const { m_surface->didDraw(rect); } void didDraw(const FloatRect&) const;
bool wasDrawnToAfterSnapshot() const { return m_snapshotState == DrawnToAfterSnapshot; }
void setFilterQuality(SkFilterQuality filterQuality) { m_surface->setFilterQuality(filterQuality); } void setFilterQuality(SkFilterQuality filterQuality) { m_surface->setFilterQuality(filterQuality); }
void setIsHidden(bool hidden) { m_surface->setIsHidden(hidden); } void setIsHidden(bool hidden) { m_surface->setIsHidden(hidden); }
...@@ -138,6 +139,12 @@ public: ...@@ -138,6 +139,12 @@ public:
private: private:
ImageBuffer(PassOwnPtr<ImageBufferSurface>); ImageBuffer(PassOwnPtr<ImageBufferSurface>);
enum SnapshotState {
InitialSnapshotState,
DidAcquireSnapshot,
DrawnToAfterSnapshot,
};
mutable SnapshotState m_snapshotState;
OwnPtr<ImageBufferSurface> m_surface; OwnPtr<ImageBufferSurface> m_surface;
ImageBufferClient* m_client; ImageBufferClient* m_client;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment