Index: src/gpu/GrClipMaskManager.cpp |
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp |
index e04d444a545e4789954f62f76b88a57f83696d4b..f86aa9de29f7e1eb649972d4b88179505ab1c614 100644 |
--- a/src/gpu/GrClipMaskManager.cpp |
+++ b/src/gpu/GrClipMaskManager.cpp |
@@ -1,4 +1,3 @@ |
- |
/* |
* Copyright 2012 Google Inc. |
* |
@@ -24,17 +23,15 @@ |
#include "effects/GrRRectEffect.h" |
#define GR_AA_CLIP 1 |
- |
typedef SkClipStack::Element Element; |
//////////////////////////////////////////////////////////////////////////////// |
namespace { |
// set up the draw state to enable the aa clipping mask. Besides setting up the |
// stage matrix this also alters the vertex layout |
-void setup_drawstate_aaclip(GrDrawTarget* gpu, |
- GrTexture* result, |
- const SkIRect &devBound) { |
- GrDrawState* drawState = gpu->drawState(); |
+void setup_drawstate_aaclip(const SkIRect &devBound, |
+ GrDrawState* drawState, |
+ GrTexture* result) { |
SkASSERT(drawState); |
SkMatrix mat; |
@@ -58,7 +55,8 @@ void setup_drawstate_aaclip(GrDrawTarget* gpu, |
} |
bool path_needs_SW_renderer(GrContext* context, |
- GrDrawTarget* gpu, |
+ const GrDrawTarget* gpu, |
+ const GrDrawState* drawState, |
const SkPath& origPath, |
const SkStrokeRec& stroke, |
bool doAA) { |
@@ -72,9 +70,8 @@ bool path_needs_SW_renderer(GrContext* context, |
GrPathRendererChain::kColorAntiAlias_DrawType : |
GrPathRendererChain::kColor_DrawType; |
- return NULL == context->getPathRenderer(*path, stroke, gpu, false, type); |
+ return NULL == context->getPathRenderer(gpu, drawState, *path, stroke, false, type); |
} |
- |
} |
/* |
@@ -82,8 +79,8 @@ bool path_needs_SW_renderer(GrContext* context, |
* will be used on any element. If so, it returns true to indicate that the |
* entire clip should be rendered in SW and then uploaded en masse to the gpu. |
*/ |
-bool GrClipMaskManager::useSWOnlyPath(const GrReducedClip::ElementList& elements) { |
- |
+bool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState, |
+ const GrReducedClip::ElementList& elements) { |
// TODO: generalize this function so that when |
// a clip gets complex enough it can just be done in SW regardless |
// of whether it would invoke the GrSoftwarePathRenderer. |
@@ -96,7 +93,7 @@ bool GrClipMaskManager::useSWOnlyPath(const GrReducedClip::ElementList& elements |
if (Element::kRect_Type != element->getType()) { |
SkPath path; |
element->asPath(&path); |
- if (path_needs_SW_renderer(this->getContext(), fClipTarget, path, stroke, |
+ if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawState, path, stroke, |
element->isAA())) { |
return true; |
} |
@@ -105,12 +102,11 @@ bool GrClipMaskManager::useSWOnlyPath(const GrReducedClip::ElementList& elements |
return false; |
} |
-bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& elements, |
+bool GrClipMaskManager::installClipEffects(GrDrawState* drawState, |
GrDrawState::AutoRestoreEffects* are, |
+ const GrReducedClip::ElementList& elements, |
const SkVector& clipToRTOffset, |
const SkRect* drawBounds) { |
- |
- GrDrawState* drawState = fClipTarget->drawState(); |
SkRect boundsInClipSpace; |
if (drawBounds) { |
boundsInClipSpace = *drawBounds; |
@@ -120,10 +116,7 @@ bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& ele |
are->set(drawState); |
GrRenderTarget* rt = drawState->getRenderTarget(); |
GrReducedClip::ElementList::Iter iter(elements); |
- |
- bool setARE = false; |
bool failed = false; |
- |
while (iter.get()) { |
SkRegion::Op op = iter.get()->getOp(); |
bool invert; |
@@ -187,11 +180,7 @@ bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& ele |
break; |
} |
if (fp) { |
- if (!setARE) { |
- are->set(fClipTarget->drawState()); |
- setARE = true; |
- } |
- fClipTarget->drawState()->addCoverageProcessor(fp); |
+ drawState->addCoverageProcessor(fp); |
} else { |
failed = true; |
break; |
@@ -203,18 +192,18 @@ bool GrClipMaskManager::installClipEffects(const GrReducedClip::ElementList& ele |
if (failed) { |
are->set(NULL); |
} |
- |
return !failed; |
} |
//////////////////////////////////////////////////////////////////////////////// |
// sort out what kind of clip mask needs to be created: alpha, stencil, |
// scissor, or entirely software |
-bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
- const SkRect* devBounds, |
+bool GrClipMaskManager::setupClipping(GrDrawState* drawState, |
GrDrawState::AutoRestoreEffects* are, |
GrDrawState::AutoRestoreStencil* ars, |
- ScissorState* scissorState) { |
+ ScissorState* scissorState, |
+ const GrClipData* clipDataIn, |
+ const SkRect* devBounds) { |
fCurrClipMaskType = kNone_ClipMaskType; |
if (kRespectClip_StencilClipMode == fClipMode) { |
fClipMode = kIgnoreClip_StencilClipMode; |
@@ -225,10 +214,8 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
GrReducedClip::InitialState initialState; |
SkIRect clipSpaceIBounds; |
bool requiresAA; |
+ GrRenderTarget* rt = drawState->getRenderTarget(); |
- GrDrawState* drawState = fClipTarget->drawState(); |
- |
- const GrRenderTarget* rt = drawState->getRenderTarget(); |
// GrDrawTarget should have filtered this for us |
SkASSERT(rt); |
@@ -253,7 +240,7 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
} |
if (ignoreClip) { |
- this->setDrawStateStencil(ars); |
+ this->setDrawStateStencil(drawState, ars); |
return true; |
} |
@@ -269,14 +256,15 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
if (elements.isEmpty() || |
- (requiresAA && this->installClipEffects(elements, are, clipToRTOffset, devBounds))) { |
+ (requiresAA && this->installClipEffects(drawState, are, elements, clipToRTOffset, |
+ devBounds))) { |
SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
scissorSpaceIBounds.offset(-clipDataIn->fOrigin); |
if (NULL == devBounds || |
!SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
scissorState->set(scissorSpaceIBounds); |
} |
- this->setDrawStateStencil(ars); |
+ this->setDrawStateStencil(drawState, ars); |
return true; |
} |
} |
@@ -286,7 +274,7 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
if (0 == rt->numSamples() && requiresAA) { |
GrTexture* result = NULL; |
- if (this->useSWOnlyPath(elements)) { |
+ if (this->useSWOnlyPath(drawState, elements)) { |
// The clip geometry is complex enough that it will be more efficient to create it |
// entirely in software |
result = this->createSoftwareClipMask(genID, |
@@ -305,9 +293,8 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
// clipSpace bounds. We determine the mask's position WRT to the render target here. |
SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); |
- are->set(fClipTarget->drawState()); |
- setup_drawstate_aaclip(fClipTarget, result, rtSpaceMaskBounds); |
- this->setDrawStateStencil(ars); |
+ setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result); |
+ this->setDrawStateStencil(drawState, ars); |
return true; |
} |
// if alpha clip mask creation fails fall through to the non-AA code paths |
@@ -323,7 +310,8 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
// use the stencil clip if we can't represent the clip as a rectangle. |
SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; |
- this->createStencilClipMask(genID, |
+ this->createStencilClipMask(rt, |
+ genID, |
initialState, |
elements, |
clipSpaceIBounds, |
@@ -335,27 +323,15 @@ bool GrClipMaskManager::setupClipping(const GrClipData* clipDataIn, |
SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
scissorState->set(scissorSpaceIBounds); |
- this->setDrawStateStencil(ars); |
+ this->setDrawStateStencil(drawState, ars); |
return true; |
} |
-#define VISUALIZE_COMPLEX_CLIP 0 |
- |
-#if VISUALIZE_COMPLEX_CLIP |
- #include "SkRandom.h" |
- SkRandom gRandom; |
- #define SET_RANDOM_COLOR drawState->setColor(0xff000000 | gRandom.nextU()); |
-#else |
- #define SET_RANDOM_COLOR |
-#endif |
- |
namespace { |
- |
//////////////////////////////////////////////////////////////////////////////// |
// set up the OpenGL blend function to perform the specified |
// boolean operation for alpha clip mask creation |
-void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { |
- |
+void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) { |
switch (op) { |
case SkRegion::kReplace_Op: |
drawState->setBlendFunc(kOne_GrBlendCoeff, kZero_GrBlendCoeff); |
@@ -380,14 +356,14 @@ void setup_boolean_blendcoeffs(GrDrawState* drawState, SkRegion::Op op) { |
break; |
} |
} |
- |
} |
//////////////////////////////////////////////////////////////////////////////// |
-bool GrClipMaskManager::drawElement(GrTexture* target, |
+bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
+ GrTexture* target, |
const SkClipStack::Element* element, |
GrPathRenderer* pr) { |
- GrDrawState* drawState = fClipTarget->drawState(); |
+ GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
drawState->setRenderTarget(target->asRenderTarget()); |
@@ -401,11 +377,12 @@ bool GrClipMaskManager::drawElement(GrTexture* target, |
// the entire mask bounds and writes 0 outside the rect. |
if (element->isAA()) { |
this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
+ drawState, |
element->getRect(), |
SkMatrix::I(), |
element->getRect()); |
} else { |
- fClipTarget->drawSimpleRect(element->getRect()); |
+ fClipTarget->drawSimpleRect(drawState, element->getRect()); |
} |
return true; |
default: { |
@@ -420,22 +397,24 @@ bool GrClipMaskManager::drawElement(GrTexture* target, |
GrPathRendererChain::DrawType type; |
type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType : |
GrPathRendererChain::kColor_DrawType; |
- pr = this->getContext()->getPathRenderer(path, stroke, fClipTarget, false, type); |
+ pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, |
+ false, type); |
} |
if (NULL == pr) { |
return false; |
} |
- pr->drawPath(path, stroke, fClipTarget, element->isAA()); |
+ |
+ pr->drawPath(fClipTarget, drawState, path, stroke, element->isAA()); |
break; |
} |
} |
return true; |
} |
-bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, |
- const SkClipStack::Element* element, |
- GrPathRenderer** pr) { |
- GrDrawState* drawState = fClipTarget->drawState(); |
+bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, |
+ GrTexture* target, |
+ GrPathRenderer** pr, |
+ const SkClipStack::Element* element) { |
drawState->setRenderTarget(target->asRenderTarget()); |
if (Element::kRect_Type == element->getType()) { |
@@ -452,24 +431,23 @@ bool GrClipMaskManager::canStencilAndDrawElement(GrTexture* target, |
GrPathRendererChain::DrawType type = element->isAA() ? |
GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : |
GrPathRendererChain::kStencilAndColor_DrawType; |
- *pr = this->getContext()->getPathRenderer(path, stroke, fClipTarget, false, type); |
+ *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, path, stroke, false, |
+ type); |
return SkToBool(*pr); |
} |
} |
-void GrClipMaskManager::mergeMask(GrTexture* dstMask, |
+void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
+ GrTexture* dstMask, |
GrTexture* srcMask, |
SkRegion::Op op, |
const SkIRect& dstBound, |
const SkIRect& srcBound) { |
- GrDrawState::AutoViewMatrixRestore avmr; |
- GrDrawState* drawState = fClipTarget->drawState(); |
- SkAssertResult(avmr.setIdentity(drawState)); |
- GrDrawState::AutoRestoreEffects are(drawState); |
+ SkAssertResult(drawState->setIdentityViewMatrix()); |
drawState->setRenderTarget(dstMask->asRenderTarget()); |
- setup_boolean_blendcoeffs(drawState, op); |
+ setup_boolean_blendcoeffs(op, drawState); |
SkMatrix sampleM; |
sampleM.setIDiv(srcMask->width(), srcMask->height()); |
@@ -480,7 +458,7 @@ void GrClipMaskManager::mergeMask(GrTexture* dstMask, |
GrTextureDomain::MakeTexelDomain(srcMask, srcBound), |
GrTextureDomain::kDecal_Mode, |
GrTextureParams::kNone_FilterMode))->unref(); |
- fClipTarget->drawSimpleRect(SkRect::Make(dstBound)); |
+ fClipTarget->drawSimpleRect(drawState, SkRect::Make(dstBound)); |
} |
GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
@@ -563,13 +541,6 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
// Set the matrix so that rendered clip elements are transformed to mask space from clip space. |
SkMatrix translate; |
translate.setTranslate(clipToMaskOffset); |
- GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::kReset_ASRInit, |
- &translate); |
- |
- GrDrawState* drawState = fClipTarget->drawState(); |
- |
- // We're drawing a coverage mask and want coverage to be run through the blend function. |
- drawState->enableState(GrDrawState::kCoverageDrawing_StateBit); |
// The scratch texture that we are drawing into can be substantially larger than the mask. Only |
// clear the part that we care about. |
@@ -583,18 +554,21 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
// pass must not set values outside of this bounds or stencil values outside the rect won't be |
// cleared. |
GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
- drawState->enableState(GrDrawState::kClip_StateBit); |
- |
SkAutoTUnref<GrTexture> temp; |
+ |
// walk through each clip element and perform its set op |
for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) { |
const Element* element = iter.get(); |
SkRegion::Op op = element->getOp(); |
bool invert = element->isInverseFilled(); |
- |
if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) { |
+ GrDrawState drawState(translate); |
+ // We're drawing a coverage mask and want coverage to be run through the blend function. |
+ drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | |
+ GrDrawState::kClip_StateBit); |
+ |
GrPathRenderer* pr = NULL; |
- bool useTemp = !this->canStencilAndDrawElement(result, element, &pr); |
+ bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &pr, element); |
GrTexture* dst; |
// This is the bounds of the clip element in the space of the alpha-mask. The temporary |
// mask buffer can be substantially larger than the actually clip stack element. We |
@@ -622,11 +596,10 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
dst = temp; |
// clear the temp target and set blend to replace |
fClipTarget->clear(&maskSpaceElementIBounds, |
- invert ? 0xffffffff : 0x00000000, |
- true, |
- dst->asRenderTarget()); |
- setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); |
- |
+ invert ? 0xffffffff : 0x00000000, |
+ true, |
+ dst->asRenderTarget()); |
+ setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); |
} else { |
// draw directly into the result with the stencil set to make the pixels affected |
// by the clip shape be non-zero. |
@@ -638,13 +611,17 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
0xffff, |
0xffff, |
0xffff); |
- drawState->setStencil(kStencilInElement); |
- setup_boolean_blendcoeffs(drawState, op); |
+ drawState.setStencil(kStencilInElement); |
+ setup_boolean_blendcoeffs(op, &drawState); |
} |
- drawState->setAlpha(invert ? 0x00 : 0xff); |
+ drawState.setAlpha(invert ? 0x00 : 0xff); |
- if (!this->drawElement(dst, element, pr)) { |
+ // We have to backup the drawstate because the drawElement call may call into |
+ // renderers which consume it. |
+ GrDrawState backupDrawState(drawState); |
+ |
+ if (!this->drawElement(&drawState, dst, element, pr)) { |
fAACache.reset(); |
return NULL; |
} |
@@ -652,14 +629,15 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
if (useTemp) { |
// Now draw into the accumulator using the real operation and the temp buffer as a |
// texture |
- this->mergeMask(result, |
+ this->mergeMask(&backupDrawState, |
+ result, |
temp, |
op, |
maskSpaceIBounds, |
maskSpaceElementIBounds); |
} else { |
// Draw to the exterior pixels (those with a zero stencil value). |
- drawState->setAlpha(invert ? 0xff : 0x00); |
+ backupDrawState.setAlpha(invert ? 0xff : 0x00); |
GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
kZero_StencilOp, |
kZero_StencilOp, |
@@ -667,15 +645,18 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
0xffff, |
0x0000, |
0xffff); |
- drawState->setStencil(kDrawOutsideElement); |
- fClipTarget->drawSimpleRect(clipSpaceIBounds); |
- drawState->disableStencil(); |
+ backupDrawState.setStencil(kDrawOutsideElement); |
+ fClipTarget->drawSimpleRect(&backupDrawState, clipSpaceIBounds); |
} |
} else { |
+ GrDrawState drawState(translate); |
+ drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | |
+ GrDrawState::kClip_StateBit); |
+ |
// all the remaining ops can just be directly draw into the accumulation buffer |
- drawState->setAlpha(0xff); |
- setup_boolean_blendcoeffs(drawState, op); |
- this->drawElement(result, element); |
+ drawState.setAlpha(0xff); |
+ setup_boolean_blendcoeffs(op, &drawState); |
+ this->drawElement(&drawState, result, element); |
} |
} |
@@ -686,18 +667,13 @@ GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID, |
//////////////////////////////////////////////////////////////////////////////// |
// Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
// (as opposed to canvas) coordinates |
-bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
+bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, |
+ int32_t elementsGenID, |
GrReducedClip::InitialState initialState, |
const GrReducedClip::ElementList& elements, |
const SkIRect& clipSpaceIBounds, |
const SkIPoint& clipSpaceToStencilOffset) { |
- |
SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
- |
- GrDrawState* drawState = fClipTarget->drawState(); |
- SkASSERT(drawState->isClipState()); |
- |
- GrRenderTarget* rt = drawState->getRenderTarget(); |
SkASSERT(rt); |
// TODO: dynamically attach a SB when needed. |
@@ -708,7 +684,6 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
if (stencilBuffer->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) { |
stencilBuffer->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset); |
- |
// Set the matrix so that rendered clip elements are transformed from clip to stencil space. |
SkVector translate = { |
SkIntToScalar(clipSpaceToStencilOffset.fX), |
@@ -716,21 +691,11 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
}; |
SkMatrix matrix; |
matrix.setTranslate(translate); |
- GrDrawTarget::AutoGeometryAndStatePush agasp(fClipTarget, GrDrawTarget::kReset_ASRInit, |
- &matrix); |
- drawState = fClipTarget->drawState(); |
- |
- drawState->setRenderTarget(rt); |
// We set the current clip to the bounds so that our recursive draws are scissored to them. |
SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
GrDrawTarget::AutoClipRestore acr(fClipTarget, stencilSpaceIBounds); |
- drawState->enableState(GrDrawState::kClip_StateBit); |
- |
-#if !VISUALIZE_COMPLEX_CLIP |
- drawState->enableState(GrDrawState::kNoColorWrites_StateBit); |
-#endif |
int clipBit = stencilBuffer->bits(); |
SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers"); |
@@ -744,20 +709,26 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
// with the existing clip. |
for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { |
const Element* element = iter.get(); |
- bool fillInverted = false; |
- // enabled at bottom of loop |
- fClipMode = kIgnoreClip_StencilClipMode; |
+ |
+ GrDrawState drawState(matrix); |
+ drawState.setRenderTarget(rt); |
+ drawState.enableState(GrDrawState::kClip_StateBit); |
+ drawState.enableState(GrDrawState::kNoColorWrites_StateBit); |
+ |
// if the target is MSAA then we want MSAA enabled when the clip is soft |
if (rt->isMultisampled()) { |
- drawState->setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); |
+ drawState.setState(GrDrawState::kHWAntialias_StateBit, element->isAA()); |
} |
+ bool fillInverted = false; |
+ // enabled at bottom of loop |
+ fClipMode = kIgnoreClip_StencilClipMode; |
+ |
// This will be used to determine whether the clip shape can be rendered into the |
// stencil with arbitrary stencil settings. |
GrPathRenderer::StencilSupport stencilSupport; |
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
- |
SkRegion::Op op = element->getOp(); |
GrPathRenderer* pr = NULL; |
@@ -771,9 +742,10 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
if (fillInverted) { |
clipPath.toggleInverseFillType(); |
} |
- pr = this->getContext()->getPathRenderer(clipPath, |
+ pr = this->getContext()->getPathRenderer(fClipTarget, |
+ &drawState, |
+ clipPath, |
stroke, |
- fClipTarget, |
false, |
GrPathRendererChain::kStencilOnly_DrawType, |
&stencilSupport); |
@@ -807,17 +779,17 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
0xffff, |
0x0000, |
0xffff); |
- SET_RANDOM_COLOR |
if (Element::kRect_Type == element->getType()) { |
- *drawState->stencil() = gDrawToStencil; |
- fClipTarget->drawSimpleRect(element->getRect()); |
+ *drawState.stencil() = gDrawToStencil; |
+ fClipTarget->drawSimpleRect(&drawState, element->getRect()); |
} else { |
if (!clipPath.isEmpty()) { |
+ GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
if (canRenderDirectToStencil) { |
- *drawState->stencil() = gDrawToStencil; |
- pr->drawPath(clipPath, stroke, fClipTarget, false); |
+ *drawState.stencil() = gDrawToStencil; |
+ pr->drawPath(fClipTarget, &drawState, clipPath, stroke, false); |
} else { |
- pr->stencilPath(clipPath, stroke, fClipTarget); |
+ pr->stencilPath(fClipTarget, &drawState, clipPath, stroke); |
} |
} |
} |
@@ -827,20 +799,20 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
// element directly or a bounding rect of the entire clip. |
fClipMode = kModifyClip_StencilClipMode; |
for (int p = 0; p < passes; ++p) { |
- *drawState->stencil() = stencilSettings[p]; |
+ GrDrawState drawStateCopy(drawState); |
+ *drawStateCopy.stencil() = stencilSettings[p]; |
+ |
if (canDrawDirectToClip) { |
if (Element::kRect_Type == element->getType()) { |
- SET_RANDOM_COLOR |
- fClipTarget->drawSimpleRect(element->getRect()); |
+ fClipTarget->drawSimpleRect(&drawStateCopy, element->getRect()); |
} else { |
- SET_RANDOM_COLOR |
- pr->drawPath(clipPath, stroke, fClipTarget, false); |
+ GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
+ pr->drawPath(fClipTarget, &drawStateCopy, clipPath, stroke, false); |
} |
} else { |
- SET_RANDOM_COLOR |
// The view matrix is setup to do clip space -> stencil space translation, so |
// draw rect in clip space. |
- fClipTarget->drawSimpleRect(SkRect::Make(clipSpaceIBounds)); |
+ fClipTarget->drawSimpleRect(&drawStateCopy, SkRect::Make(clipSpaceIBounds)); |
} |
} |
} |
@@ -852,7 +824,6 @@ bool GrClipMaskManager::createStencilClipMask(int32_t elementsGenID, |
return true; |
} |
- |
// mapping of clip-respecting stencil funcs to normal stencil funcs |
// mapping depends on whether stencil-clipping is in effect. |
static const GrStencilFunc |
@@ -905,33 +876,32 @@ const GrStencilSettings& basic_apply_stencil_clip_settings() { |
} |
} |
-void GrClipMaskManager::setDrawStateStencil(GrDrawState::AutoRestoreStencil* ars) { |
+void GrClipMaskManager::setDrawStateStencil(GrDrawState* drawState, |
+ GrDrawState::AutoRestoreStencil* ars) { |
// We make two copies of the StencilSettings here (except in the early |
// exit scenario. One copy from draw state to the stack var. Then another |
// from the stack var to the gpu. We could make this class hold a ptr to |
// GrGpu's fStencilSettings and eliminate the stack copy here. |
- const GrDrawState& drawState = fClipTarget->getDrawState(); |
- |
// use stencil for clipping if clipping is enabled and the clip |
// has been written into the stencil. |
- |
GrStencilSettings settings; |
+ |
// The GrGpu client may not be using the stencil buffer but we may need to |
// enable it in order to respect a stencil clip. |
- if (drawState.getStencil().isDisabled()) { |
+ if (drawState->getStencil().isDisabled()) { |
if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { |
settings = basic_apply_stencil_clip_settings(); |
} else { |
return; |
} |
} else { |
- settings = drawState.getStencil(); |
+ settings = drawState->getStencil(); |
} |
// TODO: dynamically attach a stencil buffer |
int stencilBits = 0; |
- GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuffer(); |
+ GrStencilBuffer* stencilBuffer = drawState->getRenderTarget()->getStencilBuffer(); |
if (stencilBuffer) { |
stencilBits = stencilBuffer->bits(); |
} |
@@ -939,8 +909,8 @@ void GrClipMaskManager::setDrawStateStencil(GrDrawState::AutoRestoreStencil* ars |
SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); |
SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); |
this->adjustStencilParams(&settings, fClipMode, stencilBits); |
- ars->set(fClipTarget->drawState()); |
- fClipTarget->drawState()->setStencil(settings); |
+ ars->set(drawState); |
+ drawState->setStencil(settings); |
} |
void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, |
@@ -1045,14 +1015,12 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, |
SkMatrix matrix; |
matrix.setTranslate(SkIntToScalar(-clipSpaceIBounds.fLeft), |
SkIntToScalar(-clipSpaceIBounds.fTop)); |
- helper.init(maskSpaceIBounds, &matrix, false); |
+ helper.init(maskSpaceIBounds, &matrix, false); |
helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00); |
- |
SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) { |
- |
const Element* element = iter.get(); |
SkRegion::Op op = element->getOp(); |
@@ -1066,12 +1034,10 @@ GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID, |
// invert the entire scene |
helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF); |
} |
- |
SkPath clipPath; |
element->asPath(&clipPath); |
clipPath.toggleInverseFillType(); |
helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00); |
- |
continue; |
} |
@@ -1108,14 +1074,11 @@ void GrClipMaskManager::setClipTarget(GrClipTarget* clipTarget) { |
fAACache.setContext(clipTarget->getContext()); |
} |
-void GrClipMaskManager::adjustPathStencilParams(GrStencilSettings* settings) { |
- const GrDrawState& drawState = fClipTarget->getDrawState(); |
- |
+void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBuffer, |
+ GrStencilSettings* settings) { |
// TODO: dynamically attach a stencil buffer |
- int stencilBits = 0; |
- GrStencilBuffer* stencilBuffer = drawState.getRenderTarget()->getStencilBuffer(); |
if (stencilBuffer) { |
- stencilBits = stencilBuffer->bits(); |
+ int stencilBits = stencilBuffer->bits(); |
this->adjustStencilParams(settings, fClipMode, stencilBits); |
} |
} |