1 | /* |
2 | * Copyright 2017 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 | #ifndef GrCCPathProcessor_DEFINED |
9 | #define GrCCPathProcessor_DEFINED |
10 | |
11 | #include <array> |
12 | #include "include/core/SkPath.h" |
13 | #include "src/gpu/GrCaps.h" |
14 | #include "src/gpu/GrGeometryProcessor.h" |
15 | #include "src/gpu/GrPipeline.h" |
16 | #include "src/gpu/ccpr/GrOctoBounds.h" |
17 | |
18 | class GrCCPathCacheEntry; |
19 | class GrCCPerFlushResources; |
20 | class GrOnFlushResourceProvider; |
21 | class GrOpFlushState; |
22 | |
23 | /** |
24 | * This class draws AA paths using the coverage count masks produced by GrCCCoverageProcessor. |
25 | * |
26 | * Paths are drawn as bloated octagons, and coverage is derived from the coverage count mask and |
27 | * fill rule. |
28 | * |
29 | * To draw paths, the caller must set up an instance buffer as detailed below, then call drawPaths() |
30 | * providing its own instance buffer alongside the buffers found by calling FindIndexBuffer/ |
31 | * FindVertexBuffer. |
32 | */ |
33 | class GrCCPathProcessor : public GrGeometryProcessor { |
34 | public: |
35 | struct Instance { |
36 | SkRect fDevBounds; // "right < left" indicates even-odd fill type. |
37 | SkRect fDevBounds45; // Bounding box in "| 1 -1 | * devCoords" space. See GrOctoBounds. |
38 | // | 1 1 | |
39 | SkIVector fDevToAtlasOffset; // Translation from device space to location in atlas. |
40 | SkPMColor4f fColor; // Color always stored as 4 x fp32 |
41 | |
42 | void set(const GrOctoBounds&, const SkIVector& devToAtlasOffset, const SkPMColor4f&, |
43 | GrFillRule); |
44 | void set(const GrCCPathCacheEntry&, const SkIVector& shift, const SkPMColor4f&, GrFillRule); |
45 | }; |
46 | |
47 | static_assert(4 * 14 == sizeof(Instance)); |
48 | |
49 | static sk_sp<const GrGpuBuffer> FindVertexBuffer(GrOnFlushResourceProvider*); |
50 | static sk_sp<const GrGpuBuffer> FindIndexBuffer(GrOnFlushResourceProvider*); |
51 | |
52 | enum class CoverageMode : bool { |
53 | kCoverageCount, |
54 | kLiteral |
55 | }; |
56 | |
57 | static GrColorType GetColorTypeFromCoverageMode(CoverageMode mode) { |
58 | return mode == CoverageMode::kCoverageCount ? GrColorType::kAlpha_F16 |
59 | : GrColorType::kAlpha_8; |
60 | } |
61 | |
62 | GrCCPathProcessor(CoverageMode, const GrTexture* atlasTexture, const GrSwizzle&, |
63 | GrSurfaceOrigin atlasOrigin, |
64 | const SkMatrix& viewMatrixIfUsingLocalCoords = SkMatrix::I()); |
65 | |
66 | const char* name() const override { return "GrCCPathProcessor" ; } |
67 | void getGLSLProcessorKey(const GrShaderCaps&, GrProcessorKeyBuilder* b) const override { |
68 | b->add32((uint32_t)fCoverageMode); |
69 | } |
70 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; |
71 | |
72 | void drawPaths(GrOpFlushState*, const GrPipeline&, const GrSurfaceProxy& atlasProxy, |
73 | const GrCCPerFlushResources&, int baseInstance, int endInstance, |
74 | const SkRect& bounds) const; |
75 | |
76 | private: |
77 | const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } |
78 | |
79 | const CoverageMode fCoverageMode; |
80 | const TextureSampler fAtlasAccess; |
81 | SkISize fAtlasDimensions; |
82 | GrSurfaceOrigin fAtlasOrigin; |
83 | |
84 | SkMatrix fLocalMatrix; |
85 | static constexpr Attribute kInstanceAttribs[] = { |
86 | {"devbounds" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}, |
87 | {"devbounds45" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}, |
88 | {"dev_to_atlas_offset" , kInt2_GrVertexAttribType, kInt2_GrSLType}, |
89 | {"color" , kFloat4_GrVertexAttribType, kHalf4_GrSLType} |
90 | }; |
91 | static constexpr int kColorAttribIdx = 3; |
92 | static constexpr Attribute kCornersAttrib = |
93 | {"corners" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}; |
94 | |
95 | class Impl; |
96 | |
97 | typedef GrGeometryProcessor INHERITED; |
98 | }; |
99 | |
100 | inline void GrCCPathProcessor::Instance::set( |
101 | const GrOctoBounds& octoBounds, const SkIVector& devToAtlasOffset, const SkPMColor4f& color, |
102 | GrFillRule fillRule) { |
103 | if (GrFillRule::kNonzero == fillRule) { |
104 | // We cover "nonzero" paths with clockwise triangles, which is the default result from |
105 | // normal octo bounds. |
106 | fDevBounds = octoBounds.bounds(); |
107 | fDevBounds45 = octoBounds.bounds45(); |
108 | } else { |
109 | // We cover "even/odd" paths with counterclockwise triangles. Here we reorder the bounding |
110 | // box vertices so the output is flipped horizontally. |
111 | fDevBounds.setLTRB( |
112 | octoBounds.right(), octoBounds.top(), octoBounds.left(), octoBounds.bottom()); |
113 | fDevBounds45.setLTRB( |
114 | octoBounds.bottom45(), octoBounds.right45(), octoBounds.top45(), |
115 | octoBounds.left45()); |
116 | } |
117 | fDevToAtlasOffset = devToAtlasOffset; |
118 | fColor = color; |
119 | } |
120 | |
121 | #endif |
122 | |