diff options
-rw-r--r-- | bench/nanobench.cpp | 11 | ||||
-rw-r--r-- | include/core/SkPicture.h | 16 | ||||
-rw-r--r-- | src/core/SkBigPicture.cpp | 1 | ||||
-rw-r--r-- | src/core/SkBigPicture.h | 1 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 18 | ||||
-rw-r--r-- | src/core/SkMiniRecorder.cpp | 2 | ||||
-rw-r--r-- | src/core/SkPicturePriv.h | 28 | ||||
-rw-r--r-- | src/core/SkRecordedDrawable.cpp | 3 | ||||
-rw-r--r-- | src/core/SkRecorder.cpp | 4 | ||||
-rw-r--r-- | src/effects/SkPictureImageFilter.cpp | 3 | ||||
-rw-r--r-- | src/shaders/SkPictureShader.cpp | 4 | ||||
-rw-r--r-- | tests/ImageTest.cpp | 2 | ||||
-rw-r--r-- | tests/PictureTest.cpp | 25 | ||||
-rw-r--r-- | tests/SerializationTest.cpp | 3 | ||||
-rw-r--r-- | tools/DumpRecord.cpp | 3 |
15 files changed, 72 insertions, 52 deletions
diff --git a/bench/nanobench.cpp b/bench/nanobench.cpp index 1f275d8cc3..b9ecfa7b51 100644 --- a/bench/nanobench.cpp +++ b/bench/nanobench.cpp @@ -38,7 +38,6 @@ #include "SkLeanWindows.h" #include "SkOSFile.h" #include "SkOSPath.h" -#include "SkPicturePriv.h" #include "SkPictureRecorder.h" #include "SkSVGDOM.h" #include "SkScan.h" @@ -739,7 +738,8 @@ public: SkString name = SkOSPath::Basename(path.c_str()); fSourceType = "skp"; fBenchType = "recording"; - fSKPBytes = static_cast<double>(SkPicturePriv::ApproxBytesUsed(pic.get())); + fSKPBytes = static_cast<double>(pic->approximateBytesUsed()); + fSKPOps = pic->approximateOpCount(); return new RecordingBench(name.c_str(), pic.get(), FLAGS_bbh, FLAGS_lite); } @@ -753,7 +753,8 @@ public: SkString name = SkOSPath::Basename(path.c_str()); fSourceType = "skp"; fBenchType = "piping"; - fSKPBytes = static_cast<double>(SkPicturePriv::ApproxBytesUsed(pic.get())); + fSKPBytes = static_cast<double>(pic->approximateBytesUsed()); + fSKPOps = pic->approximateOpCount(); return new PipingBench(name.c_str(), pic.get()); } @@ -768,6 +769,7 @@ public: fSourceType = "skp"; fBenchType = "deserial"; fSKPBytes = static_cast<double>(data->size()); + fSKPOps = 0; return new DeserializePictureBench(name.c_str(), std::move(data)); } @@ -1061,6 +1063,7 @@ public: } if (0 == strcmp(fBenchType, "recording")) { log->metric("bytes", fSKPBytes); + log->metric("ops", fSKPOps); } } @@ -1090,7 +1093,7 @@ private: SkScalar fZoomMax; double fZoomPeriodMs; - double fSKPBytes; + double fSKPBytes, fSKPOps; const char* fSourceType; // What we're benching: bench, GM, SKP, ... const char* fBenchType; // How we bench it: micro, recording, playback, ... diff --git a/include/core/SkPicture.h b/include/core/SkPicture.h index d505a0a364..4887db928f 100644 --- a/include/core/SkPicture.h +++ b/include/core/SkPicture.h @@ -90,7 +90,18 @@ public: sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const; void serialize(SkWStream*, const SkSerialProcs* = nullptr) const; -protected: + /** + * Serialize to a buffer. + */ + void flatten(SkWriteBuffer&) const; + + /** Return the approximate number of operations in this picture. This + * number may be greater or less than the number of SkCanvas calls + * recorded: some calls may be recorded as more than one operation, or some + * calls may be optimized away. + */ + virtual int approximateOpCount() const = 0; + /** Returns the approximate byte size of this picture, not including large ref'd objects. */ virtual size_t approximateBytesUsed() const = 0; @@ -102,8 +113,6 @@ private: SkPicture(); friend class SkBigPicture; friend class SkEmptyPicture; - friend class SkPicturePriv; - friend class SkPictureRecorder; template <typename> friend class SkMiniPicture; void serialize(SkWStream*, const SkSerialProcs*, SkRefCntSet* typefaces) const; @@ -163,7 +172,6 @@ private: SkPictInfo createHeader() const; SkPictureData* backport() const; - void flatten(SkWriteBuffer&) const; mutable uint32_t fUniqueID; }; diff --git a/src/core/SkBigPicture.cpp b/src/core/SkBigPicture.cpp index e91f897525..2ae9248d47 100644 --- a/src/core/SkBigPicture.cpp +++ b/src/core/SkBigPicture.cpp @@ -54,6 +54,7 @@ void SkBigPicture::partialPlayback(SkCanvas* canvas, } SkRect SkBigPicture::cullRect() const { return fCullRect; } +int SkBigPicture::approximateOpCount() const { return fRecord->count(); } size_t SkBigPicture::approximateBytesUsed() const { size_t bytes = sizeof(*this) + fRecord->bytesUsed() + fApproxBytesUsedBySubPictures; if (fBBH) { bytes += fBBH->bytesUsed(); } diff --git a/src/core/SkBigPicture.h b/src/core/SkBigPicture.h index 3fc7071cf0..cbe492cc22 100644 --- a/src/core/SkBigPicture.h +++ b/src/core/SkBigPicture.h @@ -43,6 +43,7 @@ public: // SkPicture overrides void playback(SkCanvas*, AbortCallback*) const override; SkRect cullRect() const override; + int approximateOpCount() const override; size_t approximateBytesUsed() const override; const SkBigPicture* asSkBigPicture() const override { return this; } diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 4f43a936fa..49da8eb3a7 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -28,7 +28,7 @@ #include "SkNx.h" #include "SkPaintPriv.h" #include "SkPatchUtils.h" -#include "SkPicturePriv.h" +#include "SkPicture.h" #include "SkRasterClip.h" #include "SkRasterHandleAllocator.h" #include "SkRRect.h" @@ -2786,6 +2786,15 @@ void SkCanvas::drawTextOnPathHV(const void* text, size_t byteLength, /////////////////////////////////////////////////////////////////////////////// +/** + * This constant is trying to balance the speed of ref'ing a subpicture into a parent picture, + * against the playback cost of recursing into the subpicture to get at its actual ops. + * + * For now we pick a conservatively small value, though measurement (and other heuristics like + * the type of ops contained) may justify changing this value. + */ +#define kMaxPictureOpsToUnrollInsteadOfRef 1 + void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, const SkPaint* paint) { TRACE_EVENT0("skia", TRACE_FUNC); RETURN_ON_NULL(picture); @@ -2793,7 +2802,12 @@ void SkCanvas::drawPicture(const SkPicture* picture, const SkMatrix* matrix, con if (matrix && matrix->isIdentity()) { matrix = nullptr; } - this->onDrawPicture(picture, matrix, paint); + if (picture->approximateOpCount() <= kMaxPictureOpsToUnrollInsteadOfRef) { + SkAutoCanvasMatrixPaint acmp(this, matrix, paint, picture->cullRect()); + picture->playback(this); + } else { + this->onDrawPicture(picture, matrix, paint); + } } void SkCanvas::onDrawPicture(const SkPicture* picture, const SkMatrix* matrix, diff --git a/src/core/SkMiniRecorder.cpp b/src/core/SkMiniRecorder.cpp index 22b45fd0a9..6a2edf1f12 100644 --- a/src/core/SkMiniRecorder.cpp +++ b/src/core/SkMiniRecorder.cpp @@ -22,6 +22,7 @@ public: void playback(SkCanvas*, AbortCallback*) const override { } size_t approximateBytesUsed() const override { return sizeof(*this); } + int approximateOpCount() const override { return 0; } SkRect cullRect() const override { return SkRect::MakeEmpty(); } }; @@ -54,6 +55,7 @@ public: } size_t approximateBytesUsed() const override { return sizeof(*this); } + int approximateOpCount() const override { return 1; } SkRect cullRect() const override { return fCull; } private: diff --git a/src/core/SkPicturePriv.h b/src/core/SkPicturePriv.h deleted file mode 100644 index 5da3feaaa1..0000000000 --- a/src/core/SkPicturePriv.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef SkPicturePriv_DEFINED -#define SkPicturePriv_DEFINED - -#include "SkPicture.h" - -class SkWriteBuffer; - -class SkPicturePriv { -public: - static size_t ApproxBytesUsed(const SkPicture* pic) { - return pic->approximateBytesUsed(); - } - static const SkBigPicture* AsBigPicture(const SkPicture* pic) { - return pic->asSkBigPicture(); - } - static void Flatten(SkWriteBuffer& buffer, const SkPicture* pic) { - pic->flatten(buffer); - } -}; - -#endif diff --git a/src/core/SkRecordedDrawable.cpp b/src/core/SkRecordedDrawable.cpp index bead309118..be8a2cb07e 100644 --- a/src/core/SkRecordedDrawable.cpp +++ b/src/core/SkRecordedDrawable.cpp @@ -8,7 +8,6 @@ #include "SkMatrix.h" #include "SkPictureData.h" #include "SkPicturePlayback.h" -#include "SkPicturePriv.h" #include "SkPictureRecord.h" #include "SkPictureRecorder.h" #include "SkRecordedDrawable.h" @@ -34,7 +33,7 @@ SkPicture* SkRecordedDrawable::onNewPictureSnapshot() { size_t subPictureBytes = 0; for (int i = 0; pictList && i < pictList->count(); i++) { - subPictureBytes += SkPicturePriv::ApproxBytesUsed(pictList->begin()[i]); + subPictureBytes += pictList->begin()[i]->approximateBytesUsed(); } // SkBigPicture will take ownership of a ref on both fRecord and fBBH. // We're not willing to give up our ownership, so we must ref them for SkPicture. diff --git a/src/core/SkRecorder.cpp b/src/core/SkRecorder.cpp index 302b938f6c..9374b60264 100644 --- a/src/core/SkRecorder.cpp +++ b/src/core/SkRecorder.cpp @@ -9,7 +9,7 @@ #include "SkCanvasPriv.h" #include "SkImage.h" #include "SkPatchUtils.h" -#include "SkPicturePriv.h" +#include "SkPicture.h" #include "SkRecorder.h" #include "SkSurface.h" @@ -302,7 +302,7 @@ void SkRecorder::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y, void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) { if (fDrawPictureMode == Record_DrawPictureMode) { - fApproxBytesUsedBySubPictures += SkPicturePriv::ApproxBytesUsed(pic); + fApproxBytesUsedBySubPictures += pic->approximateBytesUsed(); APPEND(DrawPicture, this->copy(paint), sk_ref_sp(pic), matrix ? *matrix : SkMatrix::I()); } else { SkASSERT(fDrawPictureMode == Playback_DrawPictureMode); diff --git a/src/effects/SkPictureImageFilter.cpp b/src/effects/SkPictureImageFilter.cpp index d0ea6f3d66..304b91cf3c 100644 --- a/src/effects/SkPictureImageFilter.cpp +++ b/src/effects/SkPictureImageFilter.cpp @@ -11,7 +11,6 @@ #include "SkColorSpaceXformCanvas.h" #include "SkColorSpaceXformer.h" #include "SkImageSource.h" -#include "SkPicturePriv.h" #include "SkReadBuffer.h" #include "SkSpecialImage.h" #include "SkSpecialSurface.h" @@ -77,7 +76,7 @@ void SkPictureImageFilter::flatten(SkWriteBuffer& buffer) const { bool hasPicture = (fPicture != nullptr); buffer.writeBool(hasPicture); if (hasPicture) { - SkPicturePriv::Flatten(buffer, fPicture.get()); + fPicture->flatten(buffer); } buffer.writeRect(fCropRect); } diff --git a/src/shaders/SkPictureShader.cpp b/src/shaders/SkPictureShader.cpp index fb15f6603b..21bd5a531c 100644 --- a/src/shaders/SkPictureShader.cpp +++ b/src/shaders/SkPictureShader.cpp @@ -15,7 +15,7 @@ #include "SkImage.h" #include "SkImageShader.h" #include "SkMatrixUtils.h" -#include "SkPicturePriv.h" +#include "SkPicture.h" #include "SkPictureImageGenerator.h" #include "SkReadBuffer.h" #include "SkResourceCache.h" @@ -176,7 +176,7 @@ void SkPictureShader::flatten(SkWriteBuffer& buffer) const { buffer.writeRect(fTile); buffer.writeBool(true); - SkPicturePriv::Flatten(buffer, fPicture.get()); + fPicture->flatten(buffer); } sk_sp<SkShader> SkPictureShader::refBitmapShader(const SkMatrix& viewMatrix, const SkMatrix* localM, diff --git a/tests/ImageTest.cpp b/tests/ImageTest.cpp index 3efb72e919..6cc0fee4d9 100644 --- a/tests/ImageTest.cpp +++ b/tests/ImageTest.cpp @@ -233,6 +233,7 @@ DEF_TEST(Image_Serialize_Encoding_Failure, reporter) { canvas->drawImage(image, 0, 0); sk_sp<SkPicture> picture(recorder.finishRecordingAsPicture()); REPORTER_ASSERT(reporter, picture); + REPORTER_ASSERT(reporter, picture->approximateOpCount() > 0); bool was_called = false; SkSerialProcs procs; @@ -249,6 +250,7 @@ DEF_TEST(Image_Serialize_Encoding_Failure, reporter) { auto deserialized = SkPicture::MakeFromData(data->data(), data->size()); REPORTER_ASSERT(reporter, deserialized); + REPORTER_ASSERT(reporter, deserialized->approximateOpCount() > 0); } // Test that a draw that only partially covers the drawing surface isn't diff --git a/tests/PictureTest.cpp b/tests/PictureTest.cpp index 4eeec35497..714338f9d1 100644 --- a/tests/PictureTest.cpp +++ b/tests/PictureTest.cpp @@ -19,7 +19,7 @@ #include "SkMD5.h" #include "SkMiniRecorder.h" #include "SkPaint.h" -#include "SkPicturePriv.h" +#include "SkPicture.h" #include "SkPictureRecorder.h" #include "SkPixelRef.h" #include "SkRectPriv.h" @@ -446,7 +446,7 @@ static void test_cull_rect_reset(skiatest::Reporter* reporter) { canvas->drawRect(bounds, paint); canvas->drawRect(bounds, paint); sk_sp<SkPicture> p(recorder.finishRecordingAsPictureWithCull(bounds)); - const SkBigPicture* picture = SkPicturePriv::AsBigPicture(p.get()); + const SkBigPicture* picture = p->asSkBigPicture(); REPORTER_ASSERT(reporter, picture); SkRect finalCullRect = picture->cullRect(); @@ -813,3 +813,24 @@ DEF_TEST(Picture_UpdatedCull_2, r) { REPORTER_ASSERT(r, pic->cullRect() == SkRectPriv::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/SerializationTest.cpp b/tests/SerializationTest.cpp index b9c8a378ff..2543870667 100644 --- a/tests/SerializationTest.cpp +++ b/tests/SerializationTest.cpp @@ -17,7 +17,6 @@ #include "SkMatrixPriv.h" #include "SkOSFile.h" #include "SkReadBuffer.h" -#include "SkPicturePriv.h" #include "SkPictureRecorder.h" #include "SkShaderBase.h" #include "SkTableColorFilter.h" @@ -543,7 +542,7 @@ DEF_TEST(Serialization, reporter) { // Serialize picture SkBinaryWriteBuffer writer; - SkPicturePriv::Flatten(writer, pict.get()); + pict->flatten(writer); size_t size = writer.bytesWritten(); SkAutoTMalloc<unsigned char> data(size); writer.writeToMemory(static_cast<void*>(data.get())); diff --git a/tools/DumpRecord.cpp b/tools/DumpRecord.cpp index dfe196832b..e9374fd41a 100644 --- a/tools/DumpRecord.cpp +++ b/tools/DumpRecord.cpp @@ -7,7 +7,6 @@ #include <stdio.h> -#include "SkPicturePriv.h" #include "SkRecord.h" #include "SkRecordDraw.h" @@ -64,7 +63,7 @@ public: void print(const SkRecords::DrawPicture& command, double ns) { this->printNameAndTime(command, ns); - if (auto bp = SkPicturePriv::AsBigPicture(command.picture.get())) { + if (auto bp = command.picture->asSkBigPicture()) { ++fIndent; const SkRecord& record = *bp->record(); |