blob: ba02bbb51f6f5b1fadd113ef16b40a29276ee243 [file] [log] [blame]
joshualitt374b2f72015-07-21 08:05:03 -07001/*
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
Herb Derby86240592018-05-24 16:12:31 -04008#ifndef GrTextBlob_DEFINED
9#define GrTextBlob_DEFINED
joshualitt374b2f72015-07-21 08:05:03 -070010
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkPoint3.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "src/core/SkDescriptor.h"
13#include "src/core/SkMaskFilterBase.h"
14#include "src/core/SkOpts.h"
15#include "src/core/SkRectPriv.h"
Herb Derbye7efd082019-05-28 11:30:33 -040016#include "src/core/SkStrikeSpec.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040017#include "src/gpu/GrColor.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050018#include "src/gpu/GrDrawOpAtlas.h"
joshualitt374b2f72015-07-21 08:05:03 -070019
Brian Salomon43cbd722020-01-03 22:09:12 -050020#include <limits>
21
Robert Phillipsc4039ea2018-03-01 11:36:45 -050022class GrAtlasManager;
Herb Derby660c2ff2019-11-14 18:22:41 -050023class GrAtlasTextOp;
Robert Phillips5fa68b42020-03-31 08:34:22 -040024class GrGlyph;
Robert Phillips41bd97d2020-04-07 14:19:37 -040025class GrStrikeCache;
26class GrTextContext;
Robert Phillipsc4039ea2018-03-01 11:36:45 -050027
Robert Phillips41bd97d2020-04-07 14:19:37 -040028class SkSurfaceProps;
joshualitt2e2202e2015-12-10 11:22:08 -080029class SkTextBlob;
30class SkTextBlobRunIterator;
31
Herb Derbyc514e7d2019-12-11 17:00:31 -050032
33// A GrTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
34// on the GPU. These are initially created with valid positions and colors, but invalid
35// texture coordinates.
36//
37// A GrTextBlob contains a number of SubRuns that are created in the blob's arena. Each SubRun
38// tracks its own GrGlyph* and vertex data. The memory is organized in the arena in the following
39// way so that the pointers for the GrGlyph* and vertex data are known before creating the SubRun.
40//
41// GrGlyph*... | vertexData... | SubRun | GrGlyph*... | vertexData... | SubRun etc.
42//
Herb Derby5bf5b042019-12-12 16:37:03 -050043// In these classes, I'm trying to follow the convention about matrices and origins.
44// * draw Matrix|Origin - describes the current draw command.
45// * initial Matrix|Origin - describes the matrix and origin the GrTextBlob was created with.
46// * current Matrix|Origin - describes the matrix and origin that are currently in the SubRun's
47// vertex data.
48//
49// When handling repeated drawing using the same GrTextBlob initial data are compared to drawing
50// data to see if this blob can service this drawing. If it can, but small changes are needed to
51// the vertex data, the current data of the SubRuns is adjusted to conform to the drawing data
52// from the op using the VertexRegenerator.
53//
Herb Derbya9047642019-12-06 12:12:11 -050054class GrTextBlob final : public SkNVRefCnt<GrTextBlob>, public SkGlyphRunPainterInterface {
joshualitt2e2202e2015-12-10 11:22:08 -080055public:
Herb Derby660c2ff2019-11-14 18:22:41 -050056 class SubRun;
Herb Derbya9047642019-12-06 12:12:11 -050057 class VertexRegenerator;
joshualitt374b2f72015-07-21 08:05:03 -070058
Herb Derbya9047642019-12-06 12:12:11 -050059 enum SubRunType {
60 kDirectMask,
61 kTransformedMask,
62 kTransformedPath,
63 kTransformedSDFT
64 };
joshualitt323c2eb2016-01-20 06:48:47 -080065
66 struct Key {
Herb Derbya9047642019-12-06 12:12:11 -050067 Key();
joshualitt323c2eb2016-01-20 06:48:47 -080068 uint32_t fUniqueID;
69 // Color may affect the gamma of the mask we generate, but in a fairly limited way.
70 // Each color is assigned to on of a fixed number of buckets based on its
71 // luminance. For each luminance bucket there is a "canonical color" that
72 // represents the bucket. This functionality is currently only supported for A8
73 SkColor fCanonicalColor;
74 SkPaint::Style fStyle;
Herb Derby5c7f38a2019-12-13 16:28:42 +000075 SkPixelGeometry fPixelGeometry;
joshualitt323c2eb2016-01-20 06:48:47 -080076 bool fHasBlur;
Herb Derby5c7f38a2019-12-13 16:28:42 +000077 uint32_t fScalerContextFlags;
joshualitt323c2eb2016-01-20 06:48:47 -080078
Herb Derbya9047642019-12-06 12:12:11 -050079 bool operator==(const Key& other) const;
joshualitt323c2eb2016-01-20 06:48:47 -080080 };
81
Herb Derbya9047642019-12-06 12:12:11 -050082 // Any glyphs that can't be rendered with the base or override descriptor
83 // are rendered as paths
84 struct PathGlyph {
85 PathGlyph(const SkPath& path, SkPoint origin);
86 SkPath fPath;
87 SkPoint fOrigin;
88 };
89
Herb Derbya9047642019-12-06 12:12:11 -050090 SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrTextBlob);
91
92 // Change memory management to handle the data after GrTextBlob, but in the same allocation
93 // of memory. Only allow placement new.
94 void operator delete(void* p);
95 void* operator new(size_t);
96 void* operator new(size_t, void* p);
97
98 ~GrTextBlob() override;
99
100 // Make an empty GrTextBlob, with all the invariants set to make the right decisions when
101 // adding SubRuns.
Herb Derby659e4092019-12-06 15:38:10 -0500102 static sk_sp<GrTextBlob> Make(const SkGlyphRunList& glyphRunList,
Herb Derbya9047642019-12-06 12:12:11 -0500103 GrStrikeCache* strikeCache,
Herb Derby1c5be7b2019-12-13 12:03:06 -0500104 const SkMatrix& drawMatrix,
Herb Derbya9047642019-12-06 12:12:11 -0500105 GrColor color,
106 bool forceWForDistanceFields);
107
Herb Derbya9047642019-12-06 12:12:11 -0500108 // Key manipulation functions
Herb Derby86240592018-05-24 16:12:31 -0400109 void setupKey(const GrTextBlob::Key& key,
Mike Reed80747ef2018-01-23 15:29:32 -0500110 const SkMaskFilterBase::BlurRec& blurRec,
Herb Derbya9047642019-12-06 12:12:11 -0500111 const SkPaint& paint);
112 static const Key& GetKey(const GrTextBlob& blob);
113 static uint32_t Hash(const Key& key);
joshualitt92303772016-02-10 11:55:52 -0800114
Herb Derbya9047642019-12-06 12:12:11 -0500115 bool hasDistanceField() const;
116 bool hasBitmap() const;
117 bool hasPerspective() const;
joshualitt323c2eb2016-01-20 06:48:47 -0800118
Herb Derbya9047642019-12-06 12:12:11 -0500119 void setHasDistanceField();
120 void setHasBitmap();
121 void setMinAndMaxScale(SkScalar scaledMin, SkScalar scaledMax);
joshualitt323c2eb2016-01-20 06:48:47 -0800122
Herb Derbya9047642019-12-06 12:12:11 -0500123 static size_t GetVertexStride(GrMaskFormat maskFormat, bool hasWCoord);
joshualitt323c2eb2016-01-20 06:48:47 -0800124
Herb Derby0edb2142018-10-16 17:04:11 -0400125 bool mustRegenerate(const SkPaint&, bool, const SkMaskFilterBase::BlurRec& blurRec,
Herb Derby5bf5b042019-12-12 16:37:03 -0500126 const SkMatrix& drawMatrix, SkPoint drawOrigin);
joshualitt323c2eb2016-01-20 06:48:47 -0800127
Herb Derbyc1b482c2018-08-09 15:02:27 -0400128 void flush(GrTextTarget*, const SkSurfaceProps& props,
Brian Osmancf860852018-10-31 14:04:39 -0400129 const SkPaint& paint, const SkPMColor4f& filteredColor, const GrClip& clip,
Herb Derby5bf5b042019-12-12 16:37:03 -0500130 const SkMatrix& drawMatrix, SkPoint drawOrigin);
joshualitt323c2eb2016-01-20 06:48:47 -0800131
Herb Derby660c2ff2019-11-14 18:22:41 -0500132 void computeSubRunBounds(SkRect* outBounds, const SubRun& subRun,
Herb Derby5bf5b042019-12-12 16:37:03 -0500133 const SkMatrix& drawMatrix, SkPoint drawOrigin,
Herb Derbyeba195f2019-12-03 16:44:47 -0500134 bool needsGlyphTransform);
joshualittbc811112016-02-11 12:42:02 -0800135
Herb Derbycd498e12019-12-06 14:17:31 -0500136 // Normal text mask, SDFT, or color.
137 struct Mask2DVertex {
138 SkPoint devicePos;
139 GrColor color;
140 SkIPoint16 atlasPos;
141 };
142 struct ARGB2DVertex {
143 SkPoint devicePos;
144 SkIPoint16 atlasPos;
145 };
146
147 // Perspective SDFT or SDFT forced to 3D or perspective color.
148 struct SDFT3DVertex {
149 SkPoint3 devicePos;
150 GrColor color;
151 SkIPoint16 atlasPos;
152 };
153 struct ARGB3DVertex {
154 SkPoint3 devicePos;
155 SkIPoint16 atlasPos;
156 };
157
joshualitt323c2eb2016-01-20 06:48:47 -0800158 static const int kVerticesPerGlyph = 4;
159
Herb Derbya9047642019-12-06 12:12:11 -0500160 const Key& key() const;
161 size_t size() const;
joshualitt92303772016-02-10 11:55:52 -0800162
joshualittbc811112016-02-11 12:42:02 -0800163 // Internal test methods
Robert Phillips841c9a52020-03-27 12:41:31 -0400164 std::unique_ptr<GrDrawOp> test_makeOp(int glyphCount, const SkMatrix& drawMatrix,
165 SkPoint drawOrigin, const SkPaint& paint,
166 const SkPMColor4f& filteredColor, const SkSurfaceProps&,
Herb Derbyc1b482c2018-08-09 15:02:27 -0400167 GrTextTarget*);
joshualittbc811112016-02-11 12:42:02 -0800168
Herb Derbya9047642019-12-06 12:12:11 -0500169 bool hasW(SubRunType type) const;
Herb Derby1b8dcd12019-11-15 15:21:15 -0500170
171 SubRun* makeSubRun(SubRunType type,
172 const SkZip<SkGlyphVariant, SkPoint>& drawables,
173 const SkStrikeSpec& strikeSpec,
174 GrMaskFormat format);
175
176 void addSingleMaskFormat(
177 SubRunType type,
178 const SkZip<SkGlyphVariant, SkPoint>& drawables,
179 const SkStrikeSpec& strikeSpec,
180 GrMaskFormat format);
181
182 void addMultiMaskFormat(
183 SubRunType type,
184 const SkZip<SkGlyphVariant, SkPoint>& drawables,
185 const SkStrikeSpec& strikeSpec);
186
187 void addSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
188 const SkStrikeSpec& strikeSpec,
189 const SkFont& runFont,
190 SkScalar minScale,
191 SkScalar maxScale);
joshualitt374b2f72015-07-21 08:05:03 -0700192
Herb Derby660c2ff2019-11-14 18:22:41 -0500193private:
Herb Derbya9047642019-12-06 12:12:11 -0500194 enum TextType {
195 kHasDistanceField_TextType = 0x1,
196 kHasBitmap_TextType = 0x2,
197 };
Herb Derby00ae9592019-12-03 15:55:56 -0500198
199 struct StrokeInfo {
200 SkScalar fFrameWidth;
201 SkScalar fMiterLimit;
202 SkPaint::Join fJoin;
203 };
204
Herb Derbycb718892019-12-07 00:07:42 -0500205 GrTextBlob(size_t allocSize,
Herb Derbya9047642019-12-06 12:12:11 -0500206 GrStrikeCache* strikeCache,
Herb Derby1c5be7b2019-12-13 12:03:06 -0500207 const SkMatrix& drawMatrix,
Herb Derbya9047642019-12-06 12:12:11 -0500208 SkPoint origin,
209 GrColor color,
Herb Derbyaebc5f82019-12-10 14:07:10 -0500210 SkColor initialLuminance,
Herb Derbya9047642019-12-06 12:12:11 -0500211 bool forceWForDistanceFields);
Herb Derby00ae9592019-12-03 15:55:56 -0500212
Herb Derbycb718892019-12-07 00:07:42 -0500213 void insertSubRun(SubRun* subRun);
214
Robert Phillips841c9a52020-03-27 12:41:31 -0400215 std::unique_ptr<GrAtlasTextOp> makeOp(SubRun& info, int glyphCount, const SkMatrix& drawMatrix,
216 SkPoint drawOrigin, const SkIRect& clipRect,
217 const SkPaint& paint, const SkPMColor4f& filteredColor,
218 const SkSurfaceProps&, GrTextTarget*);
joshualitt323c2eb2016-01-20 06:48:47 -0800219
Herb Derbya9047642019-12-06 12:12:11 -0500220 // Methods to satisfy SkGlyphRunPainterInterface
Herb Derby20eafff2019-10-16 16:21:13 -0400221 void processDeviceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derby36a54c12019-06-06 10:50:56 -0400222 const SkStrikeSpec& strikeSpec) override;
Herb Derby12130412019-10-21 18:02:24 -0400223 void processSourcePaths(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derby1b8dcd12019-11-15 15:21:15 -0500224 const SkFont& runFont,
Herb Derby36a54c12019-06-06 10:50:56 -0400225 const SkStrikeSpec& strikeSpec) override;
Herb Derby20eafff2019-10-16 16:21:13 -0400226 void processSourceSDFT(const SkZip<SkGlyphVariant, SkPoint>& drawables,
Herb Derby36a54c12019-06-06 10:50:56 -0400227 const SkStrikeSpec& strikeSpec,
Herb Derbyc72594a2019-03-05 17:39:38 -0500228 const SkFont& runFont,
Herb Derbyc72594a2019-03-05 17:39:38 -0500229 SkScalar minScale,
Herb Derby1b8dcd12019-11-15 15:21:15 -0500230 SkScalar maxScale) override;
Herb Derby1b8dcd12019-11-15 15:21:15 -0500231 void processSourceMasks(const SkZip<SkGlyphVariant, SkPoint>& drawables,
232 const SkStrikeSpec& strikeSpec) override;
Herb Derbyc72594a2019-03-05 17:39:38 -0500233
Herb Derby00ae9592019-12-03 15:55:56 -0500234 // Overall size of this struct plus vertices and glyphs at the end.
235 const size_t fSize;
Herb Derby1b8dcd12019-11-15 15:21:15 -0500236
Herb Derby00ae9592019-12-03 15:55:56 -0500237 // Lifetime: The GrStrikeCache is owned by and has the same lifetime as the GrRecordingContext.
238 // The GrRecordingContext also owns the GrTextBlob cache which owns this GrTextBlob.
239 GrStrikeCache* const fStrikeCache;
240
Herb Derbye9f691d2019-12-04 12:11:13 -0500241 // The initial view matrix and its inverse. This is used for moving additional draws of this
242 // same text blob. We record the initial view matrix and initial offsets(x,y), because we
243 // record vertex bounds relative to these numbers. When blobs are reused with new matrices,
244 // we need to return to source space so we can update the vertex bounds appropriately.
Herb Derby1c5be7b2019-12-13 12:03:06 -0500245 const SkMatrix fInitialMatrix;
246 const SkMatrix fInitialMatrixInverse;
Herb Derbye9f691d2019-12-04 12:11:13 -0500247
Herb Derbyeba195f2019-12-03 16:44:47 -0500248 // Initial position of this blob. Used for calculating position differences when reusing this
249 // blob.
250 const SkPoint fInitialOrigin;
251
Herb Derby00ae9592019-12-03 15:55:56 -0500252 // From the distance field options to force distance fields to have a W coordinate.
253 const bool fForceWForDistanceFields;
254
255 // The color of the text to draw for solid colors.
256 const GrColor fColor;
Herb Derbyaebc5f82019-12-10 14:07:10 -0500257 const SkColor fInitialLuminance;
Herb Derby1b8dcd12019-11-15 15:21:15 -0500258
Herb Derby1b8dcd12019-11-15 15:21:15 -0500259 SkMaskFilterBase::BlurRec fBlurRec;
joshualitt374b2f72015-07-21 08:05:03 -0700260 StrokeInfo fStrokeInfo;
joshualitt374b2f72015-07-21 08:05:03 -0700261 Key fKey;
joshualitt374b2f72015-07-21 08:05:03 -0700262
Herb Derbyeba195f2019-12-03 16:44:47 -0500263 // We can reuse distance field text, but only if the new view matrix would not result in
joshualitt374b2f72015-07-21 08:05:03 -0700264 // a mip change. Because there can be multiple runs in a blob, we track the overall
265 // maximum minimum scale, and minimum maximum scale, we can support before we need to regen
Herb Derbya00da612019-03-04 17:10:01 -0500266 SkScalar fMaxMinScale{-SK_ScalarMax};
267 SkScalar fMinMaxScale{SK_ScalarMax};
Herb Derby1b8dcd12019-11-15 15:21:15 -0500268
Herb Derbya00da612019-03-04 17:10:01 -0500269 uint8_t fTextType{0};
Herb Derbycb718892019-12-07 00:07:42 -0500270
271 SubRun* fFirstSubRun{nullptr};
272 SubRun* fLastSubRun{nullptr};
273 SkArenaAlloc fAlloc;
joshualitt374b2f72015-07-21 08:05:03 -0700274};
275
Brian Salomon18923f92017-11-06 16:26:02 -0500276/**
277 * Used to produce vertices for a subrun of a blob. The vertices are cached in the blob itself.
278 * This is invoked each time a sub run is drawn. It regenerates the vertex data as required either
279 * because of changes to the atlas or because of different draw parameters (e.g. color change). In
280 * rare cases the draw may have to interrupted and flushed in the middle of the sub run in order to
281 * free up atlas space. Thus, this generator is stateful and should be invoked in a loop until the
282 * entire sub run has been completed.
283 */
Herb Derby86240592018-05-24 16:12:31 -0400284class GrTextBlob::VertexRegenerator {
Brian Salomon18923f92017-11-06 16:26:02 -0500285public:
286 /**
287 * Consecutive VertexRegenerators often use the same SkGlyphCache. If the same instance of
288 * SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
289 * SkGlyphCache.
290 */
Herb Derbyc514e7d2019-12-11 17:00:31 -0500291 VertexRegenerator(GrResourceProvider*, GrTextBlob::SubRun* subRun,
Herb Derby5ddc34c2020-02-01 20:38:30 -0500292 GrDeferredUploadTarget*, GrAtlasManager*);
Brian Salomon18923f92017-11-06 16:26:02 -0500293
Herb Derby23f29762020-01-10 16:26:14 -0500294 // Return {success, number of glyphs regenerated}
295 std::tuple<bool, int> regenerate(int begin, int end);
Brian Salomon18923f92017-11-06 16:26:02 -0500296
297private:
Herb Derby23f29762020-01-10 16:26:14 -0500298 // Return {success, number of glyphs regenerated}
Herb Derby3d051922020-01-31 16:59:29 -0500299 std::tuple<bool, int> updateTextureCoordinates(int begin, int end);
Brian Salomon18923f92017-11-06 16:26:02 -0500300
Robert Phillips4bc70112018-03-01 10:24:02 -0500301 GrResourceProvider* fResourceProvider;
Brian Salomon18923f92017-11-06 16:26:02 -0500302 GrDeferredUploadTarget* fUploadTarget;
Robert Phillipsc4039ea2018-03-01 11:36:45 -0500303 GrAtlasManager* fFullAtlasManager;
Herb Derbycb443a52019-11-11 18:01:36 -0500304 SkTLazy<SkBulkGlyphMetricsAndImages> fMetricsAndImages;
Herb Derby69ff8952018-11-12 11:39:12 -0500305 SubRun* fSubRun;
Brian Salomon18923f92017-11-06 16:26:02 -0500306};
307
Herb Derbya6026a22020-01-09 14:04:25 -0500308// -- GrTextBlob::SubRun ---------------------------------------------------------------------------
309// Hold data to draw the different types of sub run. SubRuns are produced knowing all the
310// glyphs that are included in them.
311class GrTextBlob::SubRun {
312public:
313 // SubRun for masks
314 SubRun(SubRunType type,
315 GrTextBlob* textBlob,
316 const SkStrikeSpec& strikeSpec,
317 GrMaskFormat format,
318 const SkSpan<GrGlyph*>& glyphs, const SkSpan<char>& vertexData,
319 sk_sp<GrTextStrike>&& grStrike);
320
321 // SubRun for paths
322 SubRun(GrTextBlob* textBlob, const SkStrikeSpec& strikeSpec);
323
324 void appendGlyphs(const SkZip<SkGlyphVariant, SkPoint>& drawables);
325
326 // TODO when this object is more internal, drop the privacy
327 void resetBulkUseToken();
328 GrDrawOpAtlas::BulkUseTokenUpdater* bulkUseToken();
329 void setStrike(sk_sp<GrTextStrike> strike);
330 GrTextStrike* strike() const;
331
332 GrMaskFormat maskFormat() const;
333
334 size_t vertexStride() const;
335 size_t colorOffset() const;
336 size_t texCoordOffset() const;
337 char* quadStart(size_t index) const;
Herb Derby23f29762020-01-10 16:26:14 -0500338 size_t quadOffset(size_t index) const;
Herb Derbya6026a22020-01-09 14:04:25 -0500339
340 const SkRect& vertexBounds() const;
341 void joinGlyphBounds(const SkRect& glyphBounds);
342
343 bool drawAsDistanceFields() const;
344 bool drawAsPaths() const;
345 bool needsTransform() const;
Robert Phillips6d3bc292020-04-06 10:29:28 -0400346 bool needsPadding() const;
Herb Derbya6026a22020-01-09 14:04:25 -0500347
348 void translateVerticesIfNeeded(const SkMatrix& drawMatrix, SkPoint drawOrigin);
349 void updateVerticesColorIfNeeded(GrColor newColor);
350 void updateTexCoords(int begin, int end);
351
352 // df properties
353 void setUseLCDText(bool useLCDText);
354 bool hasUseLCDText() const;
355 void setAntiAliased(bool antiAliased);
356 bool isAntiAliased() const;
357
358 const SkStrikeSpec& strikeSpec() const;
359
360 SubRun* fNextSubRun{nullptr};
361 const SubRunType fType;
362 GrTextBlob* const fBlob;
363 const GrMaskFormat fMaskFormat;
364 const SkSpan<GrGlyph*> fGlyphs;
365 const SkSpan<char> fVertexData;
366 const SkStrikeSpec fStrikeSpec;
367 sk_sp<GrTextStrike> fStrike;
368 struct {
369 bool useLCDText:1;
370 bool antiAliased:1;
371 } fFlags{false, false};
372 GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken;
373 SkRect fVertexBounds = SkRectPriv::MakeLargestInverted();
374 uint64_t fAtlasGeneration{GrDrawOpAtlas::kInvalidAtlasGeneration};
375 GrColor fCurrentColor;
376 SkPoint fCurrentOrigin;
377 SkMatrix fCurrentMatrix;
378 std::vector<PathGlyph> fPaths;
379
380private:
381 bool hasW() const;
382
383}; // SubRun
384
Herb Derby86240592018-05-24 16:12:31 -0400385#endif // GrTextBlob_DEFINED