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

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

Issue 1374853004: Fix caching of nvpr glyphs (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: MSVC warnings Created 5 years, 2 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/GrStencilAndCoverTextContext.h ('k') | src/gpu/batches/GrDrawPathBatch.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 2014 Google Inc. 2 * Copyright 2014 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 7
8 #include "GrStencilAndCoverTextContext.h" 8 #include "GrStencilAndCoverTextContext.h"
9 #include "GrAtlasTextContext.h" 9 #include "GrAtlasTextContext.h"
10 #include "GrDrawContext.h" 10 #include "GrDrawContext.h"
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
74 const GrClip& clip, 74 const GrClip& clip,
75 const GrPaint& paint, 75 const GrPaint& paint,
76 const SkPaint& skPaint, 76 const SkPaint& skPaint,
77 const SkMatrix& viewMatrix, 77 const SkMatrix& viewMatrix,
78 const char text[], 78 const char text[],
79 size_t byteLength, 79 size_t byteLength,
80 SkScalar x, SkScalar y, 80 SkScalar x, SkScalar y,
81 const SkIRect& clipBounds) { 81 const SkIRect& clipBounds) {
82 TextRun run(skPaint); 82 TextRun run(skPaint);
83 GrPipelineBuilder pipelineBuilder(paint, rt, clip); 83 GrPipelineBuilder pipelineBuilder(paint, rt, clip);
84 run.setText(text, byteLength, x, y, fContext, &fSurfaceProps); 84 run.setText(text, byteLength, x, y);
85 run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBound s, 85 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
86 fFallbackTextContext, skPaint); 86 fFallbackTextContext, skPaint);
87 } 87 }
88 88
89 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg et* rt, 89 void GrStencilAndCoverTextContext::onDrawPosText(GrDrawContext* dc, GrRenderTarg et* rt,
90 const GrClip& clip, 90 const GrClip& clip,
91 const GrPaint& paint, 91 const GrPaint& paint,
92 const SkPaint& skPaint, 92 const SkPaint& skPaint,
93 const SkMatrix& viewMatrix, 93 const SkMatrix& viewMatrix,
94 const char text[], 94 const char text[],
95 size_t byteLength, 95 size_t byteLength,
96 const SkScalar pos[], 96 const SkScalar pos[],
97 int scalarsPerPosition, 97 int scalarsPerPosition,
98 const SkPoint& offset, 98 const SkPoint& offset,
99 const SkIRect& clipBounds) { 99 const SkIRect& clipBounds) {
100 TextRun run(skPaint); 100 TextRun run(skPaint);
101 GrPipelineBuilder pipelineBuilder(paint, rt, clip); 101 GrPipelineBuilder pipelineBuilder(paint, rt, clip);
102 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset, fContext, &fSurfaceProps); 102 run.setPosText(text, byteLength, pos, scalarsPerPosition, offset);
103 run.draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBound s, 103 run.draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, 0, 0, clipBounds,
104 fFallbackTextContext, skPaint); 104 fFallbackTextContext, skPaint);
105 } 105 }
106 106
107 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarge t* rt, 107 void GrStencilAndCoverTextContext::drawTextBlob(GrDrawContext* dc, GrRenderTarge t* rt,
108 const GrClip& clip, const SkPain t& skPaint, 108 const GrClip& clip, const SkPain t& skPaint,
109 const SkMatrix& viewMatrix, 109 const SkMatrix& viewMatrix,
110 const SkTextBlob* skBlob, SkScal ar x, SkScalar y, 110 const SkTextBlob* skBlob, SkScal ar x, SkScalar y,
111 SkDrawFilter* drawFilter, 111 SkDrawFilter* drawFilter,
112 const SkIRect& clipBounds) { 112 const SkIRect& clipBounds) {
113 if (!this->internalCanDraw(skPaint)) { 113 if (!this->internalCanDraw(skPaint)) {
(...skipping 16 matching lines...) Expand all
130 GrPaint paint; 130 GrPaint paint;
131 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) { 131 if (!SkPaintToGrPaint(fContext, skPaint, viewMatrix, &paint)) {
132 return; 132 return;
133 } 133 }
134 134
135 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint); 135 const TextBlob& blob = this->findOrCreateTextBlob(skBlob, skPaint);
136 GrPipelineBuilder pipelineBuilder(paint, rt, clip); 136 GrPipelineBuilder pipelineBuilder(paint, rt, clip);
137 137
138 TextBlob::Iter iter(blob); 138 TextBlob::Iter iter(blob);
139 for (TextRun* run = iter.get(); run; run = iter.next()) { 139 for (TextRun* run = iter.get(); run; run = iter.next()) {
140 run->draw(dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clip Bounds, 140 run->draw(fContext, dc, &pipelineBuilder, paint.getColor(), viewMatrix, x, y, clipBounds,
141 fFallbackTextContext, skPaint); 141 fFallbackTextContext, skPaint);
142 run->releaseGlyphCache();
142 } 143 }
143 } 144 }
144 145
145 const GrStencilAndCoverTextContext::TextBlob& 146 const GrStencilAndCoverTextContext::TextBlob&
146 GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob, 147 GrStencilAndCoverTextContext::findOrCreateTextBlob(const SkTextBlob* skBlob,
147 const SkPaint& skPaint) { 148 const SkPaint& skPaint) {
148 // The font-related parameters are baked into the text blob and will overrid e this skPaint, so 149 // The font-related parameters are baked into the text blob and will overrid e this skPaint, so
149 // the only remaining properties that can affect a TextBlob are the ones rel ated to stroke. 150 // the only remaining properties that can affect a TextBlob are the ones rel ated to stroke.
150 if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path. 151 if (SkPaint::kFill_Style == skPaint.getStyle()) { // Fast path.
151 if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) { 152 if (TextBlob** found = fBlobIdCache.find(skBlob->uniqueID())) {
152 fLRUList.remove(*found); 153 fLRUList.remove(*found);
153 fLRUList.addToTail(*found); 154 fLRUList.addToTail(*found);
154 return **found; 155 return **found;
155 } 156 }
156 TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint, fCont ext, 157 TextBlob* blob = new TextBlob(skBlob->uniqueID(), skBlob, skPaint);
157 &fSurfaceProps);
158 this->purgeToFit(*blob); 158 this->purgeToFit(*blob);
159 fBlobIdCache.set(skBlob->uniqueID(), blob); 159 fBlobIdCache.set(skBlob->uniqueID(), blob);
160 fLRUList.addToTail(blob); 160 fLRUList.addToTail(blob);
161 fCacheSize += blob->cpuMemorySize(); 161 fCacheSize += blob->cpuMemorySize();
162 return *blob; 162 return *blob;
163 } else { 163 } else {
164 GrStrokeInfo stroke(skPaint); 164 GrStrokeInfo stroke(skPaint);
165 SkSTArray<4, uint32_t, true> key; 165 SkSTArray<4, uint32_t, true> key;
166 key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt()); 166 key.reset(1 + stroke.computeUniqueKeyFragmentData32Cnt());
167 key[0] = skBlob->uniqueID(); 167 key[0] = skBlob->uniqueID();
168 stroke.asUniqueKeyFragment(&key[1]); 168 stroke.asUniqueKeyFragment(&key[1]);
169 if (TextBlob** found = fBlobKeyCache.find(key)) { 169 if (TextBlob** found = fBlobKeyCache.find(key)) {
170 fLRUList.remove(*found); 170 fLRUList.remove(*found);
171 fLRUList.addToTail(*found); 171 fLRUList.addToTail(*found);
172 return **found; 172 return **found;
173 } 173 }
174 TextBlob* blob = new TextBlob(key, skBlob, skPaint, fContext, &fSurfaceP rops); 174 TextBlob* blob = new TextBlob(key, skBlob, skPaint);
175 this->purgeToFit(*blob); 175 this->purgeToFit(*blob);
176 fBlobKeyCache.set(blob); 176 fBlobKeyCache.set(blob);
177 fLRUList.addToTail(blob); 177 fLRUList.addToTail(blob);
178 fCacheSize += blob->cpuMemorySize(); 178 fCacheSize += blob->cpuMemorySize();
179 return *blob; 179 return *blob;
180 } 180 }
181 } 181 }
182 182
183 void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) { 183 void GrStencilAndCoverTextContext::purgeToFit(const TextBlob& blob) {
184 static const int maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for cac hing text blobs. 184 static const size_t maxCacheSize = 4 * 1024 * 1024; // Allow up to 4 MB for caching text blobs.
185 185
186 int maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize(); 186 size_t maxSizeForNewBlob = maxCacheSize - blob.cpuMemorySize();
187 while (fCacheSize && fCacheSize > maxSizeForNewBlob) { 187 while (fCacheSize && fCacheSize > maxSizeForNewBlob) {
188 TextBlob* lru = fLRUList.head(); 188 TextBlob* lru = fLRUList.head();
189 if (1 == lru->key().count()) { 189 if (1 == lru->key().count()) {
190 // 1-length keys are unterstood to be the blob id. 190 // 1-length keys are unterstood to be the blob id.
191 fBlobIdCache.remove(lru->key()[0]); 191 fBlobIdCache.remove(lru->key()[0]);
192 } else { 192 } else {
193 fBlobKeyCache.remove(lru->key()); 193 fBlobKeyCache.remove(lru->key());
194 } 194 }
195 fLRUList.remove(lru); 195 fLRUList.remove(lru);
196 fCacheSize -= lru->cpuMemorySize(); 196 fCacheSize -= lru->cpuMemorySize();
197 delete lru; 197 delete lru;
198 } 198 }
199 } 199 }
200 200
201 //////////////////////////////////////////////////////////////////////////////// //////////////////// 201 //////////////////////////////////////////////////////////////////////////////// ////////////////////
202 202
203 void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob, cons t SkPaint& skPaint, 203 void GrStencilAndCoverTextContext::TextBlob::init(const SkTextBlob* skBlob,
204 GrContext* ctx, const SkSurfac eProps* props) { 204 const SkPaint& skPaint) {
205 fCpuMemorySize = sizeof(TextBlob); 205 fCpuMemorySize = sizeof(TextBlob);
206 SkPaint runPaint(skPaint); 206 SkPaint runPaint(skPaint);
207 for (SkTextBlob::RunIterator iter(skBlob); !iter.done(); iter.next()) { 207 for (SkTextBlob::RunIterator iter(skBlob); !iter.done(); iter.next()) {
208 iter.applyFontToPaint(&runPaint); // No need to re-seed the paint. 208 iter.applyFontToPaint(&runPaint); // No need to re-seed the paint.
209 TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint)); 209 TextRun* run = SkNEW_INSERT_AT_LLIST_TAIL(this, TextRun, (runPaint));
210 210
211 const char* text = reinterpret_cast<const char*>(iter.glyphs()); 211 const char* text = reinterpret_cast<const char*>(iter.glyphs());
212 size_t byteLength = sizeof(uint16_t) * iter.glyphCount(); 212 size_t byteLength = sizeof(uint16_t) * iter.glyphCount();
213 const SkPoint& runOffset = iter.offset(); 213 const SkPoint& runOffset = iter.offset();
214 214
215 switch (iter.positioning()) { 215 switch (iter.positioning()) {
216 case SkTextBlob::kDefault_Positioning: 216 case SkTextBlob::kDefault_Positioning:
217 run->setText(text, byteLength, runOffset.fX, runOffset.fY, ctx, props); 217 run->setText(text, byteLength, runOffset.fX, runOffset.fY);
218 break; 218 break;
219 case SkTextBlob::kHorizontal_Positioning: 219 case SkTextBlob::kHorizontal_Positioning:
220 run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0 , runOffset.fY), 220 run->setPosText(text, byteLength, iter.pos(), 1, SkPoint::Make(0 , runOffset.fY));
221 ctx, props);
222 break; 221 break;
223 case SkTextBlob::kFull_Positioning: 222 case SkTextBlob::kFull_Positioning:
224 run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0 , 0), ctx, props); 223 run->setPosText(text, byteLength, iter.pos(), 2, SkPoint::Make(0 , 0));
225 break; 224 break;
226 } 225 }
227 226
228 fCpuMemorySize += run->cpuMemorySize(); 227 fCpuMemorySize += run->computeSizeInCache();
229 } 228 }
230 } 229 }
231 230
232 //////////////////////////////////////////////////////////////////////////////// //////////////////// 231 //////////////////////////////////////////////////////////////////////////////// ////////////////////
233 232
234 class GrStencilAndCoverTextContext::FallbackBlobBuilder { 233 class GrStencilAndCoverTextContext::FallbackBlobBuilder {
235 public: 234 public:
236 FallbackBlobBuilder() : fBuffIdx(0) {} 235 FallbackBlobBuilder() : fBuffIdx(0) {}
237 236
238 bool isInitialized() const { return SkToBool(fBuilder); } 237 bool isInitialized() const { return SkToBool(fBuilder); }
(...skipping 14 matching lines...) Expand all
253 int fBuffIdx; 252 int fBuffIdx;
254 uint16_t fGlyphIds[kWriteBufferSize]; 253 uint16_t fGlyphIds[kWriteBufferSize];
255 SkPoint fPositions[kWriteBufferSize]; 254 SkPoint fPositions[kWriteBufferSize];
256 }; 255 };
257 256
258 //////////////////////////////////////////////////////////////////////////////// //////////////////// 257 //////////////////////////////////////////////////////////////////////////////// ////////////////////
259 258
260 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke) 259 GrStencilAndCoverTextContext::TextRun::TextRun(const SkPaint& fontAndStroke)
261 : fStroke(fontAndStroke), 260 : fStroke(fontAndStroke),
262 fFont(fontAndStroke), 261 fFont(fontAndStroke),
263 fTotalGlyphCount(0) { 262 fTotalGlyphCount(0),
263 fDetachedGlyphCache(nullptr),
264 fLastDrawnGlyphsID(SK_InvalidUniqueID) {
264 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported. 265 SkASSERT(!fStroke.isHairlineStyle()); // Hairlines are not supported.
265 266
266 // Setting to "fill" ensures that no strokes get baked into font outlines. ( We use the GPU path 267 // Setting to "fill" ensures that no strokes get baked into font outlines. ( We use the GPU path
267 // rendering API for stroking). 268 // rendering API for stroking).
268 fFont.setStyle(SkPaint::kFill_Style); 269 fFont.setStyle(SkPaint::kFill_Style);
269 270
270 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle ()) { 271 if (fFont.isFakeBoldText() && SkStrokeRec::kStroke_Style != fStroke.getStyle ()) {
271 // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke. 272 // Instead of letting fake bold get baked into the glyph outlines, do it with GPU stroke.
272 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(), 273 SkScalar fakeBoldScale = SkScalarInterpFunc(fFont.getTextSize(),
273 kStdFakeBoldInterpKeys, 274 kStdFakeBoldInterpKeys,
(...skipping 26 matching lines...) Expand all
300 301
301 fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() && 302 fUsingRawGlyphPaths = SK_Scalar1 == fFont.getTextScaleX() &&
302 0 == fFont.getTextSkewX() && 303 0 == fFont.getTextSkewX() &&
303 !fFont.isFakeBoldText() && 304 !fFont.isFakeBoldText() &&
304 !fFont.isVerticalText(); 305 !fFont.isVerticalText();
305 } else { 306 } else {
306 fTextRatio = fTextInverseRatio = 1.0f; 307 fTextRatio = fTextInverseRatio = 1.0f;
307 fUsingRawGlyphPaths = false; 308 fUsingRawGlyphPaths = false;
308 } 309 }
309 310
311 // Generate the key that will be used to cache the GPU glyph path objects.
312 if (fUsingRawGlyphPaths && fStroke.isFillStyle()) {
313 static const GrUniqueKey::Domain kRawFillPathGlyphDomain = GrUniqueKey:: GenerateDomain();
314
315 const SkTypeface* typeface = fFont.getTypeface();
316 GrUniqueKey::Builder builder(&fGlyphPathsKey, kRawFillPathGlyphDomain, 1 );
317 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqueID( ) : 0;
318 } else {
319 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::Generat eDomain();
320
321 int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt();
322 if (fUsingRawGlyphPaths) {
323 const SkTypeface* typeface = fFont.getTypeface();
324 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain, 2 + strokeDataCount);
325 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu eID() : 0;
326 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount;
327 fStroke.asUniqueKeyFragment(&builder[2]);
328 } else {
329 SkGlyphCache* glyphCache = this->getGlyphCache();
330 const SkTypeface* typeface = glyphCache->getScalerContext()->getType face();
331 const SkDescriptor* desc = &glyphCache->getDescriptor();
332 int descDataCount = (desc->getLength() + 3) / 4;
333 GrUniqueKey::Builder builder(&fGlyphPathsKey, kPathGlyphDomain,
334 2 + strokeDataCount + descDataCount);
335 reinterpret_cast<uint32_t&>(builder[0]) = typeface ? typeface->uniqu eID() : 0;
336 reinterpret_cast<uint32_t&>(builder[1]) = strokeDataCount | (descDat aCount << 16);
337 fStroke.asUniqueKeyFragment(&builder[2]);
338 memcpy(&builder[2 + strokeDataCount], desc, desc->getLength());
339 }
340 }
341
310 // When drawing from canonically sized paths, the actual local coords are fT extRatio * coords. 342 // When drawing from canonically sized paths, the actual local coords are fT extRatio * coords.
311 fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio); 343 fLocalMatrixTemplate.setScale(fTextRatio, fTextRatio);
312 } 344 }
313 345
314 GrStencilAndCoverTextContext::TextRun::~TextRun() { 346 GrStencilAndCoverTextContext::TextRun::~TextRun() {
347 this->releaseGlyphCache();
315 } 348 }
316 349
317 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by teLength, 350 void GrStencilAndCoverTextContext::TextRun::setText(const char text[], size_t by teLength,
318 SkScalar x, SkScalar y, GrCo ntext* ctx, 351 SkScalar x, SkScalar y) {
319 const SkSurfaceProps* surfac eProps) {
320 SkASSERT(byteLength == 0 || text != nullptr); 352 SkASSERT(byteLength == 0 || text != nullptr);
321 353
322 SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr); 354 SkGlyphCache* glyphCache = this->getGlyphCache();
323 SkGlyphCache* glyphCache = autoGlyphCache.getCache(); 355 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
324 356
325 fTotalGlyphCount = fFont.countText(text, byteLength); 357 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor mType,
326 fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache), 358 fTotalGlyphCount = fFont.countText(text, byteLength)));
327 GrPathRendering::kTranslate_PathTransfor mType,
328 fTotalGlyphCount));
329
330 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
331 359
332 const char* stop = text + byteLength; 360 const char* stop = text + byteLength;
333 361
334 // Measure first if needed. 362 // Measure first if needed.
335 if (fFont.getTextAlign() != SkPaint::kLeft_Align) { 363 if (fFont.getTextAlign() != SkPaint::kLeft_Align) {
336 SkFixed stopX = 0; 364 SkFixed stopX = 0;
337 SkFixed stopY = 0; 365 SkFixed stopY = 0;
338 366
339 const char* textPtr = text; 367 const char* textPtr = text;
340 while (textPtr < stop) { 368 while (textPtr < stop) {
(...skipping 30 matching lines...) Expand all
371 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio); 399 fx += SkFixedMul(autokern.adjust(glyph), fixedSizeRatio);
372 if (glyph.fWidth) { 400 if (glyph.fWidth) {
373 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT oScalar(fy)), 401 this->appendGlyph(glyph, SkPoint::Make(SkFixedToScalar(fx), SkFixedT oScalar(fy)),
374 &fallback); 402 &fallback);
375 } 403 }
376 404
377 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio); 405 fx += SkFixedMul(glyph.fAdvanceX, fixedSizeRatio);
378 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio); 406 fy += SkFixedMul(glyph.fAdvanceY, fixedSizeRatio);
379 } 407 }
380 408
381 fDraw->loadGlyphPathsIfNeeded();
382
383 fFallbackTextBlob.reset(fallback.buildIfInitialized()); 409 fFallbackTextBlob.reset(fallback.buildIfInitialized());
384 } 410 }
385 411
386 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength, 412 void GrStencilAndCoverTextContext::TextRun::setPosText(const char text[], size_t byteLength,
387 const SkScalar pos[], int scalarsPerPosition, 413 const SkScalar pos[], int scalarsPerPosition,
388 const SkPoint& offset, Gr Context* ctx, 414 const SkPoint& offset) {
389 const SkSurfaceProps* sur faceProps) {
390 SkASSERT(byteLength == 0 || text != nullptr); 415 SkASSERT(byteLength == 0 || text != nullptr);
391 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition); 416 SkASSERT(1 == scalarsPerPosition || 2 == scalarsPerPosition);
392 417
393 SkAutoGlyphCacheNoGamma autoGlyphCache(fFont, surfaceProps, nullptr); 418 SkGlyphCache* glyphCache = this->getGlyphCache();
394 SkGlyphCache* glyphCache = autoGlyphCache.getCache(); 419 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
395 420
396 fTotalGlyphCount = fFont.countText(text, byteLength); 421 fDraw.reset(GrPathRangeDraw::Create(GrPathRendering::kTranslate_PathTransfor mType,
397 fDraw.reset(GrPathRangeDraw::Create(this->createGlyphs(ctx, glyphCache), 422 fTotalGlyphCount = fFont.countText(text, byteLength)));
398 GrPathRendering::kTranslate_PathTransfor mType,
399 fTotalGlyphCount));
400
401 SkDrawCacheProc glyphCacheProc = fFont.getDrawCacheProc();
402 423
403 const char* stop = text + byteLength; 424 const char* stop = text + byteLength;
404 425
405 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition); 426 SkTextMapStateProc tmsProc(SkMatrix::I(), offset, scalarsPerPosition);
406 SkTextAlignProc alignProc(fFont.getTextAlign()); 427 SkTextAlignProc alignProc(fFont.getTextAlign());
407 FallbackBlobBuilder fallback; 428 FallbackBlobBuilder fallback;
408 while (text < stop) { 429 while (text < stop) {
409 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0); 430 const SkGlyph& glyph = glyphCacheProc(glyphCache, &text, 0, 0);
410 if (glyph.fWidth) { 431 if (glyph.fWidth) {
411 SkPoint tmsLoc; 432 SkPoint tmsLoc;
412 tmsProc(pos, &tmsLoc); 433 tmsProc(pos, &tmsLoc);
413 SkPoint loc; 434 SkPoint loc;
414 alignProc(tmsLoc, glyph, &loc); 435 alignProc(tmsLoc, glyph, &loc);
415 436
416 this->appendGlyph(glyph, loc, &fallback); 437 this->appendGlyph(glyph, loc, &fallback);
417 } 438 }
418 pos += scalarsPerPosition; 439 pos += scalarsPerPosition;
419 } 440 }
420 441
421 fDraw->loadGlyphPathsIfNeeded();
422
423 fFallbackTextBlob.reset(fallback.buildIfInitialized()); 442 fFallbackTextBlob.reset(fallback.buildIfInitialized());
424 } 443 }
425 444
426 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx, 445 GrPathRange* GrStencilAndCoverTextContext::TextRun::createGlyphs(GrContext* ctx) const {
427 SkGlyphCache* g lyphCache) { 446 GrPathRange* glyphs = static_cast<GrPathRange*>(
428 SkTypeface* typeface = fUsingRawGlyphPaths ? fFont.getTypeface() 447 ctx->resourceProvider()->findAndRefResourceByUniqueKey(fGlyphPathsKe y));
429 : glyphCache->getScalerContext()- >getTypeface(); 448 if (nullptr == glyphs) {
430 const SkDescriptor* desc = fUsingRawGlyphPaths ? nullptr : &glyphCache->getD escriptor(); 449 if (fUsingRawGlyphPaths) {
431 450 glyphs = ctx->resourceProvider()->createGlyphs(fFont.getTypeface(), nullptr, fStroke);
432 static const GrUniqueKey::Domain kPathGlyphDomain = GrUniqueKey::GenerateDom ain(); 451 } else {
433 int strokeDataCount = fStroke.computeUniqueKeyFragmentData32Cnt(); 452 SkGlyphCache* cache = this->getGlyphCache();
434 GrUniqueKey glyphKey; 453 glyphs = ctx->resourceProvider()->createGlyphs(cache->getScalerConte xt()->getTypeface(),
435 GrUniqueKey::Builder builder(&glyphKey, kPathGlyphDomain, 2 + strokeDataCoun t); 454 &cache->getDescriptor (),
436 reinterpret_cast<uint32_t&>(builder[0]) = desc ? desc->getChecksum() : 0; 455 fStroke);
437 reinterpret_cast<uint32_t&>(builder[1]) = typeface ? typeface->uniqueID() : 0; 456 }
438 if (strokeDataCount > 0) { 457 ctx->resourceProvider()->assignUniqueKeyToResource(fGlyphPathsKey, glyph s);
439 fStroke.asUniqueKeyFragment(&builder[2]);
440 } 458 }
441 builder.finish(); 459 return glyphs;
442
443 SkAutoTUnref<GrPathRange> glyphs(
444 static_cast<GrPathRange*>(
445 ctx->resourceProvider()->findAndRefResourceByUniqueKey(glyphKey)));
446 if (nullptr == glyphs) {
447 glyphs.reset(ctx->resourceProvider()->createGlyphs(typeface, desc, fStro ke));
448 ctx->resourceProvider()->assignUniqueKeyToResource(glyphKey, glyphs);
449 } else {
450 SkASSERT(nullptr == desc || glyphs->isEqualTo(*desc));
451 }
452
453 return glyphs.detach();
454 } 460 }
455 461
456 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl yph, 462 inline void GrStencilAndCoverTextContext::TextRun::appendGlyph(const SkGlyph& gl yph,
457 const SkPoint& po s, 463 const SkPoint& po s,
458 FallbackBlobBuild er* fallback) { 464 FallbackBlobBuild er* fallback) {
459 // Stick the glyphs we can't draw into the fallback text blob. 465 // Stick the glyphs we can't draw into the fallback text blob.
460 if (SkMask::kARGB32_Format == glyph.fMaskFormat) { 466 if (SkMask::kARGB32_Format == glyph.fMaskFormat) {
461 if (!fallback->isInitialized()) { 467 if (!fallback->isInitialized()) {
462 fallback->init(fFont, fTextRatio); 468 fallback->init(fFont, fTextRatio);
463 } 469 }
464 fallback->appendGlyph(glyph.getGlyphID(), pos); 470 fallback->appendGlyph(glyph.getGlyphID(), pos);
465 } else { 471 } else {
466 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p os.y() }; 472 float translate[] = { fTextInverseRatio * pos.x(), fTextInverseRatio * p os.y() };
467 fDraw->append(glyph.getGlyphID(), translate); 473 fDraw->append(glyph.getGlyphID(), translate);
468 } 474 }
469 } 475 }
470 476
471 void GrStencilAndCoverTextContext::TextRun::draw(GrDrawContext* dc, 477 void GrStencilAndCoverTextContext::TextRun::draw(GrContext* ctx,
478 GrDrawContext* dc,
472 GrPipelineBuilder* pipelineBuil der, 479 GrPipelineBuilder* pipelineBuil der,
473 GrColor color, 480 GrColor color,
474 const SkMatrix& viewMatrix, 481 const SkMatrix& viewMatrix,
475 SkScalar x, SkScalar y, 482 SkScalar x, SkScalar y,
476 const SkIRect& clipBounds, 483 const SkIRect& clipBounds,
477 GrTextContext* fallbackTextCont ext, 484 GrTextContext* fallbackTextCont ext,
478 const SkPaint& originalSkPaint) const { 485 const SkPaint& originalSkPaint) const {
479 SkASSERT(fDraw); 486 SkASSERT(fDraw);
480 SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() | | 487 SkASSERT(pipelineBuilder->getRenderTarget()->isStencilBufferMultisampled() | |
481 !fFont.isAntiAlias()); 488 !fFont.isAntiAlias());
482 489
483 if (fDraw->count()) { 490 if (fDraw->count()) {
484 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is AntiAlias()); 491 pipelineBuilder->setState(GrPipelineBuilder::kHWAntialias_Flag, fFont.is AntiAlias());
485 492
486 GR_STATIC_CONST_SAME_STENCIL(kStencilPass, 493 GR_STATIC_CONST_SAME_STENCIL(kStencilPass,
487 kZero_StencilOp, 494 kZero_StencilOp,
488 kKeep_StencilOp, 495 kKeep_StencilOp,
489 kNotEqual_StencilFunc, 496 kNotEqual_StencilFunc,
490 0xffff, 497 0xffff,
491 0x0000, 498 0x0000,
492 0xffff); 499 0xffff);
493 500
494 *pipelineBuilder->stencil() = kStencilPass; 501 *pipelineBuilder->stencil() = kStencilPass;
495 502
503 SkAutoTUnref<GrPathRange> glyphs(this->createGlyphs(ctx));
504 if (fLastDrawnGlyphsID != glyphs->getUniqueID()) {
505 // Either this is the first draw or the glyphs object was purged sin ce last draw.
506 glyphs->loadPathsIfNeeded(fDraw->indices(), fDraw->count());
507 fLastDrawnGlyphsID = glyphs->getUniqueID();
508 }
509
496 SkMatrix drawMatrix(viewMatrix); 510 SkMatrix drawMatrix(viewMatrix);
497 drawMatrix.preTranslate(x, y); 511 drawMatrix.preTranslate(x, y);
498 drawMatrix.preScale(fTextRatio, fTextRatio); 512 drawMatrix.preScale(fTextRatio, fTextRatio);
499 513
500 SkMatrix& localMatrix = fLocalMatrixTemplate; 514 SkMatrix& localMatrix = fLocalMatrixTemplate;
501 localMatrix.setTranslateX(x); 515 localMatrix.setTranslateX(x);
502 localMatrix.setTranslateY(y); 516 localMatrix.setTranslateY(y);
503 517
504 dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color, fDraw, 518 dc->drawPathsFromRange(pipelineBuilder, drawMatrix, localMatrix, color, glyphs, fDraw,
505 GrPathRendering::kWinding_FillType); 519 GrPathRendering::kWinding_FillType);
506 } 520 }
507 521
508 if (fFallbackTextBlob) { 522 if (fFallbackTextBlob) {
509 SkPaint fallbackSkPaint(originalSkPaint); 523 SkPaint fallbackSkPaint(originalSkPaint);
510 fStroke.applyToPaint(&fallbackSkPaint); 524 fStroke.applyToPaint(&fallbackSkPaint);
511 if (!fStroke.isFillStyle()) { 525 if (!fStroke.isFillStyle()) {
512 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio); 526 fallbackSkPaint.setStrokeWidth(fStroke.getWidth() * fTextRatio);
513 } 527 }
514 528
515 fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget() , 529 fallbackTextContext->drawTextBlob(dc, pipelineBuilder->getRenderTarget() ,
516 pipelineBuilder->clip(), fallbackSkPai nt, viewMatrix, 530 pipelineBuilder->clip(), fallbackSkPai nt, viewMatrix,
517 fFallbackTextBlob, x, y, nullptr, clip Bounds); 531 fFallbackTextBlob, x, y, nullptr, clip Bounds);
518 } 532 }
519 } 533 }
520 534
521 int GrStencilAndCoverTextContext::TextRun::cpuMemorySize() const { 535 SkGlyphCache* GrStencilAndCoverTextContext::TextRun::getGlyphCache() const {
522 int size = sizeof(TextRun) + fTotalGlyphCount * (sizeof(uint16_t) + 2 * size of(float)); 536 if (!fDetachedGlyphCache) {
537 fDetachedGlyphCache = fFont.detachCache(nullptr, nullptr, true /*ignoreG amma*/);
538 }
539 return fDetachedGlyphCache;
540 }
541
542
543 void GrStencilAndCoverTextContext::TextRun::releaseGlyphCache() const {
544 if (fDetachedGlyphCache) {
545 SkGlyphCache::AttachCache(fDetachedGlyphCache);
546 fDetachedGlyphCache = nullptr;
547 }
548 }
549
550 size_t GrStencilAndCoverTextContext::TextRun::computeSizeInCache() const {
551 size_t size = sizeof(TextRun) +
552 fGlyphPathsKey.size() +
553 fTotalGlyphCount * (sizeof(uint16_t) + 2 * sizeof(float));
523 if (fDraw) { 554 if (fDraw) {
524 size += sizeof(GrPathRangeDraw); 555 size += sizeof(GrPathRangeDraw);
525 } 556 }
526 if (fFallbackTextBlob) { 557 if (fFallbackTextBlob) {
527 size += sizeof(SkTextBlob); 558 size += sizeof(SkTextBlob);
528 } 559 }
529 return size; 560 return size;
530 } 561 }
531 562
532 //////////////////////////////////////////////////////////////////////////////// //////////////////// 563 //////////////////////////////////////////////////////////////////////////////// ////////////////////
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
569 fBuffIdx = 0; 600 fBuffIdx = 0;
570 } 601 }
571 602
572 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInit ialized() { 603 const SkTextBlob* GrStencilAndCoverTextContext::FallbackBlobBuilder::buildIfInit ialized() {
573 if (!this->isInitialized()) { 604 if (!this->isInitialized()) {
574 return nullptr; 605 return nullptr;
575 } 606 }
576 this->flush(); 607 this->flush();
577 return fBuilder->build(); 608 return fBuilder->build();
578 } 609 }
OLDNEW
« no previous file with comments | « src/gpu/GrStencilAndCoverTextContext.h ('k') | src/gpu/batches/GrDrawPathBatch.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698