xref: /aosp_15_r20/external/skia/src/gpu/graphite/geom/Geometry.h (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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_geom_Geometry_DEFINED
9 #define skgpu_graphite_geom_Geometry_DEFINED
10 
11 #include "include/core/SkRefCnt.h"
12 #include "include/core/SkVertices.h"
13 #include "include/private/base/SkAssert.h"
14 #include "src/gpu/graphite/geom/AnalyticBlurMask.h"
15 #include "src/gpu/graphite/geom/CoverageMaskShape.h"
16 #include "src/gpu/graphite/geom/EdgeAAQuad.h"
17 #include "src/gpu/graphite/geom/Rect.h"
18 #include "src/gpu/graphite/geom/Shape.h"
19 #include "src/gpu/graphite/geom/SubRunData.h"
20 
21 #include <cstdint>
22 #include <new>
23 #include <type_traits>
24 #include <utility>
25 
26 namespace skgpu::graphite {
27 
28 /**
29  * Geometry is a container that can house Shapes, SkVertices, text SubRuns, and per-edge AA quads.
30  * TODO - Add unit tests for Geometry.
31  */
32 class Geometry {
33 public:
34     enum class Type : uint8_t {
35         kEmpty, kShape, kVertices, kSubRun, kEdgeAAQuad, kCoverageMaskShape, kAnalyticBlur
36     };
37 
Geometry()38     Geometry() {}
Geometry(Geometry && geom)39     Geometry(Geometry&& geom) { *this = std::move(geom); }
Geometry(const Geometry & geom)40     Geometry(const Geometry& geom) { *this = geom; }
41 
Geometry(const Shape & shape)42     explicit Geometry(const Shape& shape) { this->setShape(shape); }
Geometry(const SubRunData & subrun)43     explicit Geometry(const SubRunData& subrun) { this->setSubRun(subrun); }
Geometry(sk_sp<SkVertices> vertices)44     explicit Geometry(sk_sp<SkVertices> vertices) { this->setVertices(std::move(vertices)); }
Geometry(const EdgeAAQuad & edgeAAQuad)45     explicit Geometry(const EdgeAAQuad& edgeAAQuad) { this->setEdgeAAQuad(edgeAAQuad); }
Geometry(const CoverageMaskShape & mask)46     explicit Geometry(const CoverageMaskShape& mask) { this->setCoverageMaskShape(mask); }
Geometry(const AnalyticBlurMask & blur)47     explicit Geometry(const AnalyticBlurMask& blur) { this->setAnalyticBlur(blur); }
48 
~Geometry()49     ~Geometry() { this->setType(Type::kEmpty); }
50 
51     Geometry& operator=(Geometry&& geom) {
52         if (this != &geom) {
53             switch (geom.type()) {
54                 case Type::kEmpty:
55                     this->setType(Type::kEmpty);
56                     break;
57                 case Type::kShape:
58                     this->setShape(geom.shape());
59                     geom.setType(Type::kEmpty);
60                     break;
61                 case Type::kVertices:
62                     this->setVertices(std::move(geom.fVertices));
63                     geom.setType(Type::kEmpty);
64                     break;
65                 case Type::kSubRun:
66                     this->setSubRun(geom.subRunData());
67                     geom.setType(Type::kEmpty);
68                     break;
69                 case Type::kEdgeAAQuad:
70                     this->setEdgeAAQuad(geom.edgeAAQuad());
71                     geom.setType(Type::kEmpty);
72                     break;
73                 case Type::kCoverageMaskShape:
74                     this->setCoverageMaskShape(geom.coverageMaskShape());
75                     geom.setType(Type::kEmpty);
76                     break;
77                 case Type::kAnalyticBlur:
78                     this->setAnalyticBlur(geom.analyticBlurMask());
79                     geom.setType(Type::kEmpty);
80                     break;
81             }
82         }
83         return *this;
84     }
85     Geometry& operator=(const Geometry& geom) {
86         switch (geom.type()) {
87             case Type::kEmpty: this->setType(Type::kEmpty); break;
88             case Type::kShape: this->setShape(geom.shape()); break;
89             case Type::kSubRun: this->setSubRun(geom.subRunData()); break;
90             case Type::kVertices: this->setVertices(geom.fVertices); break;
91             case Type::kEdgeAAQuad: this->setEdgeAAQuad(geom.edgeAAQuad()); break;
92             case Type::kCoverageMaskShape:
93                     this->setCoverageMaskShape(geom.coverageMaskShape()); break;
94             case Type::kAnalyticBlur: this->setAnalyticBlur(geom.analyticBlurMask()); break;
95             default: break;
96         }
97         return *this;
98     }
99 
type()100     Type type() const { return fType; }
101 
isShape()102     bool isShape() const { return fType == Type::kShape; }
isVertices()103     bool isVertices() const { return fType == Type::kVertices; }
isSubRun()104     bool isSubRun() const { return fType == Type::kSubRun; }
isEdgeAAQuad()105     bool isEdgeAAQuad() const { return fType == Type::kEdgeAAQuad; }
isCoverageMaskShape()106     bool isCoverageMaskShape() const { return fType == Type::kCoverageMaskShape; }
isAnalyticBlur()107     bool isAnalyticBlur() const { return fType == Type::kAnalyticBlur; }
isEmpty()108     bool isEmpty() const {
109         return fType == (Type::kEmpty) || (this->isShape() &&
110                                            this->shape().isEmpty() &&
111                                            !this->shape().inverted());
112     }
113 
shape()114     const Shape& shape() const { SkASSERT(this->isShape()); return fShape; }
subRunData()115     const SubRunData& subRunData() const { SkASSERT(this->isSubRun()); return fSubRunData; }
edgeAAQuad()116     const EdgeAAQuad& edgeAAQuad() const { SkASSERT(this->isEdgeAAQuad()); return fEdgeAAQuad; }
coverageMaskShape()117     const CoverageMaskShape& coverageMaskShape() const {
118         SkASSERT(this->isCoverageMaskShape()); return fCoverageMaskShape;
119     }
analyticBlurMask()120     const AnalyticBlurMask& analyticBlurMask() const {
121         SkASSERT(this->isAnalyticBlur()); return fAnalyticBlurMask;
122     }
vertices()123     const SkVertices* vertices() const { SkASSERT(this->isVertices()); return fVertices.get(); }
refVertices()124     sk_sp<SkVertices> refVertices() const {
125         SkASSERT(this->isVertices());
126         return fVertices;
127     }
128 
setShape(const Shape & shape)129     void setShape(const Shape& shape) {
130         if (fType == Type::kShape) {
131             fShape = shape;
132         } else {
133             this->setType(Type::kShape);
134             new (&fShape) Shape(shape);
135         }
136     }
setSubRun(const SubRunData & subRun)137     void setSubRun(const SubRunData& subRun) {
138         if (fType == Type::kSubRun) {
139             fSubRunData = subRun;
140         } else {
141             this->setType(Type::kSubRun);
142             new (&fSubRunData) SubRunData(subRun);
143         }
144     }
setVertices(sk_sp<SkVertices> vertices)145     void setVertices(sk_sp<SkVertices> vertices) {
146         if (fType == Type::kVertices) {
147             fVertices = std::move(vertices);
148         } else {
149             this->setType(Type::kVertices);
150             new (&fVertices) sk_sp<SkVertices>(std::move(vertices));
151         }
152     }
153 
setEdgeAAQuad(const EdgeAAQuad & edgeAAQuad)154     void setEdgeAAQuad(const EdgeAAQuad& edgeAAQuad) {
155         if (fType == Type::kEdgeAAQuad) {
156             fEdgeAAQuad = edgeAAQuad;
157         } else {
158             this->setType(Type::kEdgeAAQuad);
159             new (&fEdgeAAQuad) EdgeAAQuad(edgeAAQuad);
160         }
161     }
162 
setCoverageMaskShape(const CoverageMaskShape & maskShape)163     void setCoverageMaskShape(const CoverageMaskShape& maskShape) {
164         if (fType == Type::kCoverageMaskShape) {
165             fCoverageMaskShape = maskShape;
166         } else {
167             this->setType(Type::kCoverageMaskShape);
168             new (&fCoverageMaskShape) CoverageMaskShape(maskShape);
169         }
170     }
171 
setAnalyticBlur(const AnalyticBlurMask & blur)172     void setAnalyticBlur(const AnalyticBlurMask& blur) {
173         if (fType == Type::kAnalyticBlur) {
174             fAnalyticBlurMask = blur;
175         } else {
176             this->setType(Type::kAnalyticBlur);
177             new (&fAnalyticBlurMask) AnalyticBlurMask(blur);
178         }
179     }
180 
bounds()181     Rect bounds() const {
182         switch (fType) {
183             case Type::kEmpty: return Rect(0, 0, 0, 0);
184             case Type::kShape: return fShape.bounds();
185             case Type::kVertices: return fVertices->bounds();
186             case Type::kSubRun: return fSubRunData.bounds();
187             case Type::kEdgeAAQuad: return fEdgeAAQuad.bounds();
188             case Type::kCoverageMaskShape: return fCoverageMaskShape.bounds();
189             case Type::kAnalyticBlur: return fAnalyticBlurMask.drawBounds();
190         }
191         SkUNREACHABLE;
192     }
193 
194 private:
setType(Type type)195     void setType(Type type) {
196         static_assert(std::is_trivially_destructible<EdgeAAQuad>::value);
197         if (this->isShape() && type != Type::kShape) {
198             fShape.~Shape();
199         } else if (this->isSubRun() && type != Type::kSubRun) {
200             fSubRunData.~SubRunData();
201         } else if (this->isVertices() && type != Type::kVertices) {
202             fVertices.~sk_sp<SkVertices>();
203         } else if (this->isCoverageMaskShape() && type != Type::kCoverageMaskShape) {
204             fCoverageMaskShape.~CoverageMaskShape();
205         } else if (this->isAnalyticBlur() && type != Type::kAnalyticBlur) {
206             fAnalyticBlurMask.~AnalyticBlurMask();
207         }
208         fType = type;
209     }
210 
211     Type fType = Type::kEmpty;
212     union {
213         Shape fShape;
214         SubRunData fSubRunData;
215         sk_sp<SkVertices> fVertices;
216         EdgeAAQuad fEdgeAAQuad;
217         CoverageMaskShape fCoverageMaskShape;
218         AnalyticBlurMask fAnalyticBlurMask;
219     };
220 };
221 
222 } // namespace skgpu::graphite
223 
224 #endif // skgpu_graphite_geom_Geometry_DEFINED
225