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