aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
authorGravatar jvanverth <jvanverth@google.com>2014-10-23 11:57:12 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-10-23 11:57:12 -0700
commit73f105345066b1f22f15ba6575cb3800dd9313b8 (patch)
treeace55f313b7a430ab7021fe08e5da142e43560ee /src/gpu
parent70649c174b7a978cdf33bd3a6413ca878950ecc2 (diff)
Allocate only the vertices we need for text.
This restructures the vertex allocation for text rendering to compute the max number of vertices we would need for a line of text, and then only allocate that much. If this number exceeds the quad index limit, then it will allocate for the max number of quads, and reallocate for the rest later. Review URL: https://codereview.chromium.org/663423003
Diffstat (limited to 'src/gpu')
-rwxr-xr-xsrc/gpu/GrBitmapTextContext.cpp107
-rw-r--r--src/gpu/GrBitmapTextContext.h10
-rwxr-xr-xsrc/gpu/GrDistanceFieldTextContext.cpp95
-rw-r--r--src/gpu/GrDistanceFieldTextContext.h5
-rw-r--r--src/gpu/GrTextContext.cpp6
-rw-r--r--src/gpu/GrTextContext.h5
6 files changed, 114 insertions, 114 deletions
diff --git a/src/gpu/GrBitmapTextContext.cpp b/src/gpu/GrBitmapTextContext.cpp
index fa70d3270b..afecead65d 100755
--- a/src/gpu/GrBitmapTextContext.cpp
+++ b/src/gpu/GrBitmapTextContext.cpp
@@ -47,8 +47,10 @@ extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
{kVec2f_GrVertexAttribType, sizeof(SkPoint) + sizeof(GrColor), kGeometryProcessor_GrVertexAttribBinding}
};
-static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
+static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
+static const int kVerticesPerGlyph = 4;
+static const int kIndicesPerGlyph = 6;
};
GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
@@ -57,11 +59,12 @@ GrBitmapTextContext::GrBitmapTextContext(GrContext* context,
fStrike = NULL;
fCurrTexture = NULL;
- fCurrVertex = 0;
fEffectTextureUniqueID = SK_InvalidUniqueID;
fVertices = NULL;
- fMaxVertices = 0;
+ fCurrVertex = 0;
+ fAllocVertexCount = 0;
+ fTotalVertexCount = 0;
fVertexBounds.setLargestInverted();
}
@@ -72,7 +75,7 @@ GrBitmapTextContext* GrBitmapTextContext::Create(GrContext* context,
}
GrBitmapTextContext::~GrBitmapTextContext() {
- this->flush();
+ this->finish();
}
bool GrBitmapTextContext::canDraw(const SkPaint& paint) {
@@ -88,7 +91,8 @@ inline void GrBitmapTextContext::init(const GrPaint& paint, const SkPaint& skPai
fCurrVertex = 0;
fVertices = NULL;
- fMaxVertices = 0;
+ fAllocVertexCount = 0;
+ fTotalVertexCount = 0;
}
void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPaint,
@@ -118,13 +122,13 @@ void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain
}
// need to measure first
+ int numGlyphs;
if (fSkPaint.getTextAlign() != SkPaint::kLeft_Align) {
- SkVector stop;
-
- MeasureText(cache, glyphCacheProc, text, byteLength, &stop);
+ SkVector stopVector;
+ numGlyphs = MeasureText(cache, glyphCacheProc, text, byteLength, &stopVector);
- SkScalar stopX = stop.fX;
- SkScalar stopY = stop.fY;
+ SkScalar stopX = stopVector.fX;
+ SkScalar stopY = stopVector.fY;
if (fSkPaint.getTextAlign() == SkPaint::kCenter_Align) {
stopX = SkScalarHalf(stopX);
@@ -132,7 +136,10 @@ void GrBitmapTextContext::onDrawText(const GrPaint& paint, const SkPaint& skPain
}
x -= stopX;
y -= stopY;
+ } else {
+ numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
}
+ fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
const char* stop = text + byteLength;
@@ -207,6 +214,9 @@ void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skP
GrContext::AutoMatrix autoMatrix;
autoMatrix.setIdentity(fContext, &fPaint);
+ int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
+ fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
+
const char* stop = text + byteLength;
SkTextAlignProc alignProc(fSkPaint.getTextAlign());
SkTextMapStateProc tmsProc(ctm, offset, scalarsPerPosition);
@@ -335,6 +345,28 @@ void GrBitmapTextContext::onDrawPosText(const GrPaint& paint, const SkPaint& skP
this->finish();
}
+static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useColorVerts) {
+ if (numVertices <= 0) {
+ return NULL;
+ }
+
+ // set up attributes
+ if (useColorVerts) {
+ drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+ } else {
+ drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+ }
+ void* vertices = NULL;
+ bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
+ 0,
+ &vertices,
+ NULL);
+ GrAlwaysAssert(success);
+ return vertices;
+}
+
void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
SkFixed vx, SkFixed vy,
GrFontScaler* scaler) {
@@ -418,6 +450,9 @@ void GrBitmapTextContext::appendGlyph(GrGlyph::PackedID packed,
am.setPreConcat(fContext, translate, &tmpPaint);
GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
+
+ // remove this glyph from the vertices we need to allocate
+ fTotalVertexCount -= kVerticesPerGlyph;
return;
}
@@ -434,7 +469,7 @@ HAS_ATLAS:
GrTexture* texture = glyph->fPlot->texture();
SkASSERT(texture);
- if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
+ if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fAllocVertexCount) {
this->flush();
fCurrTexture = texture;
fCurrTexture->ref();
@@ -444,44 +479,9 @@ HAS_ATLAS:
bool useColorVerts = kA8_GrMaskFormat == fCurrMaskFormat;
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;
- if (useColorVerts) {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
- SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
- } else {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
- }
- bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
- if (flush) {
- this->flush();
- fContext->flush();
- if (useColorVerts) {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
- SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
- } else {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
- }
- }
- 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,
- &fVertices,
- NULL);
- GrAlwaysAssert(success);
+ int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
+ fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
+ fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts);
}
SkFixed tx = SkIntToFixed(glyph->fAtlasLocation.fX);
@@ -597,15 +597,17 @@ void GrBitmapTextContext::flush() {
default:
SkFAIL("Unexpected mask format.");
}
- int nGlyphs = fCurrVertex / 4;
+ int nGlyphs = fCurrVertex / kVerticesPerGlyph;
fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
nGlyphs,
- 4, 6, &fVertexBounds);
+ kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
fDrawTarget->resetVertexSource();
fVertices = NULL;
- fMaxVertices = 0;
+ fAllocVertexCount = 0;
+ // reset to be those that are left
+ fTotalVertexCount -= fCurrVertex;
fCurrVertex = 0;
fVertexBounds.setLargestInverted();
SkSafeSetNull(fCurrTexture);
@@ -614,6 +616,7 @@ void GrBitmapTextContext::flush() {
inline void GrBitmapTextContext::finish() {
this->flush();
+ fTotalVertexCount = 0;
GrTextContext::finish();
}
diff --git a/src/gpu/GrBitmapTextContext.h b/src/gpu/GrBitmapTextContext.h
index 7a93820a16..d98a9f47f0 100644
--- a/src/gpu/GrBitmapTextContext.h
+++ b/src/gpu/GrBitmapTextContext.h
@@ -23,17 +23,11 @@ public:
virtual ~GrBitmapTextContext();
private:
- enum {
- kMinRequestedGlyphs = 1,
- kDefaultRequestedGlyphs = 64,
- kMinRequestedVerts = kMinRequestedGlyphs * 4,
- kDefaultRequestedVerts = kDefaultRequestedGlyphs * 4,
- };
-
GrTextStrike* fStrike;
void* fVertices;
int fCurrVertex;
- int fMaxVertices;
+ int fAllocVertexCount;
+ int fTotalVertexCount;
SkRect fVertexBounds;
GrTexture* fCurrTexture;
GrMaskFormat fCurrMaskFormat;
diff --git a/src/gpu/GrDistanceFieldTextContext.cpp b/src/gpu/GrDistanceFieldTextContext.cpp
index dcaee488af..66ec123ae7 100755
--- a/src/gpu/GrDistanceFieldTextContext.cpp
+++ b/src/gpu/GrDistanceFieldTextContext.cpp
@@ -56,6 +56,8 @@ extern const GrVertexAttrib gTextVertexWithColorAttribs[] = {
static const size_t kTextVAColorSize = 2 * sizeof(SkPoint) + sizeof(GrColor);
+static const int kVerticesPerGlyph = 4;
+static const int kIndicesPerGlyph = 6;
};
GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
@@ -70,14 +72,15 @@ GrDistanceFieldTextContext::GrDistanceFieldTextContext(GrContext* context,
fStrike = NULL;
fGammaTexture = NULL;
- fCurrTexture = NULL;
- fCurrVertex = 0;
fEffectTextureUniqueID = SK_InvalidUniqueID;
fEffectColor = GrColor_ILLEGAL;
fEffectFlags = 0;
fVertices = NULL;
- fMaxVertices = 0;
+ fCurrVertex = 0;
+ fAllocVertexCount = 0;
+ fTotalVertexCount = 0;
+ fCurrTexture = NULL;
fVertexBounds.setLargestInverted();
}
@@ -93,7 +96,7 @@ GrDistanceFieldTextContext* GrDistanceFieldTextContext::Create(GrContext* contex
}
GrDistanceFieldTextContext::~GrDistanceFieldTextContext() {
- this->flush();
+ this->finish();
SkSafeSetNull(fGammaTexture);
}
@@ -145,9 +148,10 @@ inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
scaledTextSize *= maxScale;
}
- fCurrVertex = 0;
-
fVertices = NULL;
+ fCurrVertex = 0;
+ fAllocVertexCount = 0;
+ fTotalVertexCount = 0;
if (scaledTextSize <= kSmallDFFontLimit) {
fTextRatio = textSize / kSmallDFFontSize;
@@ -166,7 +170,6 @@ inline void GrDistanceFieldTextContext::init(const GrPaint& paint, const SkPaint
fSkPaint.setAutohinted(false);
fSkPaint.setHinting(SkPaint::kNormal_Hinting);
fSkPaint.setSubpixelText(true);
-
}
static void setup_gamma_texture(GrContext* context, const SkGlyphCache* cache,
@@ -293,6 +296,9 @@ void GrDistanceFieldTextContext::onDrawPosText(const GrPaint& paint, const SkPai
setup_gamma_texture(fContext, cache, fDeviceProperties, &fGammaTexture);
+ int numGlyphs = fSkPaint.textToGlyphs(text, byteLength, NULL);
+ fTotalVertexCount = kVerticesPerGlyph*numGlyphs;
+
const char* stop = text + byteLength;
SkTArray<char> fallbackTxt;
SkTArray<SkScalar> fallbackPos;
@@ -371,6 +377,28 @@ static inline GrColor skcolor_to_grcolor_nopremultiply(SkColor c) {
return GrColorPackRGBA(r, g, b, 0xff);
}
+static void* alloc_vertices(GrDrawTarget* drawTarget, int numVertices, bool useColorVerts) {
+ if (numVertices <= 0) {
+ return NULL;
+ }
+
+ // set up attributes
+ if (useColorVerts) {
+ drawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
+ SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
+ } else {
+ drawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
+ SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
+ }
+ void* vertices = NULL;
+ bool success = drawTarget->reserveVertexAndIndexSpace(numVertices,
+ 0,
+ &vertices,
+ NULL);
+ GrAlwaysAssert(success);
+ return vertices;
+}
+
void GrDistanceFieldTextContext::setupCoverageEffect(const SkColor& filteredColor) {
GrTextureParams params(SkShader::kRepeat_TileMode, GrTextureParams::kBilerp_FilterMode);
GrTextureParams gammaParams(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
@@ -515,6 +543,9 @@ bool GrDistanceFieldTextContext::appendGlyph(GrGlyph::PackedID packed,
am.setPreConcat(fContext, ctm, &tmpPaint);
GrStrokeInfo strokeInfo(SkStrokeRec::kFill_InitStyle);
fContext->drawPath(tmpPaint, *glyph->fPath, strokeInfo);
+
+ // remove this glyph from the vertices we need to allocate
+ fTotalVertexCount -= kVerticesPerGlyph;
return true;
}
@@ -526,7 +557,7 @@ HAS_ATLAS:
GrTexture* texture = glyph->fPlot->texture();
SkASSERT(texture);
- if (fCurrTexture != texture || fCurrVertex + 4 > fMaxVertices) {
+ if (fCurrTexture != texture || fCurrVertex + kVerticesPerGlyph > fTotalVertexCount) {
this->flush();
fCurrTexture = texture;
fCurrTexture->ref();
@@ -535,44 +566,9 @@ HAS_ATLAS:
bool useColorVerts = !fUseLCDText;
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;
- if (useColorVerts) {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
- SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
- } else {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
- }
- bool flush = fDrawTarget->geometryHints(&fMaxVertices, NULL);
- if (flush) {
- this->flush();
- fContext->flush();
- if (useColorVerts) {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexWithColorAttribs>(
- SK_ARRAY_COUNT(gTextVertexWithColorAttribs), kTextVAColorSize);
- } else {
- fDrawTarget->drawState()->setVertexAttribs<gTextVertexAttribs>(
- SK_ARRAY_COUNT(gTextVertexAttribs), kTextVASize);
- }
- }
- 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,
- &fVertices,
- NULL);
- GrAlwaysAssert(success);
+ int maxQuadVertices = kVerticesPerGlyph * fContext->getQuadIndexBuffer()->maxQuads();
+ fAllocVertexCount = SkMin32(fTotalVertexCount, maxQuadVertices);
+ fVertices = alloc_vertices(fDrawTarget, fAllocVertexCount, useColorVerts);
}
SkScalar dx = SkIntToScalar(glyph->fBounds.fLeft + SK_DistanceFieldInset);
@@ -687,14 +683,14 @@ void GrDistanceFieldTextContext::flush() {
// We're using per-vertex color.
SkASSERT(drawState->hasColorVertexAttribute());
}
- int nGlyphs = fCurrVertex / 4;
+ int nGlyphs = fCurrVertex / kVerticesPerGlyph;
fDrawTarget->setIndexSourceToBuffer(fContext->getQuadIndexBuffer());
fDrawTarget->drawIndexedInstances(kTriangles_GrPrimitiveType,
nGlyphs,
- 4, 6, &fVertexBounds);
+ kVerticesPerGlyph, kIndicesPerGlyph, &fVertexBounds);
fDrawTarget->resetVertexSource();
fVertices = NULL;
- fMaxVertices = 0;
+ fTotalVertexCount -= fCurrVertex;
fCurrVertex = 0;
SkSafeSetNull(fCurrTexture);
fVertexBounds.setLargestInverted();
@@ -703,6 +699,7 @@ void GrDistanceFieldTextContext::flush() {
inline void GrDistanceFieldTextContext::finish() {
this->flush();
+ fTotalVertexCount = 0;
GrTextContext::finish();
}
diff --git a/src/gpu/GrDistanceFieldTextContext.h b/src/gpu/GrDistanceFieldTextContext.h
index e0ef7e2e44..3eefd103d0 100644
--- a/src/gpu/GrDistanceFieldTextContext.h
+++ b/src/gpu/GrDistanceFieldTextContext.h
@@ -41,9 +41,10 @@ private:
uint32_t fEffectFlags;
GrTexture* fGammaTexture;
void* fVertices;
- int32_t fMaxVertices;
- GrTexture* fCurrTexture;
int fCurrVertex;
+ int fAllocVertexCount;
+ int fTotalVertexCount;
+ GrTexture* fCurrTexture;
SkRect fVertexBounds;
GrDistanceFieldTextContext(GrContext*, const SkDeviceProperties&, bool enable);
diff --git a/src/gpu/GrTextContext.cpp b/src/gpu/GrTextContext.cpp
index 94c05a7124..259ba184aa 100644
--- a/src/gpu/GrTextContext.cpp
+++ b/src/gpu/GrTextContext.cpp
@@ -76,13 +76,14 @@ bool GrTextContext::drawPosText(const GrPaint& paint, const SkPaint& skPaint,
//*** change to output positions?
-void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+int GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
const char text[], size_t byteLength, SkVector* stopVector) {
SkFixed x = 0, y = 0;
const char* stop = text + byteLength;
SkAutoKern autokern;
+ int numGlyphs = 0;
while (text < stop) {
// don't need x, y here, since all subpixel variants will have the
// same advance
@@ -90,10 +91,13 @@ void GrTextContext::MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheP
x += autokern.adjust(glyph) + glyph.fAdvanceX;
y += glyph.fAdvanceY;
+ ++numGlyphs;
}
stopVector->set(SkFixedToScalar(x), SkFixedToScalar(y));
SkASSERT(text == stop);
+
+ return numGlyphs;
}
static void GlyphCacheAuxProc(void* data) {
diff --git a/src/gpu/GrTextContext.h b/src/gpu/GrTextContext.h
index 95344dd39f..4f7207b04c 100644
--- a/src/gpu/GrTextContext.h
+++ b/src/gpu/GrTextContext.h
@@ -57,8 +57,9 @@ protected:
void finish() { fDrawTarget = NULL; }
static GrFontScaler* GetGrFontScaler(SkGlyphCache* cache);
- static void MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
- const char text[], size_t byteLength, SkVector* stopVector);
+ // sets extent in stopVector and returns glyph count
+ static int MeasureText(SkGlyphCache* cache, SkDrawCacheProc glyphCacheProc,
+ const char text[], size_t byteLength, SkVector* stopVector);
};
#endif