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 GrTextBlob_DEFINED 9 #define GrTextBlob_DEFINED 10 11 #include <algorithm> 12 #include <limits> 13 14 #include "include/core/SkPoint3.h" 15 #include "include/core/SkRefCnt.h" 16 #include "src/core/SkGlyphRunPainter.h" 17 #include "src/core/SkIPoint16.h" 18 #include "src/core/SkMaskFilterBase.h" 19 #include "src/core/SkOpts.h" 20 #include "src/core/SkRectPriv.h" 21 #include "src/core/SkStrikeSpec.h" 22 #include "src/core/SkTInternalLList.h" 23 #include "src/core/SkTLazy.h" 24 #include "src/gpu/GrColor.h" 25 #include "src/gpu/GrSubRunAllocator.h" 26 #include "src/gpu/ops/GrOp.h" 27 28 class GrAtlasManager; 29 class GrDeferredUploadTarget; 30 class GrGlyph; 31 class GrMeshDrawTarget; 32 class GrStrikeCache; 33 class GrSubRun; 34 35 class SkMatrixProvider; 36 class SkSurfaceProps; 37 class SkTextBlob; 38 class SkTextBlobRunIterator; 39 40 namespace skgpu { namespace v1 { class SurfaceDrawContext; }} 41 42 // -- SubRun Discussion ---------------------------------------------------------------------------- 43 // There are two distinct types of SubRun, those that the GrTextBlob hold in the GrTextBlobCache, 44 // and those that are not cached at all. The type of SubRun that is not cached has NoCache 45 // appended to their name such as DirectMaskSubRunNoCache. The type of SubRun that is cached 46 // provides two interfaces the GrSubRun interface which used by the text blob caching system, and 47 // the GrAtlasSubRun which allows drawing by the AtlasTextOp system. The *NoCache SubRuns only 48 // provide the GrAtlasSubRun interface. 49 50 // -- GrAtlasSubRun -------------------------------------------------------------------------------- 51 // GrAtlasSubRun is the API that AtlasTextOp uses to generate vertex data for drawing. 52 // There are three different ways GrAtlasSubRun is specialized. 53 // * DirectMaskSubRun - this is by far the most common type of SubRun. The mask pixels are 54 // in 1:1 correspondence with the pixels on the device. The destination rectangles in this 55 // SubRun are in device space. This SubRun handles color glyphs. 56 // * TransformedMaskSubRun - handles glyph where the image in the atlas needs to be 57 // transformed to the screen. It is usually used for large color glyph which can't be 58 // drawn with paths or scaled distance fields, but will be used to draw bitmap glyphs to 59 // the screen, if the matrix does not map 1:1 to the screen. The destination rectangles 60 // are in source space. 61 // * SDFTSubRun - scaled distance field text handles largish single color glyphs that still 62 // can fit in the atlas; the sizes between direct SubRun, and path SubRun. The destination 63 // rectangles are in source space. 64 65 class GrAtlasSubRun; 66 using GrAtlasSubRunOwner = std::unique_ptr<GrAtlasSubRun, GrSubRunAllocator::Destroyer>; 67 class GrAtlasSubRun { 68 public: 69 inline static constexpr int kVerticesPerGlyph = 4; 70 71 virtual ~GrAtlasSubRun() = default; 72 73 virtual size_t vertexStride(const SkMatrix& drawMatrix) const = 0; 74 virtual int glyphCount() const = 0; 75 76 virtual std::tuple<const GrClip*, GrOp::Owner> 77 makeAtlasTextOp( 78 const GrClip*, 79 const SkMatrixProvider& viewMatrix, 80 SkPoint drawOrigin, 81 const SkPaint&, 82 skgpu::v1::SurfaceDrawContext*, 83 GrAtlasSubRunOwner subRun) const = 0; 84 85 virtual void fillVertexData( 86 void* vertexDst, int offset, int count, 87 GrColor color, const SkMatrix& positionMatrix, 88 SkIRect clip) const = 0; 89 90 virtual void testingOnly_packedGlyphIDToGrGlyph(GrStrikeCache* cache) = 0; 91 92 // This call is not thread safe. It should only be called from GrDrawOp::onPrepare which 93 // is single threaded. 94 virtual std::tuple<bool, int> regenerateAtlas( 95 int begin, int end, GrMeshDrawTarget* target) const = 0; 96 }; 97 98 // -- GrSubRun ------------------------------------------------------------------------------------- 99 // GrSubRun provides an interface used by GrTextBlob to manage the caching system. 100 // There are several types of SubRun, which can be broken into five classes: 101 // * PathSubRun - handle very large single color glyphs using paths to render the glyph. 102 // * DirectMaskSubRun - handle the majority of the glyphs where the cache entry's pixels are in 103 // 1:1 correspondence to the device pixels. 104 // * TransformedMaskSubRun - handle large bitmap/argb glyphs that need to be scaled to the screen. 105 // * SDFTSubRun - use signed distance fields to draw largish glyphs to the screen. 106 class GrSubRun; 107 using GrSubRunOwner = std::unique_ptr<GrSubRun, GrSubRunAllocator::Destroyer>; 108 class GrSubRun { 109 public: 110 virtual ~GrSubRun() = default; 111 112 // Produce GPU ops for this subRun. 113 virtual void draw(const GrClip*, 114 const SkMatrixProvider& viewMatrix, 115 const SkGlyphRunList&, 116 const SkPaint&, 117 skgpu::v1::SurfaceDrawContext*) const = 0; 118 119 // Given an already cached subRun, can this subRun handle this combination paint, matrix, and 120 // position. 121 virtual bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) const = 0; 122 123 // Return the underlying atlas SubRun if it exists. Otherwise, return nullptr. 124 // * Don't use this API. It is only to support testing. 125 virtual GrAtlasSubRun* testingOnly_atlasSubRun() = 0; 126 127 GrSubRunOwner fNext; 128 }; 129 130 struct GrSubRunList { 131 class Iterator { 132 public: 133 using value_type = GrSubRun; 134 using difference_type = ptrdiff_t; 135 using pointer = value_type*; 136 using reference = value_type&; 137 using iterator_category = std::input_iterator_tag; IteratorGrSubRunList138 Iterator(GrSubRun* subRun) : fPtr{subRun} { } 139 Iterator& operator++() { fPtr = fPtr->fNext.get(); return *this; } 140 Iterator operator++(int) { Iterator tmp(*this); operator++(); return tmp; } 141 bool operator==(const Iterator& rhs) const { return fPtr == rhs.fPtr; } 142 bool operator!=(const Iterator& rhs) const { return fPtr != rhs.fPtr; } 143 reference operator*() { return *fPtr; } 144 145 private: 146 GrSubRun* fPtr; 147 }; 148 appendGrSubRunList149 void append(GrSubRunOwner subRun) { 150 GrSubRunOwner* newTail = &subRun->fNext; 151 *fTail = std::move(subRun); 152 fTail = newTail; 153 } isEmptyGrSubRunList154 bool isEmpty() const { return fHead == nullptr; } beginGrSubRunList155 Iterator begin() { return Iterator{ fHead.get()}; } endGrSubRunList156 Iterator end() { return Iterator{nullptr}; } beginGrSubRunList157 Iterator begin() const { return Iterator{ fHead.get()}; } endGrSubRunList158 Iterator end() const { return Iterator{nullptr}; } frontGrSubRunList159 GrSubRun& front() const {return *fHead; } 160 161 GrSubRunOwner fHead{nullptr}; 162 GrSubRunOwner* fTail{&fHead}; 163 }; 164 165 // A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing 166 // on the GPU. These are initially created with valid positions and colors, but with invalid 167 // texture coordinates. 168 // 169 // A GrTextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun 170 // tracks its own GrGlyph* and vertex data. The memory is organized in the arena in the following 171 // way so that the pointers for the GrGlyph* and vertex data are known before creating the SubRun. 172 // 173 // GrGlyph*... | vertexData... | SubRun | GrGlyph*... | vertexData... | SubRun etc. 174 // 175 // In these classes, I'm trying to follow the convention about matrices and origins. 176 // * drawMatrix and drawOrigin - describes transformations for the current draw command. 177 // * initial Matrix - describes the combined initial matrix and origin the GrTextBlob was created 178 // with. 179 // 180 // 181 class GrTextBlob final : public SkRefCnt, public SkGlyphRunPainterInterface { 182 public: 183 184 // Key is not used as part of a hash map, so the hash is never taken. It's only used in a 185 // list search using operator =(). 186 struct Key { 187 static std::tuple<bool, Key> Make(const SkGlyphRunList& glyphRunList, 188 const SkPaint& paint, 189 const SkSurfaceProps& surfaceProps, 190 const GrColorInfo& colorInfo, 191 const SkMatrix& drawMatrix, 192 const GrSDFTControl& control); 193 uint32_t fUniqueID; 194 // Color may affect the gamma of the mask we generate, but in a fairly limited way. 195 // Each color is assigned to on of a fixed number of buckets based on its 196 // luminance. For each luminance bucket there is a "canonical color" that 197 // represents the bucket. This functionality is currently only supported for A8 198 SkColor fCanonicalColor; 199 SkScalar fFrameWidth; 200 SkScalar fMiterLimit; 201 SkPixelGeometry fPixelGeometry; 202 SkMaskFilterBase::BlurRec fBlurRec; 203 uint32_t fScalerContextFlags; 204 SkMatrix fDrawMatrix; 205 // Below here fields are of size 1 byte. 206 uint8_t fSetOfDrawingTypes; 207 bool fHasBlur; 208 SkPaint::Style fStyle; 209 SkPaint::Join fJoin; 210 211 bool operator==(const Key& other) const; 212 }; 213 214 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob); 215 216 // Make a GrTextBlob and its sub runs. 217 static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList, 218 const SkPaint& paint, 219 const SkMatrix& drawMatrix, 220 const GrSDFTControl& control, 221 SkGlyphRunListPainter* painter); 222 223 ~GrTextBlob() override; 224 225 // Change memory management to handle the data after GrTextBlob, but in the same allocation 226 // of memory. Only allow placement new. 227 void operator delete(void* p); 228 void* operator new(size_t); 229 void* operator new(size_t, void* p); 230 key()231 const Key& key() { return fKey; } 232 233 void addKey(const Key& key); 234 bool hasPerspective() const; initialMatrix()235 const SkMatrix& initialMatrix() const { return fInitialMatrix; } 236 scaleBounds()237 std::tuple<SkScalar, SkScalar> scaleBounds() const { return {fMaxMinScale, fMinMaxScale}; } 238 bool canReuse(const SkPaint& paint, const SkMatrix& drawMatrix) const; 239 240 const Key& key() const; 241 size_t size() const; 242 subRunList()243 const GrSubRunList& subRunList() const { return fSubRunList; } 244 245 private: 246 GrTextBlob(int allocSize, const SkMatrix& drawMatrix, SkColor initialLuminance); 247 248 template<typename AddSingleMaskFormat> 249 void addMultiMaskFormat( 250 AddSingleMaskFormat addSingle, 251 const SkZip<SkGlyphVariant, SkPoint>& drawables, 252 sk_sp<SkStrike>&& strike, 253 SkScalar strikeToSourceScale); 254 255 // Methods to satisfy SkGlyphRunPainterInterface 256 void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 257 sk_sp<SkStrike>&& strike) override; 258 void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables, 259 const SkFont& runFont, 260 SkScalar strikeToSourceScale) override; 261 void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, 262 sk_sp<SkStrike>&& strike, 263 SkScalar strikeToSourceScale, 264 const SkFont& runFont, 265 SkScalar minScale, 266 SkScalar maxScale) override; 267 void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 268 sk_sp<SkStrike>&& strike, 269 SkScalar strikeToSourceScale) override; 270 271 // The allocator must come first because it needs to be destroyed last. Other fields of this 272 // structure may have pointers into it. 273 GrSubRunAllocator fAlloc; 274 275 // Owner and list of the SubRun. 276 GrSubRunList fSubRunList; 277 278 // Overall size of this struct plus vertices and glyphs at the end. 279 const int fSize; 280 281 // The initial view matrix combined with the initial origin. Used to determine if a cached 282 // subRun can be used in this draw situation. 283 const SkMatrix fInitialMatrix; 284 285 const SkColor fInitialLuminance; 286 287 Key fKey; 288 289 // We can reuse distance field text, but only if the new view matrix would not result in 290 // a mip change. Because there can be multiple runs in a blob, we track the overall 291 // maximum minimum scale, and minimum maximum scale, we can support before we need to regen 292 SkScalar fMaxMinScale{-SK_ScalarMax}; 293 SkScalar fMinMaxScale{SK_ScalarMax}; 294 295 bool fSomeGlyphsExcluded{false}; 296 }; 297 298 class GrSubRunNoCachePainter : public SkGlyphRunPainterInterface { 299 public: 300 GrSubRunNoCachePainter(skgpu::v1::SurfaceDrawContext*, 301 GrSubRunAllocator*, 302 const GrClip*, 303 const SkMatrixProvider& viewMatrix, 304 const SkGlyphRunList&, 305 const SkPaint&); 306 void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 307 sk_sp<SkStrike>&& strike) override; 308 void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables, 309 sk_sp<SkStrike>&& strike, 310 SkScalar strikeToSourceScale) override; 311 void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables, 312 const SkFont& runFont, 313 SkScalar strikeToSourceScale) override; 314 void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables, 315 sk_sp<SkStrike>&& strike, 316 SkScalar strikeToSourceScale, 317 const SkFont& runFont, 318 SkScalar minScale, SkScalar maxScale) override; 319 320 private: 321 322 // Draw passes ownership of the sub run to the op. 323 void draw(GrAtlasSubRunOwner subRun); 324 325 skgpu::v1::SurfaceDrawContext* const fSDC; 326 GrSubRunAllocator* const fAlloc; 327 const GrClip* const fClip; 328 const SkMatrixProvider& fViewMatrix; 329 const SkGlyphRunList& fGlyphRunList; 330 const SkPaint& fPaint; 331 }; 332 333 #endif // GrTextBlob_DEFINED 334