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 | |
69 | GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override; |
70 | |
71 | void drawPaths(GrOpFlushState*, const GrPipeline&, const GrSurfaceProxy& atlasProxy, |
72 | const GrCCPerFlushResources&, int baseInstance, int endInstance, |
73 | const SkRect& bounds) const; |
74 | |
75 | private: |
76 | const TextureSampler& onTextureSampler(int) const override { return fAtlasAccess; } |
77 | |
78 | const CoverageMode fCoverageMode; |
79 | const TextureSampler fAtlasAccess; |
80 | SkISize fAtlasDimensions; |
81 | GrSurfaceOrigin fAtlasOrigin; |
82 | |
83 | SkMatrix fLocalMatrix; |
84 | static constexpr Attribute kInstanceAttribs[] = { |
85 | {"devbounds" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}, |
86 | {"devbounds45" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}, |
87 | {"dev_to_atlas_offset" , kInt2_GrVertexAttribType, kInt2_GrSLType}, |
88 | {"color" , kFloat4_GrVertexAttribType, kHalf4_GrSLType} |
89 | }; |
90 | static constexpr int kColorAttribIdx = 3; |
91 | static constexpr Attribute kCornersAttrib = |
92 | {"corners" , kFloat4_GrVertexAttribType, kFloat4_GrSLType}; |
93 | |
94 | class Impl; |
95 | |
96 | typedef GrGeometryProcessor INHERITED; |
97 | }; |
98 | |
99 | inline void GrCCPathProcessor::Instance::set( |
100 | const GrOctoBounds& octoBounds, const SkIVector& devToAtlasOffset, const SkPMColor4f& color, |
101 | GrFillRule fillRule) { |
102 | if (GrFillRule::kNonzero == fillRule) { |
103 | // We cover "nonzero" paths with clockwise triangles, which is the default result from |
104 | // normal octo bounds. |
105 | fDevBounds = octoBounds.bounds(); |
106 | fDevBounds45 = octoBounds.bounds45(); |
107 | } else { |
108 | // We cover "even/odd" paths with counterclockwise triangles. Here we reorder the bounding |
109 | // box vertices so the output is flipped horizontally. |
110 | fDevBounds.setLTRB( |
111 | octoBounds.right(), octoBounds.top(), octoBounds.left(), octoBounds.bottom()); |
112 | fDevBounds45.setLTRB( |
113 | octoBounds.bottom45(), octoBounds.right45(), octoBounds.top45(), |
114 | octoBounds.left45()); |
115 | } |
116 | fDevToAtlasOffset = devToAtlasOffset; |
117 | fColor = color; |
118 | } |
119 | |
120 | #endif |
121 | |