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

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

Issue 1062863002: Avoid regenerating cached textblobs on integer scrolls (Closed) Base URL: https://skia.googlesource.com/skia.git@atlastextcache
Patch Set: tweak 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 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
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(const BitmapTextBlob& blob, const Sk Paint& paint, 94 bool GrAtlasTextContext::MustRegenerateBlob(SkScalar* outTransX, SkScalar* outTr ansY,
95 const BitmapTextBlob& blob, const Sk Paint& paint,
95 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) { 96 const SkMatrix& viewMatrix, SkScalar x, SkScalar y) {
96 // We always regenerate blobs with patheffects or mask filters we could cach e these 97 // Color can affect the mask
97 // TODO find some way to cache the maskfilter / patheffects on the textblob 98 // TODO we can adjust the color within specific gamma slots
98 return !blob.fViewMatrix.cheapEqualTo(viewMatrix) || blob.fX != x || blob.fY != y || 99 if (blob.fColor != paint.getColor()) {
99 paint.getMaskFilter() || paint.getPathEffect() || paint.getStyle() ! = blob.fStyle; 100 return true;
101 }
102
103 if (blob.fViewMatrix.hasPerspective() != viewMatrix.hasPerspective()) {
104 return true;
105 }
106
107 if (blob.fViewMatrix.hasPerspective() && !blob.fViewMatrix.cheapEqualTo(view Matrix)) {
108 return true;
109 }
110
111 if (blob.fViewMatrix.getScaleX() != viewMatrix.getScaleX() ||
112 blob.fViewMatrix.getScaleY() != viewMatrix.getScaleY() ||
113 blob.fViewMatrix.getSkewX() != viewMatrix.getSkewX() ||
114 blob.fViewMatrix.getSkewY() != viewMatrix.getSkewY()) {
115 return true;
116 }
117
118 // We can update the positions in the cachedtextblobs without regenerating t he whole blob, but
119 // only for integer translations.
120 // 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
122 SkScalar transX = viewMatrix.getTranslateX() +
123 viewMatrix.getScaleX() * (x - blob.fX) +
124 viewMatrix.getSkewX() * (y - blob.fY) -
125 blob.fViewMatrix.getTranslateX();
126 SkScalar transY = viewMatrix.getTranslateY() +
127 viewMatrix.getSkewY() * (x - blob.fX) +
128 viewMatrix.getScaleY() * (y - blob.fY) -
129 blob.fViewMatrix.getTranslateY();
130 if (SkScalarFraction(transX) > SK_ScalarNearlyZero ||
131 SkScalarFraction(transY) > SK_ScalarNearlyZero) {
132 return true;
133 }
134
135 #ifdef SK_DEBUG
136 static const SkScalar kMinDiscernableTranslation = 0.0625;
137 // As a safeguard when debugging, we store the total error across all transl ations and print if
138 // the error becomes discernable. This is pretty unlikely to occur given th e tight bounds above
139 // on translation
140 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX));
141 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY));
142 if (blob.fTotalXError > kMinDiscernableTranslation ||
143 blob.fTotalYError > kMinDiscernableTranslation) {
144 SkDebugf("Exceeding error threshold for bitmap text translation");
145 }
146 #endif
147 (*outTransX) = transX;
148 (*outTransY) = transY;
149 return false;
100 } 150 }
101 151
102 152
103 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, 153 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run,
104 const SkPaint& skPaint, 154 const SkPaint& skPaint,
105 const SkMatrix& viewMatrix) { 155 const SkMatrix& viewMatrix) {
106 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); 156 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false);
107 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); 157 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
108 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; 158 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ;
109 } 159 }
110 160
111 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, 161 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
112 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, 162 const SkPaint& skPaint, const SkMatrix& vi ewMatrix,
113 const SkTextBlob* blob, SkScalar x, SkScal ar y, 163 const SkTextBlob* blob, SkScalar x, SkScal ar y,
114 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { 164 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) {
115 uint32_t uniqueID = blob->uniqueID(); 165 uint32_t uniqueID = blob->uniqueID();
116 BitmapTextBlob* cacheBlob = fCache->find(uniqueID); 166 SkAutoTUnref<BitmapTextBlob> cacheBlob;
167 // TODO start caching these, mix bits into the key
168 bool canCache = !(skPaint.getPathEffect() ||
169 skPaint.getMaskFilter() ||
170 skPaint.getColorFilter() ||
171 skPaint.getStyle() != SkPaint::kFill_Style ||
172 drawFilter);
173
174 if (canCache) {
175 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID)));
176 }
177
117 SkIRect clipRect; 178 SkIRect clipRect;
118 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 179 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
119 180
181 SkScalar transX = 0.f;
182 SkScalar transY = 0.f;
183
120 if (cacheBlob) { 184 if (cacheBlob) {
121 if (MustRegenerateBlob(*cacheBlob, skPaint, viewMatrix, x, y)) { 185 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix , x, y)) {
122 // We have to remake the blob because changes may invalidate our mas ks. 186 // We have to remake the blob because changes may invalidate our mas ks.
123 // TODO we could probably get away reuse most of the time if the poi nter is unique, 187 // TODO we could probably get away reuse most of the time if the poi nter is unique,
124 // but we'd have to clear the subrun information 188 // but we'd have to clear the subrun information
125 fCache->remove(cacheBlob); 189 fCache->remove(cacheBlob);
126 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); 190 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
127 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, 191 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
128 clipRect); 192 clipRect);
129 } else { 193 } else {
194 // 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
196 cacheBlob->fViewMatrix = viewMatrix;
197 cacheBlob->fX = x;
198 cacheBlob->fY = y;
130 fCache->makeMRU(cacheBlob); 199 fCache->makeMRU(cacheBlob);
131 } 200 }
132 } else { 201 } else {
133 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); 202 if (canCache) {
203 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
204 } else {
205 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
206 }
134 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); 207 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect);
135 } 208 }
136 209
137 // Though for the time being runs in the textblob can override the paint, th ey only touch font 210 // Though for the time being runs in the textblob can override the paint, th ey only touch font
138 // info. 211 // info.
139 GrPaint grPaint; 212 GrPaint grPaint;
140 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); 213 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
141 214
142 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, 215 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter,
143 clip, viewMatrix, clipBounds, x, y); 216 clip, viewMatrix, clipBounds, x, y, transX, transY);
144 } 217 }
145 218
146 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, 219 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
147 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 220 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
148 const SkTextBlob* blob, SkScalar x, SkScalar y, 221 const SkTextBlob* blob, SkScalar x, SkScalar y,
149 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { 222 SkDrawFilter* drawFilter, const SkIR ect& clipRect) {
150 cacheBlob->fViewMatrix = viewMatrix; 223 cacheBlob->fViewMatrix = viewMatrix;
151 cacheBlob->fX = x; 224 cacheBlob->fX = x;
152 cacheBlob->fY = y; 225 cacheBlob->fY = y;
226 cacheBlob->fColor = skPaint.getColor();
153 cacheBlob->fStyle = skPaint.getStyle(); 227 cacheBlob->fStyle = skPaint.getStyle();
154 228
155 // Regenerate textblob 229 // Regenerate textblob
156 SkPaint runPaint = skPaint; 230 SkPaint runPaint = skPaint;
157 SkTextBlob::RunIterator it(blob); 231 SkTextBlob::RunIterator it(blob);
158 for (int run = 0; !it.done(); it.next(), run++) { 232 for (int run = 0; !it.done(); it.next(), run++) {
159 int glyphCount = it.glyphCount(); 233 int glyphCount = it.glyphCount();
160 size_t textLen = glyphCount * sizeof(uint16_t); 234 size_t textLen = glyphCount * sizeof(uint16_t);
161 const SkPoint& offset = it.offset(); 235 const SkPoint& offset = it.offset();
162 // applyFontToPaint() always overwrites the exact same attributes, 236 // applyFontToPaint() always overwrites the exact same attributes,
(...skipping 15 matching lines...) Expand all
178 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); 252 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back();
179 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( ); 253 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( );
180 254
181 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; 255 newRun.fVertexStartIndex = lastRun.fVertexEndIndex;
182 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; 256 newRun.fVertexEndIndex = lastRun.fVertexEndIndex;
183 257
184 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; 258 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex;
185 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; 259 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex;
186 } 260 }
187 261
188 if (SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix)) { 262 if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
189 cacheBlob->fRuns[run].fDrawAsPaths = true; 263 cacheBlob->fRuns[run].fDrawAsPaths = true;
190 continue; 264 continue;
191 } 265 }
192 cacheBlob->fRuns[run].fDrawAsPaths = false; 266 cacheBlob->fRuns[run].fDrawAsPaths = false;
193 267
194 switch (it.positioning()) { 268 switch (it.positioning()) {
195 case SkTextBlob::kDefault_Positioning: 269 case SkTextBlob::kDefault_Positioning:
196 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix, 270 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix,
197 (const char *)it.glyphs(), textLen, 271 (const char *)it.glyphs(), textLen,
198 x + offset.x(), y + offset.y(), clipRect) ; 272 x + offset.x(), y + offset.y(), clipRect) ;
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 return; 603 return;
530 } 604 }
531 605
532 int x = vx + glyph->fBounds.fLeft; 606 int x = vx + glyph->fBounds.fLeft;
533 int y = vy + glyph->fBounds.fTop; 607 int y = vy + glyph->fBounds.fTop;
534 608
535 // keep them as ints until we've done the clip-test 609 // keep them as ints until we've done the clip-test
536 int width = glyph->fBounds.width(); 610 int width = glyph->fBounds.width();
537 int height = glyph->fBounds.height(); 611 int height = glyph->fBounds.height();
538 612
613 #if 0
614 // Not checking the clip bounds might introduce a performance regression. H owever, its not
615 // clear if this is still true today with the larger tiles we use in Chrome. For repositionable
616 // blobs, we want to make sure we have all of the glyphs, so clipping them o ut is not ideal.
617 // We could store the cliprect in the key, but then we'd lose the ability to do integer scrolls
618 // TODO verify this
539 // check if we clipped out 619 // check if we clipped out
540 if (clipRect.quickReject(x, y, x + width, y + height)) { 620 if (clipRect.quickReject(x, y, x + width, y + height)) {
541 return; 621 return;
542 } 622 }
623 #endif
543 624
544 // If the glyph is too large we fall back to paths 625 // If the glyph is too large we fall back to paths
545 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) { 626 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) {
546 if (NULL == glyph->fPath) { 627 if (NULL == glyph->fPath) {
547 SkPath* path = SkNEW(SkPath); 628 SkPath* path = SkNEW(SkPath);
548 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { 629 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
549 // flag the glyph as being dead? 630 // flag the glyph as being dead?
550 SkDELETE(path); 631 SkDELETE(path);
551 return; 632 return;
552 } 633 }
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex); 672 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex);
592 673
593 // V0 674 // V0
594 SkPoint* position = reinterpret_cast<SkPoint*>(vertex); 675 SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
595 position->set(r.fLeft, r.fTop); 676 position->set(r.fLeft, r.fTop);
596 if (kA8_GrMaskFormat == format) { 677 if (kA8_GrMaskFormat == format) {
597 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 678 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
598 *colorPtr = color; 679 *colorPtr = color;
599 } 680 }
600 vertex += vertexStride; 681 vertex += vertexStride;
601
602 // V1 682 // V1
603 position = reinterpret_cast<SkPoint*>(vertex); 683 position = reinterpret_cast<SkPoint*>(vertex);
604 position->set(r.fLeft, r.fBottom); 684 position->set(r.fLeft, r.fBottom);
605 if (kA8_GrMaskFormat == format) { 685 if (kA8_GrMaskFormat == format) {
606 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 686 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
607 *colorPtr = color; 687 *colorPtr = color;
608 } 688 }
609 vertex += vertexStride; 689 vertex += vertexStride;
610 690
611 // V2 691 // V2
(...skipping 21 matching lines...) Expand all
633 public: 713 public:
634 typedef GrAtlasTextContext::BitmapTextBlob Blob; 714 typedef GrAtlasTextContext::BitmapTextBlob Blob;
635 typedef Blob::Run Run; 715 typedef Blob::Run Run;
636 typedef Run::SubRunInfo TextInfo; 716 typedef Run::SubRunInfo TextInfo;
637 struct Geometry { 717 struct Geometry {
638 Geometry() {} 718 Geometry() {}
639 Geometry(const Geometry& geometry) 719 Geometry(const Geometry& geometry)
640 : fBlob(SkRef(geometry.fBlob.get())) 720 : fBlob(SkRef(geometry.fBlob.get()))
641 , fRun(geometry.fRun) 721 , fRun(geometry.fRun)
642 , fSubRun(geometry.fSubRun) 722 , fSubRun(geometry.fSubRun)
643 , fColor(geometry.fColor) {} 723 , fColor(geometry.fColor)
724 , fTransX(geometry.fTransX)
725 , fTransY(geometry.fTransY) {}
644 SkAutoTUnref<Blob> fBlob; 726 SkAutoTUnref<Blob> fBlob;
645 int fRun; 727 int fRun;
646 int fSubRun; 728 int fSubRun;
647 GrColor fColor; 729 GrColor fColor;
730 SkScalar fTransX;
731 SkScalar fTransY;
648 }; 732 };
649 733
650 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat, 734 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat,
651 int glyphCount, GrBatchFontCache* fontCache) { 735 int glyphCount, GrBatchFontCache* fontCache) {
652 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache)); 736 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache));
653 } 737 }
654 738
655 const char* name() const override { return "BitmapTextBatch"; } 739 const char* name() const override { return "BitmapTextBatch"; }
656 740
657 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 741 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 int instancesToFlush = 0; 841 int instancesToFlush = 0;
758 for (int i = 0; i < instanceCount; i++) { 842 for (int i = 0; i < instanceCount; i++) {
759 Geometry& args = fGeoData[i]; 843 Geometry& args = fGeoData[i];
760 Blob* blob = args.fBlob; 844 Blob* blob = args.fBlob;
761 Run& run = blob->fRuns[args.fRun]; 845 Run& run = blob->fRuns[args.fRun];
762 TextInfo& info = run.fSubRunInfo[args.fSubRun]; 846 TextInfo& info = run.fSubRunInfo[args.fSubRun];
763 847
764 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); 848 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat);
765 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen; 849 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen;
766 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor; 850 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor;
851 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0. f;
767 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 852 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
768 853
769 // We regenerate both texture coords and colors in the blob itself, and update the 854 // We regenerate both texture coords and colors in the blob itself, and update the
770 // atlas generation. If we don't end up purging any unused plots, w e can avoid 855 // atlas generation. If we don't end up purging any unused plots, w e can avoid
771 // regenerating the coords. We could take a finer grained approach to updating texture 856 // regenerating the coords. We could take a finer grained approach to updating texture
772 // coords but its not clear if the extra bookkeeping would offset an y gains. 857 // coords but its not clear if the extra bookkeeping would offset an y gains.
773 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color 858 // To avoid looping over the glyphs twice, we do one loop and condit ionally update color
774 // or coords as needed. One final note, if we have to break a run f or an atlas eviction 859 // or coords as needed. One final note, if we have to break a run f or an atlas eviction
775 // then we can't really trust the atlas has all of the correct data. Atlas evictions 860 // then we can't really trust the atlas has all of the correct data. Atlas evictions
776 // should be pretty rare, so we just always regenerate in those case s 861 // should be pretty rare, so we just always regenerate in those case s
777 if (regenerateTextureCoords || regenerateColors) { 862 if (regenerateTextureCoords || regenerateColors || regeneratePositio ns) {
778 // first regenerate texture coordinates / colors if need be 863 // first regenerate texture coordinates / colors if need be
779 const SkDescriptor* desc = NULL; 864 const SkDescriptor* desc = NULL;
780 SkGlyphCache* cache = NULL; 865 SkGlyphCache* cache = NULL;
781 GrFontScaler* scaler = NULL; 866 GrFontScaler* scaler = NULL;
782 GrBatchTextStrike* strike = NULL; 867 GrBatchTextStrike* strike = NULL;
783 bool brokenRun = false; 868 bool brokenRun = false;
784 if (regenerateTextureCoords) { 869 if (regenerateTextureCoords) {
785 info.fBulkUseToken.reset(); 870 info.fBulkUseToken.reset();
786 desc = run.fDescriptor.getDesc(); 871 desc = run.fDescriptor.getDesc();
787 cache = SkGlyphCache::DetachCache(run.fTypeface, desc); 872 cache = SkGlyphCache::DetachCache(run.fTypeface, desc);
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 this->regenerateTextureCoords(glyph, vertex, vertexStrid e); 906 this->regenerateTextureCoords(glyph, vertex, vertexStrid e);
822 } 907 }
823 908
824 if (regenerateColors) { 909 if (regenerateColors) {
825 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); 910 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
826 vertex += info.fVertexStartIndex; 911 vertex += info.fVertexStartIndex;
827 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); 912 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
828 this->regenerateColors(vertex, vertexStride, args.fColor ); 913 this->regenerateColors(vertex, vertexStride, args.fColor );
829 } 914 }
830 915
916 if (regeneratePositions) {
917 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
918 vertex += info.fVertexStartIndex;
919 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
920 SkScalar transX = args.fTransX;
921 SkScalar transY = args.fTransY;
922 this->regeneratePositions(vertex, vertexStride, transX, transY);
923 }
831 instancesToFlush++; 924 instancesToFlush++;
832 } 925 }
833 926
927 // We my have changed the color so update it here
928 run.fColor = args.fColor;
834 if (regenerateTextureCoords) { 929 if (regenerateTextureCoords) {
835 SkGlyphCache::AttachCache(cache); 930 SkGlyphCache::AttachCache(cache);
836 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration : 931 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration :
837 fFontCache->atlasGenerat ion(fMaskFormat); 932 fFontCache->atlasGenerat ion(fMaskFormat);
838 } 933 }
839 } else { 934 } else {
840 instancesToFlush += glyphCount; 935 instancesToFlush += glyphCount;
841 936
842 // set use tokens for all of the glyphs in our subrun. This is only valid if we 937 // set use tokens for all of the glyphs in our subrun. This is only valid if we
843 // have a valid atlas generation 938 // have a valid atlas generation
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 } 998 }
904 999
905 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { 1000 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
906 for (int i = 0; i < kVerticesPerGlyph; i++) { 1001 for (int i = 0; i < kVerticesPerGlyph; i++) {
907 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); 1002 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
908 *vcolor = color; 1003 *vcolor = color;
909 vertex += vertexStride; 1004 vertex += vertexStride;
910 } 1005 }
911 } 1006 }
912 1007
1008 void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar tran sX,
1009 SkScalar transY) {
1010 for (int i = 0; i < kVerticesPerGlyph; i++) {
1011 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
1012 point->fX += transX;
1013 point->fY += transY;
1014 vertex += vertexStride;
1015 }
1016 }
1017
913 void initDraw(GrBatchTarget* batchTarget, 1018 void initDraw(GrBatchTarget* batchTarget,
914 const GrGeometryProcessor* gp, 1019 const GrGeometryProcessor* gp,
915 const GrPipeline* pipeline) { 1020 const GrPipeline* pipeline) {
916 batchTarget->initDraw(gp, pipeline); 1021 batchTarget->initDraw(gp, pipeline);
917 1022
918 // TODO remove this when batch is everywhere 1023 // TODO remove this when batch is everywhere
919 GrPipelineInfo init; 1024 GrPipelineInfo init;
920 init.fColorIgnored = fBatch.fColorIgnored; 1025 init.fColorIgnored = fBatch.fColorIgnored;
921 init.fOverrideColor = GrColor_ILLEGAL; 1026 init.fOverrideColor = GrColor_ILLEGAL;
922 init.fCoverageIgnored = fBatch.fCoverageIgnored; 1027 init.fCoverageIgnored = fBatch.fCoverageIgnored;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 break; 1114 break;
1010 case SkTextBlob::kFull_Positioning: 1115 case SkTextBlob::kFull_Positioning:
1011 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (), 1116 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (),
1012 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds); 1117 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds);
1013 break; 1118 break;
1014 } 1119 }
1015 } 1120 }
1016 1121
1017 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder, 1122 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder,
1018 BitmapTextBlob* cacheBlob, int run, GrC olor color, 1123 BitmapTextBlob* cacheBlob, int run, GrC olor color,
1019 uint8_t paintAlpha) { 1124 uint8_t paintAlpha, SkScalar transX, Sk Scalar transY) {
1020 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) { 1125 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) {
1021 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; 1126 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun];
1022 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 1127 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
1023 if (0 == glyphCount) { 1128 if (0 == glyphCount) {
1024 continue; 1129 continue;
1025 } 1130 }
1026 1131
1027 GrMaskFormat format = info.fMaskFormat; 1132 GrMaskFormat format = info.fMaskFormat;
1028 GrColor subRunColor = kARGB_GrMaskFormat == format ? 1133 GrColor subRunColor = kARGB_GrMaskFormat == format ?
1029 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) : 1134 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) :
1030 color; 1135 color;
1031 1136
1032 BitmapTextBatch::Geometry geometry; 1137 BitmapTextBatch::Geometry geometry;
1033 geometry.fBlob.reset(SkRef(cacheBlob)); 1138 geometry.fBlob.reset(SkRef(cacheBlob));
1034 geometry.fRun = run; 1139 geometry.fRun = run;
1035 geometry.fSubRun = subRun; 1140 geometry.fSubRun = subRun;
1036 geometry.fColor = subRunColor; 1141 geometry.fColor = subRunColor;
1142 geometry.fTransX = transX;
1143 geometry.fTransY = transY;
1037 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount, 1144 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount,
1038 fContext->getBatchFo ntCache())); 1145 fContext->getBatchFo ntCache()));
1039 1146
1040 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds); 1147 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds);
1041 } 1148 }
1042 } 1149 }
1043 1150
1044 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt, 1151 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt,
1045 const GrPaint& grPaint, const GrC lip& clip) { 1152 const GrPaint& grPaint, const GrC lip& clip,
1153 SkScalar transX, SkScalar transY) {
1046 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { 1154 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) {
1047 const BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; 1155 BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i];
1156 bigGlyph.fVx += SkScalarTruncToInt(transX);
1157 bigGlyph.fVy += SkScalarTruncToInt(transY);
1048 SkMatrix translate; 1158 SkMatrix translate;
1049 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy)); 1159 translate.setTranslate(SkIntToScalar(bigGlyph.fVx),
1160 SkIntToScalar(bigGlyph.fVy));
1050 SkPath tmpPath(bigGlyph.fPath); 1161 SkPath tmpPath(bigGlyph.fPath);
1051 tmpPath.transform(translate); 1162 tmpPath.transform(translate);
1052 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); 1163 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
1053 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo ); 1164 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo );
1054 } 1165 }
1055 } 1166 }
1056 1167
1057 void GrAtlasTextContext::flush(GrDrawTarget* target, 1168 void GrAtlasTextContext::flush(GrDrawTarget* target,
1058 const SkTextBlob* blob, 1169 const SkTextBlob* blob,
1059 BitmapTextBlob* cacheBlob, 1170 BitmapTextBlob* cacheBlob,
1060 GrRenderTarget* rt, 1171 GrRenderTarget* rt,
1061 const SkPaint& skPaint, 1172 const SkPaint& skPaint,
1062 const GrPaint& grPaint, 1173 const GrPaint& grPaint,
1063 SkDrawFilter* drawFilter, 1174 SkDrawFilter* drawFilter,
1064 const GrClip& clip, 1175 const GrClip& clip,
1065 const SkMatrix& viewMatrix, 1176 const SkMatrix& viewMatrix,
1066 const SkIRect& clipBounds, 1177 const SkIRect& clipBounds,
1067 SkScalar x, 1178 SkScalar x, SkScalar y,
1068 SkScalar y) { 1179 SkScalar transX, SkScalar transY) {
1069 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush 1180 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush
1070 // it as paths 1181 // it as paths
1071 GrPipelineBuilder pipelineBuilder; 1182 GrPipelineBuilder pipelineBuilder;
1072 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1183 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1073 1184
1074 GrColor color = grPaint.getColor(); 1185 GrColor color = grPaint.getColor();
1075 uint8_t paintAlpha = skPaint.getAlpha(); 1186 uint8_t paintAlpha = skPaint.getAlpha();
1076 1187
1077 SkTextBlob::RunIterator it(blob); 1188 SkTextBlob::RunIterator it(blob);
1078 for (int run = 0; !it.done(); it.next(), run++) { 1189 for (int run = 0; !it.done(); it.next(), run++) {
1079 if (cacheBlob->fRuns[run].fDrawAsPaths) { 1190 if (cacheBlob->fRuns[run].fDrawAsPaths) {
1080 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y); 1191 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y);
1081 continue; 1192 continue;
1082 } 1193 }
1083 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1194 cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
1195 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, transX, transY);
1084 } 1196 }
1085 1197
1086 // Now flush big glyphs 1198 // Now flush big glyphs
1087 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1199 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, transX, transY);
1088 } 1200 }
1089 1201
1090 void GrAtlasTextContext::flush(GrDrawTarget* target, 1202 void GrAtlasTextContext::flush(GrDrawTarget* target,
1091 BitmapTextBlob* cacheBlob, 1203 BitmapTextBlob* cacheBlob,
1092 GrRenderTarget* rt, 1204 GrRenderTarget* rt,
1093 const SkPaint& skPaint, 1205 const SkPaint& skPaint,
1094 const GrPaint& grPaint, 1206 const GrPaint& grPaint,
1095 const GrClip& clip, 1207 const GrClip& clip,
1096 const SkMatrix& viewMatrix) { 1208 const SkMatrix& viewMatrix) {
1097 GrPipelineBuilder pipelineBuilder; 1209 GrPipelineBuilder pipelineBuilder;
1098 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1210 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1099 1211
1100 GrColor color = grPaint.getColor(); 1212 GrColor color = grPaint.getColor();
1101 uint8_t paintAlpha = skPaint.getAlpha(); 1213 uint8_t paintAlpha = skPaint.getAlpha();
1102 for (int run = 0; run < cacheBlob->fRunCount; run++) { 1214 for (int run = 0; run < cacheBlob->fRunCount; run++) {
1103 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1215 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0);
1104 } 1216 }
1105 1217
1106 // Now flush big glyphs 1218 // Now flush big glyphs
1107 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1219 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0);
1108 } 1220 }
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