diff options
author | yunchao.he <yunchao.he@intel.com> | 2014-09-14 18:59:04 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2014-09-14 18:59:04 -0700 |
commit | 8e45c3777d886ba3fe239bb549d06b0693692152 (patch) | |
tree | 4beac796cef0ce3d6278985c0728478fd8a43622 /src | |
parent | abaef86f2b37d8a939506a2076da07f6db456951 (diff) |
Picture Recording: fix the performance bottleneck in SkDeferredCanvas::isFullFrame
blink skips all pending commands during picture recording if it is drawing an opaque full-frame
geometry or image. This may improve performance for some edge cases. To recognize an opaque
full-frame drawing should be cheap enough. Otherwise, the overhead will offset the improvement.
Unfortunately, data from perf for content_shell on Nexus7 shows that SkDeferredCanvas::isFullFrame
is far from cheap. Table below shows that how much isFullFrame() costs in the whole render process.
benchmark percentage
my local benchmark(draw 1000 sprites) 4.1%
speedReading 2.8%
FishIETank(1000 fishes) 1.5%
GUIMark3 Bitmap 2.0%
By contrast, real recording (SkGPipeCanvas::drawBitmapRectToRect) and real rasterization
(GrDrawTarget::drawRect) cost ~4% and ~6% in the whole render process respectively. Apparently,
SkDeferredCanvas::isFullFrame() is nontrivial.
getDeviceSize() is the main contributor to this hotspot. The change simply save the canvasSize and
reuse it among drawings if it is not a fresh frame. This change cut off ~65% (or improved ~2 times)
of isFullFrame().
telemetry smoothness canvas_tough_test didn't show obvious improvement or regression.
BUG=411166
R=junov@chromium.org, tomhudson@google.com, reed@google.com
Author: yunchao.he@intel.com
Review URL: https://codereview.chromium.org/545813002
Diffstat (limited to 'src')
-rw-r--r-- | src/utils/SkDeferredCanvas.cpp | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/utils/SkDeferredCanvas.cpp b/src/utils/SkDeferredCanvas.cpp index b46e92a4a0..cce5dde538 100644 --- a/src/utils/SkDeferredCanvas.cpp +++ b/src/utils/SkDeferredCanvas.cpp @@ -526,6 +526,8 @@ SkDeferredCanvas::SkDeferredCanvas(SkDeferredDevice* device) : SkCanvas (device) void SkDeferredCanvas::init() { fBitmapSizeThreshold = kDeferredCanvasBitmapSizeThreshold; fDeferredDrawing = true; // On by default + fCachedCanvasSize.setEmpty(); + fCachedCanvasSizeDirty = true; } void SkDeferredCanvas::setMaxRecordingStorage(size_t maxStorage) { @@ -589,6 +591,14 @@ bool SkDeferredCanvas::isFreshFrame() const { return this->getDeferredDevice()->isFreshFrame(); } +SkISize SkDeferredCanvas::getCanvasSize() const { + if (fCachedCanvasSizeDirty) { + fCachedCanvasSize = this->getBaseLayerSize(); + fCachedCanvasSizeDirty = false; + } + return fCachedCanvasSize; +} + bool SkDeferredCanvas::hasPendingCommands() const { return this->getDeferredDevice()->hasPendingCommands(); } @@ -609,6 +619,7 @@ SkSurface* SkDeferredCanvas::setSurface(SkSurface* surface) { // all pending commands, which can help to seamlessly recover from // a lost accelerated graphics context. deferredDevice->setSurface(surface); + fCachedCanvasSizeDirty = true; return surface; } @@ -632,7 +643,7 @@ SkImage* SkDeferredCanvas::newImageSnapshot() { bool SkDeferredCanvas::isFullFrame(const SkRect* rect, const SkPaint* paint) const { SkCanvas* canvas = this->drawingCanvas(); - SkISize canvasSize = this->getDeviceSize(); + SkISize canvasSize = this->getCanvasSize(); if (rect) { if (!canvas->getTotalMatrix().rectStaysRect()) { return false; // conservative |