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

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

Issue 1065293003: Start caching masks / stroke fills for textblobs (Closed) Base URL: https://skia.googlesource.com/skia.git@textblobloopergm
Patch Set: rebase 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/GrTextBlobCache.h » ('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"
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 case kARGB_GrMaskFormat: 53 case kARGB_GrMaskFormat:
54 return kColorTextVASize; 54 return kColorTextVASize;
55 default: 55 default:
56 return kLCDTextVASize; 56 return kLCDTextVASize;
57 } 57 }
58 } 58 }
59 59
60 }; 60 };
61 61
62 // TODO 62 // TODO
63 // More tests 63 // Gamma slotting to preserve color
64 // move to SkCache 64 // Better reuse on regeneration
65 // handle textblobs where the whole run is larger than the cache size 65 // Telemetry tests
66 // TODO implement micro speedy hash map for fast refing of glyphs 66 // possibly consider having a regeneration ratio on the textblob itself for anim ated textblobs
67 67
68 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, 68 GrAtlasTextContext::GrAtlasTextContext(GrContext* context,
69 SkGpuDevice* gpuDevice, 69 SkGpuDevice* gpuDevice,
70 const SkDeviceProperties& properties) 70 const SkDeviceProperties& properties)
71 : 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 72 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
73 // vertexStride 73 // vertexStride
74 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize, 74 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCDTextVASize,
75 vertex_attribute_changed); 75 vertex_attribute_changed);
76 fCurrStrike = NULL; 76 fCurrStrike = NULL;
77 fCache = context->getTextBlobCache(); 77 fCache = context->getTextBlobCache();
78 } 78 }
79 79
80 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context, 80 GrAtlasTextContext* GrAtlasTextContext::Create(GrContext* context,
81 SkGpuDevice* gpuDevice, 81 SkGpuDevice* gpuDevice,
82 const SkDeviceProperties& props) { 82 const SkDeviceProperties& props) {
83 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props)); 83 return SkNEW_ARGS(GrAtlasTextContext, (context, gpuDevice, props));
84 } 84 }
85 85
86 bool GrAtlasTextContext::canDraw(const GrRenderTarget*, 86 bool GrAtlasTextContext::canDraw(const GrRenderTarget*,
87 const GrClip&, 87 const GrClip&,
88 const GrPaint&, 88 const GrPaint&,
89 const SkPaint& skPaint, 89 const SkPaint& skPaint,
90 const SkMatrix& viewMatrix) { 90 const SkMatrix& viewMatrix) {
91 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix); 91 return !SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix);
92 } 92 }
93 93
94 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr ansY, 94 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr ansY,
95 const BitmapTextBlob& blob, const Sk Paint& paint, 95 const BitmapTextBlob& blob, const Sk Paint& paint,
96 const SkMaskFilter::BlurRec& blurRec ,
96 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { 97 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
97 // Color can affect the mask 98 // Color can affect the mask
98 // TODO we can adjust the color within specific gamma slots 99 // TODO we can adjust the color within specific gamma slots
99 if (blob.fColor != paint.getColor()) { 100 if (blob.fColor != paint.getColor()) {
100 return true; 101 return true;
101 } 102 }
102 103
103 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) { 104 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
104 return true; 105 return true;
105 } 106 }
106 107
107 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view Matrix)) { 108 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view Matrix)) {
108 return true; 109 return true;
109 } 110 }
110 111
111 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() || 112 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
112 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() || 113 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
113 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() || 114 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
114 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) { 115 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
115 return true; 116 return true;
116 } 117 }
117 118
119 // We only cache one masked version
120 if (blob.fKey.fHasBlur &&
121 (blob.fBlurRec.fSigma != blurRec.fSigma ||
122 blob.fBlurRec.fStyle != blurRec.fStyle ||
123 blob.fBlurRec.fQuality != blurRec.fQuality)) {
124 return true;
125 }
126
127 // Similarly, we only cache one version for each style
128 if (blob.fKey.fStyle != SkPaint::kFill_Style &&
129 (blob.fStrokeInfo.fFrameWidth != paint.getStrokeWidth() ||
130 blob.fStrokeInfo.fMiterLimit != paint.getStrokeMiter() ||
131 blob.fStrokeInfo.fJoin != paint.getStrokeJoin())) {
132 return true;
133 }
134
118 // We can update the positions in the cachedtextblobs without regenerating t he whole blob, but 135 // We can update the positions in the cachedtextblobs without regenerating t he whole blob, but
119 // only for integer translations. 136 // only for integer translations.
120 // This cool bit of math will determine the necessary translation to apply t o the already 137 // This cool bit of math will determine the necessary translation to apply t o the already
121 // generated vertex coordinates to move them to the correct position 138 // generated vertex coordinates to move them to the correct position
122 SkScalar transX = viewMatrix.getTranslateX() + 139 SkScalar transX = viewMatrix.getTranslateX() +
123 viewMatrix.getScaleX() * (x - blob.fX) + 140 viewMatrix.getScaleX() * (x - blob.fX) +
124 viewMatrix.getSkewX() * (y - blob.fY) - 141 viewMatrix.getSkewX() * (y - blob.fY) -
125 blob.fViewMatrix.getTranslateX(); 142 blob.fViewMatrix.getTranslateX();
126 SkScalar transY = viewMatrix.getTranslateY() + 143 SkScalar transY = viewMatrix.getTranslateY() +
127 viewMatrix.getSkewY() * (x - blob.fX) + 144 viewMatrix.getSkewY() * (x - blob.fX) +
(...skipping 27 matching lines...) Expand all
155 const SkMatrix& viewMatrix) { 172 const SkMatrix& viewMatrix) {
156 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); 173 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false);
157 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); 174 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
158 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; 175 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ;
159 } 176 }
160 177
161 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, 178 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
162 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, 179 const SkPaint& skPaint, const SkMatrix& vi ewMatrix,
163 const SkTextBlob* blob, SkScalar x, SkScal ar y, 180 const SkTextBlob* blob, SkScalar x, SkScal ar y,
164 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { 181 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) {
165 uint32_t uniqueID = blob->uniqueID();
166 SkAutoTUnref<BitmapTextBlob> cacheBlob; 182 SkAutoTUnref<BitmapTextBlob> cacheBlob;
167 // TODO start caching these, mix bits into the key 183
184 SkMaskFilter::BlurRec blurRec;
185 BitmapTextBlob::Key key;
186 // It might be worth caching these things, but its not clear at this time
187 // TODO for animated mask filters, this will fill up our cache. We need a s afeguard here
188 const SkMaskFilter* mf = skPaint.getMaskFilter();
168 bool canCache = !(skPaint.getPathEffect() || 189 bool canCache = !(skPaint.getPathEffect() ||
169 skPaint.getMaskFilter() || 190 (mf && !mf->asABlur(&blurRec)) ||
170 skPaint.getColorFilter() ||
171 skPaint.getStyle() != SkPaint::kFill_Style ||
172 drawFilter); 191 drawFilter);
173 192
174 if (canCache) { 193 if (canCache) {
175 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID))); 194 key.fUniqueID = blob->uniqueID();
195 key.fStyle = skPaint.getStyle();
196 key.fHasBlur = SkToBool(mf);
197 cacheBlob.reset(SkSafeRef(fCache->find(key)));
176 } 198 }
177 199
178 SkIRect clipRect; 200 SkIRect clipRect;
179 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 201 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
180 202
181 SkScalar transX = 0.f; 203 SkScalar transX = 0.f;
182 SkScalar transY = 0.f; 204 SkScalar transY = 0.f;
183 205
184 if (cacheBlob) { 206 if (cacheBlob) {
185 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix , x, y)) { 207 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, blurRec, v iewMatrix, x, y)) {
186 // We have to remake the blob because changes may invalidate our mas ks. 208 // We have to remake the blob because changes may invalidate our mas ks.
187 // TODO we could probably get away reuse most of the time if the poi nter is unique, 209 // TODO we could probably get away reuse most of the time if the poi nter is unique,
188 // but we'd have to clear the subrun information 210 // but we'd have to clear the subrun information
189 fCache->remove(cacheBlob); 211 fCache->remove(cacheBlob);
190 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize ))); 212 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint,
213 kGrayTextVASize)));
191 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, 214 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
192 clipRect); 215 clipRect);
193 } else { 216 } else {
194 // If we can reuse the blob, then make sure we update the blob's vie wmatrix and x/y 217 // If we can reuse the blob, then make sure we update the blob's vie wmatrix and x/y
195 // offsets to reflect the results of any translations we may apply i n generateGeometry 218 // offsets to reflect the results of any translations we may apply i n generateGeometry
196 cacheBlob->fViewMatrix = viewMatrix; 219 cacheBlob->fViewMatrix = viewMatrix;
197 cacheBlob->fX = x; 220 cacheBlob->fX = x;
198 cacheBlob->fY = y; 221 cacheBlob->fY = y;
199 fCache->makeMRU(cacheBlob); 222 fCache->makeMRU(cacheBlob);
200 } 223 }
201 } else { 224 } else {
202 if (canCache) { 225 if (canCache) {
203 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize ))); 226 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint,
227 kGrayTextVASize)));
204 } else { 228 } else {
205 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); 229 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
206 } 230 }
207 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); 231 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect);
208 } 232 }
209 233
210 // Though for the time being runs in the textblob can override the paint, th ey only touch font 234 // Though for the time being runs in the textblob can override the paint, th ey only touch font
211 // info. 235 // info.
212 GrPaint grPaint; 236 GrPaint grPaint;
213 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); 237 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
214 238
215 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, 239 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter,
216 clip, viewMatrix, clipBounds, x, y, transX, transY); 240 clip, viewMatrix, clipBounds, x, y, transX, transY);
217 } 241 }
218 242
219 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, 243 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
220 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 244 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
221 const SkTextBlob* blob, SkScalar x, SkScalar y, 245 const SkTextBlob* blob, SkScalar x, SkScalar y,
222 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { 246 SkDrawFilter* drawFilter, const SkIR ect& clipRect) {
223 cacheBlob->fViewMatrix = viewMatrix; 247 cacheBlob->fViewMatrix = viewMatrix;
224 cacheBlob->fX = x; 248 cacheBlob->fX = x;
225 cacheBlob->fY = y; 249 cacheBlob->fY = y;
226 cacheBlob->fColor = skPaint.getColor(); 250 cacheBlob->fColor = skPaint.getColor();
227 cacheBlob->fStyle = skPaint.getStyle();
228 251
229 // Regenerate textblob 252 // Regenerate textblob
230 SkPaint runPaint = skPaint; 253 SkPaint runPaint = skPaint;
231 SkTextBlob::RunIterator it(blob); 254 SkTextBlob::RunIterator it(blob);
232 for (int run = 0; !it.done(); it.next(), run++) { 255 for (int run = 0; !it.done(); it.next(), run++) {
233 int glyphCount = it.glyphCount(); 256 int glyphCount = it.glyphCount();
234 size_t textLen = glyphCount * sizeof(uint16_t); 257 size_t textLen = glyphCount * sizeof(uint16_t);
235 const SkPoint& offset = it.offset(); 258 const SkPoint& offset = it.offset();
236 // applyFontToPaint() always overwrites the exact same attributes, 259 // applyFontToPaint() always overwrites the exact same attributes,
237 // so it is safe to not re-seed the paint for this reason. 260 // so it is safe to not re-seed the paint for this reason.
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, 318 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip,
296 const GrPaint& paint, const SkPaint& skPaint , 319 const GrPaint& paint, const SkPaint& skPaint ,
297 const SkMatrix& viewMatrix, 320 const SkMatrix& viewMatrix,
298 const char text[], size_t byteLength, 321 const char text[], size_t byteLength,
299 SkScalar x, SkScalar y, const SkIRect& regio nClipBounds) { 322 SkScalar x, SkScalar y, const SkIRect& regio nClipBounds) {
300 int glyphCount = skPaint.countText(text, byteLength); 323 int glyphCount = skPaint.countText(text, byteLength);
301 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize)); 324 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize));
302 blob->fViewMatrix = viewMatrix; 325 blob->fViewMatrix = viewMatrix;
303 blob->fX = x; 326 blob->fX = x;
304 blob->fY = y; 327 blob->fY = y;
305 blob->fStyle = skPaint.getStyle();
306 328
307 SkIRect clipRect; 329 SkIRect clipRect;
308 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 330 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
309 331
310 // setup cache 332 // setup cache
311 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ; 333 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ;
312 this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength , x, y, clipRect); 334 this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength , x, y, clipRect);
313 SkGlyphCache::AttachCache(cache); 335 SkGlyphCache::AttachCache(cache);
314 336
315 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewM atrix); 337 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewM atrix);
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
406 } 428 }
407 429
408 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, 430 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip,
409 const GrPaint& paint, const SkPaint& skPa int, 431 const GrPaint& paint, const SkPaint& skPa int,
410 const SkMatrix& viewMatrix, 432 const SkMatrix& viewMatrix,
411 const char text[], size_t byteLength, 433 const char text[], size_t byteLength,
412 const SkScalar pos[], int scalarsPerPosit ion, 434 const SkScalar pos[], int scalarsPerPosit ion,
413 const SkPoint& offset, const SkIRect& reg ionClipBounds) { 435 const SkPoint& offset, const SkIRect& reg ionClipBounds) {
414 int glyphCount = skPaint.countText(text, byteLength); 436 int glyphCount = skPaint.countText(text, byteLength);
415 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize)); 437 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex tVASize));
416 blob->fStyle = skPaint.getStyle();
417 blob->fViewMatrix = viewMatrix; 438 blob->fViewMatrix = viewMatrix;
418 439
419 SkIRect clipRect; 440 SkIRect clipRect;
420 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 441 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
421 442
422 // setup cache 443 // setup cache
423 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ; 444 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix) ;
424 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen gth, pos, 445 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen gth, pos,
425 scalarsPerPosition, offset, clipRect); 446 scalarsPerPosition, offset, clipRect);
426 SkGlyphCache::AttachCache(cache); 447 SkGlyphCache::AttachCache(cache);
(...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after
1211 1232
1212 GrColor color = grPaint.getColor(); 1233 GrColor color = grPaint.getColor();
1213 uint8_t paintAlpha = skPaint.getAlpha(); 1234 uint8_t paintAlpha = skPaint.getAlpha();
1214 for (int run = 0; run < cacheBlob->fRunCount; run++) { 1235 for (int run = 0; run < cacheBlob->fRunCount; run++) {
1215 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0); 1236 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0);
1216 } 1237 }
1217 1238
1218 // Now flush big glyphs 1239 // Now flush big glyphs
1219 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); 1240 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0);
1220 } 1241 }
OLDNEW
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrTextBlobCache.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698