1 /* 2 * Copyright 2011 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 9 #include "GrPathRendererChain.h" 10 #include "GrCaps.h" 11 #include "GrShaderCaps.h" 12 #include "GrContext.h" 13 #include "GrContextPriv.h" 14 #include "GrGpu.h" 15 #include "ccpr/GrCoverageCountingPathRenderer.h" 16 #include "ops/GrAAConvexPathRenderer.h" 17 #include "ops/GrAAHairLinePathRenderer.h" 18 #include "ops/GrAALinearizingConvexPathRenderer.h" 19 #include "ops/GrSmallPathRenderer.h" 20 #include "ops/GrDashLinePathRenderer.h" 21 #include "ops/GrDefaultPathRenderer.h" 22 #include "ops/GrStencilAndCoverPathRenderer.h" 23 #include "ops/GrTessellatingPathRenderer.h" 24 25 GrPathRendererChain::GrPathRendererChain(GrContext* context, const Options& options) { 26 const GrCaps& caps = *context->contextPriv().caps(); 27 if (options.fGpuPathRenderers & GpuPathRenderers::kDashLine) { 28 fChain.push_back(sk_make_sp<GrDashLinePathRenderer>()); 29 } 30 if (options.fGpuPathRenderers & GpuPathRenderers::kStencilAndCover) { 31 sk_sp<GrPathRenderer> pr( 32 GrStencilAndCoverPathRenderer::Create(context->contextPriv().resourceProvider(), caps)); 33 if (pr) { 34 fChain.push_back(std::move(pr)); 35 } 36 } 37 if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) { 38 fChain.push_back(sk_make_sp<GrAAConvexPathRenderer>()); 39 } 40 if (options.fGpuPathRenderers & GpuPathRenderers::kCoverageCounting) { 41 using AllowCaching = GrCoverageCountingPathRenderer::AllowCaching; 42 if (auto ccpr = GrCoverageCountingPathRenderer::CreateIfSupported( 43 caps, AllowCaching(options.fAllowPathMaskCaching), 44 context->contextPriv().contextID())) { 45 fCoverageCountingPathRenderer = ccpr.get(); 46 context->contextPriv().addOnFlushCallbackObject(fCoverageCountingPathRenderer); 47 fChain.push_back(std::move(ccpr)); 48 } 49 } 50 if (options.fGpuPathRenderers & GpuPathRenderers::kAAHairline) { 51 fChain.push_back(sk_make_sp<GrAAHairLinePathRenderer>()); 52 } 53 if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) { 54 fChain.push_back(sk_make_sp<GrAALinearizingConvexPathRenderer>()); 55 } 56 if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) { 57 auto spr = sk_make_sp<GrSmallPathRenderer>(); 58 context->contextPriv().addOnFlushCallbackObject(spr.get()); 59 fChain.push_back(std::move(spr)); 60 } 61 if (options.fGpuPathRenderers & GpuPathRenderers::kTessellating) { 62 fChain.push_back(sk_make_sp<GrTessellatingPathRenderer>()); 63 } 64 65 // We always include the default path renderer (as well as SW), so we can draw any path 66 fChain.push_back(sk_make_sp<GrDefaultPathRenderer>()); 67 } 68 69 GrPathRenderer* GrPathRendererChain::getPathRenderer( 70 const GrPathRenderer::CanDrawPathArgs& args, 71 DrawType drawType, 72 GrPathRenderer::StencilSupport* stencilSupport) { 73 GR_STATIC_ASSERT(GrPathRenderer::kNoSupport_StencilSupport < 74 GrPathRenderer::kStencilOnly_StencilSupport); 75 GR_STATIC_ASSERT(GrPathRenderer::kStencilOnly_StencilSupport < 76 GrPathRenderer::kNoRestriction_StencilSupport); 77 GrPathRenderer::StencilSupport minStencilSupport; 78 if (DrawType::kStencil == drawType) { 79 minStencilSupport = GrPathRenderer::kStencilOnly_StencilSupport; 80 } else if (DrawType::kStencilAndColor == drawType) { 81 minStencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 82 } else { 83 minStencilSupport = GrPathRenderer::kNoSupport_StencilSupport; 84 } 85 if (minStencilSupport != GrPathRenderer::kNoSupport_StencilSupport) { 86 // We don't support (and shouldn't need) stenciling of non-fill paths. 87 if (!args.fShape->style().isSimpleFill()) { 88 return nullptr; 89 } 90 } 91 92 GrPathRenderer* bestPathRenderer = nullptr; 93 for (const sk_sp<GrPathRenderer>& pr : fChain) { 94 GrPathRenderer::StencilSupport support = GrPathRenderer::kNoSupport_StencilSupport; 95 if (GrPathRenderer::kNoSupport_StencilSupport != minStencilSupport) { 96 support = pr->getStencilSupport(*args.fShape); 97 if (support < minStencilSupport) { 98 continue; 99 } 100 } 101 GrPathRenderer::CanDrawPath canDrawPath = pr->canDrawPath(args); 102 if (GrPathRenderer::CanDrawPath::kNo == canDrawPath) { 103 continue; 104 } 105 if (GrPathRenderer::CanDrawPath::kAsBackup == canDrawPath && bestPathRenderer) { 106 continue; 107 } 108 if (stencilSupport) { 109 *stencilSupport = support; 110 } 111 bestPathRenderer = pr.get(); 112 if (GrPathRenderer::CanDrawPath::kYes == canDrawPath) { 113 break; 114 } 115 } 116 return bestPathRenderer; 117 } 118