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