• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 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 skgpu_graphite_DrawParams_DEFINED
9 #define skgpu_graphite_DrawParams_DEFINED
10 
11 
12 #include "include/core/SkPaint.h"
13 #include "include/core/SkRect.h"
14 #include "src/gpu/graphite/DrawOrder.h"
15 #include "src/gpu/graphite/geom/Geometry.h"
16 #include "src/gpu/graphite/geom/NonMSAAClip.h"
17 #include "src/gpu/graphite/geom/Rect.h"
18 #include "src/gpu/graphite/geom/Transform.h"
19 
20 #include <optional>
21 
22 namespace skgpu::graphite {
23 
24 // NOTE: Only represents the stroke or hairline styles; stroke-and-fill must be handled higher up.
25 class StrokeStyle {
26 public:
StrokeStyle()27     StrokeStyle() : fHalfWidth(0.f), fJoinLimit(0.f), fCap(SkPaint::kButt_Cap) {}
StrokeStyle(float width,float miterLimit,SkPaint::Join join,SkPaint::Cap cap)28     StrokeStyle(float width,
29                 float miterLimit,
30                 SkPaint::Join join,
31                 SkPaint::Cap cap)
32             : fHalfWidth(std::max(0.f, 0.5f * width))
33             , fJoinLimit(join == SkPaint::kMiter_Join ? std::max(0.f, miterLimit) :
34                          (join == SkPaint::kBevel_Join ? 0.f : -1.f))
35             , fCap(cap) {}
36 
37     StrokeStyle(const StrokeStyle&) = default;
38 
39     StrokeStyle& operator=(const StrokeStyle&) = default;
40 
isMiterJoin()41     bool isMiterJoin() const { return fJoinLimit > 0.f;  }
isBevelJoin()42     bool isBevelJoin() const { return fJoinLimit == 0.f; }
isRoundJoin()43     bool isRoundJoin() const { return fJoinLimit < 0.f;  }
44 
halfWidth()45     float         halfWidth()  const { return fHalfWidth;                }
width()46     float         width()      const { return 2.f * fHalfWidth;          }
miterLimit()47     float         miterLimit() const { return std::max(0.f, fJoinLimit); }
cap()48     SkPaint::Cap  cap()        const { return fCap;                      }
join()49     SkPaint::Join join()       const {
50         return fJoinLimit > 0.f ? SkPaint::kMiter_Join :
51                (fJoinLimit == 0.f ? SkPaint::kBevel_Join : SkPaint::kRound_Join);
52     }
53 
54     // Raw join limit, compatible with tess::StrokeParams
joinLimit()55     float joinLimit() const { return fJoinLimit; }
56 
57 private:
58     float        fHalfWidth; // >0: relative to transform; ==0: hairline, 1px in device space
59     float        fJoinLimit; // >0: miter join; ==0: bevel join; <0: round join
60     SkPaint::Cap fCap;
61 };
62 
63 // TBD: Separate DashParams extracted from an SkDashPathEffect? Or folded into StrokeStyle?
64 
65 class Clip {
66 public:
67     Clip() = default;
Clip(const Rect & drawBounds,const Rect & shapeBounds,const SkIRect & scissor,const NonMSAAClip & nonMSAAClip,const SkShader * shader)68     Clip(const Rect& drawBounds,
69          const Rect& shapeBounds,
70          const SkIRect& scissor,
71          const NonMSAAClip& nonMSAAClip,
72          const SkShader* shader)
73             : fDrawBounds(drawBounds)
74             , fTransformedShapeBounds(shapeBounds)
75             , fScissor(scissor)
76             , fNonMSAAClip(nonMSAAClip)
77             , fShader(shader) {}
78 
79     // Tight bounds of the draw, including any padding/outset for stroking and expansion due to
80     // inverse fill and intersected with the scissor.
drawBounds()81     const Rect& drawBounds() const { return fDrawBounds; }
82 
83     // The scissor rectangle obtained by restricting the bounds of the clip stack that affects the
84     // draw to the device bounds. The scissor must contain drawBounds() and must already be
85     // intersected with the device bounds.
scissor()86     const SkIRect& scissor() const { return fScissor; }
87 
88     // Clipped bounds of the shape in device space, including any padding/outset for stroking,
89     // intersected with the scissor and ignoring the fill rule. For a regular fill this is identical
90     // to drawBounds(). For an inverse fill, this is a subset of drawBounds().
transformedShapeBounds()91     const Rect& transformedShapeBounds() const { return fTransformedShapeBounds; }
92 
93     // If set, the shape's bounds and/or an atlas mask are further used to clip the draw.
nonMSAAClip()94     const NonMSAAClip& nonMSAAClip() const { return fNonMSAAClip; }
95 
96     // If set, the clip shader's output alpha is further used to clip the draw.
shader()97     const SkShader* shader() const { return fShader; }
98 
isClippedOut()99     bool isClippedOut() const { return fDrawBounds.isEmptyNegativeOrNaN(); }
100 
needsCoverage()101     bool needsCoverage() const { return SkToBool(fShader) || !fNonMSAAClip.isEmpty(); }
102 
103 private:
104     // DrawList assumes the DrawBounds are correct for a given shape, transform, and style. They
105     // are provided to the DrawList to avoid re-calculating the same bounds.
106     Rect              fDrawBounds;
107     Rect              fTransformedShapeBounds;
108     SkIRect           fScissor;
109     NonMSAAClip       fNonMSAAClip;
110     const SkShader*   fShader;
111 };
112 
113 // Encapsulates all geometric state for a single high-level draw call. RenderSteps are responsible
114 // for transforming this state into actual rendering; shading from PaintParams is handled separately
115 class DrawParams {
116 public:
DrawParams(const Transform & transform,const Geometry & geometry,const Clip & clip,DrawOrder drawOrder,const StrokeStyle * stroke)117     DrawParams(const Transform& transform,
118                const Geometry& geometry,
119                const Clip& clip,
120                DrawOrder drawOrder,
121                const StrokeStyle* stroke)
122             : fTransform(transform)
123             , fGeometry(geometry)
124             , fClip(clip)
125             , fOrder(drawOrder)
126             , fStroke(stroke ? std::optional<StrokeStyle>(*stroke) : std::nullopt) {}
127 
transform()128     const Transform& transform() const { return fTransform; }
geometry()129     const Geometry&  geometry()  const { return fGeometry;  }
clip()130     const Clip&      clip()      const { return fClip;      }
order()131     DrawOrder        order()     const { return fOrder;     }
132 
133     // Optional stroke parameters if the geometry is stroked instead of filled
isStroke()134     bool isStroke() const { return fStroke.has_value(); }
strokeStyle()135     const StrokeStyle& strokeStyle() const {
136         SkASSERT(this->isStroke());
137         return *fStroke;
138     }
139 
140 private:
141     const Transform& fTransform; // Lifetime of the transform must be held longer than the geometry
142 
143     Geometry  fGeometry;
144     Clip      fClip;
145     DrawOrder fOrder;
146 
147     std::optional<StrokeStyle> fStroke; // Not present implies fill
148 };
149 
150 }  // namespace skgpu::graphite
151 
152 #endif // skgpu_graphite_DrawParams_DEFINED
153