diff options
author | reed <reed@chromium.org> | 2015-04-07 04:40:48 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-04-07 04:40:48 -0700 |
commit | b679ca8926a832274b14fdb512f88f64b61d32ea (patch) | |
tree | 9f3f568ac6153528bcef9291281f722cfd9ec65a | |
parent | ff271c29a64f59d538e644210b0f207666f856b5 (diff) |
reduce alloc overhead for SkCanvas
use pre-allocated space in the canvas to avoid initial calls to malloc
BUG=skia:
Review URL: https://codereview.chromium.org/1060583007
-rw-r--r-- | include/core/SkCanvas.h | 12 | ||||
-rw-r--r-- | src/core/SkCanvas.cpp | 37 |
2 files changed, 30 insertions, 19 deletions
diff --git a/include/core/SkCanvas.h b/include/core/SkCanvas.h index 8df29893ff..1dbca3a0a2 100644 --- a/include/core/SkCanvas.h +++ b/include/core/SkCanvas.h @@ -1089,7 +1089,7 @@ public: * @return the current clip stack ("list" of individual clip elements) */ const SkClipStack* getClipStack() const { - return fClipStack; + return &fClipStack; } typedef SkCanvasClipVisitor ClipVisitor; @@ -1251,12 +1251,18 @@ protected: private: class MCRec; - SkAutoTUnref<SkClipStack> fClipStack; + SkClipStack fClipStack; SkDeque fMCStack; // points to top of stack MCRec* fMCRec; // the first N recs that can fit here mean we won't call malloc - uint32_t fMCRecStorage[32]; + enum { + kMCRecSize = 128, // most recent measurement + kMCRecCount = 8, // common depth for save/restores + }; + intptr_t fMCRecStorage[kMCRecSize * kMCRecCount / sizeof(intptr_t)]; + // for our base DeviceCM + intptr_t fBaseLayerStorage[kMCRecSize / sizeof(intptr_t)]; const SkSurfaceProps fProps; diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index 5310c9f7d5..83eee62ea0 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -233,7 +233,7 @@ public: fCanvas = canvas; canvas->updateDeviceCMCache(); - fClipStack = canvas->fClipStack.get(); + fClipStack = &canvas->fClipStack; fCurrLayer = canvas->fMCRec->fTopLayer; fSkipEmptyClips = skipEmptyClips; } @@ -438,13 +438,14 @@ SkBaseDevice* SkCanvas::init(SkBaseDevice* device, InitFlags flags) { fMCRec = (MCRec*)fMCStack.push_back(); new (fMCRec) MCRec(fConservativeRasterClip); - fMCRec->fLayer = SkNEW_ARGS(DeviceCM, (NULL, NULL, NULL, fConservativeRasterClip)); + SkASSERT(sizeof(DeviceCM) <= sizeof(fBaseLayerStorage)); + fMCRec->fLayer = (DeviceCM*)fBaseLayerStorage; + new (fBaseLayerStorage) DeviceCM(NULL, NULL, NULL, fConservativeRasterClip); + fMCRec->fTopLayer = fMCRec->fLayer; fSurfaceBase = NULL; - fClipStack.reset(SkNEW(SkClipStack)); - if (device) { device->initForRootLayer(fProps.pixelGeometry()); if (device->forceConservativeRasterClip()) { @@ -738,11 +739,11 @@ void SkCanvas::updateDeviceCMCache() { DeviceCM* layer = fMCRec->fTopLayer; if (NULL == layer->fNext) { // only one layer - layer->updateMC(totalMatrix, totalClip, *fClipStack, NULL); + layer->updateMC(totalMatrix, totalClip, fClipStack, NULL); } else { SkRasterClip clip(totalClip); do { - layer->updateMC(totalMatrix, clip, *fClipStack, &clip); + layer->updateMC(totalMatrix, clip, fClipStack, &clip); } while ((layer = layer->fNext) != NULL); } fDeviceCMDirty = false; @@ -819,7 +820,7 @@ void SkCanvas::internalSave() { new (newTop) MCRec(*fMCRec); // balanced in restore() fMCRec = newTop; - fClipStack->save(); + fClipStack.save(); } static bool bounds_affects_clip(SkCanvas::SaveFlags flags) { @@ -864,7 +865,7 @@ bool SkCanvas::clipRectBounds(const SkRect* bounds, SaveFlags flags, if (bounds_affects_clip(flags)) { // Simplify the current clips since they will be applied properly during restore() fCachedLocalClipBoundsDirty = true; - fClipStack->clipDevRect(ir, SkRegion::kReplace_Op); + fClipStack.clipDevRect(ir, SkRegion::kReplace_Op); fMCRec->fRasterClip.setRect(ir); } @@ -973,7 +974,7 @@ void SkCanvas::internalRestore() { fDeviceCMDirty = true; fCachedLocalClipBoundsDirty = true; - fClipStack->restore(); + fClipStack.restore(); // reserve our layer (if any) DeviceCM* layer = fMCRec->fLayer; // may be null @@ -996,8 +997,12 @@ void SkCanvas::internalRestore() { layer->fPaint); // reset this, since internalDrawDevice will have set it to true fDeviceCMDirty = true; + SkDELETE(layer); + } else { + // we're at the root + SkASSERT(layer == (void*)fBaseLayerStorage); + layer->~DeviceCM(); } - SkDELETE(layer); } } @@ -1278,7 +1283,7 @@ void SkCanvas::onClipRect(const SkRect& rect, SkRegion::Op op, ClipEdgeStyle edg SkRect r; fMCRec->fMatrix.mapRect(&r, rect); - fClipStack->clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); + fClipStack.clipDevRect(r, op, kSoft_ClipEdgeStyle == edgeStyle); fMCRec->fRasterClip.op(r, this->getBaseLayerSize(), op, kSoft_ClipEdgeStyle == edgeStyle); } else { // since we're rotated or some such thing, we convert the rect to a path @@ -1318,7 +1323,7 @@ void SkCanvas::onClipRRect(const SkRRect& rrect, SkRegion::Op op, ClipEdgeStyle edgeStyle = kHard_ClipEdgeStyle; } - fClipStack->clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); + fClipStack.clipDevRRect(transformedRRect, op, kSoft_ClipEdgeStyle == edgeStyle); SkPath devPath; devPath.addRRect(transformedRRect); @@ -1383,7 +1388,7 @@ void SkCanvas::onClipPath(const SkPath& path, SkRegion::Op op, ClipEdgeStyle edg } // if we called path.swap() we could avoid a deep copy of this path - fClipStack->clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); + fClipStack.clipDevPath(devPath, op, kSoft_ClipEdgeStyle == edgeStyle); if (fAllowSimplifyClip) { bool clipIsAA = getClipStack()->asPath(&devPath); @@ -1410,7 +1415,7 @@ void SkCanvas::onClipRegion(const SkRegion& rgn, SkRegion::Op op) { // todo: signal fClipStack that we have a region, and therefore (I guess) // we have to ignore it, and use the region directly? - fClipStack->clipDevRect(rgn.getBounds(), op); + fClipStack.clipDevRect(rgn.getBounds(), op); fMCRec->fRasterClip.op(rgn, op); } @@ -1428,7 +1433,7 @@ void SkCanvas::validateClip() const { ir.set(0, 0, device->width(), device->height()); SkRasterClip tmpClip(ir, fConservativeRasterClip); - SkClipStack::B2TIter iter(*fClipStack); + SkClipStack::B2TIter iter(fClipStack); const SkClipStack::Element* element; while ((element = iter.next()) != NULL) { switch (element->getType()) { @@ -1451,7 +1456,7 @@ void SkCanvas::validateClip() const { #endif void SkCanvas::replayClips(ClipVisitor* visitor) const { - SkClipStack::B2TIter iter(*fClipStack); + SkClipStack::B2TIter iter(fClipStack); const SkClipStack::Element* element; while ((element = iter.next()) != NULL) { |