aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2014-08-12 05:35:58 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-12 05:35:58 -0700
commitc019ec412ba2704bc6e2cdfd321ea06787ba415d (patch)
treed59bc976c3ac002d73961cfdeb7edc6f4dbc2960
parentea13afff6e46d8a969611cdd56c996bfb05a27c1 (diff)
Add layer counting to SkPictureRecord
This will be used for a SkPicture::suitableForOptimization entry point. Committed: https://skia.googlesource.com/skia/+/4a2b2e8ed2e35171bf98bad68a69daaced11ec7c R=bsalomon@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/464433002
-rw-r--r--src/core/SkPictureContentInfo.cpp68
-rw-r--r--src/core/SkPictureContentInfo.h30
-rw-r--r--src/core/SkPictureData.cpp3
-rw-r--r--src/core/SkPictureData.h2
-rw-r--r--src/core/SkPictureRecord.cpp24
-rw-r--r--src/gpu/SkGpuDevice.cpp4
6 files changed, 126 insertions, 5 deletions
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<uint32_t> 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());
}
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index 3e6bf1b6e4..e459a116df 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1850,6 +1850,10 @@ SkSurface* SkGpuDevice::newSurface(const SkImageInfo& info) {
void SkGpuDevice::EXPERIMENTAL_optimize(const SkPicture* picture) {
fContext->getLayerCache()->processDeletedPictures();
+ if (NULL != picture->fData.get() && !picture->fData->suitableForLayerOptimization()) {
+ return;
+ }
+
SkPicture::AccelData::Key key = GPUAccelData::ComputeAccelDataKey();
const SkPicture::AccelData* existing = picture->EXPERIMENTAL_getAccelData(key);