diff --git a/src/gpu/GrAtlasTextBlob.h b/src/gpu/GrAtlasTextBlob.h index 6ea8662700..09f9dc01a8 100644 --- a/src/gpu/GrAtlasTextBlob.h +++ b/src/gpu/GrAtlasTextBlob.h @@ -77,7 +77,6 @@ struct GrAtlasTextBlob : public SkRefCnt { , fVertexEndIndex(0) , fGlyphStartIndex(0) , fGlyphEndIndex(0) - , fTextRatio(1.0f) , fMaskFormat(kA8_GrMaskFormat) , fDrawAsDistanceFields(false) , fUseLCDText(false) {} @@ -89,18 +88,44 @@ struct GrAtlasTextBlob : public SkRefCnt { , fVertexEndIndex(that.fVertexEndIndex) , fGlyphStartIndex(that.fGlyphStartIndex) , fGlyphEndIndex(that.fGlyphEndIndex) - , fTextRatio(that.fTextRatio) , fMaskFormat(that.fMaskFormat) , fDrawAsDistanceFields(that.fDrawAsDistanceFields) , fUseLCDText(that.fUseLCDText) { } - // Distance field text cannot draw coloremoji, and so has to fall back. However, - // though the distance field text and the coloremoji may share the same run, they - // will have different descriptors. If fOverrideDescriptor is non-nullptr, then it - // will be used in place of the run's descriptor to regen texture coords - // TODO we could have a descriptor cache, it would reduce the size of these blobs - // significantly, and then the subrun could just have a refed pointer to the - // correct descriptor. + + void resetBulkUseToken() { fBulkUseToken.reset(); } + GrBatchAtlas::BulkUseTokenUpdater* bulkUseToken() { return &fBulkUseToken; } + void setStrike(GrBatchTextStrike* strike) { fStrike.reset(SkRef(strike)); } + GrBatchTextStrike* strike() const { return fStrike.get(); } + + void setAtlasGeneration(uint64_t atlasGeneration) { fAtlasGeneration = atlasGeneration;} + uint64_t atlasGeneration() const { return fAtlasGeneration; } + + size_t byteCount() const { return fVertexEndIndex - fVertexStartIndex; } + void setVertexStartIndex(size_t vertStartIndex) { fVertexStartIndex = vertStartIndex;} + size_t vertexStartIndex() const { return fVertexStartIndex; } + void setVertexEndIndex(size_t vertEndIndex) { fVertexEndIndex = vertEndIndex; } + size_t vertexEndIndex() const { return fVertexEndIndex; } + void appendVertices(size_t vertexStride) { + fVertexEndIndex += vertexStride * kVerticesPerGlyph; + } + + uint32_t glyphCount() const { return fGlyphEndIndex - fGlyphStartIndex; } + void setGlyphStartIndex(uint32_t glyphStartIndex) { fGlyphStartIndex = glyphStartIndex;} + uint32_t glyphStartIndex() const { return fGlyphStartIndex; } + void setGlyphEndIndex(uint32_t glyphEndIndex) { fGlyphEndIndex = glyphEndIndex; } + uint32_t glyphEndIndex() const { return fGlyphEndIndex; } + void glyphAppended() { fGlyphEndIndex++; } + void setMaskFormat(GrMaskFormat format) { fMaskFormat = format; } + GrMaskFormat maskFormat() const { return fMaskFormat; } + + // df properties + void setUseLCDText(bool useLCDText) { fUseLCDText = useLCDText; } + bool hasUseLCDText() const { return fUseLCDText; } + void setDrawAsDistanceFields() { fDrawAsDistanceFields = true; } + bool drawAsDistanceFields() const { return fDrawAsDistanceFields; } + + private: GrBatchAtlas::BulkUseTokenUpdater fBulkUseToken; SkAutoTUnref fStrike; uint64_t fAtlasGeneration; @@ -108,7 +133,6 @@ struct GrAtlasTextBlob : public SkRefCnt { size_t fVertexEndIndex; uint32_t fGlyphStartIndex; uint32_t fGlyphEndIndex; - SkScalar fTextRatio; // df property GrMaskFormat fMaskFormat; bool fDrawAsDistanceFields; // df property bool fUseLCDText; // df property @@ -119,11 +143,11 @@ struct GrAtlasTextBlob : public SkRefCnt { SubRunInfo& newSubRun = fSubRunInfo.push_back(); SubRunInfo& prevSubRun = fSubRunInfo.fromBack(1); - newSubRun.fGlyphStartIndex = prevSubRun.fGlyphEndIndex; - newSubRun.fGlyphEndIndex = prevSubRun.fGlyphEndIndex; + newSubRun.setGlyphStartIndex(prevSubRun.glyphEndIndex()); + newSubRun.setGlyphEndIndex(prevSubRun.glyphEndIndex()); - newSubRun.fVertexStartIndex = prevSubRun.fVertexEndIndex; - newSubRun.fVertexEndIndex = prevSubRun.fVertexEndIndex; + newSubRun.setVertexStartIndex(prevSubRun.vertexEndIndex()); + newSubRun.setVertexEndIndex(prevSubRun.vertexEndIndex()); return newSubRun; } static const int kMinSubRuns = 1; @@ -131,6 +155,11 @@ struct GrAtlasTextBlob : public SkRefCnt { SkRect fVertexBounds; SkSTArray fSubRunInfo; SkAutoDescriptor fDescriptor; + + // Distance field text cannot draw coloremoji, and so has to fall back. However, + // though the distance field text and the coloremoji may share the same run, they + // will have different descriptors. If fOverrideDescriptor is non-nullptr, then it + // will be used in place of the run's descriptor to regen texture coords SkAutoTDelete fOverrideDescriptor; // df properties GrColor fColor; bool fInitialized; @@ -240,6 +269,12 @@ struct GrAtlasTextBlob : public SkRefCnt { bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); } void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; } void setHasBitmap() { fTextType |= kHasBitmap_TextType; } + void appendGlyph(Run::SubRunInfo* subrun, GrGlyph* glyph) { + this->fGlyphs[subrun->glyphEndIndex()] = glyph; + subrun->glyphAppended(); + } + + static const int kVerticesPerGlyph = 4; #ifdef CACHE_SANITY_CHECK static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&); diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp index bfc58f58b9..cac52fb2f0 100644 --- a/src/gpu/GrAtlasTextContext.cpp +++ b/src/gpu/GrAtlasTextContext.cpp @@ -466,11 +466,11 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, PerSubRunInfo& newRun = cacheBlob->fRuns[run].fSubRunInfo.back(); PerSubRunInfo& lastRun = cacheBlob->fRuns[run - 1].fSubRunInfo.back(); - newRun.fVertexStartIndex = lastRun.fVertexEndIndex; - newRun.fVertexEndIndex = lastRun.fVertexEndIndex; + newRun.setVertexStartIndex(lastRun.vertexEndIndex()); + newRun.setVertexEndIndex(lastRun.vertexEndIndex()); - newRun.fGlyphStartIndex = lastRun.fGlyphEndIndex; - newRun.fGlyphEndIndex = lastRun.fGlyphEndIndex; + newRun.setGlyphStartIndex(lastRun.glyphEndIndex()); + newRun.setGlyphEndIndex(lastRun.glyphEndIndex()); } if (this->canDrawAsDistanceFields(runPaint, viewMatrix)) { @@ -480,8 +480,8 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, this->initDistanceFieldPaint(cacheBlob, &dfPaint, &textRatio, viewMatrix); Run& runIdx = cacheBlob->fRuns[run]; PerSubRunInfo& subRun = runIdx.fSubRunInfo.back(); - subRun.fUseLCDText = runPaint.isLCDRenderText(); - subRun.fDrawAsDistanceFields = true; + subRun.setUseLCDText(runPaint.isLCDRenderText()); + subRun.setDrawAsDistanceFields(); SkTDArray fallbackTxt; SkTDArray fallbackPos; @@ -641,8 +641,8 @@ GrAtlasTextContext::setupDFBlob(int glyphCount, const SkPaint& origPaint, blob->fViewMatrix = viewMatrix; Run& run = blob->fRuns[0]; PerSubRunInfo& subRun = run.fSubRunInfo.back(); - subRun.fUseLCDText = origPaint.isLCDRenderText(); - subRun.fDrawAsDistanceFields = true; + subRun.setUseLCDText(origPaint.isLCDRenderText()); + subRun.setDrawAsDistanceFields(); return blob; } @@ -1007,11 +1007,11 @@ void GrAtlasTextContext::bmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, GrMaskFormat format = glyph->fMaskFormat; PerSubRunInfo* subRun = &run.fSubRunInfo.back(); - if (run.fInitialized && subRun->fMaskFormat != format) { + if (run.fInitialized && subRun->maskFormat() != format) { subRun = &run.push_back(); - subRun->fStrike.reset(SkRef(fCurrStrike)); + subRun->setStrike(fCurrStrike); } else if (!run.fInitialized) { - subRun->fStrike.reset(SkRef(fCurrStrike)); + subRun->setStrike(SkRef(fCurrStrike)); } run.fInitialized = true; @@ -1023,7 +1023,7 @@ void GrAtlasTextContext::bmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, r.fTop = SkIntToScalar(y); r.fRight = r.fLeft + SkIntToScalar(width); r.fBottom = r.fTop + SkIntToScalar(height); - subRun->fMaskFormat = format; + subRun->setMaskFormat(format); this->appendGlyphCommon(blob, &run, subRun, r, color, vertexStride, kA8_GrMaskFormat == format, glyph); } @@ -1075,16 +1075,16 @@ bool GrAtlasTextContext::dfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, PerSubRunInfo* subRun = &run.fSubRunInfo.back(); if (!run.fInitialized) { - subRun->fStrike.reset(SkRef(fCurrStrike)); + subRun->setStrike(fCurrStrike); } run.fInitialized = true; SkASSERT(glyph->fMaskFormat == kA8_GrMaskFormat); - subRun->fMaskFormat = kA8_GrMaskFormat; + subRun->setMaskFormat(kA8_GrMaskFormat); size_t vertexStride = GrAtlasTextBatch::GetVertexStrideDf(kA8_GrMaskFormat, - subRun->fUseLCDText); + subRun->hasUseLCDText()); - bool useColorVerts = !subRun->fUseLCDText; + bool useColorVerts = !subRun->hasUseLCDText(); this->appendGlyphCommon(blob, &run, subRun, glyphRect, color, vertexStride, useColorVerts, glyph); return true; @@ -1110,11 +1110,11 @@ inline void GrAtlasTextContext::appendGlyphCommon(GrAtlasTextBlob* blob, Run* ru const SkRect& positions, GrColor color, size_t vertexStride, bool useVertexColor, GrGlyph* glyph) { - blob->fGlyphs[subRun->fGlyphEndIndex] = glyph; + blob->appendGlyph(subRun, glyph); run->fVertexBounds.joinNonEmptyArg(positions); run->fColor = color; - intptr_t vertex = reinterpret_cast(blob->fVertices + subRun->fVertexEndIndex); + intptr_t vertex = reinterpret_cast(blob->fVertices + subRun->vertexEndIndex()); if (useVertexColor) { // V0 @@ -1163,9 +1163,7 @@ inline void GrAtlasTextContext::appendGlyphCommon(GrAtlasTextBlob* blob, Run* ru position = reinterpret_cast(vertex); position->set(positions.fRight, positions.fTop); } - - subRun->fGlyphEndIndex++; - subRun->fVertexEndIndex += vertexStride * GrAtlasTextBatch::kVerticesPerGlyph; + subRun->appendVertices(vertexStride); } void GrAtlasTextContext::flushRunAsPaths(GrDrawContext* dc, @@ -1211,7 +1209,7 @@ GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo& int glyphCount, int run, int subRun, GrColor color, SkScalar transX, SkScalar transY, const SkPaint& skPaint) { - GrMaskFormat format = info.fMaskFormat; + GrMaskFormat format = info.maskFormat(); GrColor subRunColor; if (kARGB_GrMaskFormat == format) { uint8_t paintAlpha = skPaint.getAlpha(); @@ -1221,7 +1219,7 @@ GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo& } GrAtlasTextBatch* batch; - if (info.fDrawAsDistanceFields) { + if (info.drawAsDistanceFields()) { SkColor filteredColor; SkColorFilter* colorFilter = skPaint.getColorFilter(); if (colorFilter) { @@ -1232,7 +1230,7 @@ GrAtlasTextContext::createBatch(GrAtlasTextBlob* cacheBlob, const PerSubRunInfo& bool useBGR = SkPixelGeometryIsBGR(fSurfaceProps.pixelGeometry()); batch = GrAtlasTextBatch::CreateDistanceField(glyphCount, fContext->getBatchFontCache(), fDistanceAdjustTable, filteredColor, - info.fUseLCDText, useBGR); + info.hasUseLCDText(), useBGR); } else { batch = GrAtlasTextBatch::CreateBitmap(format, glyphCount, fContext->getBatchFontCache()); } @@ -1254,7 +1252,7 @@ inline void GrAtlasTextContext::flushRun(GrDrawContext* dc, GrPipelineBuilder* p const SkPaint& skPaint) { for (int subRun = 0; subRun < cacheBlob->fRuns[run].fSubRunInfo.count(); subRun++) { const PerSubRunInfo& info = cacheBlob->fRuns[run].fSubRunInfo[subRun]; - int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; + int glyphCount = info.glyphCount(); if (0 == glyphCount) { continue; } diff --git a/src/gpu/batches/GrAtlasTextBatch.cpp b/src/gpu/batches/GrAtlasTextBatch.cpp index fa34036af6..b1ec1f8ef5 100644 --- a/src/gpu/batches/GrAtlasTextBatch.cpp +++ b/src/gpu/batches/GrAtlasTextBatch.cpp @@ -135,7 +135,7 @@ inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl static_assert(!regenGlyphs || regenTexCoords, "must regenTexCoords along regenGlyphs"); GrBatchTextStrike* strike = nullptr; if (regenTexCoords) { - info->fBulkUseToken.reset(); + info->resetBulkUseToken(); // We can reuse if we have a valid strike and our descriptors / typeface are the // same. The override descriptor is only for the non distance field text within @@ -151,14 +151,14 @@ inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl *desc = newDesc; *cache = SkGlyphCache::DetachCache(run->fTypeface, *desc); *scaler = GrTextContext::GetGrFontScaler(*cache); - strike = info->fStrike; + strike = info->strike(); *typeface = run->fTypeface; } if (regenGlyphs) { strike = fFontCache->getStrike(*scaler); } else { - strike = info->fStrike; + strike = info->strike(); } } @@ -166,7 +166,7 @@ inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl for (int glyphIdx = 0; glyphIdx < glyphCount; glyphIdx++) { GrGlyph* glyph = nullptr; if (regenTexCoords) { - size_t glyphOffset = glyphIdx + info->fGlyphStartIndex; + size_t glyphOffset = glyphIdx + info->glyphStartIndex(); if (regenGlyphs) { // Get the id from the old glyph, and use the new strike to lookup @@ -190,12 +190,12 @@ inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl this->maskFormat()); SkASSERT(success); } - fFontCache->addGlyphToBulkAndSetUseToken(&info->fBulkUseToken, glyph, + fFontCache->addGlyphToBulkAndSetUseToken(info->bulkUseToken(), glyph, target->currentToken()); } intptr_t vertex = reinterpret_cast(blob->fVertices); - vertex += info->fVertexStartIndex; + vertex += info->vertexStartIndex(); vertex += vertexStride * glyphIdx * GrAtlasTextBatch::kVerticesPerGlyph; regen_vertices(vertex, glyph, vertexStride, this->usesDistanceFields(), transX, @@ -207,10 +207,10 @@ inline void GrAtlasTextBatch::regenBlob(Target* target, FlushInfo* flushInfo, Bl run->fColor = color; if (regenTexCoords) { if (regenGlyphs) { - info->fStrike.reset(SkRef(strike)); + info->setStrike(strike); } - info->fAtlasGeneration = brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration : - fFontCache->atlasGeneration(this->maskFormat()); + info->setAtlasGeneration(brokenRun ? GrBatchAtlas::kInvalidAtlasGeneration : + fFontCache->atlasGeneration(this->maskFormat())); } } /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -378,8 +378,8 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { // new strike, we instead keep our ref to the old strike and use the packed ids from // it. These ids will still be valid as long as we hold the ref. When we are done // updating our cache of the GrGlyph*s, we drop our ref on the old strike - bool regenerateGlyphs = info.fStrike->isAbandoned(); - bool regenerateTextureCoords = info.fAtlasGeneration != currentAtlasGen || + bool regenerateGlyphs = info.strike()->isAbandoned(); + bool regenerateTextureCoords = info.atlasGeneration() != currentAtlasGen || regenerateGlyphs; bool regenerateColors; if (usesDistanceFields) { @@ -388,7 +388,7 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { regenerateColors = kA8_GrMaskFormat == maskFormat && run.fColor != args.fColor; } bool regeneratePositions = args.fTransX != 0.f || args.fTransY != 0.f; - int glyphCount = info.fGlyphEndIndex - info.fGlyphStartIndex; + int glyphCount = info.glyphCount(); uint32_t regenMaskBits = kNoRegen; regenMaskBits |= regeneratePositions ? kRegenPos : 0; @@ -416,13 +416,14 @@ void GrAtlasTextBatch::onPrepareDraws(Target* target) const { // set use tokens for all of the glyphs in our subrun. This is only valid if we // have a valid atlas generation - fFontCache->setUseTokenBulk(info.fBulkUseToken, target->currentToken(), maskFormat); + fFontCache->setUseTokenBulk(*info.bulkUseToken(), target->currentToken(), + maskFormat); break; } // now copy all vertices - size_t byteCount = info.fVertexEndIndex - info.fVertexStartIndex; - memcpy(currVertex, blob->fVertices + info.fVertexStartIndex, byteCount); + size_t byteCount = info.byteCount(); + memcpy(currVertex, blob->fVertices + info.vertexStartIndex(), byteCount); currVertex += byteCount; } diff --git a/src/gpu/batches/GrAtlasTextBatch.h b/src/gpu/batches/GrAtlasTextBatch.h index 65fd07d7bb..11cd89ea9a 100644 --- a/src/gpu/batches/GrAtlasTextBatch.h +++ b/src/gpu/batches/GrAtlasTextBatch.h @@ -20,7 +20,7 @@ public: // position + local coord static const size_t kColorTextVASize = sizeof(SkPoint) + sizeof(SkIPoint16); static const size_t kGrayTextVASize = sizeof(SkPoint) + sizeof(GrColor) + sizeof(SkIPoint16); - static const int kVerticesPerGlyph = 4; + static const int kVerticesPerGlyph = GrAtlasTextBlob::kVerticesPerGlyph; static const int kIndicesPerGlyph = 6; typedef GrAtlasTextContext::DistanceAdjustTable DistanceAdjustTable; @@ -89,7 +89,7 @@ public: // We don't yet position distance field text on the cpu, so we have to map the vertex bounds // into device space const Run& run = geo.fBlob->fRuns[geo.fRun]; - if (run.fSubRunInfo[geo.fSubRun].fDrawAsDistanceFields) { + if (run.fSubRunInfo[geo.fSubRun].drawAsDistanceFields()) { SkRect bounds = run.fVertexBounds; fBatch.fViewMatrix.mapRect(&bounds); this->setBounds(bounds);