OLD | NEW |
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 Loading... |
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 | |
67 | 66 |
68 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, | 67 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, |
69 SkGpuDevice* gpuDevice, | 68 SkGpuDevice* gpuDevice, |
70 const SkDeviceProperties& properties) | 69 const SkDeviceProperties& properties) |
71 : INHERITED(context, gpuDevice, properties) { | 70 : INHERITED(context, gpuDevice, properties) { |
72 // We overallocate vertices in our textblobs based on the assumption that A8
has the greatest | 71 // We overallocate vertices in our textblobs based on the assumption that A8
has the greatest |
73 // vertexStride | 72 // vertexStride |
74 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >=
kLCDTextVASize, | 73 SK_COMPILE_ASSERT(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >=
kLCDTextVASize, |
75 vertex_attribute_changed); | 74 vertex_attribute_changed); |
76 fCurrStrike = NULL; | 75 fCurrStrike = NULL; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
150 const SkMatrix& viewMatrix)
{ | 149 const SkMatrix& viewMatrix)
{ |
151 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v
iewMatrix, false); | 150 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v
iewMatrix, false); |
152 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); | 151 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); |
153 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc())
; | 152 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc())
; |
154 } | 153 } |
155 | 154 |
156 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, | 155 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, |
157 const SkPaint& skPaint, const SkMatrix& vi
ewMatrix, | 156 const SkPaint& skPaint, const SkMatrix& vi
ewMatrix, |
158 const SkTextBlob* blob, SkScalar x, SkScal
ar y, | 157 const SkTextBlob* blob, SkScalar x, SkScal
ar y, |
159 SkDrawFilter* drawFilter, const SkIRect& c
lipBounds) { | 158 SkDrawFilter* drawFilter, const SkIRect& c
lipBounds) { |
160 uint32_t uniqueID = blob->uniqueID(); | |
161 SkAutoTUnref<BitmapTextBlob> cacheBlob; | 159 SkAutoTUnref<BitmapTextBlob> cacheBlob; |
162 // TODO start caching these, mix bits into the key | 160 |
| 161 BitmapTextBlob::Key key; |
| 162 // It might be worth caching these things, but its not clear at this time |
| 163 // TODO for animated mask filters, this will fill up our cache. We need a s
afeguard here |
| 164 const SkMaskFilter* mf = skPaint.getMaskFilter(); |
163 bool mustNotCache = skPaint.getPathEffect() || | 165 bool mustNotCache = skPaint.getPathEffect() || |
164 skPaint.getMaskFilter() || | 166 (mf && !mf->asABlur(&key.fBlurRec)) || |
165 skPaint.getColorFilter() || | |
166 skPaint.getStyle() != SkPaint::kFill_Style || | |
167 drawFilter; | 167 drawFilter; |
168 | 168 |
169 if (!mustNotCache) { | 169 if (!mustNotCache) { |
170 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID))); | 170 key.fUniqueID = blob->uniqueID(); |
| 171 key.fStyle = skPaint.getStyle(); |
| 172 if (key.fStyle != SkPaint::kFill_Style) { |
| 173 key.fStrokeInfo.fFrameWidth = skPaint.getStrokeWidth(); |
| 174 key.fStrokeInfo.fMiterLimit = skPaint.getStrokeMiter(); |
| 175 key.fStrokeInfo.fStrokeJoin = SkToU8(skPaint.getStrokeJoin()); |
| 176 } |
| 177 cacheBlob.reset(SkSafeRef(fCache->find(key))); |
171 } | 178 } |
172 | 179 |
173 SkIRect clipRect; | 180 SkIRect clipRect; |
174 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); | 181 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); |
175 | 182 |
176 SkScalar transX = 0.f; | 183 SkScalar transX = 0.f; |
177 SkScalar transY = 0.f; | 184 SkScalar transY = 0.f; |
178 | 185 |
179 if (cacheBlob) { | 186 if (cacheBlob) { |
180 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix
, x, y)) { | 187 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix
, x, y)) { |
181 // We have to remake the blob because changes may invalidate our mas
ks. | 188 // We have to remake the blob because changes may invalidate our mas
ks. |
182 // TODO we could probably get away reuse most of the time if the poi
nter is unique, | 189 // TODO we could probably get away reuse most of the time if the poi
nter is unique, |
183 // but we'd have to clear the subrun information | 190 // but we'd have to clear the subrun information |
184 fCache->remove(cacheBlob); | 191 fCache->remove(cacheBlob); |
185 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize
))); | 192 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, kGrayTextV
ASize))); |
186 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y,
drawFilter, | 193 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y,
drawFilter, |
187 clipRect); | 194 clipRect); |
188 } else { | 195 } else { |
189 // If we can reuse the blob, then make sure we update the blob's vie
wmatrix and x/y | 196 // 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 | 197 // offsets to reflect the results of any translations we may apply i
n generateGeometry |
191 cacheBlob->fViewMatrix = viewMatrix; | 198 cacheBlob->fViewMatrix = viewMatrix; |
192 cacheBlob->fX = x; | 199 cacheBlob->fX = x; |
193 cacheBlob->fY = y; | 200 cacheBlob->fY = y; |
194 fCache->makeMRU(cacheBlob); | 201 fCache->makeMRU(cacheBlob); |
195 } | 202 } |
196 } else { | 203 } else { |
197 if (mustNotCache) { | 204 if (mustNotCache) { |
198 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); | 205 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); |
199 } else { | 206 } else { |
200 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize
))); | 207 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, kGrayTextV
ASize))); |
201 } | 208 } |
202 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra
wFilter, clipRect); | 209 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra
wFilter, clipRect); |
203 } | 210 } |
204 | 211 |
205 // Though for the time being runs in the textblob can override the paint, th
ey only touch font | 212 // Though for the time being runs in the textblob can override the paint, th
ey only touch font |
206 // info. | 213 // info. |
207 GrPaint grPaint; | 214 GrPaint grPaint; |
208 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); | 215 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); |
209 | 216 |
210 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint
, drawFilter, | 217 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint
, drawFilter, |
211 clip, viewMatrix, clipBounds, x, y, transX, transY); | 218 clip, viewMatrix, clipBounds, x, y, transX, transY); |
212 } | 219 } |
213 | 220 |
214 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, | 221 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, |
215 const SkPaint& skPaint, const SkMatr
ix& viewMatrix, | 222 const SkPaint& skPaint, const SkMatr
ix& viewMatrix, |
216 const SkTextBlob* blob, SkScalar x,
SkScalar y, | 223 const SkTextBlob* blob, SkScalar x,
SkScalar y, |
217 SkDrawFilter* drawFilter, const SkIR
ect& clipRect) { | 224 SkDrawFilter* drawFilter, const SkIR
ect& clipRect) { |
218 cacheBlob->fViewMatrix = viewMatrix; | 225 cacheBlob->fViewMatrix = viewMatrix; |
219 cacheBlob->fX = x; | 226 cacheBlob->fX = x; |
220 cacheBlob->fY = y; | 227 cacheBlob->fY = y; |
221 cacheBlob->fColor = skPaint.getColor(); | 228 cacheBlob->fColor = skPaint.getColor(); |
222 cacheBlob->fStyle = skPaint.getStyle(); | |
223 | 229 |
224 // Regenerate textblob | 230 // Regenerate textblob |
225 SkPaint runPaint = skPaint; | 231 SkPaint runPaint = skPaint; |
226 SkTextBlob::RunIterator it(blob); | 232 SkTextBlob::RunIterator it(blob); |
227 for (int run = 0; !it.done(); it.next(), run++) { | 233 for (int run = 0; !it.done(); it.next(), run++) { |
228 int glyphCount = it.glyphCount(); | 234 int glyphCount = it.glyphCount(); |
229 size_t textLen = glyphCount * sizeof(uint16_t); | 235 size_t textLen = glyphCount * sizeof(uint16_t); |
230 const SkPoint& offset = it.offset(); | 236 const SkPoint& offset = it.offset(); |
231 // applyFontToPaint() always overwrites the exact same attributes, | 237 // applyFontToPaint() always overwrites the exact same attributes, |
232 // so it is safe to not re-seed the paint for this reason. | 238 // 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 Loading... |
290 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, | 296 void GrAtlasTextContext::onDrawText(GrRenderTarget* rt, const GrClip& clip, |
291 const GrPaint& paint, const SkPaint& skPaint
, | 297 const GrPaint& paint, const SkPaint& skPaint
, |
292 const SkMatrix& viewMatrix, | 298 const SkMatrix& viewMatrix, |
293 const char text[], size_t byteLength, | 299 const char text[], size_t byteLength, |
294 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { | 300 SkScalar x, SkScalar y, const SkIRect& regio
nClipBounds) { |
295 int glyphCount = skPaint.countText(text, byteLength); | 301 int glyphCount = skPaint.countText(text, byteLength); |
296 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex
tVASize)); | 302 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex
tVASize)); |
297 blob->fViewMatrix = viewMatrix; | 303 blob->fViewMatrix = viewMatrix; |
298 blob->fX = x; | 304 blob->fX = x; |
299 blob->fY = y; | 305 blob->fY = y; |
300 blob->fStyle = skPaint.getStyle(); | |
301 | 306 |
302 SkIRect clipRect; | 307 SkIRect clipRect; |
303 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); | 308 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); |
304 | 309 |
305 // setup cache | 310 // setup cache |
306 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix)
; | 311 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix)
; |
307 this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength
, x, y, clipRect); | 312 this->internalDrawText(blob, 0, cache, skPaint, viewMatrix, text, byteLength
, x, y, clipRect); |
308 SkGlyphCache::AttachCache(cache); | 313 SkGlyphCache::AttachCache(cache); |
309 | 314 |
310 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewM
atrix); | 315 this->flush(fContext->getTextTarget(), blob, rt, skPaint, paint, clip, viewM
atrix); |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
401 } | 406 } |
402 | 407 |
403 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, | 408 void GrAtlasTextContext::onDrawPosText(GrRenderTarget* rt, const GrClip& clip, |
404 const GrPaint& paint, const SkPaint& skPa
int, | 409 const GrPaint& paint, const SkPaint& skPa
int, |
405 const SkMatrix& viewMatrix, | 410 const SkMatrix& viewMatrix, |
406 const char text[], size_t byteLength, | 411 const char text[], size_t byteLength, |
407 const SkScalar pos[], int scalarsPerPosit
ion, | 412 const SkScalar pos[], int scalarsPerPosit
ion, |
408 const SkPoint& offset, const SkIRect& reg
ionClipBounds) { | 413 const SkPoint& offset, const SkIRect& reg
ionClipBounds) { |
409 int glyphCount = skPaint.countText(text, byteLength); | 414 int glyphCount = skPaint.countText(text, byteLength); |
410 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex
tVASize)); | 415 SkAutoTUnref<BitmapTextBlob> blob(fCache->createBlob(glyphCount, 1, kGrayTex
tVASize)); |
411 blob->fStyle = skPaint.getStyle(); | |
412 blob->fViewMatrix = viewMatrix; | 416 blob->fViewMatrix = viewMatrix; |
413 | 417 |
414 SkIRect clipRect; | 418 SkIRect clipRect; |
415 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); | 419 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); |
416 | 420 |
417 // setup cache | 421 // setup cache |
418 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix)
; | 422 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, viewMatrix)
; |
419 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen
gth, pos, | 423 this->internalDrawPosText(blob, 0, cache, skPaint, viewMatrix, text, byteLen
gth, pos, |
420 scalarsPerPosition, offset, clipRect); | 424 scalarsPerPosition, offset, clipRect); |
421 SkGlyphCache::AttachCache(cache); | 425 SkGlyphCache::AttachCache(cache); |
(...skipping 766 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1188 | 1192 |
1189 GrColor color = grPaint.getColor(); | 1193 GrColor color = grPaint.getColor(); |
1190 uint8_t paintAlpha = skPaint.getAlpha(); | 1194 uint8_t paintAlpha = skPaint.getAlpha(); |
1191 for (int run = 0; run < cacheBlob->fRunCount; run++) { | 1195 for (int run = 0; run < cacheBlob->fRunCount; run++) { |
1192 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp
ha, 0, 0); | 1196 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp
ha, 0, 0); |
1193 } | 1197 } |
1194 | 1198 |
1195 // Now flush big glyphs | 1199 // Now flush big glyphs |
1196 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); | 1200 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0); |
1197 } | 1201 } |
OLD | NEW |