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