diff options
author | 2013-10-16 18:15:34 +0000 | |
---|---|---|
committer | 2013-10-16 18:15:34 +0000 | |
commit | c7a40fad0b4c243087ad1adb14ebc2184d42cac0 (patch) | |
tree | 0221bd972c7e7b7d7df8571762dee010f3c026b6 /src | |
parent | 3f1f2a3a59c43e5bce67ab98e55df45bc7c933a3 (diff) |
Split out GrBitmapTextContext from GrTextContext.
This is a stepping stone to having a variety of different text context types
(bitmaps, distance fields, NV path rendering).
R=bsalomon@google.com
Review URL: https://codereview.chromium.org/27199002
git-svn-id: http://skia.googlecode.com/svn/trunk@11820 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src')
-rwxr-xr-x | src/gpu/GrBitmapTextContext.cpp | 248 | ||||
-rw-r--r-- | src/gpu/GrTextContext.cpp | 241 | ||||
-rw-r--r-- | src/gpu/SkGpuDevice.cpp | 6 |
3 files changed, 251 insertions, 244 deletions
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp new file mode 100755 index 0000000000..7a99f093e5 --- /dev/null +++ b/src/gpu/GrBitmapTextContext.cpp @@ -0,0 +1,248 @@ +/* + * Copyright 2013 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrBitmapTextContext.h" +#include "GrAtlas.h" +#include "GrDrawTarget.h" +#include "GrFontScaler.h" +#include "GrIndexBuffer.h" +#include "GrTextStrike.h" +#include "GrTextStrike_impl.h" +#include "SkPath.h" +#include "SkRTConf.h" +#include "SkStrokeRec.h" +#include "effects/GrCustomCoordsTextureEffect.h" + +static const int kGlyphCoordsAttributeIndex = 1; + +SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, + "Dump the contents of the font cache before every purge."); + +GrBitmapTextContext::GrBitmapTextContext(GrContext* context, const GrPaint& paint) : + GrTextContext(context, paint) { + fAutoMatrix.setIdentity(fContext, &fPaint); + + fStrike = NULL; + + fCurrTexture = NULL; + fCurrVertex = 0; + + fVertices = NULL; + fMaxVertices = 0; +} + +GrBitmapTextContext::~GrBitmapTextContext() { + this->flushGlyphs(); +} + +void GrBitmapTextContext::flushGlyphs() { + if (NULL == fDrawTarget) { + return; + } + + GrDrawState* drawState = fDrawTarget->drawState(); + GrDrawState::AutoRestoreEffects are(drawState); + drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); + + if (fCurrVertex > 0) { + // setup our sampler state for our text texture/atlas + SkASSERT(GrIsALIGN4(fCurrVertex)); + SkASSERT(fCurrTexture); + GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); + + // This effect could be stored with one of the cache objects (atlas?) + drawState->addCoverageEffect( + GrCustomCoordsTextureEffect::Create(fCurrTexture, params), + kGlyphCoordsAttributeIndex)->unref(); + + if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { + if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || + kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || + fPaint.numColorStages()) { + GrPrintf("LCD Text will not draw correctly.\n"); + } + // setup blend so that we get mask * paintColor + (1-mask)*dstColor + drawState->setBlendConstant(fPaint.getColor()); + drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); + // don't modulate by the paint's color in the frag since we're + // already doing it via the blend const. + drawState->setColor(0xffffffff); + } else { + // set back to normal in case we took LCD path previously. + drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); + drawState->setColor(fPaint.getColor()); + } + + int nGlyphs = fCurrVertex / 4; + fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); + fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, + nGlyphs, + 4, 6); + fDrawTarget->resetVertexSource(); + fVertices = NULL; + fMaxVertices = 0; + fCurrVertex = 0; + SkSafeSetNull(fCurrTexture); + } +} + +namespace { + +// position + texture coord +extern const GrVertexAttrib gTextVertexAttribs[] = { + {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, + {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} +}; + +}; + +void GrBitmapTextContext::drawPackedGlyph(GrGlyph::PackedID packed, + GrFixed vx, GrFixed vy, + GrFontScaler* scaler) { + if (NULL == fDrawTarget) { + return; + } + if (NULL == fStrike) { + fStrike = fContext->getFontCache()->getStrike(scaler); + } + + GrGlyph* glyph = fStrike->getGlyph(packed, scaler); + if (NULL == glyph || glyph->fBounds.isEmpty()) { + return; + } + + vx += SkIntToFixed(glyph->fBounds.fLeft); + vy += SkIntToFixed(glyph->fBounds.fTop); + + // keep them as ints until we've done the clip-test + GrFixed width = glyph->fBounds.width(); + GrFixed height = glyph->fBounds.height(); + + // check if we clipped out + if (true || NULL == glyph->fPlot) { + int x = vx >> 16; + int y = vy >> 16; + if (fClipRect.quickReject(x, y, x + width, y + height)) { +// SkCLZ(3); // so we can set a break-point in the debugger + return; + } + } + + if (NULL == glyph->fPlot) { + if (fStrike->getGlyphAtlas(glyph, scaler)) { + goto HAS_ATLAS; + } + + // try to clear out an unused plot before we flush + fContext->getFontCache()->freePlotExceptFor(fStrike); + if (fStrike->getGlyphAtlas(glyph, scaler)) { + goto HAS_ATLAS; + } + + if (c_DumpFontCache) { +#ifdef SK_DEVELOPER + fContext->getFontCache()->dump(); +#endif + } + + // before we purge the cache, we must flush any accumulated draws + this->flushGlyphs(); + fContext->flush(); + + // try to purge + fContext->getFontCache()->purgeExceptFor(fStrike); + // need to use new flush count here + if (fStrike->getGlyphAtlas(glyph, scaler)) { + goto HAS_ATLAS; + } + + if (NULL == glyph->fPath) { + SkPath* path = SkNEW(SkPath); + if (!scaler->getGlyphPath(glyph->glyphID(), path)) { + // flag the glyph as being dead? + delete path; + return; + } + glyph->fPath = path; + } + + GrContext::AutoMatrix am; + SkMatrix translate; + translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)), + SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop))); + GrPaint tmpPaint(fPaint); + am.setPreConcat(fContext, translate, &tmpPaint); + SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); + fContext->drawPath(tmpPaint, *glyph->fPath, stroke); + return; + } + +HAS_ATLAS: + SkASSERT(glyph->fPlot); + GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); + glyph->fPlot->setDrawToken(drawToken); + + // now promote them to fixed (TODO: Rethink using fixed pt). + width = SkIntToFixed(width); + height = SkIntToFixed(height); + + GrTexture* texture = glyph->fPlot->texture(); + SkASSERT(texture); + + if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { + this->flushGlyphs(); + fCurrTexture = texture; + fCurrTexture->ref(); + } + + if (NULL == fVertices) { + // If we need to reserve vertices allow the draw target to suggest + // a number of verts to reserve and whether to perform a flush. + fMaxVertices = kMinRequestedVerts; + fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( + SK_ARRAY_COUNT(gTextVertexAttribs)); + bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); + if (flush) { + this->flushGlyphs(); + fContext->flush(); + fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( + SK_ARRAY_COUNT(gTextVertexAttribs)); + } + fMaxVertices = kDefaultRequestedVerts; + // ignore return, no point in flushing again. + fDrawTarget->geometryHints(&fMaxVertices, NULL); + + int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); + if (fMaxVertices < kMinRequestedVerts) { + fMaxVertices = kDefaultRequestedVerts; + } else if (fMaxVertices > maxQuadVertices) { + // don't exceed the limit of the index buffer + fMaxVertices = maxQuadVertices; + } + bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, + 0, + GrTCast<void**>(&fVertices), + NULL); + GrAlwaysAssert(success); + SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize()); + } + + GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); + GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); + + fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx), + SkFixedToFloat(vy), + SkFixedToFloat(vx + width), + SkFixedToFloat(vy + height), + 2 * sizeof(SkPoint)); + fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), + SkFixedToFloat(texture->normalizeFixedY(ty)), + SkFixedToFloat(texture->normalizeFixedX(tx + width)), + SkFixedToFloat(texture->normalizeFixedY(ty + height)), + 2 * sizeof(SkPoint)); + fCurrVertex += 4; +} diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp index 8178032ae7..363a817778 100644 --- a/src/gpu/GrTextContext.cpp +++ b/src/gpu/GrTextContext.cpp @@ -6,82 +6,10 @@ */ - #include "GrTextContext.h" -#include "GrAtlas.h" -#include "GrContext.h" -#include "GrDrawTarget.h" -#include "GrFontScaler.h" -#include "GrIndexBuffer.h" -#include "GrTextStrike.h" -#include "GrTextStrike_impl.h" -#include "SkPath.h" -#include "SkRTConf.h" -#include "SkStrokeRec.h" -#include "effects/GrCustomCoordsTextureEffect.h" - -static const int kGlyphCoordsAttributeIndex = 1; - -SK_CONF_DECLARE(bool, c_DumpFontCache, "gpu.dumpFontCache", false, - "Dump the contents of the font cache before every purge."); - -void GrTextContext::flushGlyphs() { - if (NULL == fDrawTarget) { - return; - } - - GrDrawState* drawState = fDrawTarget->drawState(); - GrDrawState::AutoRestoreEffects are(drawState); - drawState->setFromPaint(fPaint, SkMatrix::I(), fContext->getRenderTarget()); - - if (fCurrVertex > 0) { - // setup our sampler state for our text texture/atlas - SkASSERT(GrIsALIGN4(fCurrVertex)); - SkASSERT(fCurrTexture); - GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kNone_FilterMode); - - // This effect could be stored with one of the cache objects (atlas?) - drawState->addCoverageEffect( - GrCustomCoordsTextureEffect::Create(fCurrTexture, params), - kGlyphCoordsAttributeIndex)->unref(); - - if (!GrPixelConfigIsAlphaOnly(fCurrTexture->config())) { - if (kOne_GrBlendCoeff != fPaint.getSrcBlendCoeff() || - kISA_GrBlendCoeff != fPaint.getDstBlendCoeff() || - fPaint.numColorStages()) { - GrPrintf("LCD Text will not draw correctly.\n"); - } - // setup blend so that we get mask * paintColor + (1-mask)*dstColor - drawState->setBlendConstant(fPaint.getColor()); - drawState->setBlendFunc(kConstC_GrBlendCoeff, kISC_GrBlendCoeff); - // don't modulate by the paint's color in the frag since we're - // already doing it via the blend const. - drawState->setColor(0xffffffff); - } else { - // set back to normal in case we took LCD path previously. - drawState->setBlendFunc(fPaint.getSrcBlendCoeff(), fPaint.getDstBlendCoeff()); - drawState->setColor(fPaint.getColor()); - } - - int nGlyphs = fCurrVertex / 4; - fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer()); - fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType, - nGlyphs, - 4, 6); - fDrawTarget->resetVertexSource(); - fVertices = NULL; - fMaxVertices = 0; - fCurrVertex = 0; - SkSafeSetNull(fCurrTexture); - } -} GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint(paint) { fContext = context; - fStrike = NULL; - - fCurrTexture = NULL; - fCurrVertex = 0; const GrClipData* clipData = context->getClip(); @@ -95,175 +23,6 @@ GrTextContext::GrTextContext(GrContext* context, const GrPaint& paint) : fPaint( devConservativeBound.roundOut(&fClipRect); - fAutoMatrix.setIdentity(fContext, &fPaint); - fDrawTarget = fContext->getTextTarget(); - - fVertices = NULL; - fMaxVertices = 0; -} - -GrTextContext::~GrTextContext() { - this->flushGlyphs(); } -void GrTextContext::flush() { - this->flushGlyphs(); -} - -namespace { - -// position + texture coord -extern const GrVertexAttrib gTextVertexAttribs[] = { - {kVec2f_GrVertexAttribType, 0, kPosition_GrVertexAttribBinding}, - {kVec2f_GrVertexAttribType, sizeof(GrPoint), kEffect_GrVertexAttribBinding} -}; - -}; - -void GrTextContext::drawPackedGlyph(GrGlyph::PackedID packed, - GrFixed vx, GrFixed vy, - GrFontScaler* scaler) { - if (NULL == fDrawTarget) { - return; - } - if (NULL == fStrike) { - fStrike = fContext->getFontCache()->getStrike(scaler); - } - - GrGlyph* glyph = fStrike->getGlyph(packed, scaler); - if (NULL == glyph || glyph->fBounds.isEmpty()) { - return; - } - - vx += SkIntToFixed(glyph->fBounds.fLeft); - vy += SkIntToFixed(glyph->fBounds.fTop); - - // keep them as ints until we've done the clip-test - GrFixed width = glyph->fBounds.width(); - GrFixed height = glyph->fBounds.height(); - - // check if we clipped out - if (true || NULL == glyph->fPlot) { - int x = vx >> 16; - int y = vy >> 16; - if (fClipRect.quickReject(x, y, x + width, y + height)) { -// SkCLZ(3); // so we can set a break-point in the debugger - return; - } - } - - if (NULL == glyph->fPlot) { - if (fStrike->getGlyphAtlas(glyph, scaler)) { - goto HAS_ATLAS; - } - - // try to clear out an unused plot before we flush - fContext->getFontCache()->freePlotExceptFor(fStrike); - if (fStrike->getGlyphAtlas(glyph, scaler)) { - goto HAS_ATLAS; - } - - if (c_DumpFontCache) { -#ifdef SK_DEVELOPER - fContext->getFontCache()->dump(); -#endif - } - - // before we purge the cache, we must flush any accumulated draws - this->flushGlyphs(); - fContext->flush(); - - // try to purge - fContext->getFontCache()->purgeExceptFor(fStrike); - // need to use new flush count here - if (fStrike->getGlyphAtlas(glyph, scaler)) { - goto HAS_ATLAS; - } - - if (NULL == glyph->fPath) { - SkPath* path = SkNEW(SkPath); - if (!scaler->getGlyphPath(glyph->glyphID(), path)) { - // flag the glyph as being dead? - delete path; - return; - } - glyph->fPath = path; - } - - GrContext::AutoMatrix am; - SkMatrix translate; - translate.setTranslate(SkFixedToScalar(vx - SkIntToFixed(glyph->fBounds.fLeft)), - SkFixedToScalar(vy - SkIntToFixed(glyph->fBounds.fTop))); - GrPaint tmpPaint(fPaint); - am.setPreConcat(fContext, translate, &tmpPaint); - SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); - fContext->drawPath(tmpPaint, *glyph->fPath, stroke); - return; - } - -HAS_ATLAS: - SkASSERT(glyph->fPlot); - GrDrawTarget::DrawToken drawToken = fDrawTarget->getCurrentDrawToken(); - glyph->fPlot->setDrawToken(drawToken); - - // now promote them to fixed (TODO: Rethink using fixed pt). - width = SkIntToFixed(width); - height = SkIntToFixed(height); - - GrTexture* texture = glyph->fPlot->texture(); - SkASSERT(texture); - - if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) { - this->flushGlyphs(); - fCurrTexture = texture; - fCurrTexture->ref(); - } - - if (NULL == fVertices) { - // If we need to reserve vertices allow the draw target to suggest - // a number of verts to reserve and whether to perform a flush. - fMaxVertices = kMinRequestedVerts; - fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( - SK_ARRAY_COUNT(gTextVertexAttribs)); - bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL); - if (flush) { - this->flushGlyphs(); - fContext->flush(); - fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>( - SK_ARRAY_COUNT(gTextVertexAttribs)); - } - fMaxVertices = kDefaultRequestedVerts; - // ignore return, no point in flushing again. - fDrawTarget->geometryHints(&fMaxVertices, NULL); - - int maxQuadVertices = 4 * fContext->getQuadIndexBuffer()->maxQuads(); - if (fMaxVertices < kMinRequestedVerts) { - fMaxVertices = kDefaultRequestedVerts; - } else if (fMaxVertices > maxQuadVertices) { - // don't exceed the limit of the index buffer - fMaxVertices = maxQuadVertices; - } - bool success = fDrawTarget->reserveVertexAndIndexSpace(fMaxVertices, - 0, - GrTCast<void**>(&fVertices), - NULL); - GrAlwaysAssert(success); - SkASSERT(2*sizeof(GrPoint) == fDrawTarget->getDrawState().getVertexSize()); - } - - GrFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX); - GrFixed ty = SkIntToFixed(glyph->fAtlasLocation.fY); - - fVertices[2*fCurrVertex].setRectFan(SkFixedToFloat(vx), - SkFixedToFloat(vy), - SkFixedToFloat(vx + width), - SkFixedToFloat(vy + height), - 2 * sizeof(SkPoint)); - fVertices[2*fCurrVertex+1].setRectFan(SkFixedToFloat(texture->normalizeFixedX(tx)), - SkFixedToFloat(texture->normalizeFixedY(ty)), - SkFixedToFloat(texture->normalizeFixedX(tx + width)), - SkFixedToFloat(texture->normalizeFixedY(ty + height)), - 2 * sizeof(SkPoint)); - fCurrVertex += 4; -} diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp index 7bba41f60a..3c91101b34 100644 --- a/src/gpu/SkGpuDevice.cpp +++ b/src/gpu/SkGpuDevice.cpp @@ -11,7 +11,7 @@ #include "effects/GrSimpleTextureEffect.h" #include "GrContext.h" -#include "GrTextContext.h" +#include "GrBitmapTextContext.h" #include "SkGrTexturePixelRef.h" @@ -1743,7 +1743,7 @@ void SkGpuDevice::drawText(const SkDraw& draw, const void* text, if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { return; } - GrTextContext context(fContext, grPaint); + GrBitmapTextContext context(fContext, grPaint); myDraw.fProcs = this->initDrawForText(&context); this->INHERITED::drawText(myDraw, text, byteLength, x, y, paint); } @@ -1766,7 +1766,7 @@ void SkGpuDevice::drawPosText(const SkDraw& draw, const void* text, if (!skPaint2GrPaintShader(this, paint, true, &grPaint)) { return; } - GrTextContext context(fContext, grPaint); + GrBitmapTextContext context(fContext, grPaint); myDraw.fProcs = this->initDrawForText(&context); this->INHERITED::drawPosText(myDraw, text, byteLength, pos, constY, scalarsPerPos, paint); |