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