| Index: src/gpu/GrAtlasTextContext.cpp
|
| diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp
|
| index 59a875e422284e34682cdbf0a0679221f9b298d8..29dd072df1d686c68583dced602a5b3a6e725c3c 100644
|
| --- a/src/gpu/GrAtlasTextContext.cpp
|
| +++ b/src/gpu/GrAtlasTextContext.cpp
|
| @@ -782,15 +782,7 @@ public:
|
| typedef Blob::Run Run;
|
| typedef Run::SubRunInfo TextInfo;
|
| struct Geometry {
|
| - Geometry() {}
|
| - Geometry(const Geometry& geometry)
|
| - : fBlob(SkRef(geometry.fBlob.get()))
|
| - , fRun(geometry.fRun)
|
| - , fSubRun(geometry.fSubRun)
|
| - , fColor(geometry.fColor)
|
| - , fTransX(geometry.fTransX)
|
| - , fTransY(geometry.fTransY) {}
|
| - SkAutoTUnref<Blob> fBlob;
|
| + Blob* fBlob;
|
| int fRun;
|
| int fSubRun;
|
| GrColor fColor;
|
| @@ -798,9 +790,9 @@ public:
|
| SkScalar fTransY;
|
| };
|
|
|
| - static GrBatch* Create(const Geometry& geometry, GrMaskFormat maskFormat,
|
| - int glyphCount, GrBatchFontCache* fontCache) {
|
| - return SkNEW_ARGS(BitmapTextBatch, (geometry, maskFormat, glyphCount, fontCache));
|
| + static BitmapTextBatch* Create(GrMaskFormat maskFormat, int glyphCount,
|
| + GrBatchFontCache* fontCache) {
|
| + return SkNEW_ARGS(BitmapTextBatch, (maskFormat, glyphCount, fontCache));
|
| }
|
|
|
| const char* name() const override { return "BitmapTextBatch"; }
|
| @@ -876,7 +868,7 @@ public:
|
| this->initDraw(batchTarget, gp, pipeline);
|
|
|
| int glyphCount = this->numGlyphs();
|
| - int instanceCount = fGeoData.count();
|
| + int instanceCount = fInstanceCount;
|
| const GrVertexBuffer* vertexBuffer;
|
| int firstVertex;
|
|
|
| @@ -1018,19 +1010,38 @@ public:
|
| this->flush(batchTarget, &drawInfo, instancesToFlush, maxInstancesPerDraw);
|
| }
|
|
|
| - SkSTArray<1, Geometry, true>* geoData() { return &fGeoData; }
|
| + // The minimum number of Geometry we will try to allocate.
|
| + static const int kMinAllocated = 32;
|
| +
|
| + // Total number of Geometry this Batch owns
|
| + int instanceCount() const { return fInstanceCount; }
|
| + SkAutoSTMalloc<kMinAllocated, Geometry>* geoData() { return &fGeoData; }
|
| +
|
| + // to avoid even the initial copy of the struct, we have a getter for the first item which
|
| + // is used to seed the batch with its initial geometry. After seeding, the client should call
|
| + // init() so the Batch can initialize itself
|
| + Geometry& geometry() { return fGeoData[0]; }
|
| + void init() {
|
| + fBatch.fColor = fGeoData[0].fColor;
|
| + fBatch.fViewMatrix = fGeoData[0].fBlob->fViewMatrix;
|
| + }
|
|
|
| private:
|
| - BitmapTextBatch(const Geometry& geometry, GrMaskFormat maskFormat,
|
| + BitmapTextBatch(GrMaskFormat maskFormat,
|
| int glyphCount, GrBatchFontCache* fontCache)
|
| : fMaskFormat(maskFormat)
|
| , fPixelConfig(fontCache->getPixelConfig(maskFormat))
|
| , fFontCache(fontCache) {
|
| this->initClassID<BitmapTextBatch>();
|
| - fGeoData.push_back(geometry);
|
| - fBatch.fColor = geometry.fColor;
|
| - fBatch.fViewMatrix = geometry.fBlob->fViewMatrix;
|
| fBatch.fNumGlyphs = glyphCount;
|
| + fInstanceCount = 1;
|
| + fAllocatedCount = kMinAllocated;
|
| + }
|
| +
|
| + ~BitmapTextBatch() {
|
| + for (int i = 0; i < fInstanceCount; i++) {
|
| + fGeoData[i].fBlob->unref();
|
| + }
|
| }
|
|
|
| void regenerateTextureCoords(GrGlyph* glyph, intptr_t vertex, size_t vertexStride) {
|
| @@ -1133,7 +1144,25 @@ private:
|
| }
|
|
|
| fBatch.fNumGlyphs += that->numGlyphs();
|
| - fGeoData.push_back_n(that->geoData()->count(), that->geoData()->begin());
|
| +
|
| + // copy that->geoData(). We do this manually for performance reasons
|
| + SkAutoSTMalloc<kMinAllocated, Geometry>* otherGeoData = that->geoData();
|
| + int otherInstanceCount = that->instanceCount();
|
| + int allocSize = otherInstanceCount + fInstanceCount;
|
| + if (allocSize > fAllocatedCount) {
|
| + while (allocSize > fAllocatedCount) {
|
| + fAllocatedCount = fAllocatedCount << 1;
|
| + }
|
| + fGeoData.realloc(fAllocatedCount);
|
| + }
|
| +
|
| + memcpy(&fGeoData[fInstanceCount], otherGeoData->get(),
|
| + otherInstanceCount * sizeof(Geometry));
|
| + int total = fInstanceCount + otherInstanceCount;
|
| + for (int i = fInstanceCount; i < total; i++) {
|
| + fGeoData[i].fBlob->ref();
|
| + }
|
| + fInstanceCount = total;
|
| return true;
|
| }
|
|
|
| @@ -1147,7 +1176,9 @@ private:
|
| };
|
|
|
| BatchTracker fBatch;
|
| - SkSTArray<1, Geometry, true> fGeoData;
|
| + SkAutoSTMalloc<kMinAllocated, Geometry> fGeoData;
|
| + int fInstanceCount;
|
| + int fAllocatedCount;
|
| GrMaskFormat fMaskFormat;
|
| GrPixelConfig fPixelConfig;
|
| GrBatchFontCache* fFontCache;
|
| @@ -1201,15 +1232,16 @@ inline void GrAtlasTextContext::flushRun(GrDrawTarget* target, GrPipelineBuilder
|
| SkColorSetARGB(paintAlpha, paintAlpha, paintAlpha, paintAlpha) :
|
| color;
|
|
|
| - BitmapTextBatch::Geometry geometry;
|
| - geometry.fBlob.reset(SkRef(cacheBlob));
|
| + SkAutoTUnref<BitmapTextBatch> batch(BitmapTextBatch::Create(format, glyphCount,
|
| + fContext->getBatchFontCache()));
|
| + BitmapTextBatch::Geometry& geometry = batch->geometry();
|
| + geometry.fBlob = SkRef(cacheBlob);
|
| geometry.fRun = run;
|
| geometry.fSubRun = subRun;
|
| geometry.fColor = subRunColor;
|
| geometry.fTransX = transX;
|
| geometry.fTransY = transY;
|
| - SkAutoTUnref<GrBatch> batch(BitmapTextBatch::Create(geometry, format, glyphCount,
|
| - fContext->getBatchFontCache()));
|
| + batch->init();
|
|
|
| target->drawBatch(pipelineBuilder, batch, &cacheBlob->fRuns[run].fVertexBounds);
|
| }
|
|
|