| 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 |