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

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

Issue 663423003: Allocate only the vertices we need for text. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrBitmapTextContext.h ('k') | src/gpu/GrDistanceFieldTextContext.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 2013 Google Inc. 2 * Copyright 2013 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 "GrBitmapTextContext.h" 8 #include "GrBitmapTextContext.h"
9 #include "GrAtlas.h" 9 #include "GrAtlas.h"
10 #include "GrDrawTarget.h" 10 #include "GrDrawTarget.h"
(...skipping 29 matching lines...) Expand all
40 40
41 static const size_t kTextVASize = 2 * sizeof(SkPoint); 41 static const size_t kTextVASize = 2 * sizeof(SkPoint);
42 42
43 // position + color + texture coord 43 // position + color + texture coord
44 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { 44 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
45 {kVec2f_GrVertexAttribType, 0, kPosition_Gr VertexAttribBinding}, 45 {kVec2f_GrVertexAttribType, 0, kPosition_Gr VertexAttribBinding},
46 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer texAttribBinding}, 46 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer texAttribBinding},
47 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryPro cessor_GrVertexAttribBinding} 47 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryPro cessor_GrVertexAttribBinding}
48 }; 48 };
49 49
50 static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor); 50 static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
51 51
52 static const int kVerticesPerGlyph = 4;
53 static const int kIndicesPerGlyph = 6;
52 }; 54 };
53 55
54 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, 56 GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
55 const SkDeviceProperties& properties) 57 const SkDeviceProperties& properties)
56 : GrTextContext(context, properties) { 58 : GrTextContext(context, properties) {
57 fStrike = NULL; 59 fStrike = NULL;
58 60
59 fCurrTexture = NULL; 61 fCurrTexture = NULL;
60 fCurrVertex = 0;
61 fEffectTextureUniqueID = SK_InvalidUniqueID; 62 fEffectTextureUniqueID = SK_InvalidUniqueID;
62 63
63 fVertices = NULL; 64 fVertices = NULL;
64 fMaxVertices = 0; 65 fCurrVertex = 0;
66 fAllocVertexCount = 0;
67 fTotalVertexCount = 0;
65 68
66 fVertexBounds.setLargestInverted(); 69 fVertexBounds.setLargestInverted();
67 } 70 }
68 71
69 GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context, 72 GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
70 const SkDeviceProperties& props ) { 73 const SkDeviceProperties& props ) {
71 return SkNEW_ARGS(GrBitmapTextContext, (context, props)); 74 return SkNEW_ARGS(GrBitmapTextContext, (context, props));
72 } 75 }
73 76
74 GrBitmapTextContext::~GrBitmapTextContext() { 77 GrBitmapTextContext::~GrBitmapTextContext() {
75 this->flush(); 78 this->finish();
76 } 79 }
77 80
78 bool GrBitmapTextContext::canDraw(const SkPaint& paint) { 81 bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
79 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix()); 82 return !SkDraw::ShouldDrawTextAsPaths(paint, fContext->getMatrix());
80 } 83 }
81 84
82 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai nt) { 85 inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai nt) {
83 GrTextContext::init(paint, skPaint); 86 GrTextContext::init(paint, skPaint);
84 87
85 fStrike = NULL; 88 fStrike = NULL;
86 89
87 fCurrTexture = NULL; 90 fCurrTexture = NULL;
88 fCurrVertex = 0; 91 fCurrVertex = 0;
89 92
90 fVertices = NULL; 93 fVertices = NULL;
91 fMaxVertices = 0; 94 fAllocVertexCount = 0;
95 fTotalVertexCount = 0;
92 } 96 }
93 97
94 void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain t, 98 void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain t,
95 const char text[], size_t byteLength, 99 const char text[], size_t byteLength,
96 SkScalar x, SkScalar y) { 100 SkScalar x, SkScalar y) {
97 SkASSERT(byteLength == 0 || text != NULL); 101 SkASSERT(byteLength == 0 || text != NULL);
98 102
99 // nothing to draw 103 // nothing to draw
100 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) { 104 if (text == NULL || byteLength == 0 /*|| fRC->isEmpty()*/) {
101 return; 105 return;
102 } 106 }
103 107
104 this->init(paint, skPaint); 108 this->init(paint, skPaint);
105 109
106 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc(); 110 SkDrawCacheProc glyphCacheProc = fSkPaint.getDrawCacheProc();
107 111
108 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa trix()); 112 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa trix());
109 SkGlyphCache* cache = autoCache.getCache(); 113 SkGlyphCache* cache = autoCache.getCache();
110 GrFontScaler* fontScaler = GetGrFontScaler(cache); 114 GrFontScaler* fontScaler = GetGrFontScaler(cache);
111 115
112 // transform our starting point 116 // transform our starting point
113 { 117 {
114 SkPoint loc; 118 SkPoint loc;
115 fContext->getMatrix().mapXY(x, y, &loc); 119 fContext->getMatrix().mapXY(x, y, &loc);
116 x = loc.fX; 120 x = loc.fX;
117 y = loc.fY; 121 y = loc.fY;
118 } 122 }
119 123
120 // need to measure first 124 // need to measure first
125 int numGlyphs;
121 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) { 126 if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
122 SkVector stop; 127 SkVector stopVector;
128 numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVe ctor);
123 129
124 MeasureText(cache, glyphCacheProc, text, byteLength, &stop); 130 SkScalar stopX = stopVector.fX;
125 131 SkScalar stopY = stopVector.fY;
126 SkScalar stopX = stop.fX;
127 SkScalar stopY = stop.fY;
128 132
129 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) { 133 if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
130 stopX = SkScalarHalf(stopX); 134 stopX = SkScalarHalf(stopX);
131 stopY = SkScalarHalf(stopY); 135 stopY = SkScalarHalf(stopY);
132 } 136 }
133 x -= stopX; 137 x -= stopX;
134 y -= stopY; 138 y -= stopY;
139 } else {
140 numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
135 } 141 }
142 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
136 143
137 const char* stop = text + byteLength; 144 const char* stop = text + byteLength;
138 145
139 SkAutoKern autokern; 146 SkAutoKern autokern;
140 147
141 SkFixed fxMask = ~0; 148 SkFixed fxMask = ~0;
142 SkFixed fyMask = ~0; 149 SkFixed fyMask = ~0;
143 SkFixed halfSampleX, halfSampleY; 150 SkFixed halfSampleX, halfSampleY;
144 if (cache->isSubpixel()) { 151 if (cache->isSubpixel()) {
145 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits); 152 halfSampleX = halfSampleY = (SK_FixedHalf >> SkGlyph::kSubBits);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
200 207
201 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa trix()); 208 SkAutoGlyphCache autoCache(fSkPaint, &fDeviceProperties, &fContext->getMa trix());
202 SkGlyphCache* cache = autoCache.getCache(); 209 SkGlyphCache* cache = autoCache.getCache();
203 GrFontScaler* fontScaler = GetGrFontScaler(cache); 210 GrFontScaler* fontScaler = GetGrFontScaler(cache);
204 211
205 // store original matrix before we reset, so we can use it to transform posi tions 212 // store original matrix before we reset, so we can use it to transform posi tions
206 SkMatrix ctm = fContext->getMatrix(); 213 SkMatrix ctm = fContext->getMatrix();
207 GrContext::AutoMatrix autoMatrix; 214 GrContext::AutoMatrix autoMatrix;
208 autoMatrix.setIdentity(fContext, &fPaint); 215 autoMatrix.setIdentity(fContext, &fPaint);
209 216
217 int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
218 fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
219
210 const char* stop = text + byteLength; 220 const char* stop = text + byteLength;
211 SkTextAlignProc alignProc(fSkPaint.getTextAlign()); 221 SkTextAlignProc alignProc(fSkPaint.getTextAlign());
212 SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition); 222 SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition);
213 SkFixed halfSampleX = 0, halfSampleY = 0; 223 SkFixed halfSampleX = 0, halfSampleY = 0;
214 224
215 if (cache->isSubpixel()) { 225 if (cache->isSubpixel()) {
216 // maybe we should skip the rounding if linearText is set 226 // maybe we should skip the rounding if linearText is set
217 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm); 227 SkAxisAlignment baseline = SkComputeAxisAlignmentForHText(ctm);
218 228
219 SkFixed fxMask = ~0; 229 SkFixed fxMask = ~0;
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
328 fontScaler); 338 fontScaler);
329 } 339 }
330 pos += scalarsPerPosition; 340 pos += scalarsPerPosition;
331 } 341 }
332 } 342 }
333 } 343 }
334 344
335 this->finish(); 345 this->finish();
336 } 346 }
337 347
348 static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useC olorVerts) {
349 if (numVertices <= 0) {
350 return NULL;
351 }
352
353 // set up attributes
354 if (useColorVerts) {
355 drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
356 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
357 } else {
358 drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
359 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVAS ize);
360 }
361 void* vertices = NULL;
362 bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
363 0,
364 &vertices,
365 NULL);
366 GrAlwaysAssert(success);
367 return vertices;
368 }
369
338 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed, 370 void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
339 SkFixed vx, SkFixed vy, 371 SkFixed vx, SkFixed vy,
340 GrFontScaler* scaler) { 372 GrFontScaler* scaler) {
341 if (NULL == fDrawTarget) { 373 if (NULL == fDrawTarget) {
342 return; 374 return;
343 } 375 }
344 376
345 if (NULL == fStrike) { 377 if (NULL == fStrike) {
346 fStrike = fContext->getFontCache()->getStrike(scaler, false); 378 fStrike = fContext->getFontCache()->getStrike(scaler, false);
347 } 379 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
411 this->flush(); 443 this->flush();
412 444
413 GrContext::AutoMatrix am; 445 GrContext::AutoMatrix am;
414 SkMatrix translate; 446 SkMatrix translate;
415 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds. fLeft)), 447 translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds. fLeft)),
416 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds. fTop))); 448 SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds. fTop)));
417 GrPaint tmpPaint(fPaint); 449 GrPaint tmpPaint(fPaint);
418 am.setPreConcat(fContext, translate, &tmpPaint); 450 am.setPreConcat(fContext, translate, &tmpPaint);
419 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle); 451 GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
420 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo); 452 fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
453
454 // remove this glyph from the vertices we need to allocate
455 fTotalVertexCount -= kVerticesPerGlyph;
421 return; 456 return;
422 } 457 }
423 458
424 HAS_ATLAS: 459 HAS_ATLAS:
425 SkASSERT(glyph->fPlot); 460 SkASSERT(glyph->fPlot);
426 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); 461 GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken();
427 glyph->fPlot->setDrawToken(drawToken); 462 glyph->fPlot->setDrawToken(drawToken);
428 463
429 // now promote them to fixed (TODO: Rethink using fixed pt). 464 // now promote them to fixed (TODO: Rethink using fixed pt).
430 width = SkIntToFixed(width); 465 width = SkIntToFixed(width);
431 height = SkIntToFixed(height); 466 height = SkIntToFixed(height);
432 467
433 // the current texture/maskformat must match what the glyph needs 468 // the current texture/maskformat must match what the glyph needs
434 GrTexture* texture = glyph->fPlot->texture(); 469 GrTexture* texture = glyph->fPlot->texture();
435 SkASSERT(texture); 470 SkASSERT(texture);
436 471
437 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { 472 if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVerte xCount) {
438 this->flush(); 473 this->flush();
439 fCurrTexture = texture; 474 fCurrTexture = texture;
440 fCurrTexture->ref(); 475 fCurrTexture->ref();
441 fCurrMaskFormat = glyph->fMaskFormat; 476 fCurrMaskFormat = glyph->fMaskFormat;
442 } 477 }
443 478
444 bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat; 479 bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat;
445 480
446 if (NULL == fVertices) { 481 if (NULL == fVertices) {
447 // If we need to reserve vertices allow the draw target to suggest 482 int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer() ->maxQuads();
448 // a number of verts to reserve and whether to perform a flush. 483 fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
449 fMaxVertices = kMinRequestedVerts; 484 fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts );
450 if (useColorVerts) {
451 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri bs>(
452 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
453 } else {
454 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
455 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
456 }
457 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
458 if (flush) {
459 this->flush();
460 fContext->flush();
461 if (useColorVerts) {
462 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA ttribs>(
463 SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSiz e);
464 } else {
465 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
466 SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
467 }
468 }
469 fMaxVertices = kDefaultRequestedVerts;
470 // ignore return, no point in flushing again.
471 fDrawTarget->geometryHints(&fMaxVertices, NULL);
472
473 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads();
474 if (fMaxVertices < kMinRequestedVerts) {
475 fMaxVertices = kDefaultRequestedVerts;
476 } else if (fMaxVertices > maxQuadVertices) {
477 // don't exceed the limit of the index buffer
478 fMaxVertices = maxQuadVertices;
479 }
480 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices,
481 0,
482 &fVertices,
483 NULL);
484 GrAlwaysAssert(success);
485 } 485 }
486 486
487 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); 487 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
488 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); 488 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY);
489 489
490 SkRect r; 490 SkRect r;
491 r.fLeft = SkFixedToFloat(vx); 491 r.fLeft = SkFixedToFloat(vx);
492 r.fTop = SkFixedToFloat(vy); 492 r.fTop = SkFixedToFloat(vy);
493 r.fRight = SkFixedToFloat(vx + width); 493 r.fRight = SkFixedToFloat(vx + width);
494 r.fBottom = SkFixedToFloat(vy + height); 494 r.fBottom = SkFixedToFloat(vy + height);
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
590 // Grayscale/BW text 590 // Grayscale/BW text
591 case kA8_GrMaskFormat: 591 case kA8_GrMaskFormat:
592 // set back to normal in case we took LCD path previously. 592 // set back to normal in case we took LCD path previously.
593 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst BlendCoeff()); 593 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDst BlendCoeff());
594 // We're using per-vertex color. 594 // We're using per-vertex color.
595 SkASSERT(drawState->hasColorVertexAttribute()); 595 SkASSERT(drawState->hasColorVertexAttribute());
596 break; 596 break;
597 default: 597 default:
598 SkFAIL("Unexpected mask format."); 598 SkFAIL("Unexpected mask format.");
599 } 599 }
600 int nGlyphs = fCurrVertex / 4; 600 int nGlyphs = fCurrVertex / kVerticesPerGlyph;
601 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); 601 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
602 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, 602 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
603 nGlyphs, 603 nGlyphs,
604 4, 6, &fVertexBounds); 604 kVerticesPerGlyph, kIndicesPerGlyph, & fVertexBounds);
605 605
606 fDrawTarget->resetVertexSource(); 606 fDrawTarget->resetVertexSource();
607 fVertices = NULL; 607 fVertices = NULL;
608 fMaxVertices = 0; 608 fAllocVertexCount = 0;
609 // reset to be those that are left
610 fTotalVertexCount -= fCurrVertex;
609 fCurrVertex = 0; 611 fCurrVertex = 0;
610 fVertexBounds.setLargestInverted(); 612 fVertexBounds.setLargestInverted();
611 SkSafeSetNull(fCurrTexture); 613 SkSafeSetNull(fCurrTexture);
612 } 614 }
613 } 615 }
614 616
615 inline void GrBitmapTextContext::finish() { 617 inline void GrBitmapTextContext::finish() {
616 this->flush(); 618 this->flush();
619 fTotalVertexCount = 0;
617 620
618 GrTextContext::finish(); 621 GrTextContext::finish();
619 } 622 }
620 623
OLDNEW
« no previous file with comments | « src/gpu/GrBitmapTextContext.h ('k') | src/gpu/GrDistanceFieldTextContext.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698