Altered Ganesh's clip stack plumbing to pass down new GrClipData class
http://codereview.appspot.com/6454047/
git-svn-id: http://skia.googlecode.com/svn/trunk@4788 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/include/gpu/GrClip.h b/include/gpu/GrClip.h
index c802015..a017fe3 100644
--- a/include/gpu/GrClip.h
+++ b/include/gpu/GrClip.h
@@ -208,5 +208,40 @@
};
SkSTArray<kPreAllocElements, Element> fList;
};
+
+/**
+ * GrClipData encapsulates the information required to construct the clip
+ * masks. 'fOrigin' is only non-zero when saveLayer has been called
+ * with an offset bounding box. The clips in 'fClipStack' are in
+ * device coordinates (i.e., they have been translated by -fOrigin w.r.t.
+ * the canvas' device coordinates).
+ */
+class GrClipData : public SkNoncopyable {
+public:
+ const GrClip* fClipStack;
+ SkIPoint fOrigin;
+
+ GrClipData()
+ : fClipStack(NULL) {
+ fOrigin.setZero();
+ }
+
+ bool operator==(const GrClipData& other) const {
+ if (fOrigin != other.fOrigin) {
+ return false;
+ }
+
+ if (NULL != fClipStack && NULL != other.fClipStack) {
+ return *fClipStack == *other.fClipStack;
+ }
+
+ return fClipStack == other.fClipStack;
+ }
+
+ bool operator!=(const GrClipData& other) const {
+ return !(*this == other);
+ }
+};
+
#endif
diff --git a/include/gpu/GrContext.h b/include/gpu/GrContext.h
index e0f5827..2f05458 100644
--- a/include/gpu/GrContext.h
+++ b/include/gpu/GrContext.h
@@ -329,13 +329,13 @@
* Gets the current clip.
* @return the current clip.
*/
- const GrClip& getClip() const;
+ const GrClipData* getClip() const;
/**
* Sets the clip.
- * @param clip the clip to set.
+ * @param clipData the clip to set.
*/
- void setClip(const GrClip& clip);
+ void setClip(const GrClipData* clipData);
///////////////////////////////////////////////////////////////////////////
// Draws
@@ -694,9 +694,11 @@
public:
AutoClip(GrContext* context, const GrRect& newClipRect)
: fContext(context)
- , fNewClip(newClipRect) {
+ , fNewClipStack(newClipRect) {
+ fNewClipData.fClipStack = &fNewClipStack;
+
fOldClip = fContext->getClip();
- fContext->setClip(fNewClip);
+ fContext->setClip(&fNewClipData);
}
~AutoClip() {
@@ -705,9 +707,11 @@
}
}
private:
- GrContext* fContext;
- GrClip fOldClip;
- GrClip fNewClip;
+ GrContext* fContext;
+ const GrClipData* fOldClip;
+
+ GrClip fNewClipStack;
+ GrClipData fNewClipData;
};
///////////////////////////////////////////////////////////////////////////
diff --git a/include/gpu/SkGpuDevice.h b/include/gpu/SkGpuDevice.h
index 4a62813..f576ae4 100644
--- a/include/gpu/SkGpuDevice.h
+++ b/include/gpu/SkGpuDevice.h
@@ -132,6 +132,8 @@
// the clip stack - on loan to us from SkCanvas so it can be NULL.
const SkClipStack* fClipStack;
+ GrClip fGrClip;
+ GrClipData fClipData;
// state for our offscreen render-target
TexCache fCache;
diff --git a/src/gpu/GrAAHairLinePathRenderer.cpp b/src/gpu/GrAAHairLinePathRenderer.cpp
index b0e2431..988cfa7 100644
--- a/src/gpu/GrAAHairLinePathRenderer.cpp
+++ b/src/gpu/GrAAHairLinePathRenderer.cpp
@@ -513,7 +513,9 @@
GrIRect clip;
- target->getClip().getConservativeBounds().roundOut(&clip);
+ const GrClipData* clipData = target->getClip();
+ GrRect conservativeBounds = clipData->fClipStack->getConservativeBounds();
+ conservativeBounds.roundOut(&clip);
GrVertexLayout layout = GrDrawTarget::kEdge_VertexLayoutBit;
GrMatrix viewM = drawState.getViewMatrix();
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index d7287ea..a3c8537 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -132,11 +132,11 @@
////////////////////////////////////////////////////////////////////////////////
// sort out what kind of clip mask needs to be created: alpha, stencil,
// scissor, or entirely software
-bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
+bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn) {
fCurrClipMaskType = kNone_ClipMaskType;
GrDrawState* drawState = fGpu->drawState();
- if (!drawState->isClipState() || clipIn.isEmpty()) {
+ if (!drawState->isClipState() || clipDataIn->fClipStack->isEmpty()) {
fGpu->disableScissor();
this->setGpuStencil();
return true;
@@ -150,7 +150,10 @@
GrIRect rtRect;
rtRect.setLTRB(0, 0, rt->width(), rt->height());
- clipIn.getConservativeBounds().roundOut(&bounds);
+
+ GrRect conservativeBounds = clipDataIn->fClipStack->getConservativeBounds();
+
+ conservativeBounds.roundOut(&bounds);
if (!bounds.intersect(rtRect)) {
bounds.setEmpty();
}
@@ -158,20 +161,22 @@
return false;
}
- bool requiresAA = requires_AA(clipIn);
- GrAssert(requiresAA == clipIn.requiresAA());
+ bool requiresAA = requires_AA(*clipDataIn->fClipStack);
+ GrAssert(requiresAA == clipDataIn->fClipStack->requiresAA());
#if GR_SW_CLIP
// If MSAA is enabled we can do everything in the stencil buffer.
// Otherwise check if we should just create the entire clip mask
// in software (this will only happen if the clip mask is anti-aliased
// and too complex for the gpu to handle in its entirety)
- if (0 == rt->numSamples() && requiresAA && this->useSWOnlyPath(clipIn)) {
+ if (0 == rt->numSamples() &&
+ requiresAA &&
+ this->useSWOnlyPath(*clipDataIn->fClipStack)) {
// The clip geometry is complex enough that it will be more
// efficient to create it entirely in software
GrTexture* result = NULL;
GrIRect bound;
- if (this->createSoftwareClipMask(clipIn, &result, &bound)) {
+ if (this->createSoftwareClipMask(*clipDataIn, &result, &bound)) {
setup_drawstate_aaclip(fGpu, result, bound);
fGpu->disableScissor();
this->setGpuStencil();
@@ -193,7 +198,7 @@
// path does (see scissorSettings below)
GrTexture* result = NULL;
GrIRect bound;
- if (this->createAlphaClipMask(clipIn, &result, &bound)) {
+ if (this->createAlphaClipMask(*clipDataIn, &result, &bound)) {
setup_drawstate_aaclip(fGpu, result, bound);
fGpu->disableScissor();
this->setGpuStencil();
@@ -216,18 +221,17 @@
// If the clip is a rectangle then just set the scissor. Otherwise, create
// a stencil mask.
- if (clipIn.isRect()) {
+ if (clipDataIn->fClipStack->isRect()) {
fGpu->enableScissor(bounds);
this->setGpuStencil();
return true;
}
// use the stencil clip if we can't represent the clip as a rectangle.
- bool useStencil = !clipIn.isRect() && !clipIn.isEmpty() &&
- !bounds.isEmpty();
+ bool useStencil = !clipDataIn->fClipStack->isEmpty() && !bounds.isEmpty();
if (useStencil) {
- this->createStencilClipMask(clipIn, bounds);
+ this->createStencilClipMask(*clipDataIn, bounds);
}
// This must occur after createStencilClipMask. That function may change
// the scissor. Also, it only guarantees that the stencil mask is correct
@@ -529,7 +533,7 @@
// Handles caching, determination of clip mask bound & allocation (if needed)
// of the result texture
// Returns true if there is no more work to be done (i.e., we got a cache hit)
-bool GrClipMaskManager::clipMaskPreamble(const GrClip& clipIn,
+bool GrClipMaskManager::clipMaskPreamble(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect* resultBounds) {
GrDrawState* origDrawState = fGpu->drawState();
@@ -544,7 +548,8 @@
// unlike the stencil path the alpha path is not bound to the size of the
// render target - determine the minimum size required for the mask
- GrRect bounds = clipIn.getConservativeBounds();
+ GrRect bounds = clipDataIn.fClipStack->getConservativeBounds();
+
if (!bounds.intersect(rtRect)) {
// the mask will be empty in this case
GrAssert(false);
@@ -560,7 +565,7 @@
// TODO: make sure we don't outset if bounds are still 0,0 @ min
- if (fAACache.canReuse(clipIn,
+ if (fAACache.canReuse(*clipDataIn.fClipStack,
intBounds.width(),
intBounds.height())) {
*result = fAACache.getLastMask();
@@ -568,7 +573,7 @@
return true;
}
- this->setupCache(clipIn, intBounds);
+ this->setupCache(*clipDataIn.fClipStack, intBounds);
*resultBounds = intBounds;
return false;
@@ -576,13 +581,13 @@
////////////////////////////////////////////////////////////////////////////////
// Create a 8-bit clip mask in alpha
-bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
+bool GrClipMaskManager::createAlphaClipMask(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect *resultBounds) {
GrAssert(NULL != resultBounds);
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
- if (this->clipMaskPreamble(clipIn, result, resultBounds)) {
+ if (this->clipMaskPreamble(clipDataIn, result, resultBounds)) {
fCurrClipMaskType = kAlpha_ClipMaskType;
return true;
}
@@ -612,7 +617,7 @@
bool clearToInside;
SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
- GrClip::Iter iter(clipIn, GrClip::Iter::kBottom_IterStart);
+ GrClip::Iter iter(*clipDataIn.fClipStack, GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
*resultBounds,
&clearToInside,
@@ -706,7 +711,7 @@
////////////////////////////////////////////////////////////////////////////////
// Create a 1-bit clip mask in the stencil buffer
-bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
+bool GrClipMaskManager::createStencilClipMask(const GrClipData& clipDataIn,
const GrIRect& bounds) {
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
@@ -723,16 +728,21 @@
return false;
}
- if (stencilBuffer->mustRenderClip(clipIn, rt->width(), rt->height())) {
+ if (stencilBuffer->mustRenderClip(clipDataIn, rt->width(), rt->height())) {
- stencilBuffer->setLastClip(clipIn, rt->width(), rt->height());
+ stencilBuffer->setLastClip(clipDataIn, rt->width(), rt->height());
// we set the current clip to the bounds so that our recursive
// draws are scissored to them. We use the copy of the complex clip
// we just stashed on the SB to render from. We set it back after
// we finish drawing it into the stencil.
- const GrClip& clipCopy = stencilBuffer->getLastClip();
- fGpu->setClip(GrClip(bounds));
+ const GrClipData* oldClipData = fGpu->getClip();
+
+ GrClip newClipStack(bounds);
+ GrClipData newClipData;
+ newClipData.fClipStack = &newClipStack;
+
+ fGpu->setClip(&newClipData);
GrDrawTarget::AutoStateRestore asr(fGpu, GrDrawTarget::kReset_ASRInit);
drawState = fGpu->drawState();
@@ -753,7 +763,8 @@
bool clearToInside;
SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
- GrClip::Iter iter(clipCopy, GrClip::Iter::kBottom_IterStart);
+ GrClip::Iter iter(*oldClipData->fClipStack,
+ GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
rtRect,
&clearToInside,
@@ -811,7 +822,7 @@
fill, fGpu, false,
true);
if (NULL == pr) {
- fGpu->setClip(clipCopy); // restore to the original
+ fGpu->setClip(oldClipData); // restore to the original
return false;
}
canRenderDirectToStencil =
@@ -880,7 +891,7 @@
}
}
// restore clip
- fGpu->setClip(clipCopy);
+ fGpu->setClip(oldClipData);
}
// set this last because recursive draws may overwrite it back to kNone.
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
@@ -1096,12 +1107,12 @@
}
-bool GrClipMaskManager::createSoftwareClipMask(const GrClip& clipIn,
+bool GrClipMaskManager::createSoftwareClipMask(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect* resultBounds) {
GrAssert(kNone_ClipMaskType == fCurrClipMaskType);
- if (this->clipMaskPreamble(clipIn, result, resultBounds)) {
+ if (this->clipMaskPreamble(clipDataIn, result, resultBounds)) {
return true;
}
@@ -1118,7 +1129,7 @@
bool clearToInside;
SkRegion::Op firstOp = SkRegion::kReplace_Op; // suppress warning
- GrClip::Iter iter(clipIn, GrClip::Iter::kBottom_IterStart);
+ GrClip::Iter iter(*clipDataIn.fClipStack, GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = process_initial_clip_elements(&iter,
*resultBounds,
&clearToInside,
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 4346c21..0551b8c 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -33,7 +33,7 @@
*/
class GrClipMaskCache : public GrNoncopyable {
public:
- GrClipMaskCache()
+ GrClipMaskCache()
: fContext(NULL)
, fStack(sizeof(GrClipStackFrame)) {
// We need an initial frame to capture the clip state prior to
@@ -280,7 +280,7 @@
* and sets the GrGpu's scissor and stencil state. If the return is false
* then the draw can be skipped.
*/
- bool setupClipping(const GrClip& clip);
+ bool setupClipping(const GrClipData* clipDataIn);
void releaseResources();
@@ -335,15 +335,15 @@
GrClipMaskCache fAACache; // cache for the AA path
- bool createStencilClipMask(const GrClip& clip,
+ bool createStencilClipMask(const GrClipData& clipDataIn,
const GrIRect& bounds);
- bool createAlphaClipMask(const GrClip& clipIn,
+ bool createAlphaClipMask(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect *resultBounds);
- bool createSoftwareClipMask(const GrClip& clipIn,
+ bool createSoftwareClipMask(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect *resultBounds);
- bool clipMaskPreamble(const GrClip& clipIn,
+ bool clipMaskPreamble(const GrClipData& clipDataIn,
GrTexture** result,
GrIRect *resultBounds);
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index cd2b5a6..e14456a 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -579,10 +579,12 @@
////////////////////////////////////////////////////////////////////////////////
-const GrClip& GrContext::getClip() const { return fGpu->getClip(); }
+const GrClipData* GrContext::getClip() const {
+ return fGpu->getClip();
+}
-void GrContext::setClip(const GrClip& clip) {
- fGpu->setClip(clip);
+void GrContext::setClip(const GrClipData* clipData) {
+ fGpu->setClip(clipData);
fDrawState->enableState(GrDrawState::kClip_StateBit);
}
@@ -1905,7 +1907,7 @@
AutoMatrix avm(this, GrMatrix::I());
AutoClip acs(this, GrRect::MakeWH(SkIntToScalar(srcTexture->width()),
- SkIntToScalar(srcTexture->height())));
+ SkIntToScalar(srcTexture->height())));
GrTextureDesc desc;
desc.fFlags = kRenderTarget_GrTextureFlagBit | kNoStencil_GrTextureFlagBit;
desc.fWidth = SkScalarCeilToInt(rect.width());
diff --git a/src/gpu/GrDrawTarget.cpp b/src/gpu/GrDrawTarget.cpp
index 75a2cd7..8afe5b9 100644
--- a/src/gpu/GrDrawTarget.cpp
+++ b/src/gpu/GrDrawTarget.cpp
@@ -440,7 +440,7 @@
#define DEBUG_INVAL_BUFFER 0xdeadcafe
#define DEBUG_INVAL_START_IDX -1
-GrDrawTarget::GrDrawTarget() {
+GrDrawTarget::GrDrawTarget() : fClip(NULL) {
#if GR_DEBUG
VertexLayoutUnitTest();
#endif
@@ -476,12 +476,12 @@
this->resetIndexSource();
}
-void GrDrawTarget::setClip(const GrClip& clip) {
+void GrDrawTarget::setClip(const GrClipData* clip) {
clipWillBeSet(clip);
fClip = clip;
}
-const GrClip& GrDrawTarget::getClip() const {
+const GrClipData* GrDrawTarget::getClip() const {
return fClip;
}
diff --git a/src/gpu/GrDrawTarget.h b/src/gpu/GrDrawTarget.h
index a51e2cf..3fb6201 100644
--- a/src/gpu/GrDrawTarget.h
+++ b/src/gpu/GrDrawTarget.h
@@ -73,14 +73,14 @@
*
* @param description of the clipping region
*/
- void setClip(const GrClip& clip);
+ void setClip(const GrClipData* clip);
/**
* Gets the current clip.
*
* @return the clip.
*/
- const GrClip& getClip() const;
+ const GrClipData* getClip() const;
/**
* Sets the draw state object for the draw target. Note that this does not
@@ -641,8 +641,8 @@
fTarget->setClip(fClip);
}
private:
- GrDrawTarget* fTarget;
- GrClip fClip;
+ GrDrawTarget* fTarget;
+ const GrClipData* fClip;
};
////////////////////////////////////////////////////////////////////////////
@@ -987,7 +987,7 @@
// subclass overrides to be notified when clip is set. Must call
// INHERITED::clipwillBeSet
- virtual void clipWillBeSet(const GrClip& clip) {}
+ virtual void clipWillBeSet(const GrClipData* clipData) {}
// Helpers for drawRect, protected so subclasses that override drawRect
// can use them.
@@ -1013,7 +1013,7 @@
return this->getGeomSrc().fVertexLayout;
}
- GrClip fClip;
+ const GrClipData* fClip;
GrDrawState* fDrawState;
GrDrawState fDefaultDrawState;
diff --git a/src/gpu/GrInOrderDrawBuffer.cpp b/src/gpu/GrInOrderDrawBuffer.cpp
index d0bb225..d5d03cd 100644
--- a/src/gpu/GrInOrderDrawBuffer.cpp
+++ b/src/gpu/GrInOrderDrawBuffer.cpp
@@ -124,9 +124,10 @@
// simply because the clip has changed if the clip doesn't affect
// the rect.
bool disabledClip = false;
- if (drawState->isClipState() && fClip.isRect()) {
- GrClip::Iter iter(fClip, GrClip::Iter::kBottom_IterStart);
+ if (drawState->isClipState() && fClip->fClipStack->isRect()) {
+
+ GrClip::Iter iter(*fClip->fClipStack, GrClip::Iter::kBottom_IterStart);
const GrClip::Iter::Clip* clip = iter.next();
GrAssert(NULL != clip && NULL != clip->fRect);
@@ -493,6 +494,7 @@
fVertexPool.reset();
fIndexPool.reset();
fClips.reset();
+ fClipOrigins.reset();
fClipSet = true;
this->resetDrawTracking();
@@ -527,6 +529,8 @@
GrDrawState* prevDrawState = target->drawState();
prevDrawState->ref();
+ GrClipData clipData;
+
int currState = 0;
int currClip = 0;
int currClear = 0;
@@ -567,7 +571,9 @@
++currState;
break;
case kSetClip_Cmd:
- target->setClip(fClips[currClip]);
+ clipData.fClipStack = &fClips[currClip];
+ clipData.fOrigin = fClipOrigins[currClip];
+ target->setClip(&clipData);
++currClip;
break;
case kClear_Cmd:
@@ -581,6 +587,7 @@
// we should have consumed all the states, clips, etc.
GrAssert(fStates.count() == currState);
GrAssert(fClips.count() == currClip);
+ GrAssert(fClipOrigins.count() == currClip);
GrAssert(fClears.count() == currClear);
GrAssert(fDraws.count() == currDraw);
@@ -809,7 +816,9 @@
bool GrInOrderDrawBuffer::needsNewClip() const {
if (this->getDrawState().isClipState()) {
- if (fClipSet && fClips.back() != fClip) {
+ if (fClipSet &&
+ (fClips.back() != *fClip->fClipStack ||
+ fClipOrigins.back() != fClip->fOrigin)) {
return true;
}
}
@@ -817,13 +826,15 @@
}
void GrInOrderDrawBuffer::recordClip() {
- fClips.push_back() = fClip;
+ fClips.push_back() = *fClip->fClipStack;
+ fClipOrigins.push_back() = fClip->fOrigin;
fClipSet = false;
fCmds.push_back(kSetClip_Cmd);
}
void GrInOrderDrawBuffer::recordDefaultClip() {
fClips.push_back() = GrClip();
+ fClipOrigins.push_back() = SkIPoint::Make(0, 0);
fCmds.push_back(kSetClip_Cmd);
}
@@ -852,7 +863,7 @@
return &fClears.push_back();
}
-void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
- INHERITED::clipWillBeSet(newClip);
+void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
+ INHERITED::clipWillBeSet(newClipData);
fClipSet = true;
}
diff --git a/src/gpu/GrInOrderDrawBuffer.h b/src/gpu/GrInOrderDrawBuffer.h
index 00cf71a..9dfb18e 100644
--- a/src/gpu/GrInOrderDrawBuffer.h
+++ b/src/gpu/GrInOrderDrawBuffer.h
@@ -196,7 +196,7 @@
virtual void geometrySourceWillPush() SK_OVERRIDE;
virtual void geometrySourceWillPop(
const GeometrySrcState& restoredState) SK_OVERRIDE;
- virtual void clipWillBeSet(const GrClip& newClip) SK_OVERRIDE;
+ virtual void clipWillBeSet(const GrClipData* newClip) SK_OVERRIDE;
// we lazily record state and clip changes in order to skip clips and states
// that have no effect.
@@ -231,7 +231,9 @@
GrSTAllocator<kStatePreallocCnt, StencilPath> fStencilPaths;
GrSTAllocator<kStatePreallocCnt, GrDrawState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;
+
GrSTAllocator<kClipPreallocCnt, GrClip> fClips;
+ GrSTAllocator<kClipPreallocCnt, SkIPoint> fClipOrigins;
GrDrawTarget* fAutoFlushTarget;
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index ddd5b7a..0bf1cab 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -45,9 +45,11 @@
return false;
}
*pathBounds = GrIRect::MakeWH(rt->width(), rt->height());
- const GrClip& clip = target->getClip();
- clip.getConservativeBounds().roundOut(clipBounds);
+ const GrClipData* clipData = target->getClip();
+
+ SkRect conservativeBounds = clipData->fClipStack->getConservativeBounds();
+ conservativeBounds.roundOut(clipBounds);
if (!pathBounds->intersect(*clipBounds)) {
return false;
}
diff --git a/src/gpu/GrStencilBuffer.h b/src/gpu/GrStencilBuffer.h
index 5249ce8..506e5ce 100644
--- a/src/gpu/GrStencilBuffer.h
+++ b/src/gpu/GrStencilBuffer.h
@@ -30,8 +30,12 @@
int numSamples() const { return fSampleCnt; }
// called to note the last clip drawn to this buffer.
- void setLastClip(const GrClip& clip, int width, int height) {
- fLastClip = clip;
+ void setLastClip(const GrClipData& clipData, int width, int height) {
+ // the clip stack needs to be copied separately (and deeply) since
+ // it could change beneath the stencil buffer
+ fLastClipStack = *clipData.fClipStack;
+ fLastClipData.fClipStack = &fLastClipStack;
+ fLastClipData.fOrigin = clipData.fOrigin;
fLastClipWidth = width;
fLastClipHeight = height;
GrAssert(width <= fWidth);
@@ -39,18 +43,18 @@
}
// called to determine if we have to render the clip into SB.
- bool mustRenderClip(const GrClip& clip, int width, int height) const {
+ bool mustRenderClip(const GrClipData& clipData, int width, int height) const {
// The clip is in device space. That is it doesn't scale to fit a
// smaller RT. It is just truncated on the right / bottom edges.
// Note that this assumes that the viewport origin never moves within
// the stencil buffer. This is valid today.
return width > fLastClipWidth ||
height > fLastClipHeight ||
- clip != fLastClip;
+ clipData != fLastClipData;
}
- const GrClip& getLastClip() const {
- return fLastClip;
+ const GrClipData& getLastClip() const {
+ return fLastClipData;
}
// places the sb in the cache and locks it. Caller transfers
@@ -70,7 +74,8 @@
, fHeight(height)
, fBits(bits)
, fSampleCnt(sampleCnt)
- , fLastClip()
+ , fLastClipStack()
+ , fLastClipData()
, fLastClipWidth(-1)
, fLastClipHeight(-1)
, fCacheEntry(NULL)
@@ -93,9 +98,10 @@
int fBits;
int fSampleCnt;
- GrClip fLastClip;
- int fLastClipWidth;
- int fLastClipHeight;
+ GrClip fLastClipStack;
+ GrClipData fLastClipData;
+ int fLastClipWidth;
+ int fLastClipHeight;
GrResourceEntry* fCacheEntry;
int fRTAttachmentCnt;
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 86b73f8..36e6646 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -85,17 +85,19 @@
fExtMatrix.reset();
}
+ const GrClipData* clipData = context->getClip();
+
+ GrRect conservativeBound = clipData->fClipStack->getConservativeBounds();
+
if (!fExtMatrix.isIdentity()) {
GrMatrix inverse;
- GrRect r = context->getClip().getConservativeBounds();
if (fExtMatrix.invert(&inverse)) {
- inverse.mapRect(&r);
- r.roundOut(&fClipRect);
+ inverse.mapRect(&conservativeBound);
}
- } else {
- context->getClip().getConservativeBounds().roundOut(&fClipRect);
}
+ conservativeBound.roundOut(&fClipRect);
+
// save the context's original matrix off and restore in destructor
// this must be done before getTextTarget.
fOrigViewMatrix = fContext->getMatrix();
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index f290239..cb33d76 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -353,12 +353,16 @@
// Canvas promises that this ptr is valid until onDetachFromCanvas is called
fClipStack = canvas->getClipStack();
+
+ fClipData.fClipStack = NULL;
}
void SkGpuDevice::onDetachFromCanvas() {
INHERITED::onDetachFromCanvas();
fClipStack = NULL;
+
+ fClipData.fClipStack = NULL;
}
#ifdef SK_DEBUG
@@ -395,9 +399,11 @@
static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
const SkClipStack& clipStack,
+ GrClipData& clipData,
const SkRegion& clipRegion,
const SkIPoint& origin,
- int renderTargetWidth, int renderTargetHeight) {
+ int renderTargetWidth, int renderTargetHeight,
+ GrClip* result) {
context->setMatrix(matrix);
SkGrClipIterator iter;
@@ -417,15 +423,19 @@
&bounds,
&isIntersectionOfRects);
- GrClip grc(&iter, GrIntToScalar(-origin.x()), GrIntToScalar(-origin.y()),
- bounds);
+ result->setFromIterator(&iter,
+ GrIntToScalar(-origin.x()),
+ GrIntToScalar(-origin.y()),
+ bounds);
- GrAssert(grc.isRect() == isIntersectionOfRects);
+ GrAssert(result->isRect() == isIntersectionOfRects);
- context->setClip(grc);
+ clipData.fClipStack = result;
+ clipData.fOrigin = origin;
+ context->setClip(&clipData);
}
-// call this ever each draw call, to ensure that the context reflects our state,
+// call this every draw call, to ensure that the context reflects our state,
// and not the state from some other canvas/device
void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
GrAssert(NULL != fClipStack);
@@ -436,9 +446,10 @@
fContext->setRenderTarget(fRenderTarget);
SkASSERT(draw.fClipStack && draw.fClipStack == fClipStack);
- convert_matrixclip(fContext, *draw.fMatrix,
- *fClipStack, *draw.fClip, this->getOrigin(),
- fRenderTarget->width(), fRenderTarget->height());
+ convert_matrixclip(fContext, *draw.fMatrix,
+ *fClipStack, fClipData, *draw.fClip, this->getOrigin(),
+ fRenderTarget->width(), fRenderTarget->height(),
+ &fGrClip);
fNeedPrepareRenderTarget = false;
}
}
@@ -458,8 +469,8 @@
this->INHERITED::gainFocus(matrix, clip);
- convert_matrixclip(fContext, matrix, *fClipStack, clip, this->getOrigin(),
- fRenderTarget->width(), fRenderTarget->height());
+ convert_matrixclip(fContext, matrix, *fClipStack, fClipData, clip, this->getOrigin(),
+ fRenderTarget->width(), fRenderTarget->height(), &fGrClip);
DO_DEFERRED_CLEAR;
}
@@ -889,11 +900,14 @@
GrRenderTarget* oldRenderTarget = context->getRenderTarget();
// Once this code moves into GrContext, this should be changed to use
// an AutoClipRestore.
- GrClip oldClip = context->getClip();
+ const GrClipData* oldClipData = context->getClip();
+
context->setRenderTarget(pathTexture->asRenderTarget());
- GrClip newClip(srcRect);
- context->setClip(newClip);
+ GrClip newClipStack(srcRect);
+ GrClipData newClipData;
+ newClipData.fClipStack = &newClipStack;
+ context->setClip(&newClipData);
context->clear(NULL, 0);
GrPaint tempPaint;
@@ -948,7 +962,7 @@
context->drawRect(paint, srcRect);
}
context->setRenderTarget(oldRenderTarget);
- context->setClip(oldClip);
+ context->setClip(oldClipData);
if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
return false;
diff --git a/src/gpu/gl/GrGpuGL_program.cpp b/src/gpu/gl/GrGpuGL_program.cpp
index f4044fc..b7ae6c7 100644
--- a/src/gpu/gl/GrGpuGL_program.cpp
+++ b/src/gpu/gl/GrGpuGL_program.cpp
@@ -436,7 +436,8 @@
GrIRect* rect = NULL;
GrIRect clipBounds;
if (drawState.isClipState()) {
- fClip.getConservativeBounds().roundOut(&clipBounds);
+ GrRect conservativeBounds = fClip->fClipStack->getConservativeBounds();
+ conservativeBounds.roundOut(&clipBounds);
rect = &clipBounds;
}
// This must come after textures are flushed because a texture may need