Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/gpu/GrAtlasTextContext.cpp

Issue 1062863002: Avoid regenerating cached textblobs on integer scrolls (Closed) Base URL: https://skia.googlesource.com/skia.git@atlastextcache
Patch Set: some sleight bug fixes Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * Copyright 2015 Google Inc. 2 * Copyright 2015 Google Inc.
3 * 3 *
4 * Use of this source code is governed by a BSD-style license that can be 4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file. 5 * found in the LICENSE file.
6 */ 6 */
7 #include "GrAtlasTextContext.h" 7 #include "GrAtlasTextContext.h"
8 8
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrBatch.h" 10 #include "GrBatch.h"
11 #include "GrBatchFontCache.h" 11 #include "GrBatchFontCache.h"
12 #include "GrBatchTarget.h" 12 #include "GrBatchTarget.h"
13 #include "GrDefaultGeoProcFactory.h" 13 #include "GrDefaultGeoProcFactory.h"
14 #include "GrDrawTarget.h" 14 #include "GrDrawTarget.h"
15 #include "GrFontScaler.h" 15 #include "GrFontScaler.h"
16 #include "GrIndexBuffer.h" 16 #include "GrIndexBuffer.h"
17 #include "GrStrokeInfo.h" 17 #include "GrStrokeInfo.h"
18 #include "GrTextBlobCache.h"
18 #include "GrTexturePriv.h" 19 #include "GrTexturePriv.h"
19 20
20 #include "SkAutoKern.h" 21 #include "SkAutoKern.h"
21 #include "SkColorPriv.h" 22 #include "SkColorPriv.h"
22 #include "SkDraw.h" 23 #include "SkDraw.h"
23 #include "SkDrawFilter.h" 24 #include "SkDrawFilter.h"
24 #include "SkDrawProcs.h" 25 #include "SkDrawProcs.h"
25 #include "SkGlyphCache.h" 26 #include "SkGlyphCache.h"
26 #include "SkGpuDevice.h" 27 #include "SkGpuDevice.h"
27 #include "SkGr.h" 28 #include "SkGr.h"
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
59 }; 60 };
60 61
61 // TODO 62 // TODO
62 // More tests 63 // More tests
63 // move to SkCache 64 // move to SkCache
64 // handle textblobs where the whole run is larger than the cache size 65 // handle textblobs where the whole run is larger than the cache size
65 // TODO implement micro speedy hash map for fast refing of glyphs 66 // TODO implement micro speedy hash map for fast refing of glyphs
66 67
67 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, 68 GrAtlasTextContext::GrAtlasTextContext(GrContext* context,
68 SkGpuDevice* gpuDevice, 69 SkGpuDevice* gpuDevice,
69 const SkDeviceProperties& properties) 70 const SkDeviceProperties& properties)
70 : INHERITED(context, gpuDevice, properties) { 71 : INHERITED(context, gpuDevice, properties) {
72 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
73 // vertexStride
74 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize,
75 vertex_attribute_changed);
71 fCurrStrike = NULL; 76 fCurrStrike = NULL;
72 } 77 fCache = context->getTextBlobCache();
73
74 GrAtlasTextContext::~GrAtlasTextContext() {/*
75 SkTDynamicHash<BitmapTextBlob, uint32_t>::Iter iter(&fCache);
76 while (!iter.done()) {
77 (&(*iter))->unref();
78 ++iter;
79 }*/
80 } 78 }
81 79
82 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context, 80 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
83 SkGpuDevice* gpuDevice, 81 SkGpuDevice* gpuDevice,
84 const SkDeviceProperties& props) { 82 const SkDeviceProperties& props) {
85 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props)); 83 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props));
86 } 84 }
87 85
88 bool GrAtlasTextContext::canDraw(const GrRenderTarget*, 86 bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
89 const GrClip&, 87 const GrClip&,
90 const GrPaint&, 88 const GrPaint&,
91 const SkPaint& skPaint, 89 const SkPaint& skPaint,
92 const SkMatrix& viewMatrix) { 90 const SkMatrix& viewMatrix) {
93 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); 91 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
94 } 92 }
95 93
96 bool GrAtlasTextContext::MustRegenerateBlob(const BitmapTextBlob& blob, const Sk Paint& paint, 94 static const SkScalar kThreshold = 0.0625;
95
96 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr ansY,
97 const BitmapTextBlob& blob, const Sk Paint& paint,
97 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { 98 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
98 // We always regenerate blobs with patheffects or mask filters we could cach e these 99 // Color can affect the mask
99 // TODO find some way to cache the maskfilter / patheffects on the textblob 100 // TODO we can adjust the color within specific gamma slots
100 return !blob.fViewMatrix.cheapEqualTo(viewMatrix) || blob.fX != x || blob.fY != y || 101 if (blob.fColor != paint.getColor()) {
101 paint.getMaskFilter() || paint.getPathEffect() || paint.getStyle() ! = blob.fStyle; 102 return true;
103 }
104
105 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
106 return true;
107 }
108
109 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view Matrix)) {
110 return true;
111 }
112
113 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
114 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
115 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
116 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
117 return true;
118 }
119
120 // We can update the positions in the cachedtextblobs without regenerating t he whole blob, but
121 // only for integer translations.
122 // TODO I think this is wrong
123 if (SkScalarFraction(blob.fViewMatrix.getTranslateX() -
124 viewMatrix.getTranslateX()) > kThreshold ||
125 SkScalarFraction(x - blob.fX) > kThreshold ||
126 SkScalarFraction(blob.fViewMatrix.getTranslateX() -
127 viewMatrix.getTranslateX()) > kThreshold ||
128 SkScalarFraction(y - blob.fY) > kThreshold) {
129 return true;
130 }
131
132 SkScalar transX = viewMatrix.getTranslateX() +
bsalomon 2015/04/08 15:42:59 Do we need to worry about presence/absence of subp
joshualitt 2015/04/08 15:52:28 Jim, thoughts? I don't really know enough about s
133 viewMatrix.getScaleX() * (x - blob.fX) +
134 viewMatrix.getSkewX() * (y - blob.fY) -
135 blob.fViewMatrix.getTranslateX();
136
137 SkScalar transY = viewMatrix.getTranslateY() +
138 viewMatrix.getSkewY() * (x - blob.fX) +
139 viewMatrix.getScaleY() * (y - blob.fY) -
140 blob.fViewMatrix.getTranslateY();
141
142 (*outTransX) = transX;
143 (*outTransY) = transY;
bsalomon 2015/04/08 15:43:00 why have intermediates?
joshualitt 2015/04/08 15:52:28 done
144 return false;
102 } 145 }
103 146
104 147
105 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, 148 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run,
106 const SkPaint& skPaint, 149 const SkPaint& skPaint,
107 const SkMatrix& viewMatrix) { 150 const SkMatrix& viewMatrix) {
108 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); 151 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false);
109 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); 152 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
110 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; 153 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ;
111 } 154 }
112 155
113 inline void GrAtlasTextContext::BlobGlyphCount(int* glyphCount, int* runCount,
114 const SkTextBlob* blob) {
115 SkTextBlob::RunIterator itCounter(blob);
116 for (; !itCounter.done(); itCounter.next(), (*runCount)++) {
117 *glyphCount += itCounter.glyphCount();
118 }
119 }
120
121 GrAtlasTextContext::BitmapTextBlob*
122 GrAtlasTextContext::CreateBlob(int glyphCount, int runCount, GrMemoryPool* pool) {
123 // We allocate size for the BitmapTextBlob itself, plus size for the vertice s array,
124 // and size for the glyphIds array.
125 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize,
126 vertex_attribute_changed);
127 size_t verticesCount = glyphCount * kVerticesPerGlyph * kGrayTextVASize;
128 size_t size = sizeof(BitmapTextBlob) +
129 verticesCount +
130 glyphCount * sizeof(GrGlyph::PackedID) +
131 sizeof(BitmapTextBlob::Run) * runCount;
132
133 BitmapTextBlob* cacheBlob;
134 cacheBlob = SkNEW_PLACEMENT(pool->allocate(size), BitmapTextBlob);
135
136 // setup offsets for vertices / glyphs
137 cacheBlob->fVertices = sizeof(BitmapTextBlob) + reinterpret_cast<unsigned ch ar*>(cacheBlob);
138 cacheBlob->fGlyphIDs =
139 reinterpret_cast<GrGlyph::PackedID*>(cacheBlob->fVertices + vertices Count);
140 cacheBlob->fRuns = reinterpret_cast<BitmapTextBlob::Run*>(cacheBlob->fGlyphI Ds + glyphCount);
141
142 // Initialize runs
143 for (int i = 0; i < runCount; i++) {
144 SkNEW_PLACEMENT(&cacheBlob->fRuns[i], BitmapTextBlob::Run);
145 }
146 cacheBlob->fRunCount = runCount;
147 cacheBlob->fSize = size;
148 cacheBlob->fPool = pool;
149 return cacheBlob;
150 }
151
152 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, 156 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
153 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, 157 const SkPaint& skPaint, const SkMatrix& vi ewMatrix,
154 const SkTextBlob* blob, SkScalar x, SkScal ar y, 158 const SkTextBlob* blob, SkScalar x, SkScal ar y,
155 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) {/* 159 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) {
156 uint32_t uniqueID = blob->uniqueID(); 160 uint32_t uniqueID = blob->uniqueID();
157 BitmapTextBlob* cacheBlob = fCache.find(uniqueID); 161 SkAutoTUnref<BitmapTextBlob> cacheBlob;
162 // TODO start caching these, mix bits into the key
163 bool mustNotCache = skPaint.getPathEffect() ||
164 skPaint.getMaskFilter() ||
165 skPaint.getColorFilter() ||
166 skPaint.getStyle() != SkPaint::kFill_Style ||
167 drawFilter;
168
169 if (!mustNotCache) {
170 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID)));
171 }
172
158 SkIRect clipRect; 173 SkIRect clipRect;
159 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 174 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
160 175
176 SkScalar transX = 0.f;
177 SkScalar transY = 0.f;
178
161 if (cacheBlob) { 179 if (cacheBlob) {
162 if (MustRegenerateBlob(*cacheBlob, skPaint, viewMatrix, x, y)) { 180 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix , x, y)) {
163 // We have to remake the blob because changes may invalidate our mas ks. 181 // We have to remake the blob because changes may invalidate our mas ks.
164 // TODO we could probably get away reuse most of the time if the poi nter is unique, 182 // TODO we could probably get away reuse most of the time if the poi nter is unique,
165 // but we'd have to clear the subrun information 183 // but we'd have to clear the subrun information
166 fCache.remove(uniqueID); 184 fCache->remove(cacheBlob);
167 fBlobList.remove(cacheBlob); 185 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
168 cacheBlob->unref();
169 int glyphCount = 0;
170 int runCount = 0;
171 BlobGlyphCount(&glyphCount, &runCount, blob);
172 cacheBlob = CreateBlob(glyphCount, runCount, fContext->getTextTarget ()->pool());
173 cacheBlob->fUniqueID = uniqueID;
174 fCache.add(cacheBlob);
175 fBlobList.addToHead(cacheBlob);
176 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, 186 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
177 clipRect); 187 clipRect);
188 } else {
189 // If we can reuse the blob, then make sure we update the blob's vie wmatrix and x/y
190 // offsets to reflect the results of any translations we may apply i n generateGeometry
191 cacheBlob->fViewMatrix = viewMatrix;
192 cacheBlob->fX = x;
193 cacheBlob->fY = y;
194 fCache->makeMRU(cacheBlob);
178 } 195 }
179 } else { 196 } else {
180 int glyphCount = 0; 197 if (mustNotCache) {
181 int runCount = 0; 198 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
182 BlobGlyphCount(&glyphCount, &runCount, blob); 199 } else {
183 cacheBlob = CreateBlob(glyphCount, runCount, fContext->getTextTarget()-> pool()); 200 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
184 cacheBlob->fUniqueID = uniqueID; 201 }
185 fCache.add(cacheBlob);
186 fBlobList.addToHead(cacheBlob);
187 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); 202 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect);
188 } 203 }
189 204
190 // Though for the time being runs in the textblob can override the paint, th ey only touch font 205 // Though for the time being runs in the textblob can override the paint, th ey only touch font
191 // info. 206 // info.
192 GrPaint grPaint; 207 GrPaint grPaint;
193 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); 208 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
194 209
195 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, 210 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter,
196 clip, viewMatrix, clipBounds, x, y);*/ 211 clip, viewMatrix, clipBounds, x, y, transX, transY);
197 } 212 }
198 213
199 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, 214 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
200 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 215 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
201 const SkTextBlob* blob, SkScalar x, SkScalar y, 216 const SkTextBlob* blob, SkScalar x, SkScalar y,
202 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { 217 SkDrawFilter* drawFilter, const SkIR ect& clipRect) {
203 cacheBlob->fViewMatrix = viewMatrix; 218 cacheBlob->fViewMatrix = viewMatrix;
204 cacheBlob->fX = x; 219 cacheBlob->fX = x;
205 cacheBlob->fY = y; 220 cacheBlob->fY = y;
221 cacheBlob->fColor = skPaint.getColor();
206 cacheBlob->fStyle = skPaint.getStyle(); 222 cacheBlob->fStyle = skPaint.getStyle();
207 223
208 // Regenerate textblob 224 // Regenerate textblob
209 SkPaint runPaint = skPaint; 225 SkPaint runPaint = skPaint;
210 SkTextBlob::RunIterator it(blob); 226 SkTextBlob::RunIterator it(blob);
211 for (int run = 0; !it.done(); it.next(), run++) { 227 for (int run = 0; !it.done(); it.next(), run++) {
212 int glyphCount = it.glyphCount(); 228 int glyphCount = it.glyphCount();
213 size_t textLen = glyphCount * sizeof(uint16_t); 229 size_t textLen = glyphCount * sizeof(uint16_t);
214 const SkPoint& offset = it.offset(); 230 const SkPoint& offset = it.offset();
215 // applyFontToPaint() always overwrites the exact same attributes, 231 // applyFontToPaint() always overwrites the exact same attributes,
(...skipping 15 matching lines...) Expand all
231 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); 247 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back();
232 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( ); 248 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( );
233 249
234 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; 250 newRun.fVertexStartIndex = lastRun.fVertexEndIndex;
235 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; 251 newRun.fVertexEndIndex = lastRun.fVertexEndIndex;
236 252
237 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; 253 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex;
238 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; 254 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex;
239 } 255 }
240 256
241 if (SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix)) { 257 if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
242 cacheBlob->fRuns[run].fDrawAsPaths = true; 258 cacheBlob->fRuns[run].fDrawAsPaths = true;
243 continue; 259 continue;
244 } 260 }
245 cacheBlob->fRuns[run].fDrawAsPaths = false; 261 cacheBlob->fRuns[run].fDrawAsPaths = false;
246 262
247 switch (it.positioning()) { 263 switch (it.positioning()) {
248 case SkTextBlob::kDefault_Positioning: 264 case SkTextBlob::kDefault_Positioning:
249 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix, 265 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix,
250 (const char *)it.glyphs(), textLen, 266 (const char *)it.glyphs(), textLen,
251 x + offset.x(), y + offset.y(), clipRect) ; 267 x + offset.x(), y + offset.y(), clipRect) ;
(...skipping 18 matching lines...) Expand all
270 SkGlyphCache::AttachCache(cache); 286 SkGlyphCache::AttachCache(cache);
271 } 287 }
272 } 288 }
273 289
274 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, 290 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
275 const GrPaint& paint, const SkPaint& skPaint , 291 const GrPaint& paint, const SkPaint& skPaint ,
276 const SkMatrix& viewMatrix, 292 const SkMatrix& viewMatrix,
277 const char text[], size_t byteLength, 293 const char text[], size_t byteLength,
278 SkScalar x, SkScalar y, const SkIRect& regio nClipBounds) { 294 SkScalar x, SkScalar y, const SkIRect& regio nClipBounds) {
279 int glyphCount = skPaint.countText(text, byteLength); 295 int glyphCount = skPaint.countText(text, byteLength);
280 SkAutoTUnref<BitmapTextBlob> blob(CreateBlob(glyphCount, 1, fContext->getTex tTarget()->pool())); 296 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize));
281 blob->fViewMatrix = viewMatrix; 297 blob->fViewMatrix = viewMatrix;
282 blob->fX = x; 298 blob->fX = x;
283 blob->fY = y; 299 blob->fY = y;
284 blob->fStyle = skPaint.getStyle(); 300 blob->fStyle = skPaint.getStyle();
285 301
286 SkIRect clipRect; 302 SkIRect clipRect;
287 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 303 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
288 304
289 // setup cache 305 // setup cache
290 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ; 306 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
384 } 400 }
385 } 401 }
386 402
387 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, 403 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
388 const GrPaint& paint, const SkPaint& skPa int, 404 const GrPaint& paint, const SkPaint& skPa int,
389 const SkMatrix& viewMatrix, 405 const SkMatrix& viewMatrix,
390 const char text[], size_t byteLength, 406 const char text[], size_t byteLength,
391 const SkScalar pos[], int scalarsPerPosit ion, 407 const SkScalar pos[], int scalarsPerPosit ion,
392 const SkPoint& offset, const SkIRect& reg ionClipBounds) { 408 const SkPoint& offset, const SkIRect& reg ionClipBounds) {
393 int glyphCount = skPaint.countText(text, byteLength); 409 int glyphCount = skPaint.countText(text, byteLength);
394 SkAutoTUnref<BitmapTextBlob> blob(CreateBlob(glyphCount, 1, fContext->getTex tTarget()->pool())); 410 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize));
395 blob->fStyle = skPaint.getStyle(); 411 blob->fStyle = skPaint.getStyle();
396 blob->fViewMatrix = viewMatrix; 412 blob->fViewMatrix = viewMatrix;
397 413
398 SkIRect clipRect; 414 SkIRect clipRect;
399 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 415 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
400 416
401 // setup cache 417 // setup cache
402 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ; 418 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ;
403 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen gth, pos, 419 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen gth, pos,
404 scalarsPerPosition, offset, clipRect); 420 scalarsPerPosition, offset, clipRect);
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
582 return; 598 return;
583 } 599 }
584 600
585 int x = vx + glyph->fBounds.fLeft; 601 int x = vx + glyph->fBounds.fLeft;
586 int y = vy + glyph->fBounds.fTop; 602 int y = vy + glyph->fBounds.fTop;
587 603
588 // keep them as ints until we've done the clip-test 604 // keep them as ints until we've done the clip-test
589 int width = glyph->fBounds.width(); 605 int width = glyph->fBounds.width();
590 int height = glyph->fBounds.height(); 606 int height = glyph->fBounds.height();
591 607
592 // check if we clipped out
593 if (clipRect.quickReject(x, y, x + width, y + height)) {
594 return;
595 }
596
597 // If the glyph is too large we fall back to paths 608 // If the glyph is too large we fall back to paths
598 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) { 609 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) {
599 if (NULL == glyph->fPath) { 610 if (NULL == glyph->fPath) {
600 SkPath* path = SkNEW(SkPath); 611 SkPath* path = SkNEW(SkPath);
601 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { 612 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
602 // flag the glyph as being dead? 613 // flag the glyph as being dead?
603 SkDELETE(path); 614 SkDELETE(path);
604 return; 615 return;
605 } 616 }
606 glyph->fPath = path; 617 glyph->fPath = path;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
644 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex); 655 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex);
645 656
646 // V0 657 // V0
647 SkPoint* position = reinterpret_cast<SkPoint*>(vertex); 658 SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
648 position->set(r.fLeft, r.fTop); 659 position->set(r.fLeft, r.fTop);
649 if (kA8_GrMaskFormat == format) { 660 if (kA8_GrMaskFormat == format) {
650 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 661 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
651 *colorPtr = color; 662 *colorPtr = color;
652 } 663 }
653 vertex += vertexStride; 664 vertex += vertexStride;
654
655 // V1 665 // V1
656 position = reinterpret_cast<SkPoint*>(vertex); 666 position = reinterpret_cast<SkPoint*>(vertex);
657 position->set(r.fLeft, r.fBottom); 667 position->set(r.fLeft, r.fBottom);
658 if (kA8_GrMaskFormat == format) { 668 if (kA8_GrMaskFormat == format) {
659 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 669 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
660 *colorPtr = color; 670 *colorPtr = color;
661 } 671 }
662 vertex += vertexStride; 672 vertex += vertexStride;
663 673
664 // V2 674 // V2
(...skipping 21 matching lines...) Expand all
686 public: 696 public:
687 typedef GrAtlasTextContext::BitmapTextBlob Blob; 697 typedef GrAtlasTextContext::BitmapTextBlob Blob;
688 typedef Blob::Run Run; 698 typedef Blob::Run Run;
689 typedef Run::SubRunInfo TextInfo; 699 typedef Run::SubRunInfo TextInfo;
690 struct Geometry { 700 struct Geometry {
691 Geometry() {} 701 Geometry() {}
692 Geometry(const Geometry& geometry) 702 Geometry(const Geometry& geometry)
693 : fBlob(SkRef(geometry.fBlob.get())) 703 : fBlob(SkRef(geometry.fBlob.get()))
694 , fRun(geometry.fRun) 704 , fRun(geometry.fRun)
695 , fSubRun(geometry.fSubRun) 705 , fSubRun(geometry.fSubRun)
696 , fColor(geometry.fColor) {} 706 , fColor(geometry.fColor)
707 , fTransX(geometry.fTransX)
708 , fTransY(geometry.fTransY) {}
697 SkAutoTUnref<Blob> fBlob; 709 SkAutoTUnref<Blob> fBlob;
698 int fRun; 710 int fRun;
699 int fSubRun; 711 int fSubRun;
700 GrColor fColor; 712 GrColor fColor;
713 SkScalar fTransX;
714 SkScalar fTransY;
701 }; 715 };
702 716
703 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat, 717 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat,
704 int glyphCount, GrBatchFontCache* fontCache) { 718 int glyphCount, GrBatchFontCache* fontCache) {
705 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache)); 719 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache));
706 } 720 }
707 721
708 const char* name() const override { return "BitmapTextBatch"; } 722 const char* name() const override { return "BitmapTextBatch"; }
709 723
710 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 724 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
804 int instancesToFlush = 0; 818 int instancesToFlush = 0;
805 for (int i = 0; i < instanceCount; i++) { 819 for (int i = 0; i < instanceCount; i++) {
806 Geometry& args = fGeoData[i]; 820 Geometry& args = fGeoData[i];
807 Blob* blob = args.fBlob; 821 Blob* blob = args.fBlob;
808 Run& run = blob->fRuns[args.fRun]; 822 Run& run = blob->fRuns[args.fRun];
809 TextInfo& info = run.fSubRunInfo[args.fSubRun]; 823 TextInfo& info = run.fSubRunInfo[args.fSubRun];
810 824
811 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); 825 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat);
812 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen; 826 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen;
813 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor; 827 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor;
828 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0. f;
814 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 829 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
815 830
816 // We regenerate both texture coords and colors in the blob itself, and update the 831 // We regenerate both texture coords and colors in the blob itself, and update the
817 // atlas generation. If we don't end up purging any unused plots, w e can avoid 832 // atlas generation. If we don't end up purging any unused plots, w e can avoid
818 // regenerating the coords. We could take a finer grained approach to updating texture 833 // regenerating the coords. We could take a finer grained approach to updating texture
819 // coords but its not clear if the extra bookkeeping would offset an y gains. 834 // coords but its not clear if the extra bookkeeping would offset an y gains.
820 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color 835 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color
821 // or coords as needed. One final note, if we have to break a run f or an atlas eviction 836 // or coords as needed. One final note, if we have to break a run f or an atlas eviction
822 // then we can't really trust the atlas has all of the correct data. Atlas evictions 837 // then we can't really trust the atlas has all of the correct data. Atlas evictions
823 // should be pretty rare, so we just always regenerate in those case s 838 // should be pretty rare, so we just always regenerate in those case s
824 if (regenerateTextureCoords || regenerateColors) { 839 if (regenerateTextureCoords || regenerateColors || regeneratePositio ns) {
825 // first regenerate texture coordinates / colors if need be 840 // first regenerate texture coordinates / colors if need be
826 const SkDescriptor* desc = NULL; 841 const SkDescriptor* desc = NULL;
827 SkGlyphCache* cache = NULL; 842 SkGlyphCache* cache = NULL;
828 GrFontScaler* scaler = NULL; 843 GrFontScaler* scaler = NULL;
829 GrBatchTextStrike* strike = NULL; 844 GrBatchTextStrike* strike = NULL;
830 bool brokenRun = false; 845 bool brokenRun = false;
831 if (regenerateTextureCoords) { 846 if (regenerateTextureCoords) {
832 info.fBulkUseToken.reset(); 847 info.fBulkUseToken.reset();
833 desc = run.fDescriptor.getDesc(); 848 desc = run.fDescriptor.getDesc();
834 cache = SkGlyphCache::DetachCache(run.fTypeface, desc); 849 cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
868 this->regenerateTextureCoords(glyph, vertex, vertexStrid e); 883 this->regenerateTextureCoords(glyph, vertex, vertexStrid e);
869 } 884 }
870 885
871 if (regenerateColors) { 886 if (regenerateColors) {
872 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); 887 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
873 vertex += info.fVertexStartIndex; 888 vertex += info.fVertexStartIndex;
874 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); 889 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
875 this->regenerateColors(vertex, vertexStride, args.fColor ); 890 this->regenerateColors(vertex, vertexStride, args.fColor );
876 } 891 }
877 892
893 if (regeneratePositions) {
894 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
895 vertex += info.fVertexStartIndex;
896 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
897 SkScalar transX = args.fTransX;
898 SkScalar transY = args.fTransY;
899 this->regeneratePositions(vertex, vertexStride, transX, transY);
900 }
878 instancesToFlush++; 901 instancesToFlush++;
879 } 902 }
880 903
904 // We my have changed the color so update it here
905 run.fColor = args.fColor;
881 if (regenerateTextureCoords) { 906 if (regenerateTextureCoords) {
882 SkGlyphCache::AttachCache(cache); 907 SkGlyphCache::AttachCache(cache);
883 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration : 908 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration :
884 fFontCache->atlasGenerat ion(fMaskFormat); 909 fFontCache->atlasGenerat ion(fMaskFormat);
885 } 910 }
886 } else { 911 } else {
887 instancesToFlush += glyphCount; 912 instancesToFlush += glyphCount;
888 913
889 // set use tokens for all of the glyphs in our subrun. This is only valid if we 914 // set use tokens for all of the glyphs in our subrun. This is only valid if we
890 // have a valid atlas generation 915 // have a valid atlas generation
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 } 975 }
951 976
952 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { 977 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
953 for (int i = 0; i < kVerticesPerGlyph; i++) { 978 for (int i = 0; i < kVerticesPerGlyph; i++) {
954 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); 979 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
955 *vcolor = color; 980 *vcolor = color;
956 vertex += vertexStride; 981 vertex += vertexStride;
957 } 982 }
958 } 983 }
959 984
985 void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar tran sX,
986 SkScalar transY) {
987 for (int i = 0; i < kVerticesPerGlyph; i++) {
988 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
989 point->fX += transX;
990 point->fY += transY;
991 vertex += vertexStride;
992 }
993 }
994
960 void initDraw(GrBatchTarget* batchTarget, 995 void initDraw(GrBatchTarget* batchTarget,
961 const GrGeometryProcessor* gp, 996 const GrGeometryProcessor* gp,
962 const GrPipeline* pipeline) { 997 const GrPipeline* pipeline) {
963 batchTarget->initDraw(gp, pipeline); 998 batchTarget->initDraw(gp, pipeline);
964 999
965 // TODO remove this when batch is everywhere 1000 // TODO remove this when batch is everywhere
966 GrPipelineInfo init; 1001 GrPipelineInfo init;
967 init.fColorIgnored = fBatch.fColorIgnored; 1002 init.fColorIgnored = fBatch.fColorIgnored;
968 init.fOverrideColor = GrColor_ILLEGAL; 1003 init.fOverrideColor = GrColor_ILLEGAL;
969 init.fCoverageIgnored = fBatch.fCoverageIgnored; 1004 init.fCoverageIgnored = fBatch.fCoverageIgnored;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 break; 1091 break;
1057 case SkTextBlob::kFull_Positioning: 1092 case SkTextBlob::kFull_Positioning:
1058 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (), 1093 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (),
1059 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds); 1094 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds);
1060 break; 1095 break;
1061 } 1096 }
1062 } 1097 }
1063 1098
1064 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder, 1099 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder,
1065 BitmapTextBlob* cacheBlob, int run, GrC olor color, 1100 BitmapTextBlob* cacheBlob, int run, GrC olor color,
1066 uint8_t paintAlpha) { 1101 uint8_t paintAlpha, SkScalar transX, Sk Scalar transY) {
1067 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) { 1102 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) {
1068 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; 1103 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun];
1069 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 1104 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
1070 if (0 == glyphCount) { 1105 if (0 == glyphCount) {
1071 continue; 1106 continue;
1072 } 1107 }
1073 1108
1074 GrMaskFormat format = info.fMaskFormat; 1109 GrMaskFormat format = info.fMaskFormat;
1075 GrColor subRunColor = kARGB_GrMaskFormat == format ? 1110 GrColor subRunColor = kARGB_GrMaskFormat == format ?
1076 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) : 1111 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) :
1077 color; 1112 color;
1078 1113
1079 BitmapTextBatch::Geometry geometry; 1114 BitmapTextBatch::Geometry geometry;
1080 geometry.fBlob.reset(SkRef(cacheBlob)); 1115 geometry.fBlob.reset(SkRef(cacheBlob));
1081 geometry.fRun = run; 1116 geometry.fRun = run;
1082 geometry.fSubRun = subRun; 1117 geometry.fSubRun = subRun;
1083 geometry.fColor = subRunColor; 1118 geometry.fColor = subRunColor;
1119 geometry.fTransX = transX;
1120 geometry.fTransY = transY;
1084 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount, 1121 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount,
1085 fContext->getBatchFo ntCache())); 1122 fContext->getBatchFo ntCache()));
1086 1123
1087 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds); 1124 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds);
1088 } 1125 }
1089 } 1126 }
1090 1127
1091 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt, 1128 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt,
1092 const GrPaint& grPaint, const GrC lip& clip) { 1129 const GrPaint& grPaint, const GrC lip& clip,
1130 SkScalar transX, SkScalar transY) {
1093 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { 1131 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) {
1094 const BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; 1132 BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i];
1133 bigGlyph.fVx += transX;
1134 bigGlyph.fVy += transY;
1095 SkMatrix translate; 1135 SkMatrix translate;
1096 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy)); 1136 translate.setTranslate(SkIntToScalar(bigGlyph.fVx),
1137 SkIntToScalar(bigGlyph.fVy));
1097 SkPath tmpPath(bigGlyph.fPath); 1138 SkPath tmpPath(bigGlyph.fPath);
1098 tmpPath.transform(translate); 1139 tmpPath.transform(translate);
1099 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); 1140 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
1100 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo ); 1141 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo );
1101 } 1142 }
1102 } 1143 }
1103 1144
1104 void GrAtlasTextContext::flush(GrDrawTarget* target, 1145 void GrAtlasTextContext::flush(GrDrawTarget* target,
1105 const SkTextBlob* blob, 1146 const SkTextBlob* blob,
1106 BitmapTextBlob* cacheBlob, 1147 BitmapTextBlob* cacheBlob,
1107 GrRenderTarget* rt, 1148 GrRenderTarget* rt,
1108 const SkPaint& skPaint, 1149 const SkPaint& skPaint,
1109 const GrPaint& grPaint, 1150 const GrPaint& grPaint,
1110 SkDrawFilter* drawFilter, 1151 SkDrawFilter* drawFilter,
1111 const GrClip& clip, 1152 const GrClip& clip,
1112 const SkMatrix& viewMatrix, 1153 const SkMatrix& viewMatrix,
1113 const SkIRect& clipBounds, 1154 const SkIRect& clipBounds,
1114 SkScalar x, 1155 SkScalar x, SkScalar y,
1115 SkScalar y) { 1156 SkScalar transX, SkScalar transY) {
1116 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush 1157 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush
1117 // it as paths 1158 // it as paths
1118 GrPipelineBuilder pipelineBuilder; 1159 GrPipelineBuilder pipelineBuilder;
1119 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1160 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1120 1161
1121 GrColor color = grPaint.getColor(); 1162 GrColor color = grPaint.getColor();
1122 uint8_t paintAlpha = skPaint.getAlpha(); 1163 uint8_t paintAlpha = skPaint.getAlpha();
1123 1164
1124 SkTextBlob::RunIterator it(blob); 1165 SkTextBlob::RunIterator it(blob);
1125 for (int run = 0; !it.done(); it.next(), run++) { 1166 for (int run = 0; !it.done(); it.next(), run++) {
1126 if (cacheBlob->fRuns[run].fDrawAsPaths) { 1167 if (cacheBlob->fRuns[run].fDrawAsPaths) {
1127 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y); 1168 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y);
1128 continue; 1169 continue;
1129 } 1170 }
1130 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1171 cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
1172 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, transX, transY);
1131 } 1173 }
1132 1174
1133 // Now flush big glyphs 1175 // Now flush big glyphs
1134 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1176 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, transX, transY);
1135 } 1177 }
1136 1178
1137 void GrAtlasTextContext::flush(GrDrawTarget* target, 1179 void GrAtlasTextContext::flush(GrDrawTarget* target,
1138 BitmapTextBlob* cacheBlob, 1180 BitmapTextBlob* cacheBlob,
1139 GrRenderTarget* rt, 1181 GrRenderTarget* rt,
1140 const SkPaint& skPaint, 1182 const SkPaint& skPaint,
1141 const GrPaint& grPaint, 1183 const GrPaint& grPaint,
1142 const GrClip& clip, 1184 const GrClip& clip,
1143 const SkMatrix& viewMatrix) { 1185 const SkMatrix& viewMatrix) {
1144 GrPipelineBuilder pipelineBuilder; 1186 GrPipelineBuilder pipelineBuilder;
1145 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1187 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1146 1188
1147 GrColor color = grPaint.getColor(); 1189 GrColor color = grPaint.getColor();
1148 uint8_t paintAlpha = skPaint.getAlpha(); 1190 uint8_t paintAlpha = skPaint.getAlpha();
1149 for (int run = 0; run < cacheBlob->fRunCount; run++) { 1191 for (int run = 0; run < cacheBlob->fRunCount; run++) {
1150 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1192 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0);
1151 } 1193 }
1152 1194
1153 // Now flush big glyphs 1195 // Now flush big glyphs
1154 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1196 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0);
1155 } 1197 }
OLDNEW
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698