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
This commit is contained in:
robertphillips 2014-08-12 05:35:58 -07:00 committed by Commit bot
parent ea13afff6e
commit c019ec412b
6 changed files with 126 additions and 5 deletions

View File

@ -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);
}

View File

@ -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

View File

@ -617,6 +617,9 @@ bool SkPictureData::suitableForGpuRasterization(GrContext* context, const char *
}
}
bool SkPictureData::suitableForLayerOptimization() const {
return fContentInfo.numLayers() > 0;
}
#endif
///////////////////////////////////////////////////////////////////////////////

View File

@ -150,6 +150,8 @@ public:
*/
bool suitableForGpuRasterization(GrContext* context, const char **reason,
GrPixelConfig config, SkScalar dpi) const;
bool suitableForLayerOptimization() const;
#endif
private:

View File

@ -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());
}

View File

@ -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);