| 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);
|
| }
|
| }
|
|
|