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

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: tweaks 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 static const SkScalar kMinDiscernableTranslation = 0.0625;
123 SkScalar transX = viewMatrix.getTranslateX() +
124 viewMatrix.getScaleX() * (x - blob.fX) +
125 viewMatrix.getSkewX() * (y - blob.fY) -
126 blob.fViewMatrix.getTranslateX();
127 SkScalar transY = viewMatrix.getTranslateY() +
128 viewMatrix.getSkewY() * (x - blob.fX) +
129 viewMatrix.getScaleY() * (y - blob.fY) -
130 blob.fViewMatrix.getTranslateY();
131 if (SkScalarFraction(transX) > kMinDiscernableTranslation ||
132 SkScalarFraction(transY) > kMinDiscernableTranslation) {
133 return true;
134 }
135
136 #ifdef SK_DEBUG
jvanverth1 2015/04/10 15:46:31 A comment on what this all means would be useful (
137 blob.fTotalXError += SkScalarAbs(SkScalarFraction(transX) - kMinDiscernableT ranslation);
138 blob.fTotalYError += SkScalarAbs(SkScalarFraction(transY) - kMinDiscernableT ranslation);
139 if (blob.fTotalXError > kMinDiscernableTranslation ||
140 blob.fTotalYError > kMinDiscernableTranslation) {
141 SkDebugf("Exceeding error threshold for bitmap text translation");
142 }
143 #endif
144 (*outTransX) = transX;
145 (*outTransY) = transY;
146 return false;
100 } 147 }
101 148
102 149
103 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run, 150 inline SkGlyphCache* GrAtlasTextContext::setupCache(BitmapTextBlob::Run* run,
104 const SkPaint& skPaint, 151 const SkPaint& skPaint,
105 const SkMatrix& viewMatrix) { 152 const SkMatrix& viewMatrix) {
106 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false); 153 skPaint.getScalerContextDescriptor(&run->fDescriptor, &fDeviceProperties, &v iewMatrix, false);
107 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface())); 154 run->fTypeface.reset(SkSafeRef(skPaint.getTypeface()));
108 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ; 155 return SkGlyphCache::DetachCache(run->fTypeface, run->fDescriptor.getDesc()) ;
109 } 156 }
110 157
111 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip, 158 void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, const GrClip& clip,
112 const SkPaint& skPaint, const SkMatrix& vi ewMatrix, 159 const SkPaint& skPaint, const SkMatrix& vi ewMatrix,
113 const SkTextBlob* blob, SkScalar x, SkScal ar y, 160 const SkTextBlob* blob, SkScalar x, SkScal ar y,
114 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) { 161 SkDrawFilter* drawFilter, const SkIRect& c lipBounds) {
115 uint32_t uniqueID = blob->uniqueID(); 162 uint32_t uniqueID = blob->uniqueID();
116 BitmapTextBlob* cacheBlob = fCache->find(uniqueID); 163 SkAutoTUnref<BitmapTextBlob> cacheBlob;
164 // TODO start caching these, mix bits into the key
165 bool canCache = !(skPaint.getPathEffect() ||
166 skPaint.getMaskFilter() ||
167 skPaint.getColorFilter() ||
168 skPaint.getStyle() != SkPaint::kFill_Style ||
169 drawFilter);
170
171 if (canCache) {
172 cacheBlob.reset(SkSafeRef(fCache->find(uniqueID)));
173 }
174
117 SkIRect clipRect; 175 SkIRect clipRect;
118 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect); 176 clip.getConservativeBounds(rt->width(), rt->height(), &clipRect);
119 177
178 SkScalar transX = 0.f;
179 SkScalar transY = 0.f;
180
120 if (cacheBlob) { 181 if (cacheBlob) {
121 if (MustRegenerateBlob(*cacheBlob, skPaint, viewMatrix, x, y)) { 182 if (MustRegenerateBlob(&transX, &transY, *cacheBlob, skPaint, viewMatrix , x, y)) {
122 // We have to remake the blob because changes may invalidate our mas ks. 183 // 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, 184 // 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 185 // but we'd have to clear the subrun information
125 fCache->remove(cacheBlob); 186 fCache->remove(cacheBlob);
126 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); 187 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
127 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter, 188 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, drawFilter,
128 clipRect); 189 clipRect);
129 } else { 190 } else {
191 // If we can reuse the blob, then make sure we update the blob's vie wmatrix and x/y
192 // offsets to reflect the results of any translations we may apply i n generateGeometry
193 cacheBlob->fViewMatrix = viewMatrix;
194 cacheBlob->fX = x;
195 cacheBlob->fY = y;
130 fCache->makeMRU(cacheBlob); 196 fCache->makeMRU(cacheBlob);
131 } 197 }
132 } else { 198 } else {
133 cacheBlob = fCache->createCachedBlob(blob, kGrayTextVASize); 199 if (canCache) {
200 cacheBlob.reset(SkRef(fCache->createCachedBlob(blob, kGrayTextVASize )));
201 } else {
202 cacheBlob.reset(fCache->createBlob(blob, kGrayTextVASize));
203 }
134 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect); 204 this->regenerateTextBlob(cacheBlob, skPaint, viewMatrix, blob, x, y, dra wFilter, clipRect);
135 } 205 }
136 206
137 // Though for the time being runs in the textblob can override the paint, th ey only touch font 207 // Though for the time being runs in the textblob can override the paint, th ey only touch font
138 // info. 208 // info.
139 GrPaint grPaint; 209 GrPaint grPaint;
140 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint); 210 SkPaint2GrPaintShader(fContext, rt, skPaint, viewMatrix, true, &grPaint);
141 211
142 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter, 212 this->flush(fContext->getTextTarget(), blob, cacheBlob, rt, skPaint, grPaint , drawFilter,
143 clip, viewMatrix, clipBounds, x, y); 213 clip, viewMatrix, clipBounds, x, y, transX, transY);
144 } 214 }
145 215
146 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob, 216 void GrAtlasTextContext::regenerateTextBlob(BitmapTextBlob* cacheBlob,
147 const SkPaint& skPaint, const SkMatr ix& viewMatrix, 217 const SkPaint& skPaint, const SkMatr ix& viewMatrix,
148 const SkTextBlob* blob, SkScalar x, SkScalar y, 218 const SkTextBlob* blob, SkScalar x, SkScalar y,
149 SkDrawFilter* drawFilter, const SkIR ect& clipRect) { 219 SkDrawFilter* drawFilter, const SkIR ect& clipRect) {
150 cacheBlob->fViewMatrix = viewMatrix; 220 cacheBlob->fViewMatrix = viewMatrix;
151 cacheBlob->fX = x; 221 cacheBlob->fX = x;
152 cacheBlob->fY = y; 222 cacheBlob->fY = y;
223 cacheBlob->fColor = skPaint.getColor();
153 cacheBlob->fStyle = skPaint.getStyle(); 224 cacheBlob->fStyle = skPaint.getStyle();
154 225
155 // Regenerate textblob 226 // Regenerate textblob
156 SkPaint runPaint = skPaint; 227 SkPaint runPaint = skPaint;
157 SkTextBlob::RunIterator it(blob); 228 SkTextBlob::RunIterator it(blob);
158 for (int run = 0; !it.done(); it.next(), run++) { 229 for (int run = 0; !it.done(); it.next(), run++) {
159 int glyphCount = it.glyphCount(); 230 int glyphCount = it.glyphCount();
160 size_t textLen = glyphCount * sizeof(uint16_t); 231 size_t textLen = glyphCount * sizeof(uint16_t);
161 const SkPoint& offset = it.offset(); 232 const SkPoint& offset = it.offset();
162 // applyFontToPaint() always overwrites the exact same attributes, 233 // applyFontToPaint() always overwrites the exact same attributes,
(...skipping 15 matching lines...) Expand all
178 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); 249 PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back();
179 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( ); 250 PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back( );
180 251
181 newRun.fVertexStartIndex = lastRun.fVertexEndIndex; 252 newRun.fVertexStartIndex = lastRun.fVertexEndIndex;
182 newRun.fVertexEndIndex = lastRun.fVertexEndIndex; 253 newRun.fVertexEndIndex = lastRun.fVertexEndIndex;
183 254
184 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; 255 newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex;
185 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; 256 newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex;
186 } 257 }
187 258
188 if (SkDraw::ShouldDrawTextAsPaths(skPaint, viewMatrix)) { 259 if (SkDraw::ShouldDrawTextAsPaths(runPaint, viewMatrix)) {
189 cacheBlob->fRuns[run].fDrawAsPaths = true; 260 cacheBlob->fRuns[run].fDrawAsPaths = true;
190 continue; 261 continue;
191 } 262 }
192 cacheBlob->fRuns[run].fDrawAsPaths = false; 263 cacheBlob->fRuns[run].fDrawAsPaths = false;
193 264
194 switch (it.positioning()) { 265 switch (it.positioning()) {
195 case SkTextBlob::kDefault_Positioning: 266 case SkTextBlob::kDefault_Positioning:
196 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix, 267 this->internalDrawText(cacheBlob, run, cache, runPaint, viewMatr ix,
197 (const char *)it.glyphs(), textLen, 268 (const char *)it.glyphs(), textLen,
198 x + offset.x(), y + offset.y(), clipRect) ; 269 x + offset.x(), y + offset.y(), clipRect) ;
(...skipping 330 matching lines...) Expand 10 before | Expand all | Expand 10 after
529 return; 600 return;
530 } 601 }
531 602
532 int x = vx + glyph->fBounds.fLeft; 603 int x = vx + glyph->fBounds.fLeft;
533 int y = vy + glyph->fBounds.fTop; 604 int y = vy + glyph->fBounds.fTop;
534 605
535 // keep them as ints until we've done the clip-test 606 // keep them as ints until we've done the clip-test
536 int width = glyph->fBounds.width(); 607 int width = glyph->fBounds.width();
537 int height = glyph->fBounds.height(); 608 int height = glyph->fBounds.height();
538 609
539 // check if we clipped out
jvanverth1 2015/04/10 15:46:31 I recall a discussion about removing this, but upo
540 if (clipRect.quickReject(x, y, x + width, y + height)) {
541 return;
542 }
543
544 // If the glyph is too large we fall back to paths 610 // If the glyph is too large we fall back to paths
545 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) { 611 if (fCurrStrike->glyphTooLargeForAtlas(glyph)) {
546 if (NULL == glyph->fPath) { 612 if (NULL == glyph->fPath) {
547 SkPath* path = SkNEW(SkPath); 613 SkPath* path = SkNEW(SkPath);
548 if (!scaler->getGlyphPath(glyph->glyphID(), path)) { 614 if (!scaler->getGlyphPath(glyph->glyphID(), path)) {
549 // flag the glyph as being dead? 615 // flag the glyph as being dead?
550 SkDELETE(path); 616 SkDELETE(path);
551 return; 617 return;
552 } 618 }
553 glyph->fPath = path; 619 glyph->fPath = path;
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex); 657 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVertices + subRun->fVert exEndIndex);
592 658
593 // V0 659 // V0
594 SkPoint* position = reinterpret_cast<SkPoint*>(vertex); 660 SkPoint* position = reinterpret_cast<SkPoint*>(vertex);
595 position->set(r.fLeft, r.fTop); 661 position->set(r.fLeft, r.fTop);
596 if (kA8_GrMaskFormat == format) { 662 if (kA8_GrMaskFormat == format) {
597 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 663 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
598 *colorPtr = color; 664 *colorPtr = color;
599 } 665 }
600 vertex += vertexStride; 666 vertex += vertexStride;
601
602 // V1 667 // V1
603 position = reinterpret_cast<SkPoint*>(vertex); 668 position = reinterpret_cast<SkPoint*>(vertex);
604 position->set(r.fLeft, r.fBottom); 669 position->set(r.fLeft, r.fBottom);
605 if (kA8_GrMaskFormat == format) { 670 if (kA8_GrMaskFormat == format) {
606 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ; 671 SkColor* colorPtr = reinterpret_cast<SkColor*>(vertex + sizeof(SkPoint)) ;
607 *colorPtr = color; 672 *colorPtr = color;
608 } 673 }
609 vertex += vertexStride; 674 vertex += vertexStride;
610 675
611 // V2 676 // V2
(...skipping 21 matching lines...) Expand all
633 public: 698 public:
634 typedef GrAtlasTextContext::BitmapTextBlob Blob; 699 typedef GrAtlasTextContext::BitmapTextBlob Blob;
635 typedef Blob::Run Run; 700 typedef Blob::Run Run;
636 typedef Run::SubRunInfo TextInfo; 701 typedef Run::SubRunInfo TextInfo;
637 struct Geometry { 702 struct Geometry {
638 Geometry() {} 703 Geometry() {}
639 Geometry(const Geometry& geometry) 704 Geometry(const Geometry& geometry)
640 : fBlob(SkRef(geometry.fBlob.get())) 705 : fBlob(SkRef(geometry.fBlob.get()))
641 , fRun(geometry.fRun) 706 , fRun(geometry.fRun)
642 , fSubRun(geometry.fSubRun) 707 , fSubRun(geometry.fSubRun)
643 , fColor(geometry.fColor) {} 708 , fColor(geometry.fColor)
709 , fTransX(geometry.fTransX)
710 , fTransY(geometry.fTransY) {}
644 SkAutoTUnref<Blob> fBlob; 711 SkAutoTUnref<Blob> fBlob;
645 int fRun; 712 int fRun;
646 int fSubRun; 713 int fSubRun;
647 GrColor fColor; 714 GrColor fColor;
715 SkScalar fTransX;
716 SkScalar fTransY;
648 }; 717 };
649 718
650 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat, 719 static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat,
651 int glyphCount, GrBatchFontCache* fontCache) { 720 int glyphCount, GrBatchFontCache* fontCache) {
652 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache)); 721 return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fo ntCache));
653 } 722 }
654 723
655 const char* name() const override { return "BitmapTextBatch"; } 724 const char* name() const override { return "BitmapTextBatch"; }
656 725
657 void getInvariantOutputColor(GrInitInvariantOutput* out) const override { 726 void getInvariantOutputColor(GrInitInvariantOutput* out) const override {
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
757 int instancesToFlush = 0; 826 int instancesToFlush = 0;
758 for (int i = 0; i < instanceCount; i++) { 827 for (int i = 0; i < instanceCount; i++) {
759 Geometry& args = fGeoData[i]; 828 Geometry& args = fGeoData[i];
760 Blob* blob = args.fBlob; 829 Blob* blob = args.fBlob;
761 Run& run = blob->fRuns[args.fRun]; 830 Run& run = blob->fRuns[args.fRun];
762 TextInfo& info = run.fSubRunInfo[args.fSubRun]; 831 TextInfo& info = run.fSubRunInfo[args.fSubRun];
763 832
764 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat); 833 uint64_t currentAtlasGen = fFontCache->atlasGeneration(fMaskFormat);
765 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen; 834 bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlas Gen;
766 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor; 835 bool regenerateColors = kA8_GrMaskFormat == fMaskFormat && run.fColo r != args.fColor;
836 bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0. f;
767 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 837 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
768 838
769 // We regenerate both texture coords and colors in the blob itself, and update the 839 // 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 840 // 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 841 // 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. 842 // 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 843 // 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 844 // 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 845 // 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 846 // should be pretty rare, so we just always regenerate in those case s
777 if (regenerateTextureCoords || regenerateColors) { 847 if (regenerateTextureCoords || regenerateColors || regeneratePositio ns) {
778 // first regenerate texture coordinates / colors if need be 848 // first regenerate texture coordinates / colors if need be
779 const SkDescriptor* desc = NULL; 849 const SkDescriptor* desc = NULL;
780 SkGlyphCache* cache = NULL; 850 SkGlyphCache* cache = NULL;
781 GrFontScaler* scaler = NULL; 851 GrFontScaler* scaler = NULL;
782 GrBatchTextStrike* strike = NULL; 852 GrBatchTextStrike* strike = NULL;
783 bool brokenRun = false; 853 bool brokenRun = false;
784 if (regenerateTextureCoords) { 854 if (regenerateTextureCoords) {
785 info.fBulkUseToken.reset(); 855 info.fBulkUseToken.reset();
786 desc = run.fDescriptor.getDesc(); 856 desc = run.fDescriptor.getDesc();
787 cache = SkGlyphCache::DetachCache(run.fTypeface, desc); 857 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); 891 this->regenerateTextureCoords(glyph, vertex, vertexStrid e);
822 } 892 }
823 893
824 if (regenerateColors) { 894 if (regenerateColors) {
825 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices); 895 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
826 vertex += info.fVertexStartIndex; 896 vertex += info.fVertexStartIndex;
827 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint); 897 vertex += vertexStride * glyphIdx * kVerticesPerGlyph + sizeof(SkPoint);
828 this->regenerateColors(vertex, vertexStride, args.fColor ); 898 this->regenerateColors(vertex, vertexStride, args.fColor );
829 } 899 }
830 900
901 if (regeneratePositions) {
902 intptr_t vertex = reinterpret_cast<intptr_t>(blob->fVert ices);
903 vertex += info.fVertexStartIndex;
904 vertex += vertexStride * glyphIdx * kVerticesPerGlyph;
905 SkScalar transX = args.fTransX;
906 SkScalar transY = args.fTransY;
907 this->regeneratePositions(vertex, vertexStride, transX, transY);
908 }
831 instancesToFlush++; 909 instancesToFlush++;
832 } 910 }
833 911
912 // We my have changed the color so update it here
913 run.fColor = args.fColor;
834 if (regenerateTextureCoords) { 914 if (regenerateTextureCoords) {
835 SkGlyphCache::AttachCache(cache); 915 SkGlyphCache::AttachCache(cache);
836 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration : 916 info.fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAt lasGeneration :
837 fFontCache->atlasGenerat ion(fMaskFormat); 917 fFontCache->atlasGenerat ion(fMaskFormat);
838 } 918 }
839 } else { 919 } else {
840 instancesToFlush += glyphCount; 920 instancesToFlush += glyphCount;
841 921
842 // set use tokens for all of the glyphs in our subrun. This is only valid if we 922 // set use tokens for all of the glyphs in our subrun. This is only valid if we
843 // have a valid atlas generation 923 // have a valid atlas generation
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 } 983 }
904 984
905 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) { 985 void regenerateColors(intptr_t vertex, size_t vertexStride, GrColor color) {
906 for (int i = 0; i < kVerticesPerGlyph; i++) { 986 for (int i = 0; i < kVerticesPerGlyph; i++) {
907 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex); 987 SkColor* vcolor = reinterpret_cast<SkColor*>(vertex);
908 *vcolor = color; 988 *vcolor = color;
909 vertex += vertexStride; 989 vertex += vertexStride;
910 } 990 }
911 } 991 }
912 992
993 void regeneratePositions(intptr_t vertex, size_t vertexStride, SkScalar tran sX,
994 SkScalar transY) {
995 for (int i = 0; i < kVerticesPerGlyph; i++) {
996 SkPoint* point = reinterpret_cast<SkPoint*>(vertex);
997 point->fX += transX;
998 point->fY += transY;
999 vertex += vertexStride;
1000 }
1001 }
1002
913 void initDraw(GrBatchTarget* batchTarget, 1003 void initDraw(GrBatchTarget* batchTarget,
914 const GrGeometryProcessor* gp, 1004 const GrGeometryProcessor* gp,
915 const GrPipeline* pipeline) { 1005 const GrPipeline* pipeline) {
916 batchTarget->initDraw(gp, pipeline); 1006 batchTarget->initDraw(gp, pipeline);
917 1007
918 // TODO remove this when batch is everywhere 1008 // TODO remove this when batch is everywhere
919 GrPipelineInfo init; 1009 GrPipelineInfo init;
920 init.fColorIgnored = fBatch.fColorIgnored; 1010 init.fColorIgnored = fBatch.fColorIgnored;
921 init.fOverrideColor = GrColor_ILLEGAL; 1011 init.fOverrideColor = GrColor_ILLEGAL;
922 init.fCoverageIgnored = fBatch.fCoverageIgnored; 1012 init.fCoverageIgnored = fBatch.fCoverageIgnored;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
1009 break; 1099 break;
1010 case SkTextBlob::kFull_Positioning: 1100 case SkTextBlob::kFull_Positioning:
1011 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (), 1101 this->drawPosTextAsPath(runPaint, viewMatrix, (const char*)it.glyphs (),
1012 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds); 1102 textLen, it.pos(), 2, SkPoint::Make(x, y), c lipBounds);
1013 break; 1103 break;
1014 } 1104 }
1015 } 1105 }
1016 1106
1017 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder, 1107 inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder * pipelineBuilder,
1018 BitmapTextBlob* cacheBlob, int run, GrC olor color, 1108 BitmapTextBlob* cacheBlob, int run, GrC olor color,
1019 uint8_t paintAlpha) { 1109 uint8_t paintAlpha, SkScalar transX, Sk Scalar transY) {
1020 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) { 1110 for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); sub Run++) {
1021 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; 1111 const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun];
1022 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; 1112 int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex;
1023 if (0 == glyphCount) { 1113 if (0 == glyphCount) {
1024 continue; 1114 continue;
1025 } 1115 }
1026 1116
1027 GrMaskFormat format = info.fMaskFormat; 1117 GrMaskFormat format = info.fMaskFormat;
1028 GrColor subRunColor = kARGB_GrMaskFormat == format ? 1118 GrColor subRunColor = kARGB_GrMaskFormat == format ?
1029 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) : 1119 SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) :
1030 color; 1120 color;
1031 1121
1032 BitmapTextBatch::Geometry geometry; 1122 BitmapTextBatch::Geometry geometry;
1033 geometry.fBlob.reset(SkRef(cacheBlob)); 1123 geometry.fBlob.reset(SkRef(cacheBlob));
1034 geometry.fRun = run; 1124 geometry.fRun = run;
1035 geometry.fSubRun = subRun; 1125 geometry.fSubRun = subRun;
1036 geometry.fColor = subRunColor; 1126 geometry.fColor = subRunColor;
1127 geometry.fTransX = transX;
1128 geometry.fTransY = transY;
1037 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount, 1129 SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, gl yphCount,
1038 fContext->getBatchFo ntCache())); 1130 fContext->getBatchFo ntCache()));
1039 1131
1040 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds); 1132 target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertex Bounds);
1041 } 1133 }
1042 } 1134 }
1043 1135
1044 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt, 1136 inline void GrAtlasTextContext::flushBigGlyphs(BitmapTextBlob* cacheBlob, GrRend erTarget* rt,
1045 const GrPaint& grPaint, const GrC lip& clip) { 1137 const GrPaint& grPaint, const GrC lip& clip,
1138 SkScalar transX, SkScalar transY) {
1046 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) { 1139 for (int i = 0; i < cacheBlob->fBigGlyphs.count(); i++) {
1047 const BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i]; 1140 BitmapTextBlob::BigGlyph& bigGlyph = cacheBlob->fBigGlyphs[i];
1141 bigGlyph.fVx += transX;
1142 bigGlyph.fVy += transY;
1048 SkMatrix translate; 1143 SkMatrix translate;
1049 translate.setTranslate(SkIntToScalar(bigGlyph.fVx), SkIntToScalar(bigGly ph.fVy)); 1144 translate.setTranslate(SkIntToScalar(bigGlyph.fVx),
1145 SkIntToScalar(bigGlyph.fVy));
1050 SkPath tmpPath(bigGlyph.fPath); 1146 SkPath tmpPath(bigGlyph.fPath);
1051 tmpPath.transform(translate); 1147 tmpPath.transform(translate);
1052 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); 1148 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
1053 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo ); 1149 fContext->drawPath(rt, clip, grPaint, SkMatrix::I(), tmpPath, strokeInfo );
1054 } 1150 }
1055 } 1151 }
1056 1152
1057 void GrAtlasTextContext::flush(GrDrawTarget* target, 1153 void GrAtlasTextContext::flush(GrDrawTarget* target,
1058 const SkTextBlob* blob, 1154 const SkTextBlob* blob,
1059 BitmapTextBlob* cacheBlob, 1155 BitmapTextBlob* cacheBlob,
1060 GrRenderTarget* rt, 1156 GrRenderTarget* rt,
1061 const SkPaint& skPaint, 1157 const SkPaint& skPaint,
1062 const GrPaint& grPaint, 1158 const GrPaint& grPaint,
1063 SkDrawFilter* drawFilter, 1159 SkDrawFilter* drawFilter,
1064 const GrClip& clip, 1160 const GrClip& clip,
1065 const SkMatrix& viewMatrix, 1161 const SkMatrix& viewMatrix,
1066 const SkIRect& clipBounds, 1162 const SkIRect& clipBounds,
1067 SkScalar x, 1163 SkScalar x, SkScalar y,
1068 SkScalar y) { 1164 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 1165 // We loop through the runs of the blob, flushing each. If any run is too l arge, then we flush
1070 // it as paths 1166 // it as paths
1071 GrPipelineBuilder pipelineBuilder; 1167 GrPipelineBuilder pipelineBuilder;
1072 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1168 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1073 1169
1074 GrColor color = grPaint.getColor(); 1170 GrColor color = grPaint.getColor();
1075 uint8_t paintAlpha = skPaint.getAlpha(); 1171 uint8_t paintAlpha = skPaint.getAlpha();
1076 1172
1077 SkTextBlob::RunIterator it(blob); 1173 SkTextBlob::RunIterator it(blob);
1078 for (int run = 0; !it.done(); it.next(), run++) { 1174 for (int run = 0; !it.done(); it.next(), run++) {
1079 if (cacheBlob->fRuns[run].fDrawAsPaths) { 1175 if (cacheBlob->fRuns[run].fDrawAsPaths) {
1080 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y); 1176 this->flushRunAsPaths(it, skPaint, drawFilter, viewMatrix, clipBound s, x, y);
1081 continue; 1177 continue;
1082 } 1178 }
1083 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1179 cacheBlob->fRuns[run].fVertexBounds.offset(transX, transY);
1180 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, transX, transY);
1084 } 1181 }
1085 1182
1086 // Now flush big glyphs 1183 // Now flush big glyphs
1087 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1184 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, transX, transY);
1088 } 1185 }
1089 1186
1090 void GrAtlasTextContext::flush(GrDrawTarget* target, 1187 void GrAtlasTextContext::flush(GrDrawTarget* target,
1091 BitmapTextBlob* cacheBlob, 1188 BitmapTextBlob* cacheBlob,
1092 GrRenderTarget* rt, 1189 GrRenderTarget* rt,
1093 const SkPaint& skPaint, 1190 const SkPaint& skPaint,
1094 const GrPaint& grPaint, 1191 const GrPaint& grPaint,
1095 const GrClip& clip, 1192 const GrClip& clip,
1096 const SkMatrix& viewMatrix) { 1193 const SkMatrix& viewMatrix) {
1097 GrPipelineBuilder pipelineBuilder; 1194 GrPipelineBuilder pipelineBuilder;
1098 pipelineBuilder.setFromPaint(grPaint, rt, clip); 1195 pipelineBuilder.setFromPaint(grPaint, rt, clip);
1099 1196
1100 GrColor color = grPaint.getColor(); 1197 GrColor color = grPaint.getColor();
1101 uint8_t paintAlpha = skPaint.getAlpha(); 1198 uint8_t paintAlpha = skPaint.getAlpha();
1102 for (int run = 0; run < cacheBlob->fRunCount; run++) { 1199 for (int run = 0; run < cacheBlob->fRunCount; run++) {
1103 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha); 1200 this->flushRun(target, &pipelineBuilder, cacheBlob, run, color, paintAlp ha, 0, 0);
1104 } 1201 }
1105 1202
1106 // Now flush big glyphs 1203 // Now flush big glyphs
1107 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip); 1204 this->flushBigGlyphs(cacheBlob, rt, grPaint, clip, 0, 0);
1108 } 1205 }
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