aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkLiteRecorder.cpp
diff options
context:
space:
mode:
authorGravatar mtklein <mtklein@chromium.org>2016-08-06 12:51:51 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-08-06 12:51:51 -0700
commit9c5052f16b249d2b7674ea86bd24ed0038ccc61f (patch)
treedb2e05f246b2e7d65c91275943e1ada80a4856f1 /src/core/SkLiteRecorder.cpp
parentc6f411e72b1fea6608f540f64a57bcacbe3378cd (diff)
SkLite*
SkLiteRecorder, a new SkCanvas, fills out SkLiteDL, a new SkDrawable. This SkDrawable is a display list similar to SkRecord and SkBigPicture / SkRecordedDrawable, but with a few new design points inspired by Android and slimming paint: 1) SkLiteDL is structured as one big contiguous array rather than the two layer structure of SkRecord. This trades away flexibility and large-op-count performance for better data locality for small to medium size pictures. 2) We keep a global freelist of SkLiteDLs, both reusing the SkLiteDL struct itself and its contiguous byte array. This keeps the expected number of mallocs per display list allocation <1 (really, ~0) for cyclical use cases. These two together mean recording is faster. Measuring against the code we use at head, SkLiteRecorder trends about ~3x faster across various size pictures, matching speed at 0 draws and beating the special-case 1-draw pictures we have today. (I.e. we won't need those special case implementations anymore, because they're slower than this new generic code.) This new strategy records 10 drawRects() in about the same time the old strategy took for 2. This strategy stays the winner until at least 500 drawRect()s on my laptop, where I stopped checking. A simpler alternative to freelisting is also possible (but not implemented here), where we allow the client to manually reset() an SkLiteDL for reuse when its refcnt is 1. That's essentially what we're doing with the freelist, except tracking what's available for reuse globally instead of making the client do it. This code is not fully capable yet, but most of the key design points are there. The internal structure of SkLiteDL is the area I expect to be most volatile (anything involving Op), but its interface and the whole of SkLiteRecorder ought to be just about done. You can run nanobench --match picture_overhead as a demo. Everything it exercises is fully fleshed out, so what it tests is an apples-to-apples comparison as far as recording costs go. I have not yet compared playback performance. It should be simple to wrap this into an SkPicture subclass if we want. I won't start proposing we replace anything old with anything new quite yet until I have more ducks in a row, but this does look pretty promising (similar to the SkRecord over old SkPicture change a couple years ago) and I'd like to land, experiment, iterate, especially with an eye toward Android. BUG=skia: GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2213333002 Review-Url: https://codereview.chromium.org/2213333002
Diffstat (limited to 'src/core/SkLiteRecorder.cpp')
-rw-r--r--src/core/SkLiteRecorder.cpp188
1 files changed, 188 insertions, 0 deletions
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
new file mode 100644
index 0000000000..00441fdf84
--- /dev/null
+++ b/src/core/SkLiteRecorder.cpp
@@ -0,0 +1,188 @@
+/*
+ * Copyright 2016 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkLiteDL.h"
+#include "SkLiteRecorder.h"
+#include "SkSurface.h"
+
+SkLiteRecorder::SkLiteRecorder()
+ : SkCanvas({0,0,1,1}, SkCanvas::kConservativeRasterClip_InitFlag)
+ , fDL(nullptr) {}
+
+void SkLiteRecorder::reset(SkLiteDL* dl) {
+ this->resetForNextPicture(dl->getBounds().roundOut());
+ fDL = dl;
+}
+
+sk_sp<SkSurface> SkLiteRecorder::onNewSurface(const SkImageInfo&, const SkSurfaceProps&) {
+ return nullptr;
+}
+
+void SkLiteRecorder::willSave() { fDL->save(); }
+SkCanvas::SaveLayerStrategy SkLiteRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
+ fDL->saveLayer(rec.fBounds, rec.fPaint, rec.fBackdrop, rec.fSaveLayerFlags);
+ return SkCanvas::kNoLayer_SaveLayerStrategy;
+}
+void SkLiteRecorder::willRestore() { fDL->restore(); }
+
+void SkLiteRecorder::didConcat (const SkMatrix& matrix) { fDL-> concat(matrix); }
+void SkLiteRecorder::didSetMatrix(const SkMatrix& matrix) { fDL->setMatrix(matrix); }
+
+void SkLiteRecorder::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle style) {
+ fDL->clipRect(rect, op, style==kSoft_ClipEdgeStyle);
+ SkCanvas::onClipRect(rect, op, style);
+}
+void SkLiteRecorder::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle style) {
+ fDL->clipRRect(rrect, op, style==kSoft_ClipEdgeStyle);
+ SkCanvas::onClipRRect(rrect, op, style);
+}
+void SkLiteRecorder::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle style) {
+ fDL->clipPath(path, op, style==kSoft_ClipEdgeStyle);
+ SkCanvas::onClipPath(path, op, style);
+}
+void SkLiteRecorder::onClipRegion(const SkRegion& region, SkRegion::Op op) {
+ fDL->clipRegion(region, op);
+ SkCanvas::onClipRegion(region, op);
+}
+
+void SkLiteRecorder::onDrawPaint(const SkPaint& paint) {
+ fDL->drawPaint(paint);
+}
+void SkLiteRecorder::onDrawPath(const SkPath& path, const SkPaint& paint) {
+ fDL->drawPath(path, paint);
+}
+void SkLiteRecorder::onDrawRect(const SkRect& rect, const SkPaint& paint) {
+ fDL->drawRect(rect, paint);
+}
+void SkLiteRecorder::onDrawOval(const SkRect& oval, const SkPaint& paint) {
+ fDL->drawOval(oval, paint);
+}
+void SkLiteRecorder::onDrawRRect(const SkRRect& rrect, const SkPaint& paint) {
+ fDL->drawRRect(rrect, paint);
+}
+void SkLiteRecorder::onDrawDRRect(const SkRRect& out, const SkRRect& in, const SkPaint& paint) {
+ fDL->drawDRRect(out, in, paint);
+}
+
+void SkLiteRecorder::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
+ fDL->drawDrawable(drawable, matrix);
+}
+void SkLiteRecorder::onDrawPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ fDL->drawPicture(picture, matrix, paint);
+}
+void SkLiteRecorder::onDrawAnnotation(const SkRect& rect, const char key[], SkData* val) {
+ fDL->drawAnnotation(rect, key, val);
+}
+
+void SkLiteRecorder::onDrawText(const void* text, size_t bytes,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ fDL->drawText(text, bytes, x, y, paint);
+}
+void SkLiteRecorder::onDrawPosText(const void* text, size_t bytes,
+ const SkPoint pos[],
+ const SkPaint& paint) {
+ fDL->drawPosText(text, bytes, pos, paint);
+}
+void SkLiteRecorder::onDrawPosTextH(const void* text, size_t bytes,
+ const SkScalar xs[], SkScalar y,
+ const SkPaint& paint) {
+ fDL->drawPosTextH(text, bytes, xs, y, paint);
+}
+void SkLiteRecorder::onDrawTextOnPath(const void* text, size_t bytes,
+ const SkPath& path, const SkMatrix* matrix,
+ const SkPaint& paint) {
+ fDL->drawTextOnPath(text, bytes, path, matrix, paint);
+}
+void SkLiteRecorder::onDrawTextRSXform(const void* text, size_t bytes,
+ const SkRSXform xform[], const SkRect* cull,
+ const SkPaint& paint) {
+ fDL->drawTextRSXForm(text, bytes, xform, cull, paint);
+}
+void SkLiteRecorder::onDrawTextBlob(const SkTextBlob* blob,
+ SkScalar x, SkScalar y,
+ const SkPaint& paint) {
+ fDL->drawTextBlob(blob, x,y, paint);
+}
+
+void SkLiteRecorder::onDrawBitmap(const SkBitmap& bm,
+ SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ fDL->drawBitmap(bm, x,y, paint);
+}
+void SkLiteRecorder::onDrawBitmapNine(const SkBitmap& bm,
+ const SkIRect& center, const SkRect& dst,
+ const SkPaint* paint) {
+ fDL->drawBitmapNine(bm, center, dst, paint);
+}
+void SkLiteRecorder::onDrawBitmapRect(const SkBitmap& bm,
+ const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) {
+ fDL->drawBitmapRect(bm, src, dst, paint, constraint == kStrict_SrcRectConstraint);
+}
+
+void SkLiteRecorder::onDrawImage(const SkImage* img,
+ SkScalar x, SkScalar y,
+ const SkPaint* paint) {
+ fDL->drawImage(img, x,y, paint);
+}
+void SkLiteRecorder::onDrawImageNine(const SkImage* img,
+ const SkIRect& center, const SkRect& dst,
+ const SkPaint* paint) {
+ fDL->drawImageNine(img, center, dst, paint);
+}
+void SkLiteRecorder::onDrawImageRect(const SkImage* img,
+ const SkRect* src, const SkRect& dst,
+ const SkPaint* paint, SrcRectConstraint constraint) {
+ fDL->drawImageRect(img, src, dst, paint, constraint == kStrict_SrcRectConstraint);
+}
+void SkLiteRecorder::onDrawImageLattice(const SkImage* img,
+ const SkCanvas::Lattice& lattice, const SkRect& dst,
+ const SkPaint* paint) {
+ fDL->drawImageLattice(img, lattice, dst, paint);
+}
+
+
+void SkLiteRecorder::onDrawPatch(const SkPoint cubics[12],
+ const SkColor colors[4], const SkPoint texCoords[4],
+ SkXfermode* xfermode, const SkPaint& paint) {
+ fDL->drawPatch(cubics, colors, texCoords, xfermode, paint);
+}
+void SkLiteRecorder::onDrawPoints(SkCanvas::PointMode mode,
+ size_t count, const SkPoint pts[],
+ const SkPaint& paint) {
+ fDL->drawPoints(mode, count, pts, paint);
+}
+void SkLiteRecorder::onDrawVertices(SkCanvas::VertexMode mode,
+ int count, const SkPoint vertices[],
+ const SkPoint texs[], const SkColor colors[],
+ SkXfermode* xfermode,
+ const uint16_t indices[], int indexCount,
+ const SkPaint& paint) {
+ fDL->drawVertices(mode, count, vertices, texs, colors, xfermode, indices, indexCount, paint);
+}
+void SkLiteRecorder::onDrawAtlas(const SkImage* atlas,
+ const SkRSXform xforms[],
+ const SkRect texs[],
+ const SkColor colors[],
+ int count,
+ SkXfermode::Mode xfermode,
+ const SkRect* cull,
+ const SkPaint* paint) {
+ fDL->drawAtlas(atlas, xforms, texs, colors, count, xfermode, cull, paint);
+}
+
+void SkLiteRecorder::didTranslateZ(SkScalar dz) {
+ fDL->translateZ(dz);
+}
+void SkLiteRecorder::onDrawShadowedPicture(const SkPicture* picture,
+ const SkMatrix* matrix,
+ const SkPaint* paint) {
+ fDL->drawShadowedPicture(picture, matrix, paint);
+}