Eager or Lazy evaluation of sub-drawings for SkDeferredCanvas.
authorHerb Derby <herb@google.com>
Fri, 17 Mar 2017 19:51:53 +0000 (15:51 -0400)
committerSkia Commit-Bot <skia-commit-bot@chromium.org>
Mon, 20 Mar 2017 15:15:33 +0000 (15:15 +0000)
Allow evaluation choice of Lazy or Eager evaluation for SkDeferredCanvas.

Eager is used for drawing to a non-recording canvas to reduce the number of
all operations.

Lazy is used for drawing to a recording canvas to reduce the amount decode/encode
that happens.

R=reed@google.com

Change-Id: I7837c4f6e5911c153e0796162e1170edbc34839e
Reviewed-on: https://skia-review.googlesource.com/9839
Commit-Queue: Herb Derby <herb@google.com>
Reviewed-by: Mike Reed <reed@google.com>
dm/DMSrcSink.cpp
samplecode/SampleApp.cpp
src/utils/SkDeferredCanvas.cpp
src/utils/SkDeferredCanvas.h
tests/CanvasTest.cpp
tools/dump_record.cpp

index 14d5552789dd13c895f0f36cd9a940acee9b19c0..eb9ba41d968c02f4730306e9d7bd3cdf302f873b 100644 (file)
@@ -1661,7 +1661,7 @@ Error ViaPicture::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkSt
 Error ViaDefer::draw(const Src& src, SkBitmap* bitmap, SkWStream* stream, SkString* log) const {
     auto size = src.size();
     return draw_to_canvas(fSink.get(), bitmap, stream, log, size, [&](SkCanvas* canvas) -> Error {
-        SkDeferredCanvas deferred(canvas);
+        SkDeferredCanvas deferred(canvas, SkDeferredCanvas::kEager);
         return src.draw(&deferred);
     });
 }
index 9d5ea0bf5e254850463d3b9830b9ef1e3b2a190e..79023a0b997df185aee230eed09a972bab94192d 100644 (file)
@@ -1088,7 +1088,7 @@ void SampleWindow::draw(SkCanvas* canvas) {
     if (kNo_Tiling == fTilingMode) {
         SkDebugfDumper dumper;
         SkDumpCanvas dump(&dumper);
-        SkDeferredCanvas deferred(canvas);
+        SkDeferredCanvas deferred(canvas, SkDeferredCanvas::kEager);
         SkCanvas* c = fUseDeferredCanvas ? &deferred : canvas;
         this->INHERITED::draw(c); // no looping or surfaces needed
     } else {
index ecd5495e8fefe3a92577c54caff0c9b97c76558d..975f496d3b0e3cc47a01fb1ccf9412a9e993b83d 100644 (file)
@@ -8,6 +8,7 @@
 #include "SkDeferredCanvas.h"
 #include "SkDrawable.h"
 #include "SkPath.h"
+#include "SkRSXform.h"
 #include "SkRRect.h"
 #include "SkSurface.h"
 #include "SkTextBlob.h"
@@ -45,8 +46,11 @@ void SkDeferredCanvas::Rec::setConcat(const SkMatrix& m) {
 
 ///////////////////////////////////////////////////////////////////////////////////////////////////
 
-SkDeferredCanvas::SkDeferredCanvas(SkCanvas* canvas)
-    : INHERITED(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height()) {
+SkDeferredCanvas::SkDeferredCanvas(SkCanvas* canvas, EvalType evalType)
+    : INHERITED(canvas->getBaseLayerSize().width(), canvas->getBaseLayerSize().height())
+    , fCanvas(nullptr)  // must be here for reset to work.
+    , fEvalType(evalType)
+{
     this->reset(canvas);
 }
 
@@ -493,23 +497,23 @@ void SkDeferredCanvas::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScal
 #include "SkCanvasPriv.h"
 void SkDeferredCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix,
                                  const SkPaint* paint) {
-#if 0
-    SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
-    picture->playback(this);
-#else
-    this->flush_before_saves();
-    fCanvas->drawPicture(picture, matrix, paint);
-#endif
+    if (kEager == fEvalType) {
+        SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect());
+        picture->playback(this);
+    } else {
+        this->flush_before_saves();
+        fCanvas->drawPicture(picture, matrix, paint);
+    }
 }
 
 void SkDeferredCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
-    // TODO: investigate culling and applying concat to the matrix
-#if 0
-    drawable->draw(this, matrix);
-#else
-    this->flush_before_saves();
-    fCanvas->drawDrawable(drawable, matrix);
-#endif
+    if (kEager == fEvalType) {
+        // TODO: investigate culling and applying concat to the matrix
+        drawable->draw(this, matrix);
+    } else {
+        this->flush_before_saves();
+        fCanvas->drawDrawable(drawable, matrix);
+    }
 }
 
 void SkDeferredCanvas::onDrawAtlas(const SkImage* image, const SkRSXform xform[],
index b2bae1b94384b5e2e16fa4937f0e748aa0582a0b..eb07965799f2b4f3f2544411663b7ad19fdd87cc 100644 (file)
 
 class SK_API SkDeferredCanvas : public SkNoDrawCanvas {
 public:
-    SkDeferredCanvas(SkCanvas* = nullptr);
+    enum EvalType {kEager, kLazy};
+    // There are two strategies for evaluating of sub-drawings (pictures and drawables).
+    // * kEager - a sub-drawing is expanded using the using the SkDeferredCanvas. This has
+    //            the advantage of optimizing the sub drawing, and is used when the underlying
+    //            SkCanvas is drawing and not recording.
+    // * kLazy  - a sub-drawing is not expanded, but passed directly to the underlying SkCanvas.
+    //            This has the advantage of not expanding the sub drawing and then immediately
+    //            re-encoding it, and is used for recording canvases.
+    SkDeferredCanvas(SkCanvas*, EvalType);
     ~SkDeferredCanvas() override;
 
     void reset(SkCanvas*);
@@ -101,8 +109,6 @@ protected:
     class Iter;
 
 private:
-    SkCanvas* fCanvas{nullptr};
-
     enum Type {
         kSave_Type,
         kClipRect_Type,
@@ -127,7 +133,6 @@ private:
         }
         void setConcat(const SkMatrix&);
     };
-    SkTDArray<Rec>  fRecs;
 
     void push_save();
     void push_cliprect(const SkRect&);
@@ -144,6 +149,10 @@ private:
 
     void internal_flush_translate(SkScalar* x, SkScalar* y, const SkRect* boundsOrNull);
 
+    SkTDArray<Rec> fRecs;
+    SkCanvas*      fCanvas;
+    const EvalType fEvalType;
+
     typedef SkNoDrawCanvas INHERITED;
 };
 
index f6b275fccc62aae85f3a0491102e25720132c86f..cfdce628ca13b11e2cb3f702f14877eb50d6c2f9 100644 (file)
@@ -741,7 +741,7 @@ DEF_TEST(DeferredCanvas, r) {
     SkDebugfDumper dumper;
     SkDumpCanvas dumpC(&dumper);
 
-    SkDeferredCanvas canvas(&dumpC);
+    SkDeferredCanvas canvas(&dumpC, SkDeferredCanvas::kEager);
 
     SkPaint paint;
 //    paint.setShader(SkShader::MakeColorShader(SK_ColorRED));
index 98845e56ce2ea4a0bce23ea3275c894bfe6bf8c0..c1b87e7535efd275ba80fa48fac4c82ad678c65c 100644 (file)
@@ -57,7 +57,8 @@ int main(int argc, char** argv) {
         }
         if (FLAGS_defer) {
             SkPictureRecorder recorder;
-            SkDeferredCanvas deferred(recorder.beginRecording(src->cullRect()));
+            SkDeferredCanvas deferred(recorder.beginRecording(src->cullRect()),
+                                      SkDeferredCanvas::kEager);
             src->playback(&deferred);
             src = recorder.finishRecordingAsPicture();
         }