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