From 4a2b2e8ed2e35171bf98bad68a69daaced11ec7c Mon Sep 17 00:00:00 2001 From: robertphillips Date: Mon, 11 Aug 2014 14:45:38 -0700 Subject: Add layer counting to SkPictureRecord This will be used for a SkPicture::suitableForOptimization entry point. R=bsalomon@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/464433002 --- src/core/SkPictureContentInfo.cpp | 68 +++++++++++++++++++++++++++++++++++++++ src/core/SkPictureContentInfo.h | 30 +++++++++++++++++ src/core/SkPictureData.cpp | 3 ++ src/core/SkPictureData.h | 2 ++ src/core/SkPictureRecord.cpp | 24 +++++++++++--- 5 files changed, 122 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/SkPictureContentInfo.cpp b/src/core/SkPictureContentInfo.cpp index 8185d850b8..1d19f352f4 100644 --- a/src/core/SkPictureContentInfo.cpp +++ b/src/core/SkPictureContentInfo.cpp @@ -71,6 +71,62 @@ void SkPictureContentInfo::onAddPaintPtr(const SkPaint* paint) { } } +void SkPictureContentInfo::onSaveLayer() { + *fSaveStack.append() = kSaveLayer_Flag; +} + +void SkPictureContentInfo::onSave() { + *fSaveStack.append() = kSave_Flag; +} + +void SkPictureContentInfo::onRestore() { + SkASSERT(fSaveStack.count() > 0); + + bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; + + if (fSaveStack.top() & kSaveLayer_Flag) { + ++fNumLayers; + if (containedSaveLayer) { + ++fNumInteriorLayers; + } else { + ++fNumLeafLayers; + } + containedSaveLayer = true; + } + + fSaveStack.pop(); + + if (containedSaveLayer && fSaveStack.count() > 0) { + fSaveStack.top() |= kContainedSaveLayer_Flag; + } +} + +void SkPictureContentInfo::rescindLastSave() { + SkASSERT(fSaveStack.count() > 0); + SkASSERT(fSaveStack.top() & kSave_Flag); + + bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; + + fSaveStack.pop(); + + if (containedSaveLayer && fSaveStack.count() > 0) { + fSaveStack.top() |= kContainedSaveLayer_Flag; + } +} + +void SkPictureContentInfo::rescindLastSaveLayer() { + SkASSERT(fSaveStack.count() > 0); + SkASSERT(fSaveStack.top() & kSaveLayer_Flag); + + bool containedSaveLayer = fSaveStack.top() & kContainedSaveLayer_Flag; + + fSaveStack.pop(); + + if (containedSaveLayer && fSaveStack.count() > 0) { + fSaveStack.top() |= kContainedSaveLayer_Flag; + } +} + void SkPictureContentInfo::set(const SkPictureContentInfo& src) { fNumOperations = src.fNumOperations; fNumTexts = src.fNumTexts; @@ -78,6 +134,10 @@ void SkPictureContentInfo::set(const SkPictureContentInfo& src) { fNumFastPathDashEffects = src.fNumFastPathDashEffects; fNumAAConcavePaths = src.fNumAAConcavePaths; fNumAAHairlineConcavePaths = src.fNumAAHairlineConcavePaths; + fNumLayers = src.fNumLayers; + fNumInteriorLayers = src.fNumInteriorLayers; + fNumLeafLayers = src.fNumLeafLayers; + fSaveStack = src.fSaveStack; } void SkPictureContentInfo::reset() { @@ -87,6 +147,10 @@ void SkPictureContentInfo::reset() { fNumFastPathDashEffects = 0; fNumAAConcavePaths = 0; fNumAAHairlineConcavePaths = 0; + fNumLayers = 0; + fNumInteriorLayers = 0; + fNumLeafLayers = 0; + fSaveStack.rewind(); } void SkPictureContentInfo::swap(SkPictureContentInfo* other) { @@ -96,4 +160,8 @@ void SkPictureContentInfo::swap(SkPictureContentInfo* other) { SkTSwap(fNumFastPathDashEffects, other->fNumFastPathDashEffects); SkTSwap(fNumAAConcavePaths, other->fNumAAConcavePaths); SkTSwap(fNumAAHairlineConcavePaths, other->fNumAAHairlineConcavePaths); + SkTSwap(fNumLayers, other->fNumLayers); + SkTSwap(fNumInteriorLayers, other->fNumInteriorLayers); + SkTSwap(fNumLeafLayers, other->fNumLeafLayers); + fSaveStack.swap(other->fSaveStack); } diff --git a/src/core/SkPictureContentInfo.h b/src/core/SkPictureContentInfo.h index cfeedcf483..d4d1d4fc5f 100644 --- a/src/core/SkPictureContentInfo.h +++ b/src/core/SkPictureContentInfo.h @@ -17,6 +17,11 @@ public: int numOperations() const { return fNumOperations; } bool hasText() const { return fNumTexts > 0; } + + int numLayers() const { return fNumLayers; } + int numInteriorLayers() const { return fNumInteriorLayers; } + int numLeafLayers() const { return fNumLeafLayers; } + bool suitableForGpuRasterization(GrContext* context, const char **reason, int sampleCount) const; @@ -27,6 +32,12 @@ public: void onAddPaintPtr(const SkPaint* paint); void onDrawText() { ++fNumTexts; } + void onSaveLayer(); + void onSave(); + void onRestore(); + void rescindLastSave(); + void rescindLastSaveLayer(); + void set(const SkPictureContentInfo& src); void reset(); void swap(SkPictureContentInfo* other); @@ -49,6 +60,25 @@ private: // This field is incremented every time a drawPath call is // issued for a hairline stroked concave path. int fNumAAHairlineConcavePaths; + // These fields track the different layer flavors. fNumLayers is just + // a count of all saveLayers, fNumInteriorLayers is the number of layers + // with a layer inside them, fNumLeafLayers is the number of layers with + // no layer inside them. + int fNumLayers; + int fNumInteriorLayers; + int fNumLeafLayers; + + enum Flags { + kSave_Flag = 0x1, + kSaveLayer_Flag = 0x2, + + // Did the current save or saveLayer contain another saveLayer. + // Percolated back down the save stack. + kContainedSaveLayer_Flag = 0x4 + }; + + // Stack of save vs saveLayer information to track nesting + SkTDArray fSaveStack; }; #endif diff --git a/src/core/SkPictureData.cpp b/src/core/SkPictureData.cpp index 140ca88b34..ea9da79aa3 100644 --- a/src/core/SkPictureData.cpp +++ b/src/core/SkPictureData.cpp @@ -617,6 +617,9 @@ bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char * } } +bool SkPictureData::suitableForLayerOptimization() const { + return fContentInfo.numLayers() > 0; +} #endif /////////////////////////////////////////////////////////////////////////////// diff --git a/src/core/SkPictureData.h b/src/core/SkPictureData.h index e3f3d020e6..3e3ab59a44 100644 --- a/src/core/SkPictureData.h +++ b/src/core/SkPictureData.h @@ -150,6 +150,8 @@ public: */ bool suitableForGpuRasterization(GrContext* context, const char **reason, GrPixelConfig config, SkScalar dpi) const; + + bool suitableForLayerOptimization() const; #endif private: diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp index d9239ddcca..fc0b291912 100644 --- a/src/core/SkPictureRecord.cpp +++ b/src/core/SkPictureRecord.cpp @@ -151,6 +151,8 @@ void SkPictureRecord::willSave() { } void SkPictureRecord::recordSave() { + fContentInfo.onSave(); + // op only size_t size = kSaveSize; size_t initialOffset = this->addDraw(SAVE, &size); @@ -179,6 +181,8 @@ SkCanvas::SaveLayerStrategy SkPictureRecord::willSaveLayer(const SkRect* bounds, void SkPictureRecord::recordSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) { + fContentInfo.onSaveLayer(); + // op + bool for 'bounds' size_t size = 2 * kUInt32Size; if (NULL != bounds) { @@ -508,8 +512,10 @@ enum PictureRecordOptType { }; enum PictureRecordOptFlags { - kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the - // SkPicture has a bounding box hierarchy. + kSkipIfBBoxHierarchy_Flag = 0x1, // Optimization should be skipped if the + // SkPicture has a bounding box hierarchy. + kRescindLastSave_Flag = 0x2, + kRescindLastSaveLayer_Flag = 0x4, }; struct PictureRecordOpt { @@ -528,9 +534,10 @@ static const PictureRecordOpt gPictureRecordOpts[] = { // SkPictureStateTree, and applying the optimization introduces significant // record time overhead because it requires rewinding contents that were // recorded into the BBoxHierarchy. - { collapse_save_clip_restore, kRewind_OptType, kSkipIfBBoxHierarchy_Flag }, - { remove_save_layer1, kCollapseSaveLayer_OptType, 0 }, - { remove_save_layer2, kCollapseSaveLayer_OptType, 0 } + { collapse_save_clip_restore, kRewind_OptType, + kSkipIfBBoxHierarchy_Flag|kRescindLastSave_Flag }, + { remove_save_layer1, kCollapseSaveLayer_OptType, kRescindLastSaveLayer_Flag }, + { remove_save_layer2, kCollapseSaveLayer_OptType, kRescindLastSaveLayer_Flag } }; // This is called after an optimization has been applied to the command stream @@ -585,6 +592,11 @@ void SkPictureRecord::willRestore() { // Some optimization fired so don't add the RESTORE apply_optimization_to_bbh(gPictureRecordOpts[opt].fType, fStateTree, fBoundingHierarchy); + if (gPictureRecordOpts[opt].fFlags & kRescindLastSave_Flag) { + fContentInfo.rescindLastSave(); + } else if (gPictureRecordOpts[opt].fFlags & kRescindLastSaveLayer_Flag) { + fContentInfo.rescindLastSaveLayer(); + } break; } } @@ -601,6 +613,8 @@ void SkPictureRecord::willRestore() { } void SkPictureRecord::recordRestore(bool fillInSkips) { + fContentInfo.onRestore(); + if (fillInSkips) { this->fillRestoreOffsetPlaceholdersForCurrentStackLevel((uint32_t)fWriter.bytesWritten()); } -- cgit v1.2.3