blob: 4725ee529d3ae7c0536d0586881f29a2027bef8d [file] [log] [blame]
joshualitt1d89e8d2015-04-01 12:40:54 -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
8#ifndef GrAtlasTextContext_DEFINED
9#define GrAtlasTextContext_DEFINED
10
11#include "GrTextContext.h"
12
13#include "GrGeometryProcessor.h"
14#include "SkDescriptor.h"
15#include "SkTHash.h"
16
17class GrBatchTextStrike;
18class GrPipelineBuilder;
19
20/*
21 * This class implements GrTextContext using standard bitmap fonts, and can also process textblobs.
22 * TODO replace GrBitmapTextContext
23 */
joshualittdbd35932015-04-02 09:19:04 -070024class GrAtlasTextContext : public GrTextContext {
joshualitt1d89e8d2015-04-01 12:40:54 -070025public:
joshualittdbd35932015-04-02 09:19:04 -070026 static GrAtlasTextContext* Create(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
joshualitt1d89e8d2015-04-01 12:40:54 -070027
joshualittdbd35932015-04-02 09:19:04 -070028 virtual ~GrAtlasTextContext();
joshualitt1d89e8d2015-04-01 12:40:54 -070029
30private:
joshualittdbd35932015-04-02 09:19:04 -070031 GrAtlasTextContext(GrContext*, SkGpuDevice*, const SkDeviceProperties&);
joshualitt1d89e8d2015-04-01 12:40:54 -070032
33 bool canDraw(const GrRenderTarget*, const GrClip&, const GrPaint&,
34 const SkPaint&, const SkMatrix& viewMatrix) override;
35
36 void onDrawText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
37 const SkMatrix& viewMatrix, const char text[], size_t byteLength,
38 SkScalar x, SkScalar y, const SkIRect& regionClipBounds) override;
39 void onDrawPosText(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
40 const SkMatrix& viewMatrix,
41 const char text[], size_t byteLength,
42 const SkScalar pos[], int scalarsPerPosition,
43 const SkPoint& offset, const SkIRect& regionClipBounds) override;
44 void drawTextBlob(GrRenderTarget*, const GrClip&, const SkPaint&,
45 const SkMatrix& viewMatrix, const SkTextBlob*, SkScalar x, SkScalar y,
46 SkDrawFilter*, const SkIRect& clipBounds) override;
47
48 void init(GrRenderTarget*, const GrClip&, const GrPaint&, const SkPaint&,
49 const SkIRect& regionClipBounds);
50
51 /*
52 * A BitmapTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing
53 * on the GPU. These are initially created with valid positions and colors, but invalid
54 * texture coordinates. The BitmapTextBlob itself has a few Blob-wide properties, and also
55 * consists of a number of runs. Runs inside a blob are flushed individually so they can be
56 * reordered.
57 *
58 * The only thing(aside from a memcopy) required to flush a BitmapTextBlob is to ensure that
59 * the GrAtlas will not evict anything the Blob needs.
60 * TODO this is currently a bug
61 */
62 struct BitmapTextBlob : public SkRefCnt {
63 // Each Run inside of the blob can have its texture coordinates regenerated if required.
64 // To determine if regeneration is necessary, fAtlasGeneration is used. If there have been
65 // any evictions inside of the atlas, then we will simply regenerate Runs. We could track
66 // this at a more fine grained level, but its not clear if this is worth it, as evictions
67 // should be fairly rare.
68 // One additional point, each run can contain glyphs with any of the three mask formats.
69 // We call these SubRuns. Because a subrun must be a contiguous range, we have to create
70 // a new subrun each time the mask format changes in a run. In theory, a run can have as
71 // many SubRuns as it has glyphs, ie if a run alternates between color emoji and A8. In
72 // practice, the vast majority of runs have only a single subrun.
73
74 struct Run {
75 Run() : fColor(GrColor_ILLEGAL), fInitialized(false) {
76 fVertexBounds.setLargestInverted();
77 // We insert the first subrun to gurantee a run always has atleast one subrun.
78 // We do this to simplify things when we 'hand off' data from one subrun to the
79 // next
80 fSubRunInfo.push_back();
81 }
82 struct SubRunInfo {
83 SubRunInfo()
84 : fAtlasGeneration(GrBatchAtlas::kInvalidAtlasGeneration)
85 , fGlyphStartIndex(0)
86 , fGlyphEndIndex(0)
87 , fVertexStartIndex(0)
88 , fVertexEndIndex(0) {}
89 GrMaskFormat fMaskFormat;
90 uint64_t fAtlasGeneration;
91 uint32_t fGlyphStartIndex;
92 uint32_t fGlyphEndIndex;
93 size_t fVertexStartIndex;
94 size_t fVertexEndIndex;
95 };
96 SkSTArray<1, SubRunInfo, true> fSubRunInfo;
97 SkAutoDescriptor fDescriptor;
98 SkAutoTUnref<SkTypeface> fTypeface;
99 SkRect fVertexBounds;
100 GrColor fColor;
101 bool fInitialized;
102 };
103
104 struct BigGlyph {
105 BigGlyph(const SkPath& path, int vx, int vy) : fPath(path), fVx(vx), fVy(vy) {}
106 SkPath fPath;
107 int fVx;
108 int fVy;
109 };
110
111 SkTArray<BigGlyph> fBigGlyphs;
112 SkMatrix fViewMatrix;
113 SkScalar fX;
114 SkScalar fY;
115 SkPaint::Style fStyle;
116 uint32_t fRunCount;
117
118 // all glyph / vertex offsets are into these pools.
119 unsigned char* fVertices;
120 GrGlyph::PackedID* fGlyphIDs;
121 Run* fRuns;
122
123 static uint32_t Hash(const uint32_t& key) {
124 return SkChecksum::Mix(key);
125 }
126
127 void operator delete(void* p) { sk_free(p); }
128 void* operator new(size_t) {
129 SkFAIL("All blobs are created by placement new.");
130 return sk_malloc_throw(0);
131 }
132
133 void* operator new(size_t, void* p) { return p; }
134 void operator delete(void* target, void* placement) {
135 ::operator delete(target, placement);
136 }
137 };
138
139 typedef BitmapTextBlob::Run Run;
140 typedef Run::SubRunInfo PerSubRunInfo;
141
142 BitmapTextBlob* CreateBlob(int glyphCount, int runCount);
143
144 void appendGlyph(BitmapTextBlob*, int runIndex, GrGlyph::PackedID, int left, int top,
145 GrFontScaler*, const SkIRect& clipRect);
146 void flush(GrDrawTarget*, BitmapTextBlob*, GrRenderTarget*, const GrPaint&, const GrClip&,
147 const SkMatrix& viewMatrix, int paintAlpha);
148
149 void internalDrawText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
150 const SkMatrix& viewMatrix, const char text[], size_t byteLength,
151 SkScalar x, SkScalar y, const SkIRect& clipRect);
152 void internalDrawPosText(BitmapTextBlob*, int runIndex, SkGlyphCache*, const SkPaint&,
153 const SkMatrix& viewMatrix,
154 const char text[], size_t byteLength,
155 const SkScalar pos[], int scalarsPerPosition,
156 const SkPoint& offset, const SkIRect& clipRect);
157
158 // sets up the descriptor on the blob and returns a detached cache. Client must attach
159 inline SkGlyphCache* setupCache(Run*, const SkPaint&, const SkMatrix& viewMatrix);
160 static inline bool MustRegenerateBlob(const BitmapTextBlob&, const SkPaint&,
161 const SkMatrix& viewMatrix, SkScalar x, SkScalar y);
162 void regenerateTextBlob(BitmapTextBlob* bmp, const SkPaint& skPaint, const SkMatrix& viewMatrix,
163 const SkTextBlob* blob, SkScalar x, SkScalar y,
164 SkDrawFilter* drawFilter, const SkIRect& clipRect);
165
166 // TODO this currently only uses the public interface of SkTextBlob, however, I may need to add
167 // functionality to it while looping over the runs so I'm putting this here for the time being.
168 // If this lands in Chrome without changes, move it to SkTextBlob.
169 static inline void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob*);
170
171 GrBatchTextStrike* fCurrStrike;
172
173 // TODO use real cache
174 static void ClearCacheEntry(uint32_t key, BitmapTextBlob**);
175 SkTHashMap<uint32_t, BitmapTextBlob*, BitmapTextBlob::Hash> fCache;
176
177 friend class BitmapTextBatch;
178
179 typedef GrTextContext INHERITED;
180};
181
182#endif