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

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

Issue 1458233003: Factor out GrAtlasTextBatch fromt GrAtlasTextContext (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: linux build Created 5 years, 1 month 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/GrTextContext.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 "GrBatchFontCache.h"
10 #include "GrBatchFlushState.h"
11 #include "GrBatchTest.h"
12 #include "GrBlurUtils.h" 9 #include "GrBlurUtils.h"
13 #include "GrDefaultGeoProcFactory.h"
14 #include "GrDrawContext.h" 10 #include "GrDrawContext.h"
15 #include "GrDrawTarget.h" 11 #include "GrDrawTarget.h"
16 #include "GrFontScaler.h" 12 #include "GrFontScaler.h"
17 #include "GrResourceProvider.h"
18 #include "GrStrokeInfo.h" 13 #include "GrStrokeInfo.h"
19 #include "GrTextBlobCache.h" 14 #include "GrTextBlobCache.h"
20 #include "GrTexturePriv.h" 15 #include "GrTexturePriv.h"
21 #include "GrVertexBuffer.h" 16 #include "GrVertexBuffer.h"
22 17
23 #include "SkAutoKern.h" 18 #include "SkAutoKern.h"
24 #include "SkColorPriv.h" 19 #include "SkColorPriv.h"
25 #include "SkColorFilter.h" 20 #include "SkColorFilter.h"
26 #include "SkDistanceFieldGen.h" 21 #include "SkDistanceFieldGen.h"
27 #include "SkDraw.h" 22 #include "SkDraw.h"
28 #include "SkDrawFilter.h" 23 #include "SkDrawFilter.h"
29 #include "SkDrawProcs.h" 24 #include "SkDrawProcs.h"
30 #include "SkFindAndPlaceGlyph.h" 25 #include "SkFindAndPlaceGlyph.h"
31 #include "SkGlyphCache.h" 26 #include "SkGlyphCache.h"
32 #include "SkGpuDevice.h" 27 #include "SkGpuDevice.h"
33 #include "SkGrPriv.h" 28 #include "SkGrPriv.h"
34 #include "SkPath.h" 29 #include "SkPath.h"
35 #include "SkRTConf.h" 30 #include "SkRTConf.h"
36 #include "SkStrokeRec.h" 31 #include "SkStrokeRec.h"
37 #include "SkTextBlob.h" 32 #include "SkTextBlob.h"
38 #include "SkTextMapStateProc.h" 33 #include "SkTextMapStateProc.h"
39 34
40 #include "batches/GrVertexBatch.h" 35 #include "batches/GrAtlasTextBatch.h"
41
42 #include "effects/GrBitmapTextGeoProc.h"
43 #include "effects/GrDistanceFieldGeoProc.h"
44 36
45 namespace { 37 namespace {
46 static const size_t kLCDTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
47
48 // position + local coord
49 static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16);
50
51 static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof (SkIPoint16);
52
53 static const int kMinDFFontSize = 18; 38 static const int kMinDFFontSize = 18;
54 static const int kSmallDFFontSize = 32; 39 static const int kSmallDFFontSize = 32;
55 static const int kSmallDFFontLimit = 32; 40 static const int kSmallDFFontLimit = 32;
56 static const int kMediumDFFontSize = 72; 41 static const int kMediumDFFontSize = 72;
57 static const int kMediumDFFontLimit = 72; 42 static const int kMediumDFFontLimit = 72;
58 static const int kLargeDFFontSize = 162; 43 static const int kLargeDFFontSize = 162;
59 #ifdef SK_BUILD_FOR_ANDROID 44 #ifdef SK_BUILD_FOR_ANDROID
60 static const int kLargeDFFontLimit = 384; 45 static const int kLargeDFFontLimit = 384;
61 #else 46 #else
62 static const int kLargeDFFontLimit = 2 * kLargeDFFontSize; 47 static const int kLargeDFFontLimit = 2 * kLargeDFFontSize;
63 #endif 48 #endif
64 49
65 SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;) 50 SkDEBUGCODE(static const int kExpectedDistanceAdjustTableSize = 8;)
66 static const int kDistanceAdjustLumShift = 5;
67
68 static const int kVerticesPerGlyph = 4;
69 static const int kIndicesPerGlyph = 6;
70
71 static size_t get_vertex_stride(GrMaskFormat maskFormat) {
72 switch (maskFormat) {
73 case kA8_GrMaskFormat:
74 return kGrayTextVASize;
75 case kARGB_GrMaskFormat:
76 return kColorTextVASize;
77 default:
78 return kLCDTextVASize;
79 }
80 }
81
82 static size_t get_vertex_stride_df(GrMaskFormat maskFormat, bool useLCDText) {
83 SkASSERT(maskFormat == kA8_GrMaskFormat);
84 if (useLCDText) {
85 return kLCDTextVASize;
86 } else {
87 return kGrayTextVASize;
88 }
89 }
90
91 static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
92 unsigned r = SkColorGetR(c);
93 unsigned g = SkColorGetG(c);
94 unsigned b = SkColorGetB(c);
95 return GrColorPackRGBA(r, g, b, 0xff);
96 }
97
98 }; 51 };
99 52
100 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps& surfaceProps) 53 GrAtlasTextContext::GrAtlasTextContext(GrContext* context, const SkSurfaceProps& surfaceProps)
101 : INHERITED(context, surfaceProps) 54 : INHERITED(context, surfaceProps)
102 , fDistanceAdjustTable(new DistanceAdjustTable) { 55 , fDistanceAdjustTable(new DistanceAdjustTable) {
103 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest 56 // We overallocate vertices in our textblobs based on the assumption that A8 has the greatest
104 // vertexStride 57 // vertexStride
105 static_assert(kGrayTextVASize >= kColorTextVASize && kGrayTextVASize >= kLCD TextVASize, 58 static_assert(GrAtlasTextBatch::kGrayTextVASize >= GrAtlasTextBatch::kColorT extVASize &&
59 GrAtlasTextBatch::kGrayTextVASize >= GrAtlasTextBatch::kLCDTex tVASize,
106 "vertex_attribute_changed"); 60 "vertex_attribute_changed");
107 fCurrStrike = nullptr; 61 fCurrStrike = nullptr;
108 fCache = context->getTextBlobCache(); 62 fCache = context->getTextBlobCache();
109 } 63 }
110 64
111 void GrAtlasTextContext::DistanceAdjustTable::buildDistanceAdjustTable() { 65 void GrAtlasTextContext::DistanceAdjustTable::buildDistanceAdjustTable() {
112 66
113 // This is used for an approximation of the mask gamma hack, used by raster and bitmap 67 // This is used for an approximation of the mask gamma hack, used by raster and bitmap
114 // text. The mask gamma hack is based off of guessing what the blend color i s going to 68 // text. The mask gamma hack is based off of guessing what the blend color i s going to
115 // be, and adjusting the mask so that when run through the linear blend will 69 // be, and adjusting the mask so that when run through the linear blend will
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
395 } 349 }
396 350
397 if (cacheBlob) { 351 if (cacheBlob) {
398 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, grPaint.ge tColor(), blurRec, 352 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, grPaint.ge tColor(), blurRec,
399 viewMatrix, x, y)) { 353 viewMatrix, x, y)) {
400 // We have to remake the blob because changes may invalidate our mas ks. 354 // We have to remake the blob because changes may invalidate our mas ks.
401 // TODO we could probably get away reuse most of the time if the poi nter is unique, 355 // TODO we could probably get away reuse most of the time if the poi nter is unique,
402 // but we'd have to clear the subrun information 356 // but we'd have to clear the subrun information
403 fCache->remove(cacheBlob); 357 fCache->remove(cacheBlob);
404 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint, 358 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint,
405 kGrayTextVASize))); 359 GrAtlasTextBatch::kGr ayTextVASize)));
406 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie wMatrix, 360 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), vie wMatrix,
407 blob, x, y, drawFilter, clipRect, rt, clip) ; 361 blob, x, y, drawFilter, clipRect, rt, clip) ;
408 } else { 362 } else {
409 // If we can reuse the blob, then make sure we update the blob's vie wmatrix, and x/y 363 // If we can reuse the blob, then make sure we update the blob's vie wmatrix, and x/y
410 // offsets. Note, we offset the vertex bounds right before flushing 364 // offsets. Note, we offset the vertex bounds right before flushing
411 cacheBlob->fViewMatrix = viewMatrix; 365 cacheBlob->fViewMatrix = viewMatrix;
412 cacheBlob->fX = x; 366 cacheBlob->fX = x;
413 cacheBlob->fY = y; 367 cacheBlob->fY = y;
414 fCache->makeMRU(cacheBlob); 368 fCache->makeMRU(cacheBlob);
415 #ifdef CACHE_SANITY_CHECK 369 #ifdef CACHE_SANITY_CHECK
416 { 370 {
417 int glyphCount = 0; 371 int glyphCount = 0;
418 int runCount = 0; 372 int runCount = 0;
419 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); 373 GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob);
420 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp hCount, runCount, 374 SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyp hCount, runCount,
421 kGra yTextVASize)); 375 kGra yTextVASize));
422 GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skP aint); 376 GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skP aint);
423 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor() , viewMatrix, 377 this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor() , viewMatrix,
424 blob, x, y, drawFilter, clipRect, rt, c lip); 378 blob, x, y, drawFilter, clipRect, rt, c lip);
425 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); 379 GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob);
426 } 380 }
427 381
428 #endif 382 #endif
429 } 383 }
430 } else { 384 } else {
431 if (canCache) { 385 if (canCache) {
432 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint, 386 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, key, blurRec, s kPaint,
433 kGrayTextVASize))); 387 GrAtlasTextBatch::kGr ayTextVASize)));
434 } else { 388 } else {
435 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize)); 389 cacheBlob.reset(fCache->createBlob(blob, GrAtlasTextBatch::kGrayText VASize));
436 } 390 }
437 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat rix, 391 this->regenerateTextBlob(cacheBlob, skPaint, grPaint.getColor(), viewMat rix,
438 blob, x, y, drawFilter, clipRect, rt, clip); 392 blob, x, y, drawFilter, clipRect, rt, clip);
439 } 393 }
440 394
441 this->flush(blob, cacheBlob, dc, rt, skPaint, grPaint, drawFilter, 395 this->flush(blob, cacheBlob, dc, rt, skPaint, grPaint, drawFilter,
442 clip, viewMatrix, clipBounds, x, y, transX, transY); 396 clip, viewMatrix, clipBounds, x, y, transX, transY);
443 } 397 }
444 398
445 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint, 399 inline bool GrAtlasTextContext::canDrawAsDistanceFields(const SkPaint& skPaint,
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 this->internalDrawBMPPosText(blob, runIndex, cache, skPaint, color, viewMatr ix, 636 this->internalDrawBMPPosText(blob, runIndex, cache, skPaint, color, viewMatr ix,
683 fallbackTxt.begin(), fallbackTxt.count(), 637 fallbackTxt.begin(), fallbackTxt.count(),
684 fallbackPos.begin(), scalarsPerPosition, offset , clipRect); 638 fallbackPos.begin(), scalarsPerPosition, offset , clipRect);
685 SkGlyphCache::AttachCache(cache); 639 SkGlyphCache::AttachCache(cache);
686 } 640 }
687 641
688 inline GrAtlasTextBlob* 642 inline GrAtlasTextBlob*
689 GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint, 643 GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint,
690 const SkMatrix& viewMatrix, SkPaint* dfPaint, 644 const SkMatrix& viewMatrix, SkPaint* dfPaint,
691 SkScalar* textRatio) { 645 SkScalar* textRatio) {
692 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 646 GrAtlasTextBlob* blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBatch:: kGrayTextVASize);
693 647
694 *dfPaint = origPaint; 648 *dfPaint = origPaint;
695 this->initDistanceFieldPaint(blob, dfPaint, textRatio, viewMatrix); 649 this->initDistanceFieldPaint(blob, dfPaint, textRatio, viewMatrix);
696 blob->fViewMatrix = viewMatrix; 650 blob->fViewMatrix = viewMatrix;
697 Run& run = blob->fRuns[0]; 651 Run& run = blob->fRuns[0];
698 PerSubRunInfo& subRun = run.fSubRunInfo.back(); 652 PerSubRunInfo& subRun = run.fSubRunInfo.back();
699 subRun.fUseLCDText = origPaint.isLCDRenderText(); 653 subRun.fUseLCDText = origPaint.isLCDRenderText();
700 subRun.fDrawAsDistanceFields = true; 654 subRun.fDrawAsDistanceFields = true;
701 655
702 return blob; 656 return blob;
(...skipping 19 matching lines...) Expand all
722 SkTDArray<SkScalar> fallbackPos; 676 SkTDArray<SkScalar> fallbackPos;
723 SkPoint offset; 677 SkPoint offset;
724 this->internalDrawDFText(blob, 0, dfPaint, paint.getColor(), viewMatrix, text, 678 this->internalDrawDFText(blob, 0, dfPaint, paint.getColor(), viewMatrix, text,
725 byteLength, x, y, clipRect, textRatio, &fallbac kTxt, &fallbackPos, 679 byteLength, x, y, clipRect, textRatio, &fallbac kTxt, &fallbackPos,
726 &offset, skPaint); 680 &offset, skPaint);
727 if (fallbackTxt.count()) { 681 if (fallbackTxt.count()) {
728 this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPai nt, viewMatrix, 682 this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPai nt, viewMatrix,
729 fallbackTxt, fallbackPos, 2, offset, clipR ect); 683 fallbackTxt, fallbackPos, 2, offset, clipR ect);
730 } 684 }
731 } else { 685 } else {
732 blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 686 blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBatch::kGrayTextVASi ze);
733 blob->fViewMatrix = viewMatrix; 687 blob->fViewMatrix = viewMatrix;
734 688
735 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa trix, false); 689 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa trix, false);
736 this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), vie wMatrix, text, 690 this->internalDrawBMPText(blob, 0, cache, skPaint, paint.getColor(), vie wMatrix, text,
737 byteLength, x, y, clipRect); 691 byteLength, x, y, clipRect);
738 SkGlyphCache::AttachCache(cache); 692 SkGlyphCache::AttachCache(cache);
739 } 693 }
740 return blob; 694 return blob;
741 } 695 }
742 696
(...skipping 19 matching lines...) Expand all
762 SkTDArray<SkScalar> fallbackPos; 716 SkTDArray<SkScalar> fallbackPos;
763 this->internalDrawDFPosText(blob, 0, dfPaint, paint.getColor(), viewMatr ix, text, 717 this->internalDrawDFPosText(blob, 0, dfPaint, paint.getColor(), viewMatr ix, text,
764 byteLength, pos, scalarsPerPosition, offset, clipRect, 718 byteLength, pos, scalarsPerPosition, offset, clipRect,
765 textRatio, &fallbackTxt, &fallbackPos); 719 textRatio, &fallbackTxt, &fallbackPos);
766 if (fallbackTxt.count()) { 720 if (fallbackTxt.count()) {
767 this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPai nt, viewMatrix, 721 this->fallbackDrawPosText(blob, 0, rt, clip, paint.getColor(), skPai nt, viewMatrix,
768 fallbackTxt, fallbackPos, scalarsPerPositi on, offset, 722 fallbackTxt, fallbackPos, scalarsPerPositi on, offset,
769 clipRect); 723 clipRect);
770 } 724 }
771 } else { 725 } else {
772 blob = fCache->createBlob(glyphCount, 1, kGrayTextVASize); 726 blob = fCache->createBlob(glyphCount, 1, GrAtlasTextBatch::kGrayTextVASi ze);
773 blob->fViewMatrix = viewMatrix; 727 blob->fViewMatrix = viewMatrix;
774 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa trix, false); 728 SkGlyphCache* cache = this->setupCache(&blob->fRuns[0], skPaint, &viewMa trix, false);
775 this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text, 729 this->internalDrawBMPPosText(blob, 0, cache, skPaint, paint.getColor(), viewMatrix, text,
776 byteLength, pos, scalarsPerPosition, offset , clipRect); 730 byteLength, pos, scalarsPerPosition, offset , clipRect);
777 SkGlyphCache::AttachCache(cache); 731 SkGlyphCache::AttachCache(cache);
778 } 732 }
779 return blob; 733 return blob;
780 } 734 }
781 735
782 void GrAtlasTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt, 736 void GrAtlasTextContext::onDrawText(GrDrawContext* dc, GrRenderTarget* rt,
(...skipping 300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1083 PerSubRunInfo* subRun = &run.fSubRunInfo.back(); 1037 PerSubRunInfo* subRun = &run.fSubRunInfo.back();
1084 if (run.fInitialized && subRun->fMaskFormat != format) { 1038 if (run.fInitialized && subRun->fMaskFormat != format) {
1085 subRun = &run.push_back(); 1039 subRun = &run.push_back();
1086 subRun->fStrike.reset(SkRef(fCurrStrike)); 1040 subRun->fStrike.reset(SkRef(fCurrStrike));
1087 } else if (!run.fInitialized) { 1041 } else if (!run.fInitialized) {
1088 subRun->fStrike.reset(SkRef(fCurrStrike)); 1042 subRun->fStrike.reset(SkRef(fCurrStrike));
1089 } 1043 }
1090 1044
1091 run.fInitialized = true; 1045 run.fInitialized = true;
1092 1046
1093 size_t vertexStride = get_vertex_stride(format); 1047 size_t vertexStride = GrAtlasTextBatch::GetVertexStride(format);
1094 1048
1095 SkRect r; 1049 SkRect r;
1096 r.fLeft = SkIntToScalar(x); 1050 r.fLeft = SkIntToScalar(x);
1097 r.fTop = SkIntToScalar(y); 1051 r.fTop = SkIntToScalar(y);
1098 r.fRight = r.fLeft + SkIntToScalar(width); 1052 r.fRight = r.fLeft + SkIntToScalar(width);
1099 r.fBottom = r.fTop + SkIntToScalar(height); 1053 r.fBottom = r.fTop + SkIntToScalar(height);
1100 subRun->fMaskFormat = format; 1054 subRun->fMaskFormat = format;
1101 this->appendGlyphCommon(blob, &run, subRun, r, color, vertexStride, kA8_GrMa skFormat == format, 1055 this->appendGlyphCommon(blob, &run, subRun, r, color, vertexStride, kA8_GrMa skFormat == format,
1102 glyph); 1056 glyph);
1103 } 1057 }
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1161 } 1115 }
1162 1116
1163 PerSubRunInfo* subRun = &run.fSubRunInfo.back(); 1117 PerSubRunInfo* subRun = &run.fSubRunInfo.back();
1164 if (!run.fInitialized) { 1118 if (!run.fInitialized) {
1165 subRun->fStrike.reset(SkRef(fCurrStrike)); 1119 subRun->fStrike.reset(SkRef(fCurrStrike));
1166 } 1120 }
1167 run.fInitialized = true; 1121 run.fInitialized = true;
1168 SkASSERT(glyph->fMaskFormat == kA8_GrMaskFormat); 1122 SkASSERT(glyph->fMaskFormat == kA8_GrMaskFormat);
1169 subRun->fMaskFormat = kA8_GrMaskFormat; 1123 subRun->fMaskFormat = kA8_GrMaskFormat;
1170 1124
1171 size_t vertexStride = get_vertex_stride_df(kA8_GrMaskFormat, subRun->fUseLCD Text); 1125 size_t vertexStride = GrAtlasTextBatch::GetVertexStrideDf(kA8_GrMaskFormat,
1126 subRun->fUseLCDTex t);
1172 1127
1173 bool useColorVerts = !subRun->fUseLCDText; 1128 bool useColorVerts = !subRun->fUseLCDText;
1174 this->appendGlyphCommon(blob, &run, subRun, glyphRect, color, vertexStride, useColorVerts, 1129 this->appendGlyphCommon(blob, &run, subRun, glyphRect, color, vertexStride, useColorVerts,
1175 glyph); 1130 glyph);
1176 return true; 1131 return true;
1177 } 1132 }
1178 1133
1179 inline void GrAtlasTextContext::appendGlyphPath(GrAtlasTextBlob* blob, GrGlyph* glyph, 1134 inline void GrAtlasTextContext::appendGlyphPath(GrAtlasTextBlob* blob, GrGlyph* glyph,
1180 GrFontScaler* scaler, const SkGl yph& skGlyph, 1135 GrFontScaler* scaler, const SkGl yph& skGlyph,
1181 SkScalar x, SkScalar y, SkScalar scale, 1136 SkScalar x, SkScalar y, SkScalar scale,
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 position = reinterpret_cast<SkPoint*>(vertex); 1199 position = reinterpret_cast<SkPoint*>(vertex);
1245 position->set(positions.fRight, positions.fBottom); 1200 position->set(positions.fRight, positions.fBottom);
1246 vertex += vertexStride; 1201 vertex += vertexStride;
1247 1202
1248 // V3 1203 // V3
1249 position = reinterpret_cast<SkPoint*>(vertex); 1204 position = reinterpret_cast<SkPoint*>(vertex);
1250 position->set(positions.fRight, positions.fTop); 1205 position->set(positions.fRight, positions.fTop);
1251 } 1206 }
1252 1207
1253 subRun->fGlyphEndIndex++; 1208 subRun->fGlyphEndIndex++;
1254 subRun->fVertexEndIndex += vertexStride * kVerticesPerGlyph; 1209 subRun->fVertexEndIndex += vertexStride * GrAtlasTextBatch::kVerticesPerGlyp h;
1255 } 1210 }
1256 1211
1257 class TextBatch : public GrVertexBatch {
1258 public:
1259 DEFINE_BATCH_CLASS_ID
1260
1261 typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable;
1262 typedef GrAtlasTextBlob Blob;
1263 typedef Blob::Run Run;
1264 typedef Run::SubRunInfo TextInfo;
1265 struct Geometry {
1266 Blob* fBlob;
1267 int fRun;
1268 int fSubRun;
1269 GrColor fColor;
1270 SkScalar fTransX;
1271 SkScalar fTransY;
1272 };
1273
1274 static TextBatch* CreateBitmap(GrMaskFormat maskFormat, int glyphCount,
1275 GrBatchFontCache* fontCache) {
1276 TextBatch* batch = new TextBatch;
1277
1278 batch->fFontCache = fontCache;
1279 switch (maskFormat) {
1280 case kA8_GrMaskFormat:
1281 batch->fMaskType = kGrayscaleCoverageMask_MaskType;
1282 break;
1283 case kA565_GrMaskFormat:
1284 batch->fMaskType = kLCDCoverageMask_MaskType;
1285 break;
1286 case kARGB_GrMaskFormat:
1287 batch->fMaskType = kColorBitmapMask_MaskType;
1288 break;
1289 }
1290 batch->fBatch.fNumGlyphs = glyphCount;
1291 batch->fGeoCount = 1;
1292 batch->fFilteredColor = 0;
1293 batch->fFontCache = fontCache;
1294 batch->fUseBGR = false;
1295 return batch;
1296 }
1297
1298 static TextBatch* CreateDistanceField(int glyphCount, GrBatchFontCache* font Cache,
1299 const DistanceAdjustTable* distanceAdj ustTable,
1300 SkColor filteredColor, bool isLCD,
1301 bool useBGR) {
1302 TextBatch* batch = new TextBatch;
1303
1304 batch->fFontCache = fontCache;
1305 batch->fMaskType = isLCD ? kLCDDistanceField_MaskType : kGrayscaleDistan ceField_MaskType;
1306 batch->fDistanceAdjustTable.reset(SkRef(distanceAdjustTable));
1307 batch->fFilteredColor = filteredColor;
1308 batch->fUseBGR = useBGR;
1309 batch->fBatch.fNumGlyphs = glyphCount;
1310 batch->fGeoCount = 1;
1311 return batch;
1312 }
1313
1314 // to avoid even the initial copy of the struct, we have a getter for the fi rst item which
1315 // is used to seed the batch with its initial geometry. After seeding, the client should call
1316 // init() so the Batch can initialize itself
1317 Geometry& geometry() { return fGeoData[0]; }
1318
1319 void init() {
1320 const Geometry& geo = fGeoData[0];
1321 fBatch.fColor = geo.fColor;
1322 fBatch.fViewMatrix = geo.fBlob->fViewMatrix;
1323
1324 // We don't yet position distance field text on the cpu, so we have to m ap the vertex bounds
1325 // into device space
1326 const Run& run = geo.fBlob->fRuns[geo.fRun];
1327 if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) {
1328 SkRect bounds = run.fVertexBounds;
1329 fBatch.fViewMatrix.mapRect(&bounds);
1330 this->setBounds(bounds);
1331 } else {
1332 this->setBounds(run.fVertexBounds);
1333 }
1334 }
1335
1336 const char* name() const override { return "TextBatch"; }
1337
1338 SkString dumpInfo() const override {
1339 SkString str;
1340
1341 for (int i = 0; i < fGeoCount; ++i) {
1342 str.appendf("%d: Color: 0x%08x Trans: %.2f,%.2f Runs: %d\n",
1343 i,
1344 fGeoData[i].fColor,
1345 fGeoData[i].fTransX,
1346 fGeoData[i].fTransY,
1347 fGeoData[i].fBlob->fRunCount);
1348 }
1349
1350 str.append(INHERITED::dumpInfo());
1351 return str;
1352 }
1353
1354 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
1355 if (kColorBitmapMask_MaskType == fMaskType) {
1356 out->setUnknownFourComponents();
1357 } else {
1358 out->setKnownFourComponents(fBatch.fColor);
1359 }
1360 }
1361
1362 void getInvariantOutputCoverage(GrInitInvariantOutput* out) const override {
1363 switch (fMaskType) {
1364 case kGrayscaleDistanceField_MaskType:
1365 case kGrayscaleCoverageMask_MaskType:
1366 out->setUnknownSingleComponent();
1367 break;
1368 case kLCDCoverageMask_MaskType:
1369 case kLCDDistanceField_MaskType:
1370 out->setUnknownOpaqueFourComponents();
1371 out->setUsingLCDCoverage();
1372 break;
1373 case kColorBitmapMask_MaskType:
1374 out->setKnownSingleComponent(0xff);
1375 }
1376 }
1377
1378 private:
1379 void initBatchTracker(const GrPipelineOptimizations& opt) override {
1380 // Handle any color overrides
1381 if (!opt.readsColor()) {
1382 fGeoData[0].fColor = GrColor_ILLEGAL;
1383 }
1384 opt.getOverrideColorIfSet(&fGeoData[0].fColor);
1385
1386 // setup batch properties
1387 fBatch.fColorIgnored = !opt.readsColor();
1388 fBatch.fColor = fGeoData[0].fColor;
1389 fBatch.fUsesLocalCoords = opt.readsLocalCoords();
1390 fBatch.fCoverageIgnored = !opt.readsCoverage();
1391 }
1392
1393 struct FlushInfo {
1394 SkAutoTUnref<const GrVertexBuffer> fVertexBuffer;
1395 SkAutoTUnref<const GrIndexBuffer> fIndexBuffer;
1396 int fGlyphsToFlush;
1397 int fVertexOffset;
1398 };
1399
1400 void onPrepareDraws(Target* target) override {
1401 // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
1402 // TODO actually only invert if we don't have RGBA
1403 SkMatrix localMatrix;
1404 if (this->usesLocalCoords() && !this->viewMatrix().invert(&localMatrix)) {
1405 SkDebugf("Cannot invert viewmatrix\n");
1406 return;
1407 }
1408
1409 GrTexture* texture = fFontCache->getTexture(this->maskFormat());
1410 if (!texture) {
1411 SkDebugf("Could not allocate backing texture for atlas\n");
1412 return;
1413 }
1414
1415 bool usesDistanceFields = this->usesDistanceFields();
1416 GrMaskFormat maskFormat = this->maskFormat();
1417 bool isLCD = this->isLCD();
1418
1419 SkAutoTUnref<const GrGeometryProcessor> gp;
1420 if (usesDistanceFields) {
1421 gp.reset(this->setupDfProcessor(this->viewMatrix(), fFilteredColor, this->color(),
1422 texture));
1423 } else {
1424 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::k None_FilterMode);
1425 gp.reset(GrBitmapTextGeoProc::Create(this->color(),
1426 texture,
1427 params,
1428 maskFormat,
1429 localMatrix,
1430 this->usesLocalCoords()));
1431 }
1432
1433 FlushInfo flushInfo;
1434 flushInfo.fGlyphsToFlush = 0;
1435 size_t vertexStride = gp->getVertexStride();
1436 SkASSERT(vertexStride == (usesDistanceFields ?
1437 get_vertex_stride_df(maskFormat, isLCD) :
1438 get_vertex_stride(maskFormat)));
1439
1440 target->initDraw(gp, this->pipeline());
1441
1442 int glyphCount = this->numGlyphs();
1443 const GrVertexBuffer* vertexBuffer;
1444
1445 void* vertices = target->makeVertexSpace(vertexStride,
1446 glyphCount * kVerticesPerGlyph,
1447 &vertexBuffer,
1448 &flushInfo.fVertexOffset);
1449 flushInfo.fVertexBuffer.reset(SkRef(vertexBuffer));
1450 flushInfo.fIndexBuffer.reset(target->resourceProvider()->refQuadIndexBuf fer());
1451 if (!vertices || !flushInfo.fVertexBuffer) {
1452 SkDebugf("Could not allocate vertices\n");
1453 return;
1454 }
1455
1456 unsigned char* currVertex = reinterpret_cast<unsigned char*>(vertices);
1457
1458 // We cache some values to avoid going to the glyphcache for the same fo ntScaler twice
1459 // in a row
1460 const SkDescriptor* desc = nullptr;
1461 SkGlyphCache* cache = nullptr;
1462 GrFontScaler* scaler = nullptr;
1463 SkTypeface* typeface = nullptr;
1464
1465 for (int i = 0; i < fGeoCount; i++) {
1466 Geometry& args = fGeoData[i];
1467 Blob* blob = args.fBlob;
1468 Run& run = blob->fRuns[args.fRun];
1469 TextInfo& info = run.fSubRunInfo[args.fSubRun];
1470
1471 uint64_t currentAtlasGen = fFontCache->atlasGeneration(maskFormat);
1472 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen ||
1473 info.fStrike->isAbandoned();
1474 bool regenerateColors;
1475 if (usesDistanceFields) {
1476 regenerateColors = !isLCD && run.fColor != args.fColor;
1477 } else {
1478 regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor != args.fColor;
1479 }
1480 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0. f;
1481 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
1482
1483 // We regenerate both texture coords and colors in the blob itself, and update the
1484 // atlas generation. If we don't end up purging any unused plots, w e can avoid
1485 // regenerating the coords. We could take a finer grained approach to updating texture
1486 // coords but its not clear if the extra bookkeeping would offset an y gains.
1487 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color
1488 // or coords as needed. One final note, if we have to break a run f or an atlas eviction
1489 // then we can't really trust the atlas has all of the correct data. Atlas evictions
1490 // should be pretty rare, so we just always regenerate in those case s
1491 if (regenerateTextureCoords || regenerateColors || regeneratePositio ns) {
1492 // first regenerate texture coordinates / colors if need be
1493 bool brokenRun = false;
1494
1495 // Because the GrBatchFontCache may evict the strike a blob depe nds on using for
1496 // generating its texture coords, we have to track whether or no t the strike has
1497 // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is
1498 // otherwise we have to get the new strike, and use that to get the correct glyphs.
1499 // Because we do not have the packed ids, and thus can't look up our glyphs in the
1500 // new strike, we instead keep our ref to the old strike and use the packed ids from
1501 // it. These ids will still be valid as long as we hold the ref . When we are done
1502 // updating our cache of the GrGlyph*s, we drop our ref on the o ld strike
1503 bool regenerateGlyphs = false;
1504 GrBatchTextStrike* strike = nullptr;
1505 if (regenerateTextureCoords) {
1506 info.fBulkUseToken.reset();
1507
1508 // We can reuse if we have a valid strike and our descriptor s / typeface are the
1509 // same. The override descriptor is only for the non distan ce field text within
1510 // a run
1511 const SkDescriptor* newDesc = (run.fOverrideDescriptor && !u sesDistanceFields) ?
1512 run.fOverrideDescriptor->getDe sc() :
1513 run.fDescriptor.getDesc();
1514 if (!cache || !SkTypeface::Equal(typeface, run.fTypeface) ||
1515 !(desc->equals(*newDesc))) {
1516 if (cache) {
1517 SkGlyphCache::AttachCache(cache);
1518 }
1519 desc = newDesc;
1520 cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
1521 scaler = GrTextContext::GetGrFontScaler(cache);
1522 strike = info.fStrike;
1523 typeface = run.fTypeface;
1524 }
1525
1526 if (info.fStrike->isAbandoned()) {
1527 regenerateGlyphs = true;
1528 strike = fFontCache->getStrike(scaler);
1529 } else {
1530 strike = info.fStrike;
1531 }
1532 }
1533
1534 for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) {
1535 if (regenerateTextureCoords) {
1536 size_t glyphOffset = glyphIdx + info.fGlyphStartIndex;
1537
1538 GrGlyph* glyph = blob->fGlyphs[glyphOffset];
1539 GrGlyph::PackedID id = glyph->fPackedID;
1540 const SkGlyph& skGlyph = scaler->grToSkGlyph(id);
1541 if (regenerateGlyphs) {
1542 // Get the id from the old glyph, and use the new st rike to lookup
1543 // the glyph.
1544 blob->fGlyphs[glyphOffset] = strike->getGlyph(skGlyp h, id, maskFormat,
1545 scaler );
1546 }
1547 glyph = blob->fGlyphs[glyphOffset];
1548 SkASSERT(glyph);
1549 SkASSERT(id == glyph->fPackedID);
1550 // We want to be able to assert this but cannot for test ing purposes.
1551 // once skbug:4143 has landed we can revist this assert
1552 //SkASSERT(glyph->fMaskFormat == this->maskFormat());
1553
1554 if (!fFontCache->hasGlyph(glyph) &&
1555 !strike->addGlyphToAtlas(target, glyph, scaler, skGl yph, maskFormat)) {
1556 this->flush(target, &flushInfo);
1557 target->initDraw(gp, this->pipeline());
1558 brokenRun = glyphIdx > 0;
1559
1560 SkDEBUGCODE(bool success =) strike->addGlyphToAtlas( target,
1561 glyph,
1562 scaler,
1563 skGlyph,
1564 maskFormat);
1565 SkASSERT(success);
1566 }
1567 fFontCache->addGlyphToBulkAndSetUseToken(&info.fBulkUseT oken, glyph,
1568 target->current Token());
1569
1570 // Texture coords are the last vertex attribute so we ge t a pointer to the
1571 // first one and then map with stride in regenerateTextu reCoords
1572 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
1573 vertex += info.fVertexStartIndex;
1574 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
1575 vertex += vertexStride - sizeof(SkIPoint16);
1576
1577 this->regenerateTextureCoords(glyph, vertex, vertexStrid e);
1578 }
1579
1580 if (regenerateColors) {
1581 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
1582 vertex += info.fVertexStartIndex;
1583 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
1584 this->regenerateColors(vertex, vertexStride, args.fColor );
1585 }
1586
1587 if (regeneratePositions) {
1588 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
1589 vertex += info.fVertexStartIndex;
1590 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
1591 SkScalar transX = args.fTransX;
1592 SkScalar transY = args.fTransY;
1593 this->regeneratePositions(vertex, vertexStride, transX, transY);
1594 }
1595 flushInfo.fGlyphsToFlush++;
1596 }
1597
1598 // We my have changed the color so update it here
1599 run.fColor = args.fColor;
1600 if (regenerateTextureCoords) {
1601 if (regenerateGlyphs) {
1602 info.fStrike.reset(SkRef(strike));
1603 }
1604 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration :
1605 fFontCache->atlasGenerat ion(maskFormat);
1606 }
1607 } else {
1608 flushInfo.fGlyphsToFlush += glyphCount;
1609
1610 // set use tokens for all of the glyphs in our subrun. This is only valid if we
1611 // have a valid atlas generation
1612 fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentT oken(), maskFormat);
1613 }
1614
1615 // now copy all vertices
1616 size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex;
1617 memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCou nt);
1618
1619 currVertex += byteCount;
1620 }
1621 // Make sure to attach the last cache if applicable
1622 if (cache) {
1623 SkGlyphCache::AttachCache(cache);
1624 }
1625 this->flush(target, &flushInfo);
1626 }
1627
1628 TextBatch() : INHERITED(ClassID()) {} // initialized in factory functions.
1629
1630 ~TextBatch() {
1631 for (int i = 0; i < fGeoCount; i++) {
1632 fGeoData[i].fBlob->unref();
1633 }
1634 }
1635
1636 GrMaskFormat maskFormat() const {
1637 switch (fMaskType) {
1638 case kLCDCoverageMask_MaskType:
1639 return kA565_GrMaskFormat;
1640 case kColorBitmapMask_MaskType:
1641 return kARGB_GrMaskFormat;
1642 case kGrayscaleCoverageMask_MaskType:
1643 case kGrayscaleDistanceField_MaskType:
1644 case kLCDDistanceField_MaskType:
1645 return kA8_GrMaskFormat;
1646 }
1647 return kA8_GrMaskFormat; // suppress warning
1648 }
1649
1650 bool usesDistanceFields() const {
1651 return kGrayscaleDistanceField_MaskType == fMaskType ||
1652 kLCDDistanceField_MaskType == fMaskType;
1653 }
1654
1655 bool isLCD() const {
1656 return kLCDCoverageMask_MaskType == fMaskType ||
1657 kLCDDistanceField_MaskType == fMaskType;
1658 }
1659
1660 void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexS tride) {
1661 int width = glyph->fBounds.width();
1662 int height = glyph->fBounds.height();
1663
1664 int u0, v0, u1, v1;
1665 if (this->usesDistanceFields()) {
1666 u0 = glyph->fAtlasLocation.fX + SK_DistanceFieldInset;
1667 v0 = glyph->fAtlasLocation.fY + SK_DistanceFieldInset;
1668 u1 = u0 + width - 2 * SK_DistanceFieldInset;
1669 v1 = v0 + height - 2 * SK_DistanceFieldInset;
1670 } else {
1671 u0 = glyph->fAtlasLocation.fX;
1672 v0 = glyph->fAtlasLocation.fY;
1673 u1 = u0 + width;
1674 v1 = v0 + height;
1675 }
1676
1677 SkIPoint16* textureCoords;
1678 // V0
1679 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
1680 textureCoords->set(u0, v0);
1681 vertex += vertexStride;
1682
1683 // V1
1684 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
1685 textureCoords->set(u0, v1);
1686 vertex += vertexStride;
1687
1688 // V2
1689 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
1690 textureCoords->set(u1, v1);
1691 vertex += vertexStride;
1692
1693 // V3
1694 textureCoords = reinterpret_cast<SkIPoint16*>(vertex);
1695 textureCoords->set(u1, v0);
1696 }
1697
1698 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
1699 for (int i = 0; i < kVerticesPerGlyph; i++) {
1700 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
1701 *vcolor = color;
1702 vertex += vertexStride;
1703 }
1704 }
1705
1706 void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar tran sX,
1707 SkScalar transY) {
1708 for (int i = 0; i < kVerticesPerGlyph; i++) {
1709 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
1710 point->fX += transX;
1711 point->fY += transY;
1712 vertex += vertexStride;
1713 }
1714 }
1715
1716 void flush(GrVertexBatch::Target* target, FlushInfo* flushInfo) {
1717 GrVertices vertices;
1718 int maxGlyphsPerDraw = flushInfo->fIndexBuffer->maxQuads();
1719 vertices.initInstanced(kTriangles_GrPrimitiveType, flushInfo->fVertexBuf fer,
1720 flushInfo->fIndexBuffer, flushInfo->fVertexOffset ,
1721 kVerticesPerGlyph, kIndicesPerGlyph, flushInfo->f GlyphsToFlush,
1722 maxGlyphsPerDraw);
1723 target->draw(vertices);
1724 flushInfo->fVertexOffset += kVerticesPerGlyph * flushInfo->fGlyphsToFlus h;
1725 flushInfo->fGlyphsToFlush = 0;
1726 }
1727
1728 GrColor color() const { return fBatch.fColor; }
1729 const SkMatrix& viewMatrix() const { return fBatch.fViewMatrix; }
1730 bool usesLocalCoords() const { return fBatch.fUsesLocalCoords; }
1731 int numGlyphs() const { return fBatch.fNumGlyphs; }
1732
1733 bool onCombineIfPossible(GrBatch* t, const GrCaps& caps) override {
1734 TextBatch* that = t->cast<TextBatch>();
1735 if (!GrPipeline::CanCombine(*this->pipeline(), this->bounds(), *that->pi peline(),
1736 that->bounds(), caps)) {
1737 return false;
1738 }
1739
1740 if (fMaskType != that->fMaskType) {
1741 return false;
1742 }
1743
1744 if (!this->usesDistanceFields()) {
1745 // TODO we can often batch across LCD text if we have dual source bl ending and don't
1746 // have to use the blend constant
1747 if (kGrayscaleCoverageMask_MaskType != fMaskType && this->color() != that->color()) {
1748 return false;
1749 }
1750 if (this->usesLocalCoords() && !this->viewMatrix().cheapEqualTo(that ->viewMatrix())) {
1751 return false;
1752 }
1753 } else {
1754 if (!this->viewMatrix().cheapEqualTo(that->viewMatrix())) {
1755 return false;
1756 }
1757
1758 if (fFilteredColor != that->fFilteredColor) {
1759 return false;
1760 }
1761
1762 if (fUseBGR != that->fUseBGR) {
1763 return false;
1764 }
1765
1766 // TODO see note above
1767 if (kLCDDistanceField_MaskType == fMaskType && this->color() != that ->color()) {
1768 return false;
1769 }
1770 }
1771
1772 fBatch.fNumGlyphs += that->numGlyphs();
1773
1774 // Reallocate space for geo data if necessary and then import that's geo data.
1775 int newGeoCount = that->fGeoCount + fGeoCount;
1776 // We assume (and here enforce) that the allocation size is the smallest power of two that
1777 // is greater than or equal to the number of geometries (and at least
1778 // kMinGeometryAllocated).
1779 int newAllocSize = GrNextPow2(newGeoCount);
1780 int currAllocSize = SkTMax<int>(kMinGeometryAllocated, GrNextPow2(fGeoCo unt));
1781
1782 if (newGeoCount > currAllocSize) {
1783 fGeoData.realloc(newAllocSize);
1784 }
1785
1786 memcpy(&fGeoData[fGeoCount], that->fGeoData.get(), that->fGeoCount * siz eof(Geometry));
1787 // We steal the ref on the blobs from the other TextBatch and set its co unt to 0 so that
1788 // it doesn't try to unref them.
1789 #ifdef SK_DEBUG
1790 for (int i = 0; i < that->fGeoCount; ++i) {
1791 that->fGeoData.get()[i].fBlob = (Blob*)0x1;
1792 }
1793 #endif
1794 that->fGeoCount = 0;
1795 fGeoCount = newGeoCount;
1796
1797 this->joinBounds(that->bounds());
1798 return true;
1799 }
1800
1801 // TODO just use class params
1802 // TODO trying to figure out why lcd is so whack
1803 GrGeometryProcessor* setupDfProcessor(const SkMatrix& viewMatrix, SkColor fi lteredColor,
1804 GrColor color, GrTexture* texture) {
1805 GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kBile rp_FilterMode);
1806 bool isLCD = this->isLCD();
1807 // set up any flags
1808 uint32_t flags = viewMatrix.isSimilarity() ? kSimilarity_DistanceFieldEf fectFlag : 0;
1809
1810 // see if we need to create a new effect
1811 if (isLCD) {
1812 flags |= kUseLCD_DistanceFieldEffectFlag;
1813 flags |= viewMatrix.rectStaysRect() ? kRectToRect_DistanceFieldEffec tFlag : 0;
1814 flags |= fUseBGR ? kBGR_DistanceFieldEffectFlag : 0;
1815
1816 GrColor colorNoPreMul = skcolor_to_grcolor_nopremultiply(filteredCol or);
1817
1818 float redCorrection =
1819 (*fDistanceAdjustTable)[GrColorUnpackR(colorNoPreMul) >> kDistan ceAdjustLumShift];
1820 float greenCorrection =
1821 (*fDistanceAdjustTable)[GrColorUnpackG(colorNoPreMul) >> kDistan ceAdjustLumShift];
1822 float blueCorrection =
1823 (*fDistanceAdjustTable)[GrColorUnpackB(colorNoPreMul) >> kDistan ceAdjustLumShift];
1824 GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
1825 GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(redCorrectio n,
1826 greenCorrect ion,
1827 blueCorrecti on);
1828
1829 return GrDistanceFieldLCDTextGeoProc::Create(color,
1830 viewMatrix,
1831 texture,
1832 params,
1833 widthAdjust,
1834 flags,
1835 this->usesLocalCoords() );
1836 } else {
1837 flags |= kColorAttr_DistanceFieldEffectFlag;
1838 #ifdef SK_GAMMA_APPLY_TO_A8
1839 U8CPU lum = SkColorSpaceLuminance::computeLuminance(SK_GAMMA_EXPONEN T, filteredColor);
1840 float correction = (*fDistanceAdjustTable)[lum >> kDistanceAdjustLum Shift];
1841 return GrDistanceFieldA8TextGeoProc::Create(color,
1842 viewMatrix,
1843 texture,
1844 params,
1845 correction,
1846 flags,
1847 this->usesLocalCoords()) ;
1848 #else
1849 return GrDistanceFieldA8TextGeoProc::Create(color,
1850 viewMatrix,
1851 texture,
1852 params,
1853 flags,
1854 this->usesLocalCoords()) ;
1855 #endif
1856 }
1857
1858 }
1859
1860 struct BatchTracker {
1861 GrColor fColor;
1862 SkMatrix fViewMatrix;
1863 bool fUsesLocalCoords;
1864 bool fColorIgnored;
1865 bool fCoverageIgnored;
1866 int fNumGlyphs;
1867 };
1868
1869 BatchTracker fBatch;
1870 // The minimum number of Geometry we will try to allocate.
1871 enum { kMinGeometryAllocated = 4 };
1872 SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData;
1873 int fGeoCount;
1874
1875 enum MaskType {
1876 kGrayscaleCoverageMask_MaskType,
1877 kLCDCoverageMask_MaskType,
1878 kColorBitmapMask_MaskType,
1879 kGrayscaleDistanceField_MaskType,
1880 kLCDDistanceField_MaskType,
1881 } fMaskType;
1882 bool fUseBGR; // fold this into the enum?
1883
1884 GrBatchFontCache* fFontCache;
1885
1886 // Distance field properties
1887 SkAutoTUnref<const DistanceAdjustTable> fDistanceAdjustTable;
1888 SkColor fFilteredColor;
1889
1890 typedef GrVertexBatch INHERITED;
1891 };
1892
1893 void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* dc, GrRenderTarget* rt, 1212 void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* dc, GrRenderTarget* rt,
1894 const SkTextBlobRunIterator& it, 1213 const SkTextBlobRunIterator& it,
1895 const GrClip& clip, const SkPaint& skPa int, 1214 const GrClip& clip, const SkPaint& skPa int,
1896 SkDrawFilter* drawFilter, const SkMatri x& viewMatrix, 1215 SkDrawFilter* drawFilter, const SkMatri x& viewMatrix,
1897 const SkIRect& clipBounds, SkScalar x, SkScalar y) { 1216 const SkIRect& clipBounds, SkScalar x, SkScalar y) {
1898 SkPaint runPaint = skPaint; 1217 SkPaint runPaint = skPaint;
1899 1218
1900 size_t textLen = it.glyphCount() * sizeof(uint16_t); 1219 size_t textLen = it.glyphCount() * sizeof(uint16_t);
1901 const SkPoint& offset = it.offset(); 1220 const SkPoint& offset = it.offset();
1902 1221
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1935 const SkPaint& skPaint) { 1254 const SkPaint& skPaint) {
1936 GrMaskFormat format = info.fMaskFormat; 1255 GrMaskFormat format = info.fMaskFormat;
1937 GrColor subRunColor; 1256 GrColor subRunColor;
1938 if (kARGB_GrMaskFormat == format) { 1257 if (kARGB_GrMaskFormat == format) {
1939 uint8_t paintAlpha = skPaint.getAlpha(); 1258 uint8_t paintAlpha = skPaint.getAlpha();
1940 subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAl pha); 1259 subRunColor = SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAl pha);
1941 } else { 1260 } else {
1942 subRunColor = color; 1261 subRunColor = color;
1943 } 1262 }
1944 1263
1945 TextBatch* batch; 1264 GrAtlasTextBatch* batch;
1946 if (info.fDrawAsDistanceFields) { 1265 if (info.fDrawAsDistanceFields) {
1947 SkColor filteredColor; 1266 SkColor filteredColor;
1948 SkColorFilter* colorFilter = skPaint.getColorFilter(); 1267 SkColorFilter* colorFilter = skPaint.getColorFilter();
1949 if (colorFilter) { 1268 if (colorFilter) {
1950 filteredColor = colorFilter->filterColor(skPaint.getColor()); 1269 filteredColor = colorFilter->filterColor(skPaint.getColor());
1951 } else { 1270 } else {
1952 filteredColor = skPaint.getColor(); 1271 filteredColor = skPaint.getColor();
1953 } 1272 }
1954 bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry()); 1273 bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry());
1955 batch = TextBatch::CreateDistanceField(glyphCount, fContext->getBatchFon tCache(), 1274 batch = GrAtlasTextBatch::CreateDistanceField(glyphCount, fContext->getB atchFontCache(),
1956 fDistanceAdjustTable, filteredCol or, 1275 fDistanceAdjustTable, filt eredColor,
1957 info.fUseLCDText, useBGR); 1276 info.fUseLCDText, useBGR);
1958 } else { 1277 } else {
1959 batch = TextBatch::CreateBitmap(format, glyphCount, fContext->getBatchFo ntCache()); 1278 batch = GrAtlasTextBatch::CreateBitmap(format, glyphCount, fContext->get BatchFontCache());
1960 } 1279 }
1961 TextBatch::Geometry& geometry = batch->geometry(); 1280 GrAtlasTextBatch::Geometry& geometry = batch->geometry();
1962 geometry.fBlob = SkRef(cacheBlob); 1281 geometry.fBlob = SkRef(cacheBlob);
1963 geometry.fRun = run; 1282 geometry.fRun = run;
1964 geometry.fSubRun = subRun; 1283 geometry.fSubRun = subRun;
1965 geometry.fColor = subRunColor; 1284 geometry.fColor = subRunColor;
1966 geometry.fTransX = transX; 1285 geometry.fTransX = transX;
1967 geometry.fTransY = transY; 1286 geometry.fTransY = transY;
1968 batch->init(); 1287 batch->init();
1969 1288
1970 return batch; 1289 return batch;
1971 } 1290 }
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
2123 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat rix, text, 1442 gTextContext->createDrawTextBlob(rt, clip, grPaint, skPaint, viewMat rix, text,
2124 static_cast<size_t>(textLen), 0, 0, noClip)); 1443 static_cast<size_t>(textLen), 0, 0, noClip));
2125 1444
2126 SkScalar transX = static_cast<SkScalar>(random->nextU()); 1445 SkScalar transX = static_cast<SkScalar>(random->nextU());
2127 SkScalar transY = static_cast<SkScalar>(random->nextU()); 1446 SkScalar transY = static_cast<SkScalar>(random->nextU());
2128 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0] ; 1447 const GrAtlasTextBlob::Run::SubRunInfo& info = blob->fRuns[0].fSubRunInfo[0] ;
2129 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t ransY, skPaint); 1448 return gTextContext->createBatch(blob, info, textLen, 0, 0, color, transX, t ransY, skPaint);
2130 } 1449 }
2131 1450
2132 #endif 1451 #endif
OLDNEW
« no previous file with comments | « src/gpu/GrAtlasTextContext.h ('k') | src/gpu/GrTextContext.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698