From 49d9fd5fdb9ffd48538c8fc5a2f6f2d43a2e4fe9 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Wed, 23 May 2012 11:44:08 +0000 Subject: [PATCH] Plumbing to propagate save & restore from SkCanvas down to GrContext & lower http://codereview.appspot.com/6203067/ git-svn-id: http://skia.googlecode.com/svn/trunk@4034 2bbb7eff-a529-9590-31e7-b0007b416f81 --- include/core/SkDevice.h | 14 ++++++++++++++ include/gpu/GrContext.h | 12 ++++++++++++ include/gpu/SkGpuDevice.h | 11 +++++++++-- src/core/SkCanvas.cpp | 16 ++++++++++++++++ src/gpu/GrClipMaskManager.h | 11 +++++++++++ src/gpu/GrContext.cpp | 8 ++++++++ src/gpu/GrDrawTarget.cpp | 3 --- src/gpu/GrDrawTarget.h | 5 ++++- src/gpu/GrGpu.h | 7 +++++++ src/gpu/GrInOrderDrawBuffer.cpp | 8 ++++---- src/gpu/GrInOrderDrawBuffer.h | 2 +- 11 files changed, 86 insertions(+), 11 deletions(-) diff --git a/include/core/SkDevice.h b/include/core/SkDevice.h index db9c542ada..1e4e0a3166 100644 --- a/include/core/SkDevice.h +++ b/include/core/SkDevice.h @@ -351,6 +351,20 @@ private: friend class SkDeviceFilteredPaint; friend class DeviceImageFilterProxy; + /** + * postSave is called by SkCanvas to inform the device that it has + * just completed a save operation. This allows derived + * classes to initialize their state-dependent caches. + */ + virtual void postSave() {}; + + /** + * preRestore is called by SkCanvas right before it executes a restore + * operation. As the partner of postSave, it allows + * derived classes to clear their state-dependent caches. + */ + virtual void preRestore() {}; + // just called by SkCanvas when built as a layer void setOrigin(int x, int y) { fOrigin.set(x, y); } // just called by SkCanvas for saveLayer diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h index 8a18331d9c..e05c48a8c4 100644 --- a/include/gpu/GrContext.h +++ b/include/gpu/GrContext.h @@ -680,6 +680,18 @@ public: void unlockStencilBuffer(GrResourceEntry* sbEntry); GrStencilBuffer* findStencilBuffer(int width, int height, int sampleCnt); + /* + * postClipPush acts as a hint to this and lower-level classes (e.g., + * GrGpu) that the clip stack has changed. + */ + virtual void postClipPush(); + + /* + * preClipPop acts as a hint that the clip stack has been restored to an + * earlier state. + */ + virtual void preClipPop(); + GrPathRenderer* getPathRenderer(const SkPath& path, GrPathFill fill, const GrDrawTarget* target, diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h index ffc24a8c4b..ee4d791931 100644 --- a/include/gpu/SkGpuDevice.h +++ b/include/gpu/SkGpuDevice.h @@ -146,11 +146,18 @@ private: // used by createCompatibleDevice SkGpuDevice(GrContext*, GrTexture* texture, TexCache, bool needClear); - // override from SkDevice + // overrides from SkDevice + virtual void postSave() SK_OVERRIDE { + fContext->postClipPush(); + } + virtual void preRestore() SK_OVERRIDE { + fContext->preClipPop(); + } + virtual SkDevice* onCreateCompatibleDevice(SkBitmap::Config config, int width, int height, bool isOpaque, - Usage usage); + Usage usage) SK_OVERRIDE; SkDrawProcs* initDrawForText(GrTextContext*); bool bindDeviceAsTexture(GrPaint* paint); diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp index f50728421a..af2e066b4f 100644 --- a/src/core/SkCanvas.cpp +++ b/src/core/SkCanvas.cpp @@ -700,6 +700,14 @@ int SkCanvas::internalSave(SaveFlags flags) { fClipStack.save(); SkASSERT(fClipStack.getSaveCount() == this->getSaveCount() - 1); + for (DeviceCM* curLayer = fMCRec->fTopLayer; + curLayer; + curLayer = curLayer->fNext) { + if (NULL != curLayer->fDevice) { + curLayer->fDevice->postSave(); + } + } + return saveCount; } @@ -870,6 +878,14 @@ void SkCanvas::restore() { void SkCanvas::internalRestore() { SkASSERT(fMCStack.count() != 0); + for (DeviceCM* curLayer = fMCRec->fTopLayer; + curLayer; + curLayer = curLayer->fNext) { + if (NULL != curLayer->fDevice) { + curLayer->fDevice->preRestore(); + } + } + fDeviceCMDirty = true; fLocalBoundsCompareTypeDirty = true; fLocalBoundsCompareTypeDirtyBW = true; diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h index aa2c0880a5..e4c9fb5dc7 100644 --- a/src/gpu/GrClipMaskManager.h +++ b/src/gpu/GrClipMaskManager.h @@ -300,6 +300,17 @@ public: fClipMaskInStencil = false; } + void postClipPush() { + // TODO: make sure that, if the clip stack is unaltered, the + // prior clip mask is reused (i.e., a push w/ no change to the + // clip stack) + fAACache.push(); + } + + void preClipPop() { + fAACache.pop(); + } + void setContext(GrContext* context) { fAACache.setContext(context); } diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index bd6d829095..b45970bdad 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -2216,4 +2216,12 @@ GrTexture* GrContext::applyMorphology(GrTexture* srcTexture, return srcTexture; } +void GrContext::postClipPush() { + fGpu->postClipPush(); +} + +void GrContext::preClipPop() { + fGpu->preClipPop(); +}; + /////////////////////////////////////////////////////////////////////////////// diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp index 715799c95f..35d50e9e77 100644 --- a/src/gpu/GrDrawTarget.cpp +++ b/src/gpu/GrDrawTarget.cpp @@ -1103,9 +1103,6 @@ GrVertexLayout GrDrawTarget::GetRectVertexLayout(StageMask stageMask, return layout; } -void GrDrawTarget::clipWillBeSet(const GrClip& clip) { -} - void GrDrawTarget::SetRectVertices(const GrRect& rect, const GrMatrix* matrix, const GrRect* srcRects[], diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h index bf6e41bb2e..a6ab6755d0 100644 --- a/src/gpu/GrDrawTarget.h +++ b/src/gpu/GrDrawTarget.h @@ -190,6 +190,9 @@ public: return 1 << (stage + (texCoordIdx * GrDrawState::kNumStages)); } + virtual void postClipPush() {}; + virtual void preClipPop() {}; + private: static const int TEX_COORD_BIT_CNT = GrDrawState::kNumStages * GrDrawState::kMaxTexCoords; @@ -1041,7 +1044,7 @@ protected: int vertexCount) = 0; // subclass overrides to be notified when clip is set. Must call // INHERITED::clipwillBeSet - virtual void clipWillBeSet(const GrClip& clip); + virtual void clipWillBeSet(const GrClip& clip) {} // Helpers for drawRect, protected so subclasses that override drawRect // can use them. diff --git a/src/gpu/GrGpu.h b/src/gpu/GrGpu.h index ba73f7da06..500673bd30 100644 --- a/src/gpu/GrGpu.h +++ b/src/gpu/GrGpu.h @@ -365,6 +365,13 @@ public: // clipping. }; + virtual void postClipPush() SK_OVERRIDE { + fClipMaskManager.postClipPush(); + } + virtual void preClipPop() SK_OVERRIDE { + fClipMaskManager.preClipPop(); + } + protected: // prepares clip flushes gpu state before a draw bool setupClipAndFlushState(GrPrimitiveType type); diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp index 553bacca59..7b3b04f75b 100644 --- a/src/gpu/GrInOrderDrawBuffer.cpp +++ b/src/gpu/GrInOrderDrawBuffer.cpp @@ -223,7 +223,7 @@ void GrInOrderDrawBuffer::drawIndexedInstances(GrPrimitiveType type, bool clipChanged = this->needsNewClip(); bool stateChanged = this->needsNewState(); if (clipChanged) { - this->pushClip(); + this->storeClip(); } if (stateChanged) { this->pushState(); @@ -342,7 +342,7 @@ void GrInOrderDrawBuffer::onDrawIndexed(GrPrimitiveType primitiveType, draw.fClipChanged = this->needsNewClip(); if (draw.fClipChanged) { - this->pushClip(); + this->storeClip(); } draw.fStateChanged = this->needsNewState(); @@ -409,7 +409,7 @@ void GrInOrderDrawBuffer::onDrawNonIndexed(GrPrimitiveType primitiveType, draw.fClipChanged = this->needsNewClip(); if (draw.fClipChanged) { - this->pushClip(); + this->storeClip(); } draw.fStateChanged = this->needsNewState(); @@ -801,7 +801,7 @@ bool GrInOrderDrawBuffer::needsNewClip() const { return false; } -void GrInOrderDrawBuffer::pushClip() { +void GrInOrderDrawBuffer::storeClip() { fClips.push_back() = fClip; fClipSet = false; } diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h index 3b27d70f3d..fa3e0a2613 100644 --- a/src/gpu/GrInOrderDrawBuffer.h +++ b/src/gpu/GrInOrderDrawBuffer.h @@ -167,7 +167,7 @@ private: bool needsNewClip() const; void pushState(); - void pushClip(); + void storeClip(); // call this to invalidate the tracking data that is used to concatenate // multiple draws into a single draw.