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