Record SkCanvas::flush().
We can record multiple frames in an .skp by recording SkCanvas::flush().
This should make SkPictures, SkLiteDL, and .skp files all record flush().
Change-Id: I6cf6e0e4ef993530d9f92fa168a53702ffce7d5e
Reviewed-on: https://skia-review.googlesource.com/34081
Reviewed-by: Derek Sollenberger <djsollen@google.com>
Commit-Queue: Mike Klein <mtklein@chromium.org>
diff --git a/src/core/SkLiteDL.cpp b/src/core/SkLiteDL.cpp
index 1565dae..c5144e5 100644
--- a/src/core/SkLiteDL.cpp
+++ b/src/core/SkLiteDL.cpp
@@ -47,8 +47,8 @@
}
namespace {
-#define TYPES(M) \
- M(SetDrawFilter) M(Save) M(Restore) M(SaveLayer) \
+#define TYPES(M) \
+ M(SetDrawFilter) M(Flush) M(Save) M(Restore) M(SaveLayer) \
M(Concat) M(SetMatrix) M(Translate) \
M(ClipPath) M(ClipRect) M(ClipRRect) M(ClipRegion) \
M(DrawPaint) M(DrawPath) M(DrawRect) M(DrawRegion) M(DrawOval) M(DrawArc) \
@@ -81,6 +81,11 @@
}
};
+ struct Flush final : Op {
+ static const auto kType = Type::Flush;
+ void draw(SkCanvas* c, const SkMatrix&) const { c->flush(); }
+ };
+
struct Save final : Op {
static const auto kType = Type::Save;
void draw(SkCanvas* c, const SkMatrix&) const { c->save(); }
@@ -530,6 +535,8 @@
}
#endif
+void SkLiteDL::flush() { this->push<Flush>(0); }
+
void SkLiteDL:: save() { this->push <Save>(0); }
void SkLiteDL::restore() { this->push<Restore>(0); }
void SkLiteDL::saveLayer(const SkRect* bounds, const SkPaint* paint,
diff --git a/src/core/SkLiteDL.h b/src/core/SkLiteDL.h
index 31ef38e..6d63657 100644
--- a/src/core/SkLiteDL.h
+++ b/src/core/SkLiteDL.h
@@ -29,6 +29,8 @@
void setDrawFilter(SkDrawFilter*);
#endif
+ void flush();
+
void save();
void saveLayer(const SkRect*, const SkPaint*, const SkImageFilter*, const SkImage*,
const SkMatrix*, SkCanvas::SaveLayerFlags);
diff --git a/src/core/SkLiteRecorder.cpp b/src/core/SkLiteRecorder.cpp
index dbee48e..bd41ff3 100644
--- a/src/core/SkLiteRecorder.cpp
+++ b/src/core/SkLiteRecorder.cpp
@@ -29,6 +29,8 @@
}
#endif
+void SkLiteRecorder::onFlush() { fDL->flush(); }
+
void SkLiteRecorder::willSave() { fDL->save(); }
SkCanvas::SaveLayerStrategy SkLiteRecorder::getSaveLayerStrategy(const SaveLayerRec& rec) {
fDL->saveLayer(rec.fBounds, rec.fPaint, rec.fBackdrop, rec.fClipMask, rec.fClipMatrix,
diff --git a/src/core/SkLiteRecorder.h b/src/core/SkLiteRecorder.h
index 4d49eb5..92b425b 100644
--- a/src/core/SkLiteRecorder.h
+++ b/src/core/SkLiteRecorder.h
@@ -27,6 +27,8 @@
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
void willRestore() override;
+ void onFlush() override;
+
void didConcat(const SkMatrix&) override;
void didSetMatrix(const SkMatrix&) override;
void didTranslate(SkScalar, SkScalar) override;
diff --git a/src/core/SkPictureFlat.h b/src/core/SkPictureFlat.h
index 3c257b9..866c707 100644
--- a/src/core/SkPictureFlat.h
+++ b/src/core/SkPictureFlat.h
@@ -95,7 +95,9 @@
DRAW_REGION,
DRAW_VERTICES_OBJECT,
- LAST_DRAWTYPE_ENUM = DRAW_VERTICES_OBJECT
+ FLUSH,
+
+ LAST_DRAWTYPE_ENUM = FLUSH
};
// In the 'match' method, this constant will match any flavor of DRAW_BITMAP*
diff --git a/src/core/SkPicturePlayback.cpp b/src/core/SkPicturePlayback.cpp
index 9ebb178..c0adaaa 100644
--- a/src/core/SkPicturePlayback.cpp
+++ b/src/core/SkPicturePlayback.cpp
@@ -134,9 +134,12 @@
SkASSERT(size >= 4);
reader->skip(size - 4);
} break;
+ case FLUSH:
+ canvas->flush();
+ break;
case CLIP_PATH: {
- const SkPath& path = fPictureData->getPath(reader);
- uint32_t packed = reader->readInt();
+ const SkPath& path = fPictureData->getPath(reader);
+ uint32_t packed = reader->readInt();
SkClipOp clipOp = ClipParams_unpackRegionOp(reader, packed);
bool doAA = ClipParams_unpackDoAA(packed);
size_t offsetToRestore = reader->readInt();
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index 4421633..2ebe7bb 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -42,6 +42,12 @@
///////////////////////////////////////////////////////////////////////////////
+void SkPictureRecord::onFlush() {
+ size_t size = sizeof(kUInt32Size);
+ size_t initialOffset = this->addDraw(FLUSH, &size);
+ this->validate(initialOffset, size);
+}
+
void SkPictureRecord::willSave() {
// record the offset to us, making it non-positive to distinguish a save
// from a clip entry.
diff --git a/src/core/SkPictureRecord.h b/src/core/SkPictureRecord.h
index 9a93bf9..f3d991a 100644
--- a/src/core/SkPictureRecord.h
+++ b/src/core/SkPictureRecord.h
@@ -157,6 +157,8 @@
sk_sp<SkSurface> onNewSurface(const SkImageInfo&, const SkSurfaceProps&) override;
bool onPeekPixels(SkPixmap*) override { return false; }
+ void onFlush() override;
+
void willSave() override;
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
void willRestore() override;
diff --git a/src/core/SkRecordDraw.cpp b/src/core/SkRecordDraw.cpp
index df68f8a..56bde16 100644
--- a/src/core/SkRecordDraw.cpp
+++ b/src/core/SkRecordDraw.cpp
@@ -73,6 +73,7 @@
template <> void Draw::draw(const NoOp&) {}
#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
+DRAW(Flush, flush());
DRAW(Restore, restore());
DRAW(Save, save());
DRAW(SaveLayer, saveLayer(SkCanvas::SaveLayerRec(r.bounds,
@@ -388,6 +389,8 @@
}
}
+ Bounds bounds(const Flush&) const { return fCurrentClipBounds; }
+
// FIXME: this method could use better bounds
Bounds bounds(const DrawText&) const { return fCurrentClipBounds; }
diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp
index 1eeef53..3d53e93 100644
--- a/src/core/SkRecorder.cpp
+++ b/src/core/SkRecorder.cpp
@@ -346,6 +346,10 @@
APPEND(DrawAnnotation, rect, SkString(key), sk_ref_sp(value));
}
+void SkRecorder::onFlush() {
+ APPEND(Flush);
+}
+
void SkRecorder::willSave() {
APPEND(Save);
}
diff --git a/src/core/SkRecorder.h b/src/core/SkRecorder.h
index 04e75ed..382048f 100644
--- a/src/core/SkRecorder.h
+++ b/src/core/SkRecorder.h
@@ -53,6 +53,8 @@
// Make SkRecorder forget entirely about its SkRecord*; all calls to SkRecorder will fail.
void forgetRecord();
+ void onFlush() override;
+
void willSave() override;
SaveLayerStrategy getSaveLayerStrategy(const SaveLayerRec&) override;
void willRestore() override {}
diff --git a/src/core/SkRecords.h b/src/core/SkRecords.h
index 8821a3e..bbac445 100644
--- a/src/core/SkRecords.h
+++ b/src/core/SkRecords.h
@@ -47,6 +47,7 @@
// you keep them semantically grouped, especially the Draws. It's also nice to leave NoOp at 0.
#define SK_RECORD_TYPES(M) \
M(NoOp) \
+ M(Flush) \
M(Restore) \
M(Save) \
M(SaveLayer) \
@@ -174,6 +175,7 @@
};
RECORD(NoOp, 0);
+RECORD(Flush, 0);
RECORD(Restore, 0,
SkIRect devBounds;
TypedMatrix matrix);
diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp
index d407fc0..799405e 100644
--- a/tests/PictureTest.cpp
+++ b/tests/PictureTest.cpp
@@ -1171,3 +1171,25 @@
pic = recorder.finishRecordingAsPicture();
REPORTER_ASSERT(r, pic->cullRect() == SkRect::MakeLargest());
}
+
+DEF_TEST(Picture_RecordsFlush, r) {
+ SkPictureRecorder recorder;
+
+ auto canvas = recorder.beginRecording(SkRect::MakeWH(100,100));
+ for (int i = 0; i < 10; i++) {
+ canvas->clear(0);
+ for (int j = 0; j < 10; j++) {
+ canvas->drawRect(SkRect::MakeXYWH(i*10,j*10,10,10), SkPaint());
+ }
+ canvas->flush();
+ }
+
+ // Did we record the flushes?
+ auto pic = recorder.finishRecordingAsPicture();
+ REPORTER_ASSERT(r, pic->approximateOpCount() == 120); // 10 clears, 100 draws, 10 flushes
+
+ // Do we serialize and deserialize flushes?
+ auto skp = pic->serialize();
+ auto back = SkPicture::MakeFromData(skp->data(), skp->size());
+ REPORTER_ASSERT(r, back->approximateOpCount() == pic->approximateOpCount());
+}
diff --git a/tests/SkLiteDLTest.cpp b/tests/SkLiteDLTest.cpp
index 514464a..d719c0b 100644
--- a/tests/SkLiteDLTest.cpp
+++ b/tests/SkLiteDLTest.cpp
@@ -51,3 +51,14 @@
c->drawRect(SkRect{0,0,9,9}, SkPaint{});
c->restore();
}
+
+DEF_TEST(SkLiteRecorder_RecordsFlush, r) {
+ SkLiteDL dl;
+
+ SkLiteRecorder canvas;
+ canvas.reset(&dl, {0,0,100,100});
+
+ REPORTER_ASSERT(r, dl.empty());
+ canvas.flush();
+ REPORTER_ASSERT(r, !dl.empty());
+}