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 #include "src/gpu/ganesh/PathRendererChain.h" 8 9 #include "include/gpu/ganesh/GrRecordingContext.h" 10 #include "src/gpu/ganesh/GrRecordingContextPriv.h" 11 #include "src/gpu/ganesh/GrStyle.h" 12 #include "src/gpu/ganesh/geometry/GrStyledShape.h" 13 #include "src/gpu/ganesh/ops/AAConvexPathRenderer.h" 14 #include "src/gpu/ganesh/ops/AAHairLinePathRenderer.h" 15 #include "src/gpu/ganesh/ops/AALinearizingConvexPathRenderer.h" 16 #include "src/gpu/ganesh/ops/AtlasPathRenderer.h" 17 #include "src/gpu/ganesh/ops/DashLinePathRenderer.h" 18 #include "src/gpu/ganesh/ops/DefaultPathRenderer.h" 19 #include "src/gpu/ganesh/ops/SmallPathRenderer.h" 20 #include "src/gpu/ganesh/ops/TessellationPathRenderer.h" 21 #include "src/gpu/ganesh/ops/TriangulatingPathRenderer.h" 22 23 #include <utility> 24 25 class GrCaps; 26 27 namespace skgpu::ganesh { 28 PathRendererChain(GrRecordingContext * context,const Options & options)29PathRendererChain::PathRendererChain(GrRecordingContext* context, const Options& options) { 30 const GrCaps& caps = *context->priv().caps(); 31 if (options.fGpuPathRenderers & GpuPathRenderers::kDashLine) { 32 fChain.push_back(sk_make_sp<ganesh::DashLinePathRenderer>()); 33 } 34 if (options.fGpuPathRenderers & GpuPathRenderers::kAAConvex) { 35 fChain.push_back(sk_make_sp<AAConvexPathRenderer>()); 36 } 37 if (options.fGpuPathRenderers & GpuPathRenderers::kAAHairline) { 38 fChain.push_back(sk_make_sp<AAHairLinePathRenderer>()); 39 } 40 if (options.fGpuPathRenderers & GpuPathRenderers::kAALinearizing) { 41 fChain.push_back(sk_make_sp<AALinearizingConvexPathRenderer>()); 42 } 43 if (options.fGpuPathRenderers & GpuPathRenderers::kAtlas) { 44 if (auto atlasPathRenderer = AtlasPathRenderer::Make(context)) { 45 fAtlasPathRenderer = atlasPathRenderer.get(); 46 context->priv().addOnFlushCallbackObject(atlasPathRenderer.get()); 47 fChain.push_back(std::move(atlasPathRenderer)); 48 } 49 } 50 #if !defined(SK_ENABLE_OPTIMIZE_SIZE) 51 if (options.fGpuPathRenderers & GpuPathRenderers::kSmall) { 52 fChain.push_back(sk_make_sp<SmallPathRenderer>()); 53 } 54 if (options.fGpuPathRenderers & GpuPathRenderers::kTriangulating) { 55 fChain.push_back(sk_make_sp<TriangulatingPathRenderer>()); 56 } 57 #endif 58 if (options.fGpuPathRenderers & GpuPathRenderers::kTessellation) { 59 if (TessellationPathRenderer::IsSupported(caps)) { 60 auto tess = sk_make_sp<TessellationPathRenderer>(); 61 fTessellationPathRenderer = tess.get(); 62 fChain.push_back(std::move(tess)); 63 } 64 } 65 66 // We always include the default path renderer (as well as SW), so we can draw any path 67 fChain.push_back(sk_make_sp<DefaultPathRenderer>()); 68 } 69 getPathRenderer(const PathRenderer::CanDrawPathArgs & args,DrawType drawType,PathRenderer::StencilSupport * stencilSupport)70PathRenderer* PathRendererChain::getPathRenderer(const PathRenderer::CanDrawPathArgs& args, 71 DrawType drawType, 72 PathRenderer::StencilSupport* stencilSupport) { 73 static_assert(PathRenderer::kNoSupport_StencilSupport < 74 PathRenderer::kStencilOnly_StencilSupport); 75 static_assert(PathRenderer::kStencilOnly_StencilSupport < 76 PathRenderer::kNoRestriction_StencilSupport); 77 PathRenderer::StencilSupport minStencilSupport; 78 if (DrawType::kStencil == drawType) { 79 minStencilSupport = PathRenderer::kStencilOnly_StencilSupport; 80 } else if (DrawType::kStencilAndColor == drawType) { 81 minStencilSupport = PathRenderer::kNoRestriction_StencilSupport; 82 } else { 83 minStencilSupport = PathRenderer::kNoSupport_StencilSupport; 84 } 85 if (minStencilSupport != PathRenderer::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 PathRenderer* bestPathRenderer = nullptr; 93 for (const sk_sp<PathRenderer>& pr : fChain) { 94 PathRenderer::StencilSupport support = PathRenderer::kNoSupport_StencilSupport; 95 if (PathRenderer::kNoSupport_StencilSupport != minStencilSupport) { 96 support = pr->getStencilSupport(*args.fShape); 97 if (support < minStencilSupport) { 98 continue; 99 } 100 } 101 PathRenderer::CanDrawPath canDrawPath = pr->canDrawPath(args); 102 if (PathRenderer::CanDrawPath::kNo == canDrawPath) { 103 continue; 104 } 105 if (PathRenderer::CanDrawPath::kAsBackup == canDrawPath && bestPathRenderer) { 106 continue; 107 } 108 if (stencilSupport) { 109 *stencilSupport = support; 110 } 111 bestPathRenderer = pr.get(); 112 if (PathRenderer::CanDrawPath::kYes == canDrawPath) { 113 break; 114 } 115 } 116 return bestPathRenderer; 117 } 118 119 } // namespace skgpu::ganesh 120