1 /* 2 * Copyright 2015 Google Inc. 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 AtlasTextOp_DEFINED 9 #define AtlasTextOp_DEFINED 10 11 #include "src/gpu/effects/GrDistanceFieldGeoProc.h" 12 #include "src/gpu/ops/GrMeshDrawOp.h" 13 #include "src/gpu/text/GrTextBlob.h" 14 15 class GrRecordingContext; 16 17 namespace skgpu::v1 { 18 19 class AtlasTextOp final : public GrMeshDrawOp { 20 public: 21 DEFINE_OP_CLASS_ID 22 ~AtlasTextOp()23 ~AtlasTextOp() override { 24 for (const Geometry* g = fHead; g != nullptr;) { 25 const Geometry* next = g->fNext; 26 g->~Geometry(); 27 g = next; 28 } 29 } 30 31 void* operator new(size_t s); 32 void operator delete(void* b) noexcept; 33 static void ClearCache(); 34 35 static const int kVerticesPerGlyph = GrAtlasSubRun::kVerticesPerGlyph; 36 static const int kIndicesPerGlyph = 6; 37 38 struct Geometry { GeometryGeometry39 Geometry(const GrAtlasSubRun& subRun, 40 const SkMatrix& drawMatrix, 41 SkPoint drawOrigin, 42 SkIRect clipRect, 43 sk_sp<GrTextBlob> blob, 44 GrAtlasSubRunOwner subRunOwner, 45 const SkPMColor4f& color) 46 : fSubRun{subRun} 47 , fSupportDataKeepAlive{std::move(blob)} 48 , fSubRunDtor{std::move(subRunOwner)} 49 , fDrawMatrix{drawMatrix} 50 , fDrawOrigin{drawOrigin} 51 , fClipRect{clipRect} 52 , fColor{color} { 53 SkASSERT(fSupportDataKeepAlive != nullptr || fSubRunDtor != nullptr); 54 SkASSERT(SkToBool(fSubRunDtor) != SkToBool(fSupportDataKeepAlive)); 55 } 56 57 static Geometry* MakeForBlob(const GrAtlasSubRun& subRun, 58 const SkMatrix& drawMatrix, 59 SkPoint drawOrigin, 60 SkIRect clipRect, 61 sk_sp<GrTextBlob> blob, 62 const SkPMColor4f& color, 63 SkArenaAlloc* alloc); 64 65 void fillVertexData(void* dst, int offset, int count) const; 66 67 const GrAtlasSubRun& fSubRun; 68 69 // Either this Geometry holds a ref to the support data in the case of a blob based 70 // SubRun (WithCaching case), or it holds a unique_ptr to a SubRun allocated on the 71 // GrTextBlobAllocator in the NoCache case. It must hold one, and can't hold both. 72 sk_sp<SkRefCnt> fSupportDataKeepAlive; 73 GrAtlasSubRunOwner fSubRunDtor; 74 75 const SkMatrix fDrawMatrix; 76 const SkPoint fDrawOrigin; 77 78 // fClipRect is only used in the DirectMaskSubRun case to do geometric clipping. 79 // TransformedMaskSubRun, and SDFTSubRun don't use this field, and expect an empty rect. 80 const SkIRect fClipRect; 81 82 // Color is updated after processor analysis if it was determined the shader resolves to 83 // a constant color that we then evaluate on the CPU. 84 // TODO: This can be made const once processor analysis is separated from op creation. 85 SkPMColor4f fColor; 86 Geometry* fNext{nullptr}; 87 }; 88 name()89 const char* name() const override { return "AtlasTextOp"; } 90 91 void visitProxies(const GrVisitProxyFunc&) const override; 92 93 FixedFunctionFlags fixedFunctionFlags() const override; 94 95 GrProcessorSet::Analysis finalize(const GrCaps&, const GrAppliedClip*, GrClampType) override; 96 97 enum class MaskType : uint32_t { 98 kGrayscaleCoverage, 99 kLCDCoverage, 100 kColorBitmap, 101 kAliasedDistanceField, 102 kGrayscaleDistanceField, 103 kLCDDistanceField, 104 kLCDBGRDistanceField, 105 106 kLast = kLCDBGRDistanceField 107 }; 108 inline static constexpr int kMaskTypeCount = static_cast<int>(MaskType::kLast) + 1; 109 110 #if GR_TEST_UTILS && SK_GPU_V1 111 static GrOp::Owner CreateOpTestingOnly(skgpu::v1::SurfaceDrawContext*, 112 const SkPaint&, 113 const SkFont&, 114 const SkMatrixProvider&, 115 const char* text, 116 int x, 117 int y); 118 #endif 119 120 private: 121 friend class GrOp; // for ctor 122 123 struct FlushInfo { 124 sk_sp<const GrBuffer> fVertexBuffer; 125 sk_sp<const GrBuffer> fIndexBuffer; 126 GrGeometryProcessor* fGeometryProcessor; 127 const GrSurfaceProxy** fPrimProcProxies; 128 int fGlyphsToFlush = 0; 129 int fVertexOffset = 0; 130 int fNumDraws = 0; 131 }; 132 133 AtlasTextOp(MaskType maskType, 134 bool needsTransform, 135 int glyphCount, 136 SkRect deviceRect, 137 Geometry* geo, 138 GrPaint&& paint); 139 140 AtlasTextOp(MaskType maskType, 141 bool needsTransform, 142 int glyphCount, 143 SkRect deviceRect, 144 SkColor luminanceColor, 145 bool useGammaCorrectDistanceTable, 146 uint32_t DFGPFlags, 147 Geometry* geo, 148 GrPaint&& paint); 149 programInfo()150 GrProgramInfo* programInfo() override { 151 // TODO [PI]: implement 152 return nullptr; 153 } 154 addGeometry(Geometry * geometry)155 void addGeometry(Geometry* geometry) { 156 *fTail = geometry; 157 // The geometry may have many entries. Find the end. 158 do { 159 fTail = &(*fTail)->fNext; 160 } while (*fTail != nullptr); 161 } 162 onCreateProgramInfo(const GrCaps *,SkArenaAlloc *,const GrSurfaceProxyView & writeView,bool usesMSAASurface,GrAppliedClip &&,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)163 void onCreateProgramInfo(const GrCaps*, 164 SkArenaAlloc*, 165 const GrSurfaceProxyView& writeView, 166 bool usesMSAASurface, 167 GrAppliedClip&&, 168 const GrDstProxyView&, 169 GrXferBarrierFlags renderPassXferBarriers, 170 GrLoadOp colorLoadOp) override { 171 // We cannot surface the AtlasTextOp's programInfo at record time. As currently 172 // implemented, the GP is modified at flush time based on the number of pages in the 173 // atlas. 174 } 175 onPrePrepareDraws(GrRecordingContext *,const GrSurfaceProxyView & writeView,GrAppliedClip *,const GrDstProxyView &,GrXferBarrierFlags renderPassXferBarriers,GrLoadOp colorLoadOp)176 void onPrePrepareDraws(GrRecordingContext*, 177 const GrSurfaceProxyView& writeView, 178 GrAppliedClip*, 179 const GrDstProxyView&, 180 GrXferBarrierFlags renderPassXferBarriers, 181 GrLoadOp colorLoadOp) override { 182 // TODO [PI]: implement 183 } 184 185 void onPrepareDraws(GrMeshDrawTarget*) override; 186 void onExecute(GrOpFlushState*, const SkRect& chainBounds) override; 187 188 #if GR_TEST_UTILS 189 SkString onDumpInfo() const override; 190 #endif 191 maskFormat()192 GrMaskFormat maskFormat() const { 193 switch (this->maskType()) { 194 case MaskType::kLCDCoverage: 195 return kA565_GrMaskFormat; 196 case MaskType::kColorBitmap: 197 return kARGB_GrMaskFormat; 198 case MaskType::kGrayscaleCoverage: 199 case MaskType::kAliasedDistanceField: 200 case MaskType::kGrayscaleDistanceField: 201 case MaskType::kLCDDistanceField: 202 case MaskType::kLCDBGRDistanceField: 203 return kA8_GrMaskFormat; 204 } 205 // SkUNREACHABLE; 206 return kA8_GrMaskFormat; 207 } 208 usesDistanceFields()209 bool usesDistanceFields() const { 210 return MaskType::kAliasedDistanceField == this->maskType() || 211 MaskType::kGrayscaleDistanceField == this->maskType() || 212 MaskType::kLCDDistanceField == this->maskType() || 213 MaskType::kLCDBGRDistanceField == this->maskType(); 214 } 215 isLCD()216 bool isLCD() const { 217 return MaskType::kLCDCoverage == this->maskType() || 218 MaskType::kLCDDistanceField == this->maskType() || 219 MaskType::kLCDBGRDistanceField == this->maskType(); 220 } 221 222 inline void createDrawForGeneratedGlyphs( 223 GrMeshDrawTarget* target, FlushInfo* flushInfo) const; 224 maskType()225 MaskType maskType() const { return static_cast<MaskType>(fMaskType); } 226 227 CombineResult onCombineIfPossible(GrOp* t, SkArenaAlloc*, const GrCaps& caps) override; 228 229 GrGeometryProcessor* setupDfProcessor(SkArenaAlloc*, 230 const GrShaderCaps&, 231 const SkMatrix& localMatrix, 232 const GrSurfaceProxyView* views, 233 unsigned int numActiveViews) const; 234 235 GrProcessorSet fProcessors; 236 int fNumGlyphs; // Sum of glyphs in each geometry's subrun 237 238 // All combinable atlas ops have equal bit field values 239 uint32_t fDFGPFlags : 9; // Distance field properties 240 uint32_t fMaskType : 3; // MaskType 241 uint32_t fUsesLocalCoords : 1; // Filled in post processor analysis 242 uint32_t fNeedsGlyphTransform : 1; 243 uint32_t fHasPerspective : 1; // True if perspective affects draw 244 uint32_t fUseGammaCorrectDistanceTable : 1; 245 static_assert(kMaskTypeCount <= 8, "MaskType does not fit in 3 bits"); 246 static_assert(kInvalid_DistanceFieldEffectFlag <= (1 << 8), "DFGP Flags do not fit in 9 bits"); 247 248 // Only used for distance fields; per-channel luminance for LCD, or gamma-corrected luminance 249 // for single-channel distance fields. 250 const SkColor fLuminanceColor{0}; 251 252 Geometry* fHead{nullptr}; 253 Geometry** fTail{&fHead}; 254 255 using INHERITED = GrMeshDrawOp; 256 }; 257 258 } // namespace skgpu::v1 259 260 #endif // AtlasTextOp_DEFINED 261