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
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)
{
m_size = size;
......
......@@ -138,6 +138,7 @@ public:
AffineTransform baseTransform() const;
bool is3D() const;
bool isAnimated2D() const;
bool hasImageBuffer() const { return m_imageBuffer; }
void discardImageBuffer();
......
......@@ -1353,6 +1353,20 @@ void CanvasRenderingContext2D::drawImageInternal(SkCanvas* c, CanvasImageSource*
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,
float sx, float sy, float sw, float sh,
float dx, float dy, float dw, float dh, ExceptionState& exceptionState)
......@@ -1388,12 +1402,7 @@ void CanvasRenderingContext2D::drawImage(CanvasImageSource* imageSource,
if (srcRect.isEmpty())
return;
// 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())
if (shouldDisableDeferral(imageSource))
canvas()->disableDeferral();
validateStateStack();
......
......@@ -76,7 +76,8 @@ PassOwnPtr<ImageBuffer> ImageBuffer::create(const IntSize& size, OpacityMode opa
}
ImageBuffer::ImageBuffer(PassOwnPtr<ImageBufferSurface> surface)
: m_surface(surface)
: m_snapshotState(InitialSnapshotState)
, m_surface(surface)
, m_client(0)
{
m_surface->setImageBuffer(this);
......@@ -149,6 +150,9 @@ void ImageBuffer::resetCanvas(SkCanvas* canvas) const
PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const
{
if (m_snapshotState == InitialSnapshotState)
m_snapshotState = DidAcquireSnapshot;
if (!isSurfaceValid())
return nullptr;
return m_surface->newImageSnapshot();
......@@ -156,14 +160,19 @@ PassRefPtr<SkImage> ImageBuffer::newSkImageSnapshot() const
PassRefPtr<Image> ImageBuffer::newImageSnapshot() const
{
if (!isSurfaceValid())
return nullptr;
RefPtr<SkImage> snapshot = m_surface->newImageSnapshot();
RefPtr<SkImage> snapshot = newSkImageSnapshot();
if (!snapshot)
return nullptr;
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
{
return m_surface->layer();
......
......@@ -82,7 +82,8 @@ public:
bool isExpensiveToPaint() const { return m_surface->isExpensiveToPaint(); }
bool isSurfaceValid() 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 setIsHidden(bool hidden) { m_surface->setIsHidden(hidden); }
......@@ -138,6 +139,12 @@ public:
private:
ImageBuffer(PassOwnPtr<ImageBufferSurface>);
enum SnapshotState {
InitialSnapshotState,
DidAcquireSnapshot,
DrawnToAfterSnapshot,
};
mutable SnapshotState m_snapshotState;
OwnPtr<ImageBufferSurface> m_surface;
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