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:
parent
cc6493bbef
commit
beb1af78d0
@ -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
|
||||
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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,
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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());
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user