From 5c6ac64516bb56bbdb5d7aedee1a348acc16e29b Mon Sep 17 00:00:00 2001 From: Brian Salomon Date: Tue, 19 Dec 2017 11:09:32 -0500 Subject: Revert "Revert "move homogenous with stride to matrixpriv"" This reverts commit de71572f650005e36d4fc2fe95fb5677a25ae4f6. Revert "Revert "Transform vertices for distance field glyphs on CPU."" This reverts commit f226e66d75374e370f3ae2c6895bc689670e9e18. Change-Id: I2545afae3beb1d6b14bba056853ed826ae7a4679 Reviewed-on: https://skia-review.googlesource.com/86603 Reviewed-by: Greg Daniel Commit-Queue: Brian Salomon --- src/gpu/text/GrAtlasTextBlob.cpp | 79 +++++++++-------------- src/gpu/text/GrAtlasTextBlob.h | 29 +++++++-- src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp | 8 ++- src/gpu/text/GrAtlasTextContext.cpp | 3 +- 4 files changed, 61 insertions(+), 58 deletions(-) (limited to 'src/gpu/text') diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp index 0b25a34ed1..02f3ab0a21 100644 --- a/src/gpu/text/GrAtlasTextBlob.cpp +++ b/src/gpu/text/GrAtlasTextBlob.cpp @@ -96,7 +96,13 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, run.fInitialized = true; - size_t vertexStride = GetVertexStride(format); + bool hasW = subRun->hasWCoord(); + // DF glyphs drawn in perspective must always have a w coord. + SkASSERT(hasW || !subRun->drawAsDistanceFields() || !fInitialViewMatrix.hasPerspective()); + // Non-DF glyphs should never have a w coord. + SkASSERT(!hasW || subRun->drawAsDistanceFields()); + + size_t vertexStride = GetVertexStride(format, hasW); subRun->setMaskFormat(format); @@ -105,53 +111,29 @@ void GrAtlasTextBlob::appendGlyph(int runIndex, intptr_t vertex = reinterpret_cast(this->fVertices + subRun->vertexEndIndex()); - if (kARGB_GrMaskFormat != glyph->fMaskFormat) { - // V0 - SkPoint* position = reinterpret_cast(vertex); - position->set(positions.fLeft, positions.fTop); - SkColor* colorPtr = reinterpret_cast(vertex + sizeof(SkPoint)); - *colorPtr = color; - vertex += vertexStride; - - // V1 - position = reinterpret_cast(vertex); - position->set(positions.fLeft, positions.fBottom); - colorPtr = reinterpret_cast(vertex + sizeof(SkPoint)); - *colorPtr = color; - vertex += vertexStride; - - // V2 - position = reinterpret_cast(vertex); - position->set(positions.fRight, positions.fTop); - colorPtr = reinterpret_cast(vertex + sizeof(SkPoint)); - *colorPtr = color; - vertex += vertexStride; - - // V3 - position = reinterpret_cast(vertex); - position->set(positions.fRight, positions.fBottom); - colorPtr = reinterpret_cast(vertex + sizeof(SkPoint)); - *colorPtr = color; - } else { - // V0 - SkPoint* position = reinterpret_cast(vertex); - position->set(positions.fLeft, positions.fTop); - vertex += vertexStride; - - // V1 - position = reinterpret_cast(vertex); - position->set(positions.fLeft, positions.fBottom); - vertex += vertexStride; - - // V2 - position = reinterpret_cast(vertex); - position->set(positions.fRight, positions.fTop); - vertex += vertexStride; - - // V3 - position = reinterpret_cast(vertex); - position->set(positions.fRight, positions.fBottom); - } + // We always write the third position component used by SDFs. If it is unused it gets + // overwritten. Similarly, we always write the color and the blob will later overwrite it + // with texture coords if it is unused. + size_t colorOffset = hasW ? sizeof(SkPoint3) : sizeof(SkPoint); + // V0 + *reinterpret_cast(vertex) = {positions.fLeft, positions.fTop, 1.f}; + *reinterpret_cast(vertex + colorOffset) = color; + vertex += vertexStride; + + // V1 + *reinterpret_cast(vertex) = {positions.fLeft, positions.fBottom, 1.f}; + *reinterpret_cast(vertex + colorOffset) = color; + vertex += vertexStride; + + // V2 + *reinterpret_cast(vertex) = {positions.fRight, positions.fTop, 1.f}; + *reinterpret_cast(vertex + colorOffset) = color; + vertex += vertexStride; + + // V3 + *reinterpret_cast(vertex) = {positions.fRight, positions.fBottom, 1.f}; + *reinterpret_cast(vertex + colorOffset) = color; + subRun->appendVertices(vertexStride); fGlyphs[subRun->glyphEndIndex()] = glyph; subRun->glyphAppended(); @@ -185,6 +167,7 @@ bool GrAtlasTextBlob::mustRegenerate(const GrTextUtils::Paint& paint, return true; } + /** This could be relaxed for blobs with only distance field glyphs. */ if (fInitialViewMatrix.hasPerspective() && !fInitialViewMatrix.cheapEqualTo(viewMatrix)) { return true; } diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h index 450e256d38..282fa98141 100644 --- a/src/gpu/text/GrAtlasTextBlob.h +++ b/src/gpu/text/GrAtlasTextBlob.h @@ -17,6 +17,7 @@ #include "SkMaskFilter.h" #include "SkOpts.h" #include "SkPathEffect.h" +#include "SkPoint3.h" #include "SkRasterizer.h" #include "SkSurfaceProps.h" #include "SkTInternalLList.h" @@ -53,6 +54,12 @@ public: static sk_sp Make(GrMemoryPool* pool, int glyphCount, int runCount); + /** + * We currently force regeneration of a blob if old or new matrix differ in having perspective. + * If we ever change that then the key must contain the perspectiveness when there are distance + * fields as perspective distance field use 3 component vertex positions and non-perspective + * uses 2. + */ struct Key { Key() { sk_bzero(this, sizeof(Key)); @@ -126,12 +133,13 @@ public: } // sets the last subrun of runIndex to use distance field text - void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias) { + void setSubRunHasDistanceFields(int runIndex, bool hasLCD, bool isAntiAlias, bool hasWCoord) { Run& run = fRuns[runIndex]; Run::SubRunInfo& subRun = run.fSubRunInfo.back(); subRun.setUseLCDText(hasLCD); subRun.setAntiAliased(isAntiAlias); subRun.setDrawAsDistanceFields(); + subRun.setHasWCoord(hasWCoord); } void setRunDrawAsPaths(int runIndex) { @@ -169,13 +177,15 @@ public: SkGlyphCache*, const SkGlyph& skGlyph, SkScalar x, SkScalar y, SkScalar scale, bool treatAsBMP); - static size_t GetVertexStride(GrMaskFormat maskFormat) { + static size_t GetVertexStride(GrMaskFormat maskFormat, bool isDistanceFieldWithWCoord) { switch (maskFormat) { case kA8_GrMaskFormat: - return kGrayTextVASize; + return isDistanceFieldWithWCoord ? kGrayTextDFPerspectiveVASize : kGrayTextVASize; case kARGB_GrMaskFormat: + SkASSERT(!isDistanceFieldWithWCoord); return kColorTextVASize; default: + SkASSERT(!isDistanceFieldWithWCoord); return kLCDTextVASize; } } @@ -232,8 +242,10 @@ 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 size_t kGrayTextDFPerspectiveVASize = + sizeof(SkPoint3) + sizeof(GrColor) + sizeof(SkIPoint16); static const size_t kLCDTextVASize = kGrayTextVASize; - static const size_t kMaxVASize = kGrayTextVASize; + static const size_t kMaxVASize = kGrayTextDFPerspectiveVASize; static const int kVerticesPerGlyph = 4; static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&); @@ -419,7 +431,7 @@ private: // This function assumes the translation will be applied before it is called again void computeTranslation(const SkMatrix& viewMatrix, SkScalar x, SkScalar y, - SkScalar*transX, SkScalar* transY); + SkScalar* transX, SkScalar* transY); // df properties void setDrawAsDistanceFields() { fFlags |= kDrawAsSDF_Flag; } @@ -432,12 +444,17 @@ private: fFlags = antiAliased ? fFlags | kAntiAliased_Flag : fFlags & ~kAntiAliased_Flag; } bool isAntiAliased() const { return SkToBool(fFlags & kAntiAliased_Flag); } + void setHasWCoord(bool hasW) { + fFlags = hasW ? (fFlags | kHasWCoord_Flag) : fFlags & ~kHasWCoord_Flag; + } + bool hasWCoord() const { return SkToBool(fFlags & kHasWCoord_Flag); } private: enum Flag { kDrawAsSDF_Flag = 0x1, kUseLCDText_Flag = 0x2, - kAntiAliased_Flag = 0x4 + kAntiAliased_Flag = 0x4, + kHasWCoord_Flag = 0x8 }; GrDrawOpAtlas::BulkUseTokenUpdater fBulkUseToken; diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp index 28b2e0f0c0..1be5ae330c 100644 --- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp +++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp @@ -71,8 +71,8 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri // This is a bit wonky, but sometimes we have LCD text, in which case we won't have color // vertices, hence vertexStride - sizeof(SkIPoint16) - intptr_t colorOffset = sizeof(SkPoint); intptr_t texCoordOffset = vertexStride - sizeof(SkIPoint16); + intptr_t colorOffset = texCoordOffset - sizeof(GrColor); // V0 if (regenPos) { @@ -211,8 +211,9 @@ Regenerator::Result Regenerator::doRegen() { } } + bool hasW = fSubRun->hasWCoord(); Result result; - auto vertexStride = GetVertexStride(fSubRun->maskFormat()); + auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW); char* currVertex = fBlob->fVertices + fSubRun->vertexStartIndex() + fCurrGlyph * kVerticesPerGlyph * vertexStride; result.fFirstVertex = currVertex; @@ -300,7 +301,8 @@ Regenerator::Result Regenerator::regenerate() { return this->doRegen(); case kNoRegen: { Result result; - auto vertexStride = GetVertexStride(fSubRun->maskFormat()); + bool hasW = fSubRun->hasWCoord(); + auto vertexStride = GetVertexStride(fSubRun->maskFormat(), hasW); result.fGlyphsRegenerated = fSubRun->glyphCount() - fCurrGlyph; result.fFirstVertex = fBlob->fVertices + fSubRun->vertexStartIndex() + fCurrGlyph * kVerticesPerGlyph * vertexStride; diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index d617786944..3faa0f7b87 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -646,13 +646,14 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, SkTDArray fallbackTxt; SkTDArray fallbackPos; + bool hasWCoord = viewMatrix.hasPerspective(); // Setup distance field paint and text ratio SkScalar textRatio; SkPaint dfPaint(paint); this->initDistanceFieldPaint(blob, &dfPaint, &textRatio, viewMatrix); blob->setHasDistanceField(); blob->setSubRunHasDistanceFields(runIndex, paint.skPaint().isLCDRenderText(), - paint.skPaint().isAntiAlias()); + paint.skPaint().isAntiAlias(), hasWCoord); GrAtlasTextStrike* currStrike = nullptr; -- cgit v1.2.3