aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar yunchao.he <yunchao.he@intel.com>2014-09-14 18:59:04 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-09-14 18:59:04 -0700
commit8e45c3777d886ba3fe239bb549d06b0693692152 (patch)
tree4beac796cef0ce3d6278985c0728478fd8a43622 /src
parentabaef86f2b37d8a939506a2076da07f6db456951 (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.cpp13
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