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