diff options
author | joshualitt <joshualitt@chromium.org> | 2015-07-21 11:39:34 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-07-21 11:39:35 -0700 |
commit | 259fbf191625d504e20c7ede69d988735fc569ad (patch) | |
tree | 35e29f248d57965594e8cdcfa22f1fc38a6388cb /src | |
parent | f6e092aa9c49cbfb2e4fa4e2cf28fe8ab459499d (diff) |
Add sanity check to GrAtlasTextBlob
BUG=skia:
Review URL: https://codereview.chromium.org/1250693002
Diffstat (limited to 'src')
-rw-r--r-- | src/gpu/GrAtlasTextBlob.cpp | 109 | ||||
-rw-r--r-- | src/gpu/GrAtlasTextBlob.h | 13 | ||||
-rw-r--r-- | src/gpu/GrAtlasTextContext.cpp | 17 | ||||
-rw-r--r-- | src/gpu/GrTextBlobCache.cpp | 13 | ||||
-rw-r--r-- | src/gpu/GrTextBlobCache.h | 29 |
5 files changed, 166 insertions, 15 deletions
diff --git a/src/gpu/GrAtlasTextBlob.cpp b/src/gpu/GrAtlasTextBlob.cpp new file mode 100644 index 0000000000..d357145cbc --- /dev/null +++ b/src/gpu/GrAtlasTextBlob.cpp @@ -0,0 +1,109 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "GrAtlasTextBlob.h" + +#ifdef CACHE_SANITY_CHECK +void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) { + SkASSERT(l.fSize == r.fSize); + SkASSERT(l.fPool == r.fPool); + + SkASSERT(l.fBlurRec.fSigma == r.fBlurRec.fSigma); + SkASSERT(l.fBlurRec.fStyle == r.fBlurRec.fStyle); + SkASSERT(l.fBlurRec.fQuality == r.fBlurRec.fQuality); + + SkASSERT(l.fStrokeInfo.fFrameWidth == r.fStrokeInfo.fFrameWidth); + SkASSERT(l.fStrokeInfo.fMiterLimit == r.fStrokeInfo.fMiterLimit); + SkASSERT(l.fStrokeInfo.fJoin == r.fStrokeInfo.fJoin); + + SkASSERT(l.fBigGlyphs.count() == r.fBigGlyphs.count()); + for (int i = 0; i < l.fBigGlyphs.count(); i++) { + const BigGlyph& lBigGlyph = l.fBigGlyphs[i]; + const BigGlyph& rBigGlyph = r.fBigGlyphs[i]; + + SkASSERT(lBigGlyph.fPath == rBigGlyph.fPath); + // We can't assert that these have the same translations + } + + SkASSERT(l.fKey == r.fKey); + SkASSERT(l.fViewMatrix.cheapEqualTo(r.fViewMatrix)); + SkASSERT(l.fPaintColor == r.fPaintColor); + SkASSERT(l.fMaxMinScale == r.fMaxMinScale); + SkASSERT(l.fMinMaxScale == r.fMinMaxScale); + SkASSERT(l.fTextType == r.fTextType); + + SkASSERT(l.fRunCount == r.fRunCount); + for (int i = 0; i < l.fRunCount; i++) { + const Run& lRun = l.fRuns[i]; + const Run& rRun = r.fRuns[i]; + + if (lRun.fStrike.get()) { + SkASSERT(rRun.fStrike.get()); + SkASSERT(GrBatchTextStrike::GetKey(*lRun.fStrike) == + GrBatchTextStrike::GetKey(*rRun.fStrike)); + + } else { + SkASSERT(!rRun.fStrike.get()); + } + + if (lRun.fTypeface.get()) { + SkASSERT(rRun.fTypeface.get()); + SkASSERT(SkTypeface::Equal(lRun.fTypeface, rRun.fTypeface)); + } else { + SkASSERT(!rRun.fTypeface.get()); + } + + // TODO BOUNDS ARE ALL MESSED UP + //SkASSERT(lRun.fVertexBounds == rRun.fVertexBounds); + + SkASSERT(lRun.fDescriptor.getDesc()); + SkASSERT(rRun.fDescriptor.getDesc()); + SkASSERT(lRun.fDescriptor.getDesc()->equals(*rRun.fDescriptor.getDesc())); + + if (lRun.fOverrideDescriptor.get()) { + SkASSERT(lRun.fOverrideDescriptor->getDesc()); + SkASSERT(rRun.fOverrideDescriptor.get() && rRun.fOverrideDescriptor->getDesc());; + SkASSERT(lRun.fOverrideDescriptor->getDesc()->equals( + *rRun.fOverrideDescriptor->getDesc())); + } else { + SkASSERT(!rRun.fOverrideDescriptor.get()); + } + + // color can be changed + //SkASSERT(lRun.fColor == rRun.fColor); + SkASSERT(lRun.fInitialized == rRun.fInitialized); + SkASSERT(lRun.fDrawAsPaths == rRun.fDrawAsPaths); + + SkASSERT(lRun.fSubRunInfo.count() == rRun.fSubRunInfo.count()); + for(int j = 0; j < lRun.fSubRunInfo.count(); j++) { + const Run::SubRunInfo& lSubRun = lRun.fSubRunInfo[j]; + const Run::SubRunInfo& rSubRun = rRun.fSubRunInfo[j]; + + SkASSERT(lSubRun.fVertexStartIndex == rSubRun.fVertexStartIndex); + SkASSERT(lSubRun.fVertexEndIndex == rSubRun.fVertexEndIndex); + SkASSERT(lSubRun.fGlyphStartIndex == rSubRun.fGlyphStartIndex); + SkASSERT(lSubRun.fGlyphEndIndex == rSubRun.fGlyphEndIndex); + SkASSERT(lSubRun.fTextRatio == rSubRun.fTextRatio); + SkASSERT(lSubRun.fMaskFormat == rSubRun.fMaskFormat); + SkASSERT(lSubRun.fDrawAsDistanceFields == rSubRun.fDrawAsDistanceFields); + SkASSERT(lSubRun.fUseLCDText == rSubRun.fUseLCDText); + + //We can't compare the bulk use tokens with this method + /* + SkASSERT(lSubRun.fBulkUseToken.fPlotsToUpdate.count() == + rSubRun.fBulkUseToken.fPlotsToUpdate.count()); + SkASSERT(lSubRun.fBulkUseToken.fPlotAlreadyUpdated == + rSubRun.fBulkUseToken.fPlotAlreadyUpdated); + for (int k = 0; k < lSubRun.fBulkUseToken.fPlotsToUpdate.count(); k++) { + SkASSERT(lSubRun.fBulkUseToken.fPlotsToUpdate[k] == + rSubRun.fBulkUseToken.fPlotsToUpdate[k]); + }*/ + } + } +} + +#endif diff --git a/src/gpu/GrAtlasTextBlob.h b/src/gpu/GrAtlasTextBlob.h index a69e430779..1f37c676e2 100644 --- a/src/gpu/GrAtlasTextBlob.h +++ b/src/gpu/GrAtlasTextBlob.h @@ -10,11 +10,17 @@ #include "GrBatchAtlas.h" #include "GrBatchFontCache.h" +#include "GrColor.h" #include "SkDescriptor.h" #include "SkMaskFilter.h" #include "GrMemoryPool.h" +#include "SkSurfaceProps.h" #include "SkTInternalLList.h" +// With this flag enabled, the GrAtlasTextContext will, as a sanity check, regenerate every blob +// that comes in to verify the integrity of its cache +//#define CACHE_SANITY_CHECK // VERY SLOW + /* * A GrAtlasTextBlob contains a fully processed SkTextBlob, suitable for nearly immediate drawing * on the GPU. These are initially created with valid positions and colors, but invalid @@ -26,6 +32,8 @@ * the GrAtlas will not evict anything the Blob needs. * * Note: This struct should really be named GrCachedAtasTextBlob, but that is too verbose. + * + * *WARNING* If you add new fields to this struct, then you may need to to update AssertEqual */ struct GrAtlasTextBlob : public SkRefCnt { SK_DECLARE_INTERNAL_LLIST_INTERFACE(GrAtlasTextBlob); @@ -211,6 +219,11 @@ struct GrAtlasTextBlob : public SkRefCnt { bool hasBitmap() const { return SkToBool(fTextType & kHasBitmap_TextType); } void setHasDistanceField() { fTextType |= kHasDistanceField_TextType; } void setHasBitmap() { fTextType |= kHasBitmap_TextType; } + +#ifdef CACHE_SANITY_CHECK + static void AssertEqual(const GrAtlasTextBlob&, const GrAtlasTextBlob&); + size_t fSize; +#endif }; #endif diff --git a/src/gpu/GrAtlasTextContext.cpp b/src/gpu/GrAtlasTextContext.cpp index 8009e92f93..0e901ae40c 100644 --- a/src/gpu/GrAtlasTextContext.cpp +++ b/src/gpu/GrAtlasTextContext.cpp @@ -410,10 +410,25 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, } else { // If we can reuse the blob, then make sure we update the blob's viewmatrix, and x/y // offsets + // TODO bounds are wrong cacheBlob->fViewMatrix = viewMatrix; cacheBlob->fX = x; cacheBlob->fY = y; fCache->makeMRU(cacheBlob); +#ifdef CACHE_SANITY_CHECK + { + int glyphCount = 0; + int runCount = 0; + GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); + SkAutoTUnref<GrAtlasTextBlob> sanityBlob(fCache->createBlob(glyphCount, runCount, + kGrayTextVASize)); + GrTextBlobCache::SetupCacheBlobKey(sanityBlob, key, blurRec, skPaint); + this->regenerateTextBlob(sanityBlob, skPaint, grPaint.getColor(), viewMatrix, + blob, x, y, drawFilter, clipRect, rt, clip, grPaint); + GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); + } + +#endif } } else { if (canCache) { @@ -426,7 +441,6 @@ void GrAtlasTextContext::drawTextBlob(GrRenderTarget* rt, blob, x, y, drawFilter, clipRect, rt, clip, grPaint); } - cacheBlob->fPaintColor = skPaint.getColor(); this->flush(blob, cacheBlob, rt, skPaint, grPaint, drawFilter, clip, viewMatrix, clipBounds, x, y, transX, transY); } @@ -477,6 +491,7 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, SkDrawFilter* drawFilter, const SkIRect& clipRect, GrRenderTarget* rt, const GrClip& clip, const GrPaint& paint) { + cacheBlob->fPaintColor = skPaint.getColor(); cacheBlob->fViewMatrix = viewMatrix; cacheBlob->fX = x; cacheBlob->fY = y; diff --git a/src/gpu/GrTextBlobCache.cpp b/src/gpu/GrTextBlobCache.cpp index b1a13a866f..dd7ddc129e 100644 --- a/src/gpu/GrTextBlobCache.cpp +++ b/src/gpu/GrTextBlobCache.cpp @@ -13,8 +13,7 @@ GrTextBlobCache::~GrTextBlobCache() { this->freeAll(); } -GrAtlasTextBlob* GrTextBlobCache::createBlob(int glyphCount, int runCount, - size_t maxVASize) { +GrAtlasTextBlob* GrTextBlobCache::createBlob(int glyphCount, int runCount, size_t maxVASize) { // We allocate size for the GrAtlasTextBlob itself, plus size for the vertices array, // and size for the glyphIds array. size_t verticesCount = glyphCount * kVerticesPerGlyph * maxVASize; @@ -23,7 +22,15 @@ GrAtlasTextBlob* GrTextBlobCache::createBlob(int glyphCount, int runCount, glyphCount * sizeof(GrGlyph**) + sizeof(GrAtlasTextBlob::Run) * runCount; - GrAtlasTextBlob* cacheBlob = SkNEW_PLACEMENT(fPool.allocate(size), GrAtlasTextBlob); + void* allocation = fPool.allocate(size); +#ifdef CACHE_SANITY_CHECK + sk_bzero(allocation, size); +#endif + + GrAtlasTextBlob* cacheBlob = SkNEW_PLACEMENT(allocation, GrAtlasTextBlob); +#ifdef CACHE_SANITY_CHECK + cacheBlob->fSize = size; +#endif // setup offsets for vertices / glyphs cacheBlob->fVertices = sizeof(GrAtlasTextBlob) + reinterpret_cast<unsigned char*>(cacheBlob); diff --git a/src/gpu/GrTextBlobCache.h b/src/gpu/GrTextBlobCache.h index ca12411f7d..4c9cb14000 100644 --- a/src/gpu/GrTextBlobCache.h +++ b/src/gpu/GrTextBlobCache.h @@ -38,15 +38,10 @@ public: return cacheBlob; } - GrAtlasTextBlob* createCachedBlob(const SkTextBlob* blob, - const GrAtlasTextBlob::Key& key, - const SkMaskFilter::BlurRec& blurRec, - const SkPaint& paint, - size_t maxVAStride) { - int glyphCount = 0; - int runCount = 0; - BlobGlyphCount(&glyphCount, &runCount, blob); - GrAtlasTextBlob* cacheBlob = this->createBlob(glyphCount, runCount, maxVAStride); + static void SetupCacheBlobKey(GrAtlasTextBlob* cacheBlob, + const GrAtlasTextBlob::Key& key, + const SkMaskFilter::BlurRec& blurRec, + const SkPaint& paint) { cacheBlob->fKey = key; if (key.fHasBlur) { cacheBlob->fBlurRec = blurRec; @@ -56,6 +51,18 @@ public: cacheBlob->fStrokeInfo.fMiterLimit = paint.getStrokeMiter(); cacheBlob->fStrokeInfo.fJoin = paint.getStrokeJoin(); } + } + + GrAtlasTextBlob* createCachedBlob(const SkTextBlob* blob, + const GrAtlasTextBlob::Key& key, + const SkMaskFilter::BlurRec& blurRec, + const SkPaint& paint, + size_t maxVAStride) { + int glyphCount = 0; + int runCount = 0; + BlobGlyphCount(&glyphCount, &runCount, blob); + GrAtlasTextBlob* cacheBlob = this->createBlob(glyphCount, runCount, maxVAStride); + SetupCacheBlobKey(cacheBlob, key, blurRec, paint); this->add(cacheBlob); return cacheBlob; } @@ -115,15 +122,15 @@ public: void freeAll(); -private: // TODO move to SkTextBlob - void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) { + static void BlobGlyphCount(int* glyphCount, int* runCount, const SkTextBlob* blob) { SkTextBlob::RunIterator itCounter(blob); for (; !itCounter.done(); itCounter.next(), (*runCount)++) { *glyphCount += itCounter.glyphCount(); } } +private: typedef SkTInternalLList<GrAtlasTextBlob> BitmapBlobList; // Budget was chosen to be ~4 megabytes. The min alloc and pre alloc sizes in the pool are |