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