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