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
This commit is contained in:
robertphillips@google.com 2012-07-26 18:52:16 +00:00
parent cc6493bbef
commit beb1af78d0
16 changed files with 193 additions and 99 deletions

View File

@ -208,5 +208,40 @@ private:
};
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

View File

@ -329,13 +329,13 @@ public:
* 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:
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 @@ public:
}
}
private:
GrContext* fContext;
GrClip fOldClip;
GrClip fNewClip;
GrContext* fContext;
const GrClipData* fOldClip;
GrClip fNewClipStack;
GrClipData fNewClipData;
};
///////////////////////////////////////////////////////////////////////////

View File

@ -132,6 +132,8 @@ private:
// 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;

View File

@ -513,7 +513,9 @@ bool GrAAHairLinePathRenderer::createGeom(
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();

View File

@ -132,11 +132,11 @@ bool GrClipMaskManager::useSWOnlyPath(const GrClip& clipIn) {
////////////////////////////////////////////////////////////////////////////////
// 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 @@ bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
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 @@ bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
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 @@ bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
// 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 @@ bool GrClipMaskManager::setupClipping(const GrClip& clipIn) {
// 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 @@ void GrClipMaskManager::setupCache(const GrClip& clipIn,
// 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 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClip& clipIn,
// 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 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClip& clipIn,
// 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 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClip& clipIn,
return true;
}
this->setupCache(clipIn, intBounds);
this->setupCache(*clipDataIn.fClipStack, intBounds);
*resultBounds = intBounds;
return false;
@ -576,13 +581,13 @@ bool GrClipMaskManager::clipMaskPreamble(const GrClip& clipIn,
////////////////////////////////////////////////////////////////////////////////
// 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 GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
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 @@ bool GrClipMaskManager::createAlphaClipMask(const GrClip& clipIn,
////////////////////////////////////////////////////////////////////////////////
// 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 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
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 GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
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 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
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 @@ bool GrClipMaskManager::createStencilClipMask(const GrClip& clipIn,
}
}
// 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 @@ GrPathFill invert_fill(GrPathFill fill) {
}
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 GrClipMaskManager::createSoftwareClipMask(const GrClip& clipIn,
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,

View File

@ -33,7 +33,7 @@ class GrDrawState;
*/
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 @@ public:
* 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 @@ private:
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);

View File

@ -579,10 +579,12 @@ bool GrContext::supportsIndex8PixelConfig(const GrTextureParams* params,
////////////////////////////////////////////////////////////////////////////////
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 @@ GrTexture* GrContext::applyMorphology(GrTexture* srcTexture,
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());

View File

@ -440,7 +440,7 @@ void GrDrawTarget::VertexLayoutUnitTest() {
#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 @@ void GrDrawTarget::releaseGeometry() {
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;
}

View File

@ -73,14 +73,14 @@ public:
*
* @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 @@ public:
fTarget->setClip(fClip);
}
private:
GrDrawTarget* fTarget;
GrClip fClip;
GrDrawTarget* fTarget;
const GrClipData* fClip;
};
////////////////////////////////////////////////////////////////////////////
@ -987,7 +987,7 @@ protected:
// 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 @@ protected:
return this->getGeomSrc().fVertexLayout;
}
GrClip fClip;
const GrClipData* fClip;
GrDrawState* fDrawState;
GrDrawState fDefaultDrawState;

View File

@ -124,9 +124,10 @@ void GrInOrderDrawBuffer::drawRect(const GrRect& rect,
// 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 @@ void GrInOrderDrawBuffer::reset() {
fVertexPool.reset();
fIndexPool.reset();
fClips.reset();
fClipOrigins.reset();
fClipSet = true;
this->resetDrawTracking();
@ -527,6 +529,8 @@ bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
GrDrawState* prevDrawState = target->drawState();
prevDrawState->ref();
GrClipData clipData;
int currState = 0;
int currClip = 0;
int currClear = 0;
@ -567,7 +571,9 @@ bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
++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 @@ bool GrInOrderDrawBuffer::playback(GrDrawTarget* target) {
// 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::needsNewState() const {
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 @@ bool GrInOrderDrawBuffer::needsNewClip() const {
}
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 @@ GrInOrderDrawBuffer::Clear* GrInOrderDrawBuffer::recordClear() {
return &fClears.push_back();
}
void GrInOrderDrawBuffer::clipWillBeSet(const GrClip& newClip) {
INHERITED::clipWillBeSet(newClip);
void GrInOrderDrawBuffer::clipWillBeSet(const GrClipData* newClipData) {
INHERITED::clipWillBeSet(newClipData);
fClipSet = true;
}

View File

@ -196,7 +196,7 @@ private:
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 @@ private:
GrSTAllocator<kStatePreallocCnt, StencilPath> fStencilPaths;
GrSTAllocator<kStatePreallocCnt, GrDrawState> fStates;
GrSTAllocator<kClearPreallocCnt, Clear> fClears;
GrSTAllocator<kClipPreallocCnt, GrClip> fClips;
GrSTAllocator<kClipPreallocCnt, SkIPoint> fClipOrigins;
GrDrawTarget* fAutoFlushTarget;

View File

@ -45,9 +45,11 @@ bool get_path_and_clip_bounds(const GrDrawTarget* target,
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;
}

View File

@ -30,8 +30,12 @@ public:
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 @@ public:
}
// 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 @@ protected:
, fHeight(height)
, fBits(bits)
, fSampleCnt(sampleCnt)
, fLastClip()
, fLastClipStack()
, fLastClipData()
, fLastClipWidth(-1)
, fLastClipHeight(-1)
, fCacheEntry(NULL)
@ -93,9 +98,10 @@ private:
int fBits;
int fSampleCnt;
GrClip fLastClip;
int fLastClipWidth;
int fLastClipHeight;
GrClip fLastClipStack;
GrClipData fLastClipData;
int fLastClipWidth;
int fLastClipHeight;
GrResourceEntry* fCacheEntry;
int fRTAttachmentCnt;

View File

@ -85,17 +85,19 @@ GrTextContext::GrTextContext(GrContext* context,
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();

View File

@ -353,12 +353,16 @@ void SkGpuDevice::onAttachToCanvas(SkCanvas* canvas) {
// 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 check_bounds(const SkClipStack& clipStack,
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 @@ static void convert_matrixclip(GrContext* context, const SkMatrix& matrix,
&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 @@ void SkGpuDevice::prepareRenderTarget(const SkDraw& draw) {
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 @@ void SkGpuDevice::gainFocus(const SkMatrix& matrix, const SkRegion& clip) {
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 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
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 @@ bool drawWithGPUMaskFilter(GrContext* context, const SkPath& path,
context->drawRect(paint, srcRect);
}
context->setRenderTarget(oldRenderTarget);
context->setClip(oldClip);
context->setClip(oldClipData);
if (!grp->preConcatSamplerMatricesWithInverse(matrix)) {
return false;

View File

@ -436,7 +436,8 @@ bool GrGpuGL::flushGraphicsState(DrawType type) {
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