Chromium Code Reviews| OLD | NEW |
|---|---|
| 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" |
| 11 #include "GrFontScaler.h" | 11 #include "GrFontScaler.h" |
| 12 #include "GrIndexBuffer.h" | 12 #include "GrIndexBuffer.h" |
| 13 #include "GrTextStrike.h" | 13 #include "GrTextStrike.h" |
| 14 #include "GrTextStrike_impl.h" | 14 #include "GrTextStrike_impl.h" |
| 15 #include "SkColorPriv.h" | 15 #include "SkColorPriv.h" |
| 16 #include "SkPath.h" | 16 #include "SkPath.h" |
| 17 #include "SkRTConf.h" | 17 #include "SkRTConf.h" |
| 18 #include "SkStrokeRec.h" | 18 #include "SkStrokeRec.h" |
| 19 #include "effects/GrCustomCoordsTextureEffect.h" | 19 #include "effects/GrCustomCoordsTextureEffect.h" |
| 20 | 20 |
| 21 #include "SkAutoKern.h" | 21 #include "SkAutoKern.h" |
| 22 #include "SkDraw.h" | 22 #include "SkDraw.h" |
| 23 #include "SkGlyphCache.h" | 23 #include "SkGlyphCache.h" |
| 24 #include "SkGpuDevice.h" | 24 #include "SkGpuDevice.h" |
| 25 #include "SkGr.h" | 25 #include "SkGr.h" |
| 26 | 26 |
| 27 static const int kGlyphCoordsAttributeIndex = 1; | |
| 28 | |
| 29 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, | 27 SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, |
| 30 "Dump the contents of the font cache before every purge."); | 28 "Dump the contents of the font cache before every purge."); |
| 31 | 29 |
| 30 static const int kGlyphCoordsNoColorAttributeIndex = 1; | |
| 31 static const int kGlyphCoordsWithColorAttributeIndex = 2; | |
| 32 | |
| 33 namespace { | |
| 34 // position + texture coord | |
| 35 extern const GrVertexAttrib gTextVertexAttribs[] = { | |
| 36 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, | |
| 37 {kVec2f_GrVertexAttribType, sizeof(SkPoint) , kEffect_GrVertexAttribBinding} | |
| 38 }; | |
| 39 | |
| 40 // position + color + texture coord | |
| 41 extern const GrVertexAttrib gTextVertexWithColorAttribs[] = { | |
| 42 {kVec2f_GrVertexAttribType, 0, kPosition_Gr VertexAttribBinding}, | |
| 43 {kVec4ub_GrVertexAttribType, sizeof(SkPoint), kColor_GrVer texAttribBinding}, | |
| 44 {kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kEffect_GrVe rtexAttribBinding} | |
| 45 }; | |
| 46 | |
| 47 }; | |
| 48 | |
| 32 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, | 49 GrBitmapTextContext::GrBitmapTextContext(GrContext* context, |
| 33 const SkDeviceProperties& properties) | 50 const SkDeviceProperties& properties) |
| 34 : GrTextContext(context, properties) { | 51 : GrTextContext(context, properties) { |
| 35 fStrike = NULL; | 52 fStrike = NULL; |
| 36 | 53 |
| 37 fCurrTexture = NULL; | 54 fCurrTexture = NULL; |
| 38 fCurrVertex = 0; | 55 fCurrVertex = 0; |
| 39 | 56 |
| 40 fVertices = NULL; | 57 fVertices = NULL; |
| 41 fMaxVertices = 0; | 58 fMaxVertices = 0; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 69 | 86 |
| 70 if (fCurrVertex > 0) { | 87 if (fCurrVertex > 0) { |
| 71 fContext->getFontCache()->updateTextures(); | 88 fContext->getFontCache()->updateTextures(); |
| 72 | 89 |
| 73 // setup our sampler state for our text texture/atlas | 90 // setup our sampler state for our text texture/atlas |
| 74 SkASSERT(SkIsAlign4(fCurrVertex)); | 91 SkASSERT(SkIsAlign4(fCurrVertex)); |
| 75 SkASSERT(fCurrTexture); | 92 SkASSERT(fCurrTexture); |
| 76 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon e_FilterMode); | 93 GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNon e_FilterMode); |
| 77 | 94 |
| 78 // This effect could be stored with one of the cache objects (atlas?) | 95 // This effect could be stored with one of the cache objects (atlas?) |
| 96 int coordsIdx = drawState->hasColorVertexAttribute() ? kGlyphCoordsWithC olorAttributeIndex : | |
| 97 kGlyphCoordsNoCol orAttributeIndex; | |
| 79 drawState->addCoverageEffect( | 98 drawState->addCoverageEffect( |
| 80 GrCustomCoordsTextureEffect::Create(fCurrTexture , params), | 99 GrCustomCoordsTextureEffect::Create(fCurrTexture , params), |
| 81 kGlyphCoordsAttributeIndex)->unref(); | 100 coordsIdx)->unref(); |
| 82 | 101 |
| 83 if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { | 102 if (NULL != fStrike && kARGB_GrMaskFormat == fStrike->getMaskFormat()) { |
| 103 SkASSERT(!drawState->hasColorVertexAttribute()); | |
| 84 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff()); | 104 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff()); |
| 85 drawState->setColor(0xffffffff); | 105 drawState->setColor(0xffffffff); |
| 86 } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { | 106 } else if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { |
|
bsalomon
2014/06/04 20:01:58
Should this be kA888_GrMaskFormat == fStrike->getM
jvanverth1
2014/06/05 16:52:13
I think they're equivalent, but I agree to be cons
| |
| 87 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || | 107 if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || |
| 88 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || | 108 kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || |
| 89 fPaint.numColorStages()) { | 109 fPaint.numColorStages()) { |
| 90 GrPrintf("LCD Text will not draw correctly.\n"); | 110 GrPrintf("LCD Text will not draw correctly.\n"); |
| 91 } | 111 } |
| 112 SkASSERT(!drawState->hasColorVertexAttribute()); | |
| 92 // We don't use the GrPaint's color in this case because it's been p remultiplied by | 113 // We don't use the GrPaint's color in this case because it's been p remultiplied by |
| 93 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by | 114 // alpha. Instead we feed in a non-premultiplied color, and multiply its alpha by |
| 94 // the mask texture color. The end result is that we get | 115 // the mask texture color. The end result is that we get |
| 95 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo lor | 116 // mask*paintAlpha*paintColor + (1-mask*paintAlpha)*dstCo lor |
| 96 int a = SkColorGetA(fSkPaint.getColor()); | 117 int a = SkColorGetA(fSkPaint.getColor()); |
| 97 // paintAlpha | 118 // paintAlpha |
| 98 drawState->setColor(SkColorSetARGB(a, a, a, a)); | 119 drawState->setColor(SkColorSetARGB(a, a, a, a)); |
| 99 // paintColor | 120 // paintColor |
| 100 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPain t.getColor())); | 121 drawState->setBlendConstant(skcolor_to_grcolor_nopremultiply(fSkPain t.getColor())); |
| 101 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); | 122 drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); |
| 102 } else { | 123 } else { |
| 103 // set back to normal in case we took LCD path previously. | 124 // set back to normal in case we took LCD path previously. |
| 104 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff()); | 125 drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlen dCoeff()); |
| 105 drawState->setColor(fPaint.getColor()); | 126 //drawState->setColor(fPaint.getColor()); |
| 127 // We're using per-vertex color. | |
| 128 SkASSERT(drawState->hasColorVertexAttribute()); | |
| 129 drawState->setColor(0xFFFFFFFF); | |
| 106 } | 130 } |
| 107 | 131 |
| 108 int nGlyphs = fCurrVertex / 4; | 132 int nGlyphs = fCurrVertex / 4; |
| 109 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); | 133 fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); |
| 110 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, | 134 fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, |
| 111 nGlyphs, | 135 nGlyphs, |
| 112 4, 6, &fVertexBounds); | 136 4, 6, &fVertexBounds); |
| 113 | 137 |
| 114 fDrawTarget->resetVertexSource(); | 138 fDrawTarget->resetVertexSource(); |
| 115 fVertices = NULL; | 139 fVertices = NULL; |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 126 fStrike = NULL; | 150 fStrike = NULL; |
| 127 | 151 |
| 128 fCurrTexture = NULL; | 152 fCurrTexture = NULL; |
| 129 fCurrVertex = 0; | 153 fCurrVertex = 0; |
| 130 | 154 |
| 131 fVertices = NULL; | 155 fVertices = NULL; |
| 132 fMaxVertices = 0; | 156 fMaxVertices = 0; |
| 133 } | 157 } |
| 134 | 158 |
| 135 inline void GrBitmapTextContext::finish() { | 159 inline void GrBitmapTextContext::finish() { |
| 136 flushGlyphs(); | 160 this->flushGlyphs(); |
| 137 | 161 |
| 138 GrTextContext::finish(); | 162 GrTextContext::finish(); |
| 139 } | 163 } |
| 140 | 164 |
| 141 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, | 165 void GrBitmapTextContext::drawText(const GrPaint& paint, const SkPaint& skPaint, |
| 142 const char text[], size_t byteLength, | 166 const char text[], size_t byteLength, |
| 143 SkScalar x, SkScalar y) { | 167 SkScalar x, SkScalar y) { |
| 144 SkASSERT(byteLength == 0 || text != NULL); | 168 SkASSERT(byteLength == 0 || text != NULL); |
| 145 | 169 |
| 146 // nothing to draw | 170 // nothing to draw |
| (...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 fontScaler); | 489 fontScaler); |
| 466 } | 490 } |
| 467 pos += scalarsPerPosition; | 491 pos += scalarsPerPosition; |
| 468 } | 492 } |
| 469 } | 493 } |
| 470 } | 494 } |
| 471 | 495 |
| 472 this->finish(); | 496 this->finish(); |
| 473 } | 497 } |
| 474 | 498 |
| 475 namespace { | |
| 476 | |
| 477 // position + texture coord | |
| 478 extern const GrVertexAttrib gTextVertexAttribs[] = { | |
| 479 {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding }, | |
| 480 {kVec2f_GrVertexAttribType, sizeof(SkPoint), kEffect_GrVertexAttribBinding} | |
| 481 }; | |
| 482 | |
| 483 }; | |
| 484 | |
| 485 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, | 499 void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, |
| 486 SkFixed vx, SkFixed vy, | 500 SkFixed vx, SkFixed vy, |
| 487 GrFontScaler* scaler) { | 501 GrFontScaler* scaler) { |
| 488 if (NULL == fDrawTarget) { | 502 if (NULL == fDrawTarget) { |
| 489 return; | 503 return; |
| 490 } | 504 } |
| 491 | 505 |
| 492 if (NULL == fStrike) { | 506 if (NULL == fStrike) { |
| 493 fStrike = fContext->getFontCache()->getStrike(scaler, false); | 507 fStrike = fContext->getFontCache()->getStrike(scaler, false); |
| 494 } | 508 } |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 574 | 588 |
| 575 GrTexture* texture = glyph->fPlot->texture(); | 589 GrTexture* texture = glyph->fPlot->texture(); |
| 576 SkASSERT(texture); | 590 SkASSERT(texture); |
| 577 | 591 |
| 578 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { | 592 if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { |
| 579 this->flushGlyphs(); | 593 this->flushGlyphs(); |
| 580 fCurrTexture = texture; | 594 fCurrTexture = texture; |
| 581 fCurrTexture->ref(); | 595 fCurrTexture->ref(); |
| 582 } | 596 } |
| 583 | 597 |
| 598 bool useColorVerts = kA8_GrMaskFormat == fStrike->getMaskFormat(); | |
| 599 | |
| 584 if (NULL == fVertices) { | 600 if (NULL == fVertices) { |
| 585 // If we need to reserve vertices allow the draw target to suggest | 601 // If we need to reserve vertices allow the draw target to suggest |
| 586 // a number of verts to reserve and whether to perform a flush. | 602 // a number of verts to reserve and whether to perform a flush. |
| 587 fMaxVertices = kMinRequestedVerts; | 603 fMaxVertices = kMinRequestedVerts; |
| 588 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 604 if (useColorVerts) { |
| 589 SK_ARRAY_COUNT(gTextVertexAttribs)); | 605 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttri bs>( |
| 606 SK_ARRAY_COUNT(gTextVertexWithColorAttribs)); | |
| 607 } else { | |
| 608 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
| 609 SK_ARRAY_COUNT(gTextVertexAttribs)); | |
| 610 } | |
| 590 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); | 611 bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); |
| 591 if (flush) { | 612 if (flush) { |
| 592 this->flushGlyphs(); | 613 this->flushGlyphs(); |
| 593 fContext->flush(); | 614 fContext->flush(); |
| 594 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | 615 if (useColorVerts) { |
| 595 SK_ARRAY_COUNT(gTextVertexAttribs)); | 616 fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorA ttribs>( |
| 617 SK_ARRAY_COUNT(gTextVertexWithColorAttribs)); | |
| 618 } else { | |
| 619 fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( | |
| 620 SK_ARRAY_COUNT(gTextVertexAttribs)); | |
| 621 } | |
| 596 } | 622 } |
| 597 fMaxVertices = kDefaultRequestedVerts; | 623 fMaxVertices = kDefaultRequestedVerts; |
| 598 // ignore return, no point in flushing again. | 624 // ignore return, no point in flushing again. |
| 599 fDrawTarget->geometryHints(&fMaxVertices, NULL); | 625 fDrawTarget->geometryHints(&fMaxVertices, NULL); |
| 600 | 626 |
| 601 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); | 627 int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); |
| 602 if (fMaxVertices < kMinRequestedVerts) { | 628 if (fMaxVertices < kMinRequestedVerts) { |
| 603 fMaxVertices = kDefaultRequestedVerts; | 629 fMaxVertices = kDefaultRequestedVerts; |
| 604 } else if (fMaxVertices > maxQuadVertices) { | 630 } else if (fMaxVertices > maxQuadVertices) { |
| 605 // don't exceed the limit of the index buffer | 631 // don't exceed the limit of the index buffer |
| 606 fMaxVertices = maxQuadVertices; | 632 fMaxVertices = maxQuadVertices; |
| 607 } | 633 } |
| 608 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, | 634 bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, |
| 609 0, | 635 0, |
| 610 GrTCast<void**>(& fVertices), | 636 &fVertices, |
| 611 NULL); | 637 NULL); |
| 612 GrAlwaysAssert(success); | 638 GrAlwaysAssert(success); |
| 613 SkASSERT(2*sizeof(SkPoint) == fDrawTarget->getDrawState().getVertexSize( )); | |
| 614 } | 639 } |
| 615 | 640 |
| 616 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); | 641 SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); |
| 617 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); | 642 SkFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); |
| 618 | 643 |
| 619 SkRect r; | 644 SkRect r; |
| 620 r.fLeft = SkFixedToFloat(vx); | 645 r.fLeft = SkFixedToFloat(vx); |
| 621 r.fTop = SkFixedToFloat(vy); | 646 r.fTop = SkFixedToFloat(vy); |
| 622 r.fRight = SkFixedToFloat(vx + width); | 647 r.fRight = SkFixedToFloat(vx + width); |
| 623 r.fBottom = SkFixedToFloat(vy + height); | 648 r.fBottom = SkFixedToFloat(vy + height); |
| 624 | 649 |
| 625 fVertexBounds.growToInclude(r); | 650 fVertexBounds.growToInclude(r); |
| 626 | 651 |
| 627 fVertices[2*fCurrVertex].setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, | 652 size_t vertSize = useColorVerts ? (2 * sizeof(SkPoint) + sizeof(GrColor)) : |
| 628 2 * sizeof(SkPoint)); | 653 (2 * sizeof(SkPoint)); |
| 629 fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixed X(tx)), | 654 |
| 630 SkFixedToFloat(texture->normalizeFixed Y(ty)), | 655 SkASSERT(vertSize == fDrawTarget->getDrawState().getVertexSize()); |
| 631 SkFixedToFloat(texture->normalizeFixed X(tx + width)), | 656 |
| 632 SkFixedToFloat(texture->normalizeFixed Y(ty + height)), | 657 SkPoint* positions = reinterpret_cast<SkPoint*>( |
| 633 2 * sizeof(SkPoint)); | 658 reinterpret_cast<intptr_t>(fVertices) + vertSize * fCurrVertex); |
| 659 positions->setRectFan(r.fLeft, r.fTop, r.fRight, r.fBottom, vertSize); | |
| 660 | |
| 661 // The texture coords are last in both the with and without color vertex lay outs. | |
| 662 SkPoint* textureCoords = reinterpret_cast<SkPoint*>( | |
| 663 reinterpret_cast<intptr_t>(positions) + vertSize - sizeof(SkPoint)) ; | |
| 664 textureCoords->setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), | |
| 665 SkFixedToFloat(texture->normalizeFixedY(ty)), | |
| 666 SkFixedToFloat(texture->normalizeFixedX(tx + width )), | |
| 667 SkFixedToFloat(texture->normalizeFixedY(ty + heigh t)), | |
| 668 vertSize); | |
| 669 if (useColorVerts) { | |
| 670 // color comes after position. | |
| 671 GrColor* colors = reinterpret_cast<GrColor*>(positions + 1); | |
| 672 for (int i = 0; i < 4; ++i) { | |
| 673 *colors = fPaint.getColor(); | |
| 674 colors = reinterpret_cast<GrColor*>(reinterpret_cast<intptr_t>(colors ) + vertSize); | |
| 675 } | |
| 676 } | |
| 634 fCurrVertex += 4; | 677 fCurrVertex += 4; |
| 635 } | 678 } |
| OLD | NEW |