Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(135)

Unified Diff: src/core/SkCanvas.cpp

Issue 767333002: Defer saves() until they're needed (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/core/SkCanvas.cpp
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 083a8ed7e8a8cea5ccb505b1d6a3537a8ed95fd7..69e078517539eb31c85293b1e2821c8ebe2b01ab 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -170,8 +170,6 @@ private:
*/
class SkCanvas::MCRec {
public:
- SkRasterClip fRasterClip;
- SkMatrix fMatrix;
SkDrawFilter* fFilter; // the current filter (or null)
DeviceCM* fLayer;
/* If there are any layers in the stack, this points to the top-most
@@ -180,22 +178,26 @@ public:
reference counted, since the real owner is either our fLayer field,
or a previous one in a lower level.)
*/
- DeviceCM* fTopLayer;
+ DeviceCM* fTopLayer;
+ SkRasterClip fRasterClip;
+ SkMatrix fMatrix;
+ int fDeferredSaveCount;
f(malita) 2014/12/10 19:49:33 I always imagined this to be an unsigned, but yeah
MCRec(bool conservativeRasterClip) : fRasterClip(conservativeRasterClip) {
- fMatrix.reset();
fFilter = NULL;
fLayer = NULL;
fTopLayer = NULL;
+ fMatrix.reset();
+ fDeferredSaveCount = 0;
// don't bother initializing fNext
inc_rec();
}
- MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip) {
- fMatrix = prev.fMatrix;
+ MCRec(const MCRec& prev) : fRasterClip(prev.fRasterClip), fMatrix(prev.fMatrix) {
fFilter = SkSafeRef(prev.fFilter);
fLayer = NULL;
fTopLayer = prev.fTopLayer;
+ fDeferredSaveCount = 0;
// don't bother initializing fNext
inc_rec();
@@ -423,6 +425,8 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) {
fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, 0, 0, NULL, NULL, fConservativeRasterClip));
fMCRec->fTopLayer = fMCRec->fLayer;
+ fCallingWillSave = false;
+
fSurfaceBase = NULL;
if (device) {
@@ -785,21 +789,51 @@ void SkCanvas::updateDeviceCMCache() {
///////////////////////////////////////////////////////////////////////////////
+void SkCanvas::checkForDeferredSave() {
+ if (fMCRec->fDeferredSaveCount > 0) {
+ fMCRec->fDeferredSaveCount -= 1;
+ this->doSave();
+ }
+}
+
int SkCanvas::getSaveCount() const {
f(malita) 2014/12/10 19:49:33 To avoid perf surprises, we should probably track
reed1 2014/12/10 20:06:36 Probably true :(
- return fMCStack.count();
+ int count = 0;
+ SkDeque::Iter iter(fMCStack, SkDeque::Iter::kFront_IterStart);
+ for (;;) {
+ const MCRec* rec = (const MCRec*)iter.next();
f(malita) 2014/12/10 19:49:33 I think this will miss all deferred saves on the i
reed1 2014/12/10 20:06:36 next() returns the first one : its a funny pattern
+ if (!rec) {
+ break;
+ }
+ count += 1 + rec->fDeferredSaveCount;
+ }
+ return count;
f(malita) 2014/12/10 19:49:33 Would it be simpler to just iterate over all MCRec
reed1 2014/12/10 20:06:35 see above
f(malita) 2014/12/10 20:13:58 Hmm, then something's not clicking: do we need to
}
int SkCanvas::save() {
+ fMCRec->fDeferredSaveCount += 1;
+#if 0
+ this->checkForDeferredSave();
+#endif
+ return this->getSaveCount() - 1; // return our prev value
+}
+
+void SkCanvas::doSave() {
+ fCallingWillSave = true;
this->willSave();
- return this->internalSave();
+ fCallingWillSave = false;
robertphillips 2014/12/10 18:43:53 Do we need this cast ?
reed1 2014/12/10 20:06:35 Done.
+ (void)this->internalSave();
}
void SkCanvas::restore() {
- // check for underflow
- if (fMCStack.count() > 1) {
- this->willRestore();
- this->internalRestore();
- this->didRestore();
+ if (fMCRec->fDeferredSaveCount > 0) {
+ fMCRec->fDeferredSaveCount -= 1;
+ } else {
+ // check for underflow
+ if (fMCStack.count() > 1) {
+ this->willRestore();
+ this->internalRestore();
+ this->didRestore();
+ }
}
}
@@ -815,16 +849,12 @@ void SkCanvas::restoreToCount(int count) {
}
}
-int SkCanvas::internalSave() {
- int saveCount = this->getSaveCount(); // record this before the actual save
-
+void SkCanvas::internalSave() {
MCRec* newTop = (MCRec*)fMCStack.push_back();
new (newTop) MCRec(*fMCRec); // balanced in restore()
fMCRec = newTop;
fClipStack.save();
-
- return saveCount;
}
static bool bounds_affects_clip(SkCanvas::SaveFlags flags) {
@@ -881,16 +911,17 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags,
int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
- return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
+ this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
+ return this->getSaveCount() - 1;
}
-int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
- SaveFlags flags) {
+int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags) {
SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
- return this->internalSaveLayer(bounds, paint, flags, false, strategy);
+ this->internalSaveLayer(bounds, paint, flags, false, strategy);
+ return this->getSaveCount() - 1;
}
-int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
+void SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, SaveFlags flags,
bool justForImageFilter, SaveLayerStrategy strategy) {
#ifndef SK_SUPPORT_LEGACY_CLIPTOLAYERFLAG
flags |= kClipToLayer_SaveFlag;
@@ -898,19 +929,19 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
// do this before we create the layer. We don't call the public save() since
// that would invoke a possibly overridden virtual
- int count = this->internalSave();
+ this->internalSave();
fDeviceCMDirty = true;
SkIRect ir;
if (!this->clipRectBounds(bounds, flags, &ir, paint ? paint->getImageFilter() : NULL)) {
- return count;
+ return;
}
// FIXME: do willSaveLayer() overriders returning kNoLayer_SaveLayerStrategy really care about
// the clipRectBounds() call above?
if (kNoLayer_SaveLayerStrategy == strategy) {
- return count;
+ return;
}
// Kill the imagefilter if our device doesn't allow it
@@ -919,7 +950,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
if (!this->getTopDevice()->allowImageFilter(paint->getImageFilter())) {
if (justForImageFilter) {
// early exit if the layer was just for the imageFilter
- return count;
+ return;
}
SkPaint* p = lazyP.set(*paint);
p->setImageFilter(NULL);
@@ -934,7 +965,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
SkBaseDevice* device = this->getTopDevice();
if (NULL == device) {
SkDebugf("Unable to find device for layer.");
- return count;
+ return;
}
SkBaseDevice::Usage usage = SkBaseDevice::kSaveLayer_Usage;
@@ -945,7 +976,7 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
fProps.pixelGeometry()));
if (NULL == device) {
SkDebugf("Unable to create device for layer.");
- return count;
+ return;
}
device->setOrigin(ir.fLeft, ir.fTop);
@@ -958,7 +989,6 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
fMCRec->fTopLayer = layer; // this field is NOT an owner of layer
fSaveLayerCount += 1;
- return count;
}
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
@@ -1286,6 +1316,7 @@ void SkCanvas::concat(const SkMatrix& matrix) {
return;
}
+ this->checkForDeferredSave();
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
fMCRec->fMatrix.preConcat(matrix);
@@ -1294,6 +1325,7 @@ void SkCanvas::concat(const SkMatrix& matrix) {
}
void SkCanvas::setMatrix(const SkMatrix& matrix) {
+ this->checkForDeferredSave();
fDeviceCMDirty = true;
fCachedLocalClipBoundsDirty = true;
fMCRec->fMatrix = matrix;
@@ -1310,6 +1342,7 @@ void SkCanvas::resetMatrix() {
//////////////////////////////////////////////////////////////////////////////
void SkCanvas::clipRect(const SkRect& rect, SkRegion::Op op, bool doAA) {
+ this->checkForDeferredSave();
ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
this->onClipRect(rect, op, edgeStyle);
}
@@ -1367,6 +1400,7 @@ static void rasterclip_path(SkRasterClip* rc, const SkCanvas* canvas, const SkPa
}
void SkCanvas::clipRRect(const SkRRect& rrect, SkRegion::Op op, bool doAA) {
+ this->checkForDeferredSave();
ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
if (rrect.isRect()) {
this->onClipRect(rrect.getBounds(), op, edgeStyle);
@@ -1402,6 +1436,7 @@ void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle
}
void SkCanvas::clipPath(const SkPath& path, SkRegion::Op op, bool doAA) {
+ this->checkForDeferredSave();
ClipEdgeStyle edgeStyle = doAA ? kSoft_ClipEdgeStyle : kHard_ClipEdgeStyle;
SkRect r;
if (!path.isInverseFillType() && path.isRect(&r)) {
@@ -1484,6 +1519,7 @@ void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg
}
void SkCanvas::clipRegion(const SkRegion& rgn, SkRegion::Op op) {
+ this->checkForDeferredSave();
this->onClipRegion(rgn, op);
}
« no previous file with comments | « include/core/SkCanvas.h ('k') | src/core/SkPictureRecord.cpp » ('j') | tests/RecordDrawTest.cpp » ('J')

Powered by Google App Engine
This is Rietveld 408576698