O(1) SkPictureUtils::ApproxBytesUsed()
authormtklein <mtklein@chromium.org>
Tue, 21 Apr 2015 22:23:59 +0000 (15:23 -0700)
committerCommit bot <commit-bot@chromium.org>
Tue, 21 Apr 2015 22:24:00 +0000 (15:24 -0700)
Chrome wants to call this more often, and it's quite slow today.

Seems like this could be clearer if SkPictureUtils::ApproxBytesUsed() were SkPicture::approxBytesUsed().

BUG=chromium:471873

Review URL: https://codereview.chromium.org/1090943004

include/core/SkPicture.h
src/core/SkPicture.cpp
src/core/SkPictureRecorder.cpp
src/core/SkRecorder.cpp
src/core/SkRecorder.h
src/core/SkVarAlloc.cpp
src/core/SkVarAlloc.h
src/utils/SkPictureUtils.cpp
tests/PictureTest.cpp

index 8a6216e1aa14092a9ed12b1b9c0c095bb01b2a89..a565e415eb791b4b926baa3be631fbae5c847c79 100644 (file)
@@ -260,7 +260,11 @@ private:
     static bool IsValidPictInfo(const SkPictInfo& info);
 
     // Takes ownership of the SkRecord and (optional) SnapshotArray, refs the (optional) BBH.
-    SkPicture(const SkRect& cullRect, SkRecord*, SnapshotArray*, SkBBoxHierarchy*);
+    SkPicture(const SkRect& cullRect,
+             SkRecord*,
+             SnapshotArray*,
+             SkBBoxHierarchy*,
+             size_t approxBytesUsedBySubPictures);
 
     static SkPicture* Forwardport(const SkPictInfo&, const SkPictureData*);
     static SkPictureData* Backport(const SkRecord&, const SkPictInfo&,
@@ -273,6 +277,7 @@ private:
     SkAutoTUnref<const SkRecord>          fRecord;
     SkAutoTUnref<const SkBBoxHierarchy>   fBBH;
     SkAutoTDelete<const SnapshotArray>    fDrawablePicts;
+    const size_t                          fApproxBytesUsedBySubPictures;
 
     // helpers for fDrawablePicts
     int drawableCount() const;
@@ -302,6 +307,6 @@ private:
     friend class SkPictureUtils;
     friend class SkRecordedDrawable;
 };
-SK_COMPILE_ASSERT(sizeof(SkPicture) <= 96, SkPictureSize);
+SK_COMPILE_ASSERT(sizeof(SkPicture) <= 104, SkPictureSize);
 
 #endif
index a8ddfe6656d5b18446aca9e59f3ae604ad18bf54..2a33c4db607dac4353319bab67d680bab435e5e4 100644 (file)
@@ -480,12 +480,13 @@ bool SkPicture::willPlayBackBitmaps() const { return fAnalysis.fWillPlaybackBitm
 int  SkPicture::approximateOpCount()  const { return fRecord->count(); }
 
 SkPicture::SkPicture(const SkRect& cullRect, SkRecord* record, SnapshotArray* drawablePicts,
-                     SkBBoxHierarchy* bbh)
+                     SkBBoxHierarchy* bbh, size_t approxBytesUsedBySubPictures)
     : fUniqueID(0)
     , fCullRect(cullRect)
     , fRecord(SkRef(record))
     , fBBH(SkSafeRef(bbh))
     , fDrawablePicts(drawablePicts)     // take ownership
+    , fApproxBytesUsedBySubPictures(approxBytesUsedBySubPictures)
     , fAnalysis(*fRecord)
 {}
 
index f622e66c842658df175a8b6fe2db7f411bb462b0..22b1ee3eac13ac6a8732bec8d9927695c33db986 100644 (file)
@@ -9,10 +9,11 @@
 #include "SkDrawable.h"
 #include "SkLayerInfo.h"
 #include "SkPictureRecorder.h"
+#include "SkPictureUtils.h"
 #include "SkRecord.h"
 #include "SkRecordDraw.h"
-#include "SkRecorder.h"
 #include "SkRecordOpts.h"
+#include "SkRecorder.h"
 #include "SkTypes.h"
 
 SkPictureRecorder::SkPictureRecorder() {
@@ -72,7 +73,12 @@ SkPicture* SkPictureRecorder::endRecordingAsPicture() {
         fCullRect = bbhBound;
     }
 
-    SkPicture* pict = SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH));
+    size_t subPictureBytes = fRecorder->approxBytesUsedBySubPictures();
+    for (int i = 0; pictList && i < pictList->count(); i++) {
+        subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]);
+    }
+    SkPicture* pict =
+        SkNEW_ARGS(SkPicture, (fCullRect, fRecord, pictList, fBBH, subPictureBytes));
 
     if (saveLayerData) {
         pict->EXPERIMENTAL_addAccelData(saveLayerData);
@@ -153,7 +159,12 @@ protected:
             SkRecordComputeLayers(fBounds, *fRecord, pictList, bbh, saveLayerData);
         }
 
-        SkPicture* pict = SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH));
+        size_t subPictureBytes = 0;
+        for (int i = 0; pictList && i < pictList->count(); i++) {
+            subPictureBytes += SkPictureUtils::ApproximateBytesUsed(pictList->begin()[i]);
+        }
+        SkPicture* pict =
+            SkNEW_ARGS(SkPicture, (fBounds, fRecord, pictList, fBBH, subPictureBytes));
 
         if (saveLayerData) {
             pict->EXPERIMENTAL_addAccelData(saveLayerData);
index 8684a8e2ebf7cb516ff8c8b9f8aa975aedd019e8..0a2d43edbf22c74956bdd17b83c70ec40b686e8c 100644 (file)
@@ -5,9 +5,10 @@
  * found in the LICENSE file.
  */
 
-#include "SkRecorder.h"
 #include "SkPatchUtils.h"
 #include "SkPicture.h"
+#include "SkPictureUtils.h"
+#include "SkRecorder.h"
 
 SkDrawableList::~SkDrawableList() {
     fArray.unrefAll();
@@ -33,10 +34,12 @@ void SkDrawableList::append(SkDrawable* drawable) {
 
 SkRecorder::SkRecorder(SkRecord* record, int width, int height)
     : SkCanvas(SkIRect::MakeWH(width, height), SkCanvas::kConservativeRasterClip_InitFlag)
+    , fApproxBytesUsedBySubPictures(0)
     , fRecord(record) {}
 
 SkRecorder::SkRecorder(SkRecord* record, const SkRect& bounds)
     : SkCanvas(bounds.roundOut(), SkCanvas::kConservativeRasterClip_InitFlag)
+    , fApproxBytesUsedBySubPictures(0)
     , fRecord(record) {}
 
 void SkRecorder::reset(SkRecord* record, const SkRect& bounds) {
@@ -47,6 +50,7 @@ void SkRecorder::reset(SkRecord* record, const SkRect& bounds) {
 
 void SkRecorder::forgetRecord() {
     fDrawableList.reset(NULL);
+    fApproxBytesUsedBySubPictures = 0;
     fRecord = NULL;
 }
 
@@ -248,6 +252,7 @@ void SkRecorder::onDrawTextBlob(const SkTextBlob* blob, SkScalar x, SkScalar y,
 }
 
 void SkRecorder::onDrawPicture(const SkPicture* pic, const SkMatrix* matrix, const SkPaint* paint) {
+    fApproxBytesUsedBySubPictures += SkPictureUtils::ApproximateBytesUsed(pic);
     APPEND(DrawPicture, this->copy(paint), pic, matrix ? *matrix : SkMatrix::I());
 }
 
index 6842aece58b465e2a067f5694027603ee2155f09..d0a992fc082f85fcbeaef70553d808f9a1ff711e 100644 (file)
@@ -41,6 +41,8 @@ public:
 
     void reset(SkRecord*, const SkRect& bounds);
 
+    size_t approxBytesUsedBySubPictures() const { return fApproxBytesUsedBySubPictures; }
+
     SkDrawableList* getDrawableList() const { return fDrawableList.get(); }
     SkDrawableList* detachDrawableList() { return fDrawableList.detach(); }
 
@@ -131,8 +133,8 @@ private:
         return devBounds;
     }
 
+    size_t fApproxBytesUsedBySubPictures;
     SkRecord* fRecord;
-
     SkAutoTDelete<SkDrawableList> fDrawableList;
 };
 
index fa89d38c23a286a03f4d28d92bb1996a428ae607..5d395d48418c234f8992ee36e5bc6ce1b0a86615 100644 (file)
@@ -27,13 +27,15 @@ struct SkVarAlloc::Block {
 };
 
 SkVarAlloc::SkVarAlloc(size_t minLgSize)
-    : fByte(NULL)
+    : fBytesAllocated(0)
+    , fByte(NULL)
     , fRemaining(0)
     , fLgSize(minLgSize)
     , fBlock(NULL) {}
 
 SkVarAlloc::SkVarAlloc(size_t minLgSize, char* storage, size_t len)
-    : fByte(storage)
+    : fBytesAllocated(0)
+    , fByte(storage)
     , fRemaining(len)
     , fLgSize(minLgSize)
     , fBlock(NULL) {}
@@ -54,6 +56,7 @@ void SkVarAlloc::makeSpace(size_t bytes, unsigned flags) {
     while (alloc < bytes + sizeof(Block)) {
         alloc *= 2;
     }
+    fBytesAllocated += alloc;
     fBlock = Block::Alloc(fBlock, alloc, flags);
     fByte = fBlock->data();
     fRemaining = alloc - sizeof(Block);
@@ -65,23 +68,3 @@ void SkVarAlloc::makeSpace(size_t bytes, unsigned flags) {
     //SkASSERT(alloc == malloc_usable_size(fBlock));
 #endif
 }
-
-static size_t heap_size(void* p) {
-#if defined(SK_BUILD_FOR_MAC)
-    return malloc_size(p);
-#elif defined(SK_BUILD_FOR_UNIX) && !defined(__UCLIBC__)
-    return malloc_usable_size(p);
-#elif defined(SK_BUILD_FOR_WIN32)
-    return _msize(p);
-#else
-    return 0;  // Tough luck.
-#endif
-}
-
-size_t SkVarAlloc::approxBytesAllocated() const {
-    size_t sum = 0;
-    for (Block* b = fBlock; b; b = b->prev) {
-        sum += heap_size(b);
-    }
-    return sum;
-}
index 8a55b366155fdfafdd598511a374876ffd565d24..e8236cf9920067864a0261a09a1e70aa3b536dc6 100644 (file)
@@ -35,12 +35,14 @@ public:
     }
 
     // Returns our best estimate of the number of bytes we've allocated.
-    // (We intentionally do not track this precisely to save space.)
-    size_t approxBytesAllocated() const;
+    // (We may not track this precisely to save space.)
+    size_t approxBytesAllocated() const { return fBytesAllocated; }
 
 private:
     void makeSpace(size_t bytes, unsigned flags);
 
+    size_t fBytesAllocated;
+
     char* fByte;
     unsigned fRemaining;
     unsigned fLgSize;
@@ -48,6 +50,6 @@ private:
     struct Block;
     Block* fBlock;
 };
-SK_COMPILE_ASSERT(sizeof(SkVarAlloc) <= 24, SkVarAllocSize);
+SK_COMPILE_ASSERT(sizeof(SkVarAlloc) <= 32, SkVarAllocSize);
 
 #endif//SkVarAlloc_DEFINED
index be7c431946c9d68d97df2f87b59febbe770ee04d..a8a251c92753c7d9f599475b71ba99dfc896a8c7 100644 (file)
 #include "SkRecord.h"
 #include "SkShader.h"
 
-struct MeasureRecords {
-    template <typename T> size_t operator()(const T& op) { return 0; }
-    size_t operator()(const SkRecords::DrawPicture& op) {
-        return SkPictureUtils::ApproximateBytesUsed(op.picture);
-    }
-};
-
 size_t SkPictureUtils::ApproximateBytesUsed(const SkPicture* pict) {
     size_t byteCount = sizeof(*pict);
 
@@ -26,10 +19,7 @@ size_t SkPictureUtils::ApproximateBytesUsed(const SkPicture* pict) {
     if (pict->fBBH.get()) {
         byteCount += pict->fBBH->bytesUsed();
     }
-    MeasureRecords visitor;
-    for (unsigned curOp = 0; curOp < pict->fRecord->count(); curOp++) {
-        byteCount += pict->fRecord->visit<size_t>(curOp, visitor);
-    }
+    byteCount += pict->fApproxBytesUsedBySubPictures;
 
     return byteCount;
 }
index 2fe6e47ab548e9edecc384aa9333adc24b149b2a..4fe08379dd0545e8648f660fb514d28d8098f525 100644 (file)
@@ -1119,7 +1119,7 @@ static void test_bytes_used(skiatest::Reporter* reporter) {
 
     // Protect against any unintentional bloat.
     size_t approxUsed = SkPictureUtils::ApproximateBytesUsed(empty.get());
-    REPORTER_ASSERT(reporter, approxUsed <= 416);
+    REPORTER_ASSERT(reporter, approxUsed <= 432);
 
     // Sanity check of nested SkPictures.
     SkPictureRecorder r2;