Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2012 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #include "GrClipMaskManager.h"
      9 #include "GrCaps.h"
     10 #include "GrDrawingManager.h"
     11 #include "GrDrawContext.h"
     12 #include "GrDrawTarget.h"
     13 #include "GrGpuResourcePriv.h"
     14 #include "GrPaint.h"
     15 #include "GrPathRenderer.h"
     16 #include "GrRenderTarget.h"
     17 #include "GrRenderTargetPriv.h"
     18 #include "GrResourceProvider.h"
     19 #include "GrStencilAttachment.h"
     20 #include "GrSWMaskHelper.h"
     21 #include "SkRasterClip.h"
     22 #include "SkTLazy.h"
     23 #include "batches/GrRectBatchFactory.h"
     24 #include "effects/GrConvexPolyEffect.h"
     25 #include "effects/GrPorterDuffXferProcessor.h"
     26 #include "effects/GrRRectEffect.h"
     27 #include "effects/GrTextureDomain.h"
     28 
     29 typedef SkClipStack::Element Element;
     30 
     31 ////////////////////////////////////////////////////////////////////////////////
     32 // set up the draw state to enable the aa clipping mask. Besides setting up the
     33 // stage matrix this also alters the vertex layout
     34 static const GrFragmentProcessor* create_fp_for_mask(GrTexture* result, const SkIRect &devBound) {
     35     SkMatrix mat;
     36     // We use device coords to compute the texture coordinates. We set our matrix to be a
     37     // translation to the devBound, and then a scaling matrix to normalized coords.
     38     mat.setIDiv(result->width(), result->height());
     39     mat.preTranslate(SkIntToScalar(-devBound.fLeft),
     40                      SkIntToScalar(-devBound.fTop));
     41 
     42     SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
     43     return GrTextureDomainEffect::Create(result,
     44                                          mat,
     45                                          GrTextureDomain::MakeTexelDomain(result, domainTexels),
     46                                          GrTextureDomain::kDecal_Mode,
     47                                          GrTextureParams::kNone_FilterMode,
     48                                          kDevice_GrCoordSet);
     49 }
     50 
     51 static void draw_non_aa_rect(GrDrawTarget* drawTarget,
     52                              const GrPipelineBuilder& pipelineBuilder,
     53                              GrColor color,
     54                              const SkMatrix& viewMatrix,
     55                              const SkRect& rect) {
     56     SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, viewMatrix, rect,
     57                                                                         nullptr, nullptr));
     58     drawTarget->drawBatch(pipelineBuilder, batch);
     59 }
     60 
     61 // Does the path in 'element' require SW rendering? If so, return true (and,
     62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set
     63 // 'prOut' to the non-SW path renderer that will do the job).
     64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context,
     65                                             bool isStencilDisabled,
     66                                             const GrRenderTarget* rt,
     67                                             const SkMatrix& viewMatrix,
     68                                             const Element* element,
     69                                             GrPathRenderer** prOut,
     70                                             bool needsStencil) {
     71     if (Element::kRect_Type == element->getType()) {
     72         // rects can always be drawn directly w/o using the software path
     73         // TODO: skip rrects once we're drawing them directly.
     74         if (prOut) {
     75             *prOut = nullptr;
     76         }
     77         return false;
     78     } else {
     79         // We shouldn't get here with an empty clip element.
     80         SkASSERT(Element::kEmpty_Type != element->getType());
     81 
     82         // the gpu alpha mask will draw the inverse paths as non-inverse to a temp buffer
     83         SkPath path;
     84         element->asPath(&path);
     85         if (path.isInverseFillType()) {
     86             path.toggleInverseFillType();
     87         }
     88         GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
     89 
     90         GrPathRendererChain::DrawType type;
     91 
     92         if (needsStencil) {
     93             type = element->isAA()
     94                             ? GrPathRendererChain::kStencilAndColorAntiAlias_DrawType
     95                             : GrPathRendererChain::kStencilAndColor_DrawType;
     96         } else {
     97             type = element->isAA()
     98                             ? GrPathRendererChain::kColorAntiAlias_DrawType
     99                             : GrPathRendererChain::kColor_DrawType;
    100         }
    101 
    102         GrPathRenderer::CanDrawPathArgs canDrawArgs;
    103         canDrawArgs.fShaderCaps = context->caps()->shaderCaps();
    104         canDrawArgs.fViewMatrix = &viewMatrix;
    105         canDrawArgs.fPath = &path;
    106         canDrawArgs.fStroke = &stroke;
    107         canDrawArgs.fAntiAlias = element->isAA();
    108         canDrawArgs.fIsStencilDisabled = isStencilDisabled;
    109         canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
    110 
    111         // the 'false' parameter disallows use of the SW path renderer
    112         GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawArgs, false, type);
    113         if (prOut) {
    114             *prOut = pr;
    115         }
    116         return SkToBool(!pr);
    117     }
    118 }
    119 
    120 // Determines whether it is possible to draw the element to both the stencil buffer and the
    121 // alpha mask simultaneously. If so and the element is a path a compatible path renderer is
    122 // also returned.
    123 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context,
    124                                                    GrTexture* texture,
    125                                                    const SkMatrix& viewMatrix,
    126                                                    const SkClipStack::Element* element) {
    127     GrPathRenderer* pr;
    128     static const bool kNeedsStencil = true;
    129     static const bool kStencilIsDisabled = true;
    130     PathNeedsSWRenderer(context,
    131                         kStencilIsDisabled,
    132                         texture->asRenderTarget(),
    133                         viewMatrix,
    134                         element,
    135                         &pr,
    136                         kNeedsStencil);
    137     return pr;
    138 }
    139 
    140 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBatchToBounds)
    141     : fDrawTarget(drawTarget)
    142     , fClipMode(kIgnoreClip_StencilClipMode)
    143     , fDebugClipBatchToBounds(debugClipBatchToBounds) {
    144 }
    145 
    146 GrContext* GrClipMaskManager::getContext() {
    147     return fDrawTarget->cmmAccess().context();
    148 }
    149 
    150 const GrCaps* GrClipMaskManager::caps() const {
    151     return fDrawTarget->caps();
    152 }
    153 
    154 GrResourceProvider* GrClipMaskManager::resourceProvider() {
    155     return fDrawTarget->cmmAccess().resourceProvider();
    156 }
    157 /*
    158  * This method traverses the clip stack to see if the GrSoftwarePathRenderer
    159  * will be used on any element. If so, it returns true to indicate that the
    160  * entire clip should be rendered in SW and then uploaded en masse to the gpu.
    161  */
    162 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
    163                                       const GrRenderTarget* rt,
    164                                       const SkVector& clipToMaskOffset,
    165                                       const GrReducedClip::ElementList& elements) {
    166     // TODO: generalize this function so that when
    167     // a clip gets complex enough it can just be done in SW regardless
    168     // of whether it would invoke the GrSoftwarePathRenderer.
    169 
    170     // Set the matrix so that rendered clip elements are transformed to mask space from clip
    171     // space.
    172     const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
    173 
    174     for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
    175         const Element* element = iter.get();
    176 
    177         SkRegion::Op op = element->getOp();
    178         bool invert = element->isInverseFilled();
    179         bool needsStencil = invert ||
    180                             SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op;
    181 
    182         if (PathNeedsSWRenderer(this->getContext(), pipelineBuilder.getStencil().isDisabled(),
    183                                 rt, translate, element, nullptr, needsStencil)) {
    184             return true;
    185         }
    186     }
    187     return false;
    188 }
    189 
    190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementList& elements,
    191                                                  bool abortIfAA,
    192                                                  SkVector& clipToRTOffset,
    193                                                  const SkRect* drawBounds,
    194                                                  const GrFragmentProcessor** resultFP) {
    195     SkRect boundsInClipSpace;
    196     if (drawBounds) {
    197         boundsInClipSpace = *drawBounds;
    198         boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY);
    199     }
    200     SkASSERT(elements.count() <= kMaxAnalyticElements);
    201     const GrFragmentProcessor* fps[kMaxAnalyticElements];
    202     for (int i = 0; i < kMaxAnalyticElements; ++i) {
    203         fps[i] = nullptr;
    204     }
    205     int fpCnt = 0;
    206     GrReducedClip::ElementList::Iter iter(elements);
    207     bool failed = false;
    208     while (iter.get()) {
    209         SkRegion::Op op = iter.get()->getOp();
    210         bool invert;
    211         bool skip = false;
    212         switch (op) {
    213             case SkRegion::kReplace_Op:
    214                 SkASSERT(iter.get() == elements.head());
    215                 // Fallthrough, handled same as intersect.
    216             case SkRegion::kIntersect_Op:
    217                 invert = false;
    218                 if (drawBounds && iter.get()->contains(boundsInClipSpace)) {
    219                     skip = true;
    220                 }
    221                 break;
    222             case SkRegion::kDifference_Op:
    223                 invert = true;
    224                 // We don't currently have a cheap test for whether a rect is fully outside an
    225                 // element's primitive, so don't attempt to set skip.
    226                 break;
    227             default:
    228                 failed = true;
    229                 break;
    230         }
    231         if (failed) {
    232             break;
    233         }
    234         if (!skip) {
    235             GrPrimitiveEdgeType edgeType;
    236             if (iter.get()->isAA()) {
    237                 if (abortIfAA) {
    238                     failed = true;
    239                     break;
    240                 }
    241                 edgeType =
    242                     invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProcessorEdgeType;
    243             } else {
    244                 edgeType =
    245                     invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProcessorEdgeType;
    246             }
    247 
    248             switch (iter.get()->getType()) {
    249                 case SkClipStack::Element::kPath_Type:
    250                     fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, iter.get()->getPath(),
    251                                                             &clipToRTOffset);
    252                     break;
    253                 case SkClipStack::Element::kRRect_Type: {
    254                     SkRRect rrect = iter.get()->getRRect();
    255                     rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
    256                     fps[fpCnt] = GrRRectEffect::Create(edgeType, rrect);
    257                     break;
    258                 }
    259                 case SkClipStack::Element::kRect_Type: {
    260                     SkRect rect = iter.get()->getRect();
    261                     rect.offset(clipToRTOffset.fX, clipToRTOffset.fY);
    262                     fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, rect);
    263                     break;
    264                 }
    265                 default:
    266                     break;
    267             }
    268             if (!fps[fpCnt]) {
    269                 failed = true;
    270                 break;
    271             }
    272             fpCnt++;
    273         }
    274         iter.next();
    275     }
    276 
    277     *resultFP = nullptr;
    278     if (!failed && fpCnt) {
    279         *resultFP = GrFragmentProcessor::RunInSeries(fps, fpCnt);
    280     }
    281     for (int i = 0; i < fpCnt; ++i) {
    282         fps[i]->unref();
    283     }
    284     return !failed;
    285 }
    286 
    287 static void add_rect_to_clip(const GrClip& clip, const SkRect& devRect, GrClip* out) {
    288     switch (clip.clipType()) {
    289         case GrClip::kClipStack_ClipType: {
    290             SkClipStack* stack = new SkClipStack;
    291             *stack = *clip.clipStack();
    292             // The stack is actually in clip space not device space.
    293             SkRect clipRect = devRect;
    294             SkPoint origin = { SkIntToScalar(clip.origin().fX), SkIntToScalar(clip.origin().fY) };
    295             clipRect.offset(origin);
    296             SkIRect iclipRect;
    297             clipRect.roundOut(&iclipRect);
    298             clipRect = SkRect::Make(iclipRect);
    299             stack->clipDevRect(clipRect, SkRegion::kIntersect_Op, false);
    300             out->setClipStack(stack, &clip.origin());
    301             break;
    302         }
    303         case GrClip::kWideOpen_ClipType:
    304             *out = GrClip(devRect);
    305             break;
    306         case GrClip::kIRect_ClipType: {
    307             SkIRect intersect;
    308             devRect.roundOut(&intersect);
    309             if (intersect.intersect(clip.irect())) {
    310                 *out = GrClip(intersect);
    311             } else {
    312                 *out = clip;
    313             }
    314             break;
    315         }
    316     }
    317 }
    318 
    319 ////////////////////////////////////////////////////////////////////////////////
    320 // sort out what kind of clip mask needs to be created: alpha, stencil,
    321 // scissor, or entirely software
    322 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder,
    323                                       GrPipelineBuilder::AutoRestoreStencil* ars,
    324                                       const SkRect* devBounds,
    325                                       GrAppliedClip* out) {
    326     if (kRespectClip_StencilClipMode == fClipMode) {
    327         fClipMode = kIgnoreClip_StencilClipMode;
    328     }
    329 
    330     GrReducedClip::ElementList elements;
    331     int32_t genID = 0;
    332     GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialState;
    333     SkIRect clipSpaceIBounds;
    334     bool requiresAA = false;
    335     GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
    336 
    337     // GrDrawTarget should have filtered this for us
    338     SkASSERT(rt);
    339 
    340     SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height());
    341     GrClip devBoundsClip;
    342     bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds;
    343     if (doDevBoundsClip) {
    344         add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip);
    345     }
    346     const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip();
    347 
    348     if (clip.isWideOpen(clipSpaceRTIBounds)) {
    349         this->setPipelineBuilderStencil(pipelineBuilder, ars);
    350         return true;
    351     }
    352 
    353     // The clip mask manager always draws with a single IRect so we special case that logic here
    354     // Image filters just use a rect, so we also special case that logic
    355     switch (clip.clipType()) {
    356         case GrClip::kWideOpen_ClipType:
    357             SkFAIL("Should have caught this with clip.isWideOpen()");
    358             return true;
    359         case GrClip::kIRect_ClipType: {
    360             SkIRect scissor = clip.irect();
    361             if (scissor.intersect(clipSpaceRTIBounds)) {
    362                 out->fScissorState.set(scissor);
    363                 this->setPipelineBuilderStencil(pipelineBuilder, ars);
    364                 return true;
    365             }
    366             return false;
    367         }
    368         case GrClip::kClipStack_ClipType: {
    369             clipSpaceRTIBounds.offset(clip.origin());
    370             SkIRect clipSpaceReduceQueryBounds;
    371 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 1
    372             if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) {
    373                 SkIRect devIBounds = devBounds->roundOut();
    374                 devIBounds.offset(clip.origin());
    375                 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds)) {
    376                     return false;
    377                 }
    378             } else {
    379                 clipSpaceReduceQueryBounds = clipSpaceRTIBounds;
    380             }
    381             GrReducedClip::ReduceClipStack(*clip.clipStack(),
    382                                             clipSpaceReduceQueryBounds,
    383                                             &elements,
    384                                             &genID,
    385                                             &initialState,
    386                                             &clipSpaceIBounds,
    387                                             &requiresAA);
    388             if (elements.isEmpty()) {
    389                 if (GrReducedClip::kAllIn_InitialState == initialState) {
    390                     if (clipSpaceIBounds == clipSpaceRTIBounds) {
    391                         this->setPipelineBuilderStencil(pipelineBuilder, ars);
    392                         return true;
    393                     }
    394                 } else {
    395                     return false;
    396                 }
    397             }
    398         } break;
    399     }
    400 
    401     // An element count of 4 was chosen because of the common pattern in Blink of:
    402     //   isect RR
    403     //   diff  RR
    404     //   isect convex_poly
    405     //   isect convex_poly
    406     // when drawing rounded div borders. This could probably be tuned based on a
    407     // configuration's relative costs of switching RTs to generate a mask vs
    408     // longer shaders.
    409     if (elements.count() <= kMaxAnalyticElements) {
    410         SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX),
    411                                     SkIntToScalar(-clip.origin().fY) };
    412         // When there are multiple samples we want to do per-sample clipping, not compute a
    413         // fractional pixel coverage.
    414         bool disallowAnalyticAA = rt->isUnifiedMultisampled() || pipelineBuilder.hasMixedSamples();
    415         const GrFragmentProcessor* clipFP = nullptr;
    416         if (elements.isEmpty() ||
    417             (requiresAA &&
    418              this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipToRTOffset, devBounds,
    419                                             &clipFP))) {
    420             SkIRect scissorSpaceIBounds(clipSpaceIBounds);
    421             scissorSpaceIBounds.offset(-clip.origin());
    422             if (nullptr == devBounds ||
    423                 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) {
    424                 out->fScissorState.set(scissorSpaceIBounds);
    425             }
    426             this->setPipelineBuilderStencil(pipelineBuilder, ars);
    427             out->fClipCoverageFP.reset(clipFP);
    428             return true;
    429         }
    430     }
    431 
    432     // If the stencil buffer is multisampled we can use it to do everything.
    433     if (!rt->isStencilBufferMultisampled() && requiresAA) {
    434         SkAutoTUnref<GrTexture> result;
    435 
    436         // The top-left of the mask corresponds to the top-left corner of the bounds.
    437         SkVector clipToMaskOffset = {
    438             SkIntToScalar(-clipSpaceIBounds.fLeft),
    439             SkIntToScalar(-clipSpaceIBounds.fTop)
    440         };
    441 
    442         if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)) {
    443             // The clip geometry is complex enough that it will be more efficient to create it
    444             // entirely in software
    445             result.reset(this->createSoftwareClipMask(genID,
    446                                                       initialState,
    447                                                       elements,
    448                                                       clipToMaskOffset,
    449                                                       clipSpaceIBounds));
    450         } else {
    451             result.reset(this->createAlphaClipMask(genID,
    452                                                    initialState,
    453                                                    elements,
    454                                                    clipToMaskOffset,
    455                                                    clipSpaceIBounds));
    456             // If createAlphaClipMask fails it means useSWOnlyPath has a bug
    457             SkASSERT(result);
    458         }
    459 
    460         if (result) {
    461             // The mask's top left coord should be pinned to the rounded-out top left corner of
    462             // clipSpace bounds. We determine the mask's position WRT to the render target here.
    463             SkIRect rtSpaceMaskBounds = clipSpaceIBounds;
    464             rtSpaceMaskBounds.offset(-clip.origin());
    465             out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBounds));
    466             this->setPipelineBuilderStencil(pipelineBuilder, ars);
    467             return true;
    468         }
    469         // if alpha clip mask creation fails fall through to the non-AA code paths
    470     }
    471 
    472     // use the stencil clip if we can't represent the clip as a rectangle.
    473     SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin();
    474     this->createStencilClipMask(rt,
    475                                 genID,
    476                                 initialState,
    477                                 elements,
    478                                 clipSpaceIBounds,
    479                                 clipSpaceToStencilSpaceOffset);
    480 
    481     // This must occur after createStencilClipMask. That function may change the scissor. Also, it
    482     // only guarantees that the stencil mask is correct within the bounds it was passed, so we must
    483     // use both stencil and scissor test to the bounds for the final draw.
    484     SkIRect scissorSpaceIBounds(clipSpaceIBounds);
    485     scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset);
    486     out->fScissorState.set(scissorSpaceIBounds);
    487     this->setPipelineBuilderStencil(pipelineBuilder, ars);
    488     return true;
    489 }
    490 
    491 namespace {
    492 ////////////////////////////////////////////////////////////////////////////////
    493 // Set a coverage drawing XPF on the pipelineBuilder for the given op and invertCoverage mode
    494 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage,
    495                               GrPipelineBuilder* pipelineBuilder) {
    496     SkASSERT(op <= SkRegion::kLastOp);
    497     pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage);
    498 }
    499 }
    500 
    501 ////////////////////////////////////////////////////////////////////////////////
    502 bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder,
    503                                     const SkMatrix& viewMatrix,
    504                                     GrTexture* target,
    505                                     const SkClipStack::Element* element,
    506                                     GrPathRenderer* pr) {
    507 
    508     GrRenderTarget* rt = target->asRenderTarget();
    509     pipelineBuilder->setRenderTarget(rt);
    510 
    511     // The color we use to draw does not matter since we will always be using a GrCoverageSetOpXP
    512     // which ignores color.
    513     GrColor color = GrColor_WHITE;
    514 
    515     // TODO: Draw rrects directly here.
    516     switch (element->getType()) {
    517         case Element::kEmpty_Type:
    518             SkDEBUGFAIL("Should never get here with an empty element.");
    519             break;
    520         case Element::kRect_Type: {
    521             // TODO: Do rects directly to the accumulator using a aa-rect GrProcessor that covers
    522             // the entire mask bounds and writes 0 outside the rect.
    523             if (element->isAA()) {
    524                 SkRect devRect = element->getRect();
    525                 viewMatrix.mapRect(&devRect);
    526 
    527                 SkAutoTUnref<GrDrawBatch> batch(
    528                         GrRectBatchFactory::CreateAAFill(color, viewMatrix, element->getRect(),
    529                                                          devRect));
    530 
    531                 fDrawTarget->drawBatch(*pipelineBuilder, batch);
    532             } else {
    533                 draw_non_aa_rect(fDrawTarget, *pipelineBuilder, color, viewMatrix,
    534                                  element->getRect());
    535             }
    536             return true;
    537         }
    538         default: {
    539             SkPath path;
    540             element->asPath(&path);
    541             if (path.isInverseFillType()) {
    542                 path.toggleInverseFillType();
    543             }
    544             GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
    545             if (nullptr == pr) {
    546                 GrPathRendererChain::DrawType type;
    547                 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_DrawType :
    548                                          GrPathRendererChain::kColor_DrawType;
    549 
    550                 GrPathRenderer::CanDrawPathArgs canDrawArgs;
    551                 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
    552                 canDrawArgs.fViewMatrix = &viewMatrix;
    553                 canDrawArgs.fPath = &path;
    554                 canDrawArgs.fStroke = &stroke;
    555                 canDrawArgs.fAntiAlias = element->isAA();;
    556                 canDrawArgs.fIsStencilDisabled = pipelineBuilder->getStencil().isDisabled();
    557                 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
    558 
    559                 pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false, type);
    560             }
    561             if (nullptr == pr) {
    562                 return false;
    563             }
    564             GrPathRenderer::DrawPathArgs args;
    565             args.fTarget = fDrawTarget;
    566             args.fResourceProvider = this->getContext()->resourceProvider();
    567             args.fPipelineBuilder = pipelineBuilder;
    568             args.fColor = color;
    569             args.fViewMatrix = &viewMatrix;
    570             args.fPath = &path;
    571             args.fStroke = &stroke;
    572             args.fAntiAlias = element->isAA();
    573             pr->drawPath(args);
    574             break;
    575         }
    576     }
    577     return true;
    578 }
    579 
    580 ////////////////////////////////////////////////////////////////////////////////
    581 // Create a 8-bit clip mask in alpha
    582 
    583 static void GetClipMaskKey(int32_t clipGenID, const SkIRect& bounds, GrUniqueKey* key) {
    584     static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
    585     GrUniqueKey::Builder builder(key, kDomain, 3);
    586     builder[0] = clipGenID;
    587     builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16);
    588     builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16);
    589 }
    590 
    591 GrTexture* GrClipMaskManager::createCachedMask(int width, int height, const GrUniqueKey& key,
    592                                                bool renderTarget) {
    593     GrSurfaceDesc desc;
    594     desc.fWidth = width;
    595     desc.fHeight = height;
    596     desc.fFlags = renderTarget ? kRenderTarget_GrSurfaceFlag : kNone_GrSurfaceFlags;
    597     if (!renderTarget || this->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) {
    598         desc.fConfig = kAlpha_8_GrPixelConfig;
    599     } else {
    600         desc.fConfig = kRGBA_8888_GrPixelConfig;
    601     }
    602 
    603     GrTexture* texture = this->resourceProvider()->createApproxTexture(desc, 0);
    604     if (!texture) {
    605         return nullptr;
    606     }
    607     texture->resourcePriv().setUniqueKey(key);
    608     return texture;
    609 }
    610 
    611 GrTexture* GrClipMaskManager::createAlphaClipMask(int32_t elementsGenID,
    612                                                   GrReducedClip::InitialState initialState,
    613                                                   const GrReducedClip::ElementList& elements,
    614                                                   const SkVector& clipToMaskOffset,
    615                                                   const SkIRect& clipSpaceIBounds) {
    616     GrResourceProvider* resourceProvider = this->resourceProvider();
    617     GrUniqueKey key;
    618     GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
    619     if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
    620         return texture;
    621     }
    622 
    623     // There's no texture in the cache. Let's try to allocate it then.
    624     SkAutoTUnref<GrTexture> texture(this->createCachedMask(
    625         clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
    626     if (!texture) {
    627         return nullptr;
    628     }
    629 
    630     // Set the matrix so that rendered clip elements are transformed to mask space from clip
    631     // space.
    632     const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMaskOffset.fY);
    633 
    634     // The texture may be larger than necessary, this rect represents the part of the texture
    635     // we populate with a rasterization of the clip.
    636     SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
    637 
    638     // The scratch texture that we are drawing into can be substantially larger than the mask. Only
    639     // clear the part that we care about.
    640     fDrawTarget->clear(&maskSpaceIBounds,
    641                        GrReducedClip::kAllIn_InitialState == initialState ? 0xffffffff : 0x00000000,
    642                        true,
    643                        texture->asRenderTarget());
    644 
    645     // When we use the stencil in the below loop it is important to have this clip installed.
    646     // The second pass that zeros the stencil buffer renders the rect maskSpaceIBounds so the first
    647     // pass must not set values outside of this bounds or stencil values outside the rect won't be
    648     // cleared.
    649     const GrClip clip(maskSpaceIBounds);
    650 
    651     // walk through each clip element and perform its set op
    652     for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get(); iter.next()) {
    653         const Element* element = iter.get();
    654         SkRegion::Op op = element->getOp();
    655         bool invert = element->isInverseFilled();
    656         if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
    657 
    658             GrPathRenderer* pr = GetPathRenderer(this->getContext(),
    659                                                  texture, translate, element);
    660             if (Element::kRect_Type != element->getType() && !pr) {
    661                 // useSWOnlyPath should now filter out all cases where gpu-side mask merging would
    662                 // be performed (i.e., pr would be NULL for a non-rect path). See https://bug.skia.org/4519
    663                 // for rationale and details.
    664                 SkASSERT(0);
    665                 continue;
    666             }
    667 
    668             {
    669                 GrPipelineBuilder pipelineBuilder;
    670 
    671                 pipelineBuilder.setClip(clip);
    672                 pipelineBuilder.setRenderTarget(texture->asRenderTarget());
    673                 SkASSERT(pipelineBuilder.getStencil().isDisabled());
    674 
    675                 // draw directly into the result with the stencil set to make the pixels affected
    676                 // by the clip shape be non-zero.
    677                 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement,
    678                                              kReplace_StencilOp,
    679                                              kReplace_StencilOp,
    680                                              kAlways_StencilFunc,
    681                                              0xffff,
    682                                              0xffff,
    683                                              0xffff);
    684                 pipelineBuilder.setStencil(kStencilInElement);
    685                 set_coverage_drawing_xpf(op, invert, &pipelineBuilder);
    686 
    687                 if (!this->drawElement(&pipelineBuilder, translate, texture, element, pr)) {
    688                     texture->resourcePriv().removeUniqueKey();
    689                     return nullptr;
    690                 }
    691             }
    692 
    693             {
    694                 GrPipelineBuilder backgroundPipelineBuilder;
    695                 backgroundPipelineBuilder.setRenderTarget(texture->asRenderTarget());
    696 
    697                 set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder);
    698                 // Draw to the exterior pixels (those with a zero stencil value).
    699                 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement,
    700                                              kZero_StencilOp,
    701                                              kZero_StencilOp,
    702                                              kEqual_StencilFunc,
    703                                              0xffff,
    704                                              0x0000,
    705                                              0xffff);
    706                 backgroundPipelineBuilder.setStencil(kDrawOutsideElement);
    707 
    708                 // The color passed in here does not matter since the coverageSetOpXP won't read it.
    709                 draw_non_aa_rect(fDrawTarget, backgroundPipelineBuilder, GrColor_WHITE, translate,
    710                                  SkRect::Make(clipSpaceIBounds));
    711             }
    712         } else {
    713             GrPipelineBuilder pipelineBuilder;
    714 
    715             // all the remaining ops can just be directly draw into the accumulation buffer
    716             set_coverage_drawing_xpf(op, false, &pipelineBuilder);
    717             // The color passed in here does not matter since the coverageSetOpXP won't read it.
    718             this->drawElement(&pipelineBuilder, translate, texture, element);
    719         }
    720     }
    721 
    722     return texture.detach();
    723 }
    724 
    725 ////////////////////////////////////////////////////////////////////////////////
    726 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device
    727 // (as opposed to canvas) coordinates
    728 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt,
    729                                               int32_t elementsGenID,
    730                                               GrReducedClip::InitialState initialState,
    731                                               const GrReducedClip::ElementList& elements,
    732                                               const SkIRect& clipSpaceIBounds,
    733                                               const SkIPoint& clipSpaceToStencilOffset) {
    734     SkASSERT(rt);
    735 
    736     GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachStencilAttachment(rt);
    737     if (nullptr == stencilAttachment) {
    738         return false;
    739     }
    740 
    741     if (stencilAttachment->mustRenderClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset)) {
    742         stencilAttachment->setLastClip(elementsGenID, clipSpaceIBounds, clipSpaceToStencilOffset);
    743         // Set the matrix so that rendered clip elements are transformed from clip to stencil space.
    744         SkVector translate = {
    745             SkIntToScalar(clipSpaceToStencilOffset.fX),
    746             SkIntToScalar(clipSpaceToStencilOffset.fY)
    747         };
    748         SkMatrix viewMatrix;
    749         viewMatrix.setTranslate(translate);
    750 
    751         // We set the current clip to the bounds so that our recursive draws are scissored to them.
    752         SkIRect stencilSpaceIBounds(clipSpaceIBounds);
    753         stencilSpaceIBounds.offset(clipSpaceToStencilOffset);
    754         GrClip clip(stencilSpaceIBounds);
    755 
    756         int clipBit = stencilAttachment->bits();
    757         SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil buffers");
    758         clipBit = (1 << (clipBit-1));
    759 
    760         fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds,
    761             GrReducedClip::kAllIn_InitialState == initialState, rt);
    762 
    763         // walk through each clip element and perform its set op
    764         // with the existing clip.
    765         for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
    766             const Element* element = iter.get();
    767 
    768             GrPipelineBuilder pipelineBuilder;
    769             pipelineBuilder.setClip(clip);
    770             pipelineBuilder.setRenderTarget(rt);
    771 
    772             pipelineBuilder.setDisableColorXPFactory();
    773 
    774             // if the target is MSAA then we want MSAA enabled when the clip is soft
    775             if (rt->isStencilBufferMultisampled()) {
    776                 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, element->isAA());
    777             }
    778 
    779             bool fillInverted = false;
    780             // enabled at bottom of loop
    781             fClipMode = kIgnoreClip_StencilClipMode;
    782 
    783             // This will be used to determine whether the clip shape can be rendered into the
    784             // stencil with arbitrary stencil settings.
    785             GrPathRenderer::StencilSupport stencilSupport;
    786 
    787             GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
    788             SkRegion::Op op = element->getOp();
    789 
    790             GrPathRenderer* pr = nullptr;
    791             SkPath clipPath;
    792             if (Element::kRect_Type == element->getType()) {
    793                 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
    794                 fillInverted = false;
    795             } else {
    796                 element->asPath(&clipPath);
    797                 fillInverted = clipPath.isInverseFillType();
    798                 if (fillInverted) {
    799                     clipPath.toggleInverseFillType();
    800                 }
    801 
    802                 SkASSERT(pipelineBuilder.getStencil().isDisabled());
    803 
    804                 GrPathRenderer::CanDrawPathArgs canDrawArgs;
    805                 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps();
    806                 canDrawArgs.fViewMatrix = &viewMatrix;
    807                 canDrawArgs.fPath = &clipPath;
    808                 canDrawArgs.fStroke = &stroke;
    809                 canDrawArgs.fAntiAlias = false;
    810                 canDrawArgs.fIsStencilDisabled = pipelineBuilder.getStencil().isDisabled();
    811                 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled();
    812 
    813                 pr = this->getContext()->drawingManager()->getPathRenderer(canDrawArgs, false,
    814                                                                            GrPathRendererChain::kStencilOnly_DrawType,
    815                                                                            &stencilSupport);
    816                 if (nullptr == pr) {
    817                     return false;
    818                 }
    819             }
    820 
    821             int passes;
    822             GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClipPasses];
    823 
    824             bool canRenderDirectToStencil =
    825                 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport;
    826             bool canDrawDirectToClip; // Given the renderer, the element,
    827                                       // fill rule, and set operation can
    828                                       // we render the element directly to
    829                                       // stencil bit used for clipping.
    830             canDrawDirectToClip = GrStencilSettings::GetClipPasses(op,
    831                                                                    canRenderDirectToStencil,
    832                                                                    clipBit,
    833                                                                    fillInverted,
    834                                                                    &passes,
    835                                                                    stencilSettings);
    836 
    837             // draw the element to the client stencil bits if necessary
    838             if (!canDrawDirectToClip) {
    839                 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil,
    840                                              kIncClamp_StencilOp,
    841                                              kIncClamp_StencilOp,
    842                                              kAlways_StencilFunc,
    843                                              0xffff,
    844                                              0x0000,
    845                                              0xffff);
    846                 if (Element::kRect_Type == element->getType()) {
    847                     *pipelineBuilder.stencil() = gDrawToStencil;
    848 
    849                     draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE, viewMatrix,
    850                                      element->getRect());
    851                 } else {
    852                     if (!clipPath.isEmpty()) {
    853                         if (canRenderDirectToStencil) {
    854                             *pipelineBuilder.stencil() = gDrawToStencil;
    855 
    856                             GrPathRenderer::DrawPathArgs args;
    857                             args.fTarget = fDrawTarget;
    858                             args.fResourceProvider = this->getContext()->resourceProvider();
    859                             args.fPipelineBuilder = &pipelineBuilder;
    860                             args.fColor = GrColor_WHITE;
    861                             args.fViewMatrix = &viewMatrix;
    862                             args.fPath = &clipPath;
    863                             args.fStroke = &stroke;
    864                             args.fAntiAlias = false;
    865                             pr->drawPath(args);
    866                         } else {
    867                             GrPathRenderer::StencilPathArgs args;
    868                             args.fTarget = fDrawTarget;
    869                             args.fResourceProvider = this->getContext()->resourceProvider();
    870                             args.fPipelineBuilder = &pipelineBuilder;
    871                             args.fViewMatrix = &viewMatrix;
    872                             args.fPath = &clipPath;
    873                             args.fStroke = &stroke;
    874                             pr->stencilPath(args);
    875                         }
    876                     }
    877                 }
    878             }
    879 
    880             // now we modify the clip bit by rendering either the clip
    881             // element directly or a bounding rect of the entire clip.
    882             fClipMode = kModifyClip_StencilClipMode;
    883             for (int p = 0; p < passes; ++p) {
    884                 *pipelineBuilder.stencil() = stencilSettings[p];
    885 
    886                 if (canDrawDirectToClip) {
    887                     if (Element::kRect_Type == element->getType()) {
    888                         draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE, viewMatrix,
    889                                          element->getRect());
    890                     } else {
    891                         GrPathRenderer::DrawPathArgs args;
    892                         args.fTarget = fDrawTarget;
    893                         args.fResourceProvider = this->getContext()->resourceProvider();
    894                         args.fPipelineBuilder = &pipelineBuilder;
    895                         args.fColor = GrColor_WHITE;
    896                         args.fViewMatrix = &viewMatrix;
    897                         args.fPath = &clipPath;
    898                         args.fStroke = &stroke;
    899                         args.fAntiAlias = false;
    900                         pr->drawPath(args);
    901                     }
    902                 } else {
    903                     // The view matrix is setup to do clip space -> stencil space translation, so
    904                     // draw rect in clip space.
    905                     draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE, viewMatrix,
    906                                      SkRect::Make(clipSpaceIBounds));
    907                 }
    908             }
    909         }
    910     }
    911     fClipMode = kRespectClip_StencilClipMode;
    912     return true;
    913 }
    914 
    915 // mapping of clip-respecting stencil funcs to normal stencil funcs
    916 // mapping depends on whether stencil-clipping is in effect.
    917 static const GrStencilFunc
    918     gSpecialToBasicStencilFunc[2][kClipStencilFuncCount] = {
    919     {// Stencil-Clipping is DISABLED,  we are effectively always inside the clip
    920         // In the Clip Funcs
    921         kAlways_StencilFunc,          // kAlwaysIfInClip_StencilFunc
    922         kEqual_StencilFunc,           // kEqualIfInClip_StencilFunc
    923         kLess_StencilFunc,            // kLessIfInClip_StencilFunc
    924         kLEqual_StencilFunc,          // kLEqualIfInClip_StencilFunc
    925         // Special in the clip func that forces user's ref to be 0.
    926         kNotEqual_StencilFunc,        // kNonZeroIfInClip_StencilFunc
    927                                       // make ref 0 and do normal nequal.
    928     },
    929     {// Stencil-Clipping is ENABLED
    930         // In the Clip Funcs
    931         kEqual_StencilFunc,           // kAlwaysIfInClip_StencilFunc
    932                                       // eq stencil clip bit, mask
    933                                       // out user bits.
    934 
    935         kEqual_StencilFunc,           // kEqualIfInClip_StencilFunc
    936                                       // add stencil bit to mask and ref
    937 
    938         kLess_StencilFunc,            // kLessIfInClip_StencilFunc
    939         kLEqual_StencilFunc,          // kLEqualIfInClip_StencilFunc
    940                                       // for both of these we can add
    941                                       // the clip bit to the mask and
    942                                       // ref and compare as normal
    943         // Special in the clip func that forces user's ref to be 0.
    944         kLess_StencilFunc,            // kNonZeroIfInClip_StencilFunc
    945                                       // make ref have only the clip bit set
    946                                       // and make comparison be less
    947                                       // 10..0 < 1..user_bits..
    948     }
    949 };
    950 
    951 namespace {
    952 // Sets the settings to clip against the stencil buffer clip while ignoring the
    953 // client bits.
    954 const GrStencilSettings& basic_apply_stencil_clip_settings() {
    955     // stencil settings to use when clip is in stencil
    956     GR_STATIC_CONST_SAME_STENCIL_STRUCT(gSettings,
    957         kKeep_StencilOp,
    958         kKeep_StencilOp,
    959         kAlwaysIfInClip_StencilFunc,
    960         0x0000,
    961         0x0000,
    962         0x0000);
    963     return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings);
    964 }
    965 }
    966 
    967 void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipelineBuilder,
    968                                                   GrPipelineBuilder::AutoRestoreStencil* ars) {
    969     // We make two copies of the StencilSettings here (except in the early
    970     // exit scenario. One copy from draw state to the stack var. Then another
    971     // from the stack var to the gpu. We could make this class hold a ptr to
    972     // GrGpu's fStencilSettings and eliminate the stack copy here.
    973 
    974     // use stencil for clipping if clipping is enabled and the clip
    975     // has been written into the stencil.
    976     GrStencilSettings settings;
    977 
    978     // The GrGpu client may not be using the stencil buffer but we may need to
    979     // enable it in order to respect a stencil clip.
    980     if (pipelineBuilder.getStencil().isDisabled()) {
    981         if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) {
    982             settings = basic_apply_stencil_clip_settings();
    983         } else {
    984             return;
    985         }
    986     } else {
    987         settings = pipelineBuilder.getStencil();
    988     }
    989 
    990     int stencilBits = 0;
    991     GrRenderTarget* rt = pipelineBuilder.getRenderTarget();
    992     GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachStencilAttachment(rt);
    993     if (stencilAttachment) {
    994         stencilBits = stencilAttachment->bits();
    995     }
    996 
    997     SkASSERT(this->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp());
    998     SkASSERT(this->caps()->twoSidedStencilSupport() || !settings.isTwoSided());
    999     this->adjustStencilParams(&settings, fClipMode, stencilBits);
   1000     ars->set(&pipelineBuilder);
   1001     ars->setStencil(settings);
   1002 }
   1003 
   1004 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings,
   1005                                             StencilClipMode mode,
   1006                                             int stencilBitCnt) {
   1007     SkASSERT(stencilBitCnt > 0);
   1008 
   1009     if (kModifyClip_StencilClipMode == mode) {
   1010         // We assume that this clip manager itself is drawing to the GrGpu and
   1011         // has already setup the correct values.
   1012         return;
   1013     }
   1014 
   1015     unsigned int clipBit = (1 << (stencilBitCnt - 1));
   1016     unsigned int userBits = clipBit - 1;
   1017 
   1018     GrStencilSettings::Face face = GrStencilSettings::kFront_Face;
   1019     bool twoSided = this->caps()->twoSidedStencilSupport();
   1020 
   1021     bool finished = false;
   1022     while (!finished) {
   1023         GrStencilFunc func = settings->func(face);
   1024         uint16_t writeMask = settings->writeMask(face);
   1025         uint16_t funcMask = settings->funcMask(face);
   1026         uint16_t funcRef = settings->funcRef(face);
   1027 
   1028         SkASSERT((unsigned) func < kStencilFuncCount);
   1029 
   1030         writeMask &= userBits;
   1031 
   1032         if (func >= kBasicStencilFuncCount) {
   1033             int respectClip = kRespectClip_StencilClipMode == mode;
   1034             if (respectClip) {
   1035                 switch (func) {
   1036                     case kAlwaysIfInClip_StencilFunc:
   1037                         funcMask = clipBit;
   1038                         funcRef = clipBit;
   1039                         break;
   1040                     case kEqualIfInClip_StencilFunc:
   1041                     case kLessIfInClip_StencilFunc:
   1042                     case kLEqualIfInClip_StencilFunc:
   1043                         funcMask = (funcMask & userBits) | clipBit;
   1044                         funcRef  = (funcRef  & userBits) | clipBit;
   1045                         break;
   1046                     case kNonZeroIfInClip_StencilFunc:
   1047                         funcMask = (funcMask & userBits) | clipBit;
   1048                         funcRef = clipBit;
   1049                         break;
   1050                     default:
   1051                         SkFAIL("Unknown stencil func");
   1052                 }
   1053             } else {
   1054                 funcMask &= userBits;
   1055                 funcRef &= userBits;
   1056             }
   1057             const GrStencilFunc* table =
   1058                 gSpecialToBasicStencilFunc[respectClip];
   1059             func = table[func - kBasicStencilFuncCount];
   1060             SkASSERT(func >= 0 && func < kBasicStencilFuncCount);
   1061         } else {
   1062             funcMask &= userBits;
   1063             funcRef &= userBits;
   1064         }
   1065 
   1066         settings->setFunc(face, func);
   1067         settings->setWriteMask(face, writeMask);
   1068         settings->setFuncMask(face, funcMask);
   1069         settings->setFuncRef(face, funcRef);
   1070 
   1071         if (GrStencilSettings::kFront_Face == face) {
   1072             face = GrStencilSettings::kBack_Face;
   1073             finished = !twoSided;
   1074         } else {
   1075             finished = true;
   1076         }
   1077     }
   1078     if (!twoSided) {
   1079         settings->copyFrontSettingsToBack();
   1080     }
   1081 }
   1082 
   1083 ////////////////////////////////////////////////////////////////////////////////
   1084 GrTexture* GrClipMaskManager::createSoftwareClipMask(int32_t elementsGenID,
   1085                                                      GrReducedClip::InitialState initialState,
   1086                                                      const GrReducedClip::ElementList& elements,
   1087                                                      const SkVector& clipToMaskOffset,
   1088                                                      const SkIRect& clipSpaceIBounds) {
   1089     GrUniqueKey key;
   1090     GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key);
   1091     GrResourceProvider* resourceProvider = this->resourceProvider();
   1092     if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)) {
   1093         return texture;
   1094     }
   1095 
   1096     // The mask texture may be larger than necessary. We round out the clip space bounds and pin
   1097     // the top left corner of the resulting rect to the top left of the texture.
   1098     SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpaceIBounds.height());
   1099 
   1100     GrSWMaskHelper helper(this->getContext());
   1101 
   1102     // Set the matrix so that rendered clip elements are transformed to mask space from clip
   1103     // space.
   1104     SkMatrix translate;
   1105     translate.setTranslate(clipToMaskOffset);
   1106 
   1107     helper.init(maskSpaceIBounds, &translate, false);
   1108     helper.clear(GrReducedClip::kAllIn_InitialState == initialState ? 0xFF : 0x00);
   1109     SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle);
   1110 
   1111     for (GrReducedClip::ElementList::Iter iter(elements.headIter()) ; iter.get(); iter.next()) {
   1112         const Element* element = iter.get();
   1113         SkRegion::Op op = element->getOp();
   1114 
   1115         if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op == op) {
   1116             // Intersect and reverse difference require modifying pixels outside of the geometry
   1117             // that is being "drawn". In both cases we erase all the pixels outside of the geometry
   1118             // but leave the pixels inside the geometry alone. For reverse difference we invert all
   1119             // the pixels before clearing the ones outside the geometry.
   1120             if (SkRegion::kReverseDifference_Op == op) {
   1121                 SkRect temp = SkRect::Make(clipSpaceIBounds);
   1122                 // invert the entire scene
   1123                 helper.draw(temp, SkRegion::kXOR_Op, false, 0xFF);
   1124             }
   1125             SkPath clipPath;
   1126             element->asPath(&clipPath);
   1127             clipPath.toggleInverseFillType();
   1128             helper.draw(clipPath, stroke, SkRegion::kReplace_Op, element->isAA(), 0x00);
   1129             continue;
   1130         }
   1131 
   1132         // The other ops (union, xor, diff) only affect pixels inside
   1133         // the geometry so they can just be drawn normally
   1134         if (Element::kRect_Type == element->getType()) {
   1135             helper.draw(element->getRect(), op, element->isAA(), 0xFF);
   1136         } else {
   1137             SkPath path;
   1138             element->asPath(&path);
   1139             helper.draw(path, stroke, op, element->isAA(), 0xFF);
   1140         }
   1141     }
   1142 
   1143     // Allocate clip mask texture
   1144     GrTexture* result = this->createCachedMask(clipSpaceIBounds.width(), clipSpaceIBounds.height(),
   1145                                                key, false);
   1146     if (nullptr == result) {
   1147         return nullptr;
   1148     }
   1149     helper.toTexture(result);
   1150 
   1151     return result;
   1152 }
   1153 
   1154 ////////////////////////////////////////////////////////////////////////////////
   1155 
   1156 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stencilAttachment,
   1157                                                 GrStencilSettings* settings) {
   1158     if (stencilAttachment) {
   1159         int stencilBits = stencilAttachment->bits();
   1160         this->adjustStencilParams(settings, fClipMode, stencilBits);
   1161     }
   1162 }
   1163