• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2019 Google LLC.
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 GrTessellationPathRenderer_DEFINED
9 #define GrTessellationPathRenderer_DEFINED
10 
11 #include "src/gpu/GrDynamicAtlas.h"
12 #include "src/gpu/GrOnFlushResourceProvider.h"
13 #include "src/gpu/GrPathRenderer.h"
14 #include <map>
15 
16 // This is the tie-in point for path rendering via GrPathTessellateOp. This path renderer draws
17 // paths using a hybrid Red Book "stencil, then cover" method. Curves get linearized by GPU
18 // tessellation shaders. This path renderer doesn't apply analytic AA, so it requires MSAA if AA is
19 // desired.
20 class GrTessellationPathRenderer : public GrPathRenderer, public GrOnFlushCallbackObject {
21 public:
22     // Don't allow linearized segments to be off by more than 1/4th of a pixel from the true curve.
23     constexpr static float kLinearizationPrecision = 4;
24 
25     // This is the maximum resolve level supported by our internal indirect draw shaders. (Indirect
26     // draws are an alternative to hardware tessellation, and we can use them when hardware support
27     // is lacking.)
28     //
29     // At a given resolveLevel, a curve gets linearized into 2^resolveLevel line segments. So the
30     // finest resolveLevel supported by our indirect draw shaders is 2^10 == 1024 line segments.
31     //
32     // 1024 line segments is enough resolution (with precision == 4) to guarantee we can render a
33     // 123575px x 123575px path. (See GrWangsFormula::worst_case_cubic.)
34     constexpr static int kMaxResolveLevel = 10;
35 
36     // We send these flags to the internal tessellation Ops to control how a path gets rendered.
37     enum class OpFlags {
38         kNone = 0,
39         // Used when tessellation is not supported, or when a path will require more resolution than
40         // the max number of segments supported by the hardware.
41         kDisableHWTessellation = (1 << 0),
42         kStencilOnly = (1 << 1),
43         kWireframe = (1 << 2)
44     };
45 
46     static bool IsSupported(const GrCaps&);
47 
48     GrTessellationPathRenderer(GrRecordingContext*);
name()49     const char* name() const final { return "GrTessellationPathRenderer"; }
onGetStencilSupport(const GrStyledShape & shape)50     StencilSupport onGetStencilSupport(const GrStyledShape& shape) const override {
51         // TODO: Single-pass (e.g., convex) paths can have full support.
52         return kStencilOnly_StencilSupport;
53     }
54     CanDrawPath onCanDrawPath(const CanDrawPathArgs&) const override;
55     bool onDrawPath(const DrawPathArgs&) override;
56     void onStencilPath(const StencilPathArgs&) override;
57     void preFlush(GrOnFlushResourceProvider*, SkSpan<const uint32_t> taskIDs) override;
58 
59 private:
60     void initAtlasFlags(GrRecordingContext*);
getAtlasUberPath(SkPathFillType fillType,bool antialias)61     SkPath* getAtlasUberPath(SkPathFillType fillType, bool antialias) {
62         int idx = (int)antialias << 1;
63         idx |= (int)fillType & 1;
64         return &fAtlasUberPaths[idx];
65     }
66     // Allocates space in fAtlas if the path is small and simple enough, and if there is room.
67     bool tryAddPathToAtlas(const GrCaps&, const SkMatrix&, const GrStyledShape&,
68                            const SkRect& devBounds, GrAAType, SkIRect* devIBounds,
69                            SkIPoint16* locationInAtlas, bool* transposedInAtlas);
70     void renderAtlas(GrOnFlushResourceProvider*);
71 
72     GrDynamicAtlas fAtlas;
73     OpFlags fStencilAtlasFlags;
74     int fMaxAtlasPathWidth;
75     SkPath fAtlasUberPaths[4];  // 2 fillTypes * 2 antialias modes.
76 };
77 
78 GR_MAKE_BITFIELD_CLASS_OPS(GrTessellationPathRenderer::OpFlags);
79 
80 #endif
81