• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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