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