diff options
Diffstat (limited to 'src/gpu')
-rw-r--r-- | src/gpu/GrContext.cpp | 33 | ||||
-rw-r--r-- | src/gpu/GrContextPriv.h | 14 | ||||
-rw-r--r-- | src/gpu/GrDrawOpAtlas.cpp | 3 | ||||
-rw-r--r-- | src/gpu/GrOpFlushState.cpp | 9 | ||||
-rw-r--r-- | src/gpu/GrOpFlushState.h | 6 | ||||
-rw-r--r-- | src/gpu/GrProxyProvider.h | 3 | ||||
-rw-r--r-- | src/gpu/ops/GrAtlasTextOp.cpp | 35 | ||||
-rw-r--r-- | src/gpu/ops/GrAtlasTextOp.h | 24 | ||||
-rw-r--r-- | src/gpu/ops/GrMeshDrawOp.h | 5 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasGlyphCache.cpp (renamed from src/gpu/text/GrGlyphCache.cpp) | 191 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasGlyphCache.h | 270 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasManager.cpp | 222 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasManager.h | 155 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.cpp | 21 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlob.h | 24 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp | 29 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.cpp | 121 | ||||
-rw-r--r-- | src/gpu/text/GrAtlasTextContext.h | 27 | ||||
-rw-r--r-- | src/gpu/text/GrGlyphCache.h | 148 | ||||
-rw-r--r-- | src/gpu/text/GrTextUtils.h | 2 |
20 files changed, 582 insertions, 760 deletions
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 6fbc4fe04f..38e170b7a0 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -77,7 +77,6 @@ public: GrDDLContext(GrContextThreadSafeProxy* proxy) : INHERITED(proxy) {} protected: - // DDL TODO: grab a GrRestrictedAtlasManager from the proxy private: typedef GrContext INHERITED; @@ -219,8 +218,7 @@ GrContext::GrContext(GrBackend backend) fResourceCache = nullptr; fResourceProvider = nullptr; fProxyProvider = nullptr; - fGlyphCache = nullptr; - fFullAtlasManager = nullptr; + fAtlasGlyphCache = nullptr; } GrContext::GrContext(GrContextThreadSafeProxy* proxy) @@ -230,8 +228,7 @@ GrContext::GrContext(GrContextThreadSafeProxy* proxy) fResourceCache = nullptr; fResourceProvider = nullptr; fProxyProvider = nullptr; - fGlyphCache = nullptr; - fFullAtlasManager = nullptr; + fAtlasGlyphCache = nullptr; } bool GrContext::init(const GrContextOptions& options) { @@ -296,17 +293,9 @@ bool GrContext::init(const GrContextOptions& options) { } else { allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; } - - fGlyphCache = new GrGlyphCache; - - // DDL TODO: in DDL-mode grab a GrRestrictedAtlasManager from the thread-proxy and - // do not add an onFlushCB - fFullAtlasManager = new GrAtlasManager(fProxyProvider, fGlyphCache, - options.fGlyphCacheTextureMaximumBytes, - allowMultitexturing); - this->contextPriv().addOnFlushCallbackObject(fFullAtlasManager); - - fGlyphCache->setGlyphSizeLimit(fFullAtlasManager->getGlyphSizeLimit()); + fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes, + allowMultitexturing); + this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache); fTextBlobCache.reset(new GrTextBlobCache(TextBlobCacheOverBudgetCB, this, this->uniqueID(), SkToBool(fGpu))); @@ -338,8 +327,7 @@ GrContext::~GrContext() { delete fResourceProvider; delete fResourceCache; delete fProxyProvider; - delete fGlyphCache; - delete fFullAtlasManager; + delete fAtlasGlyphCache; } sk_sp<GrContextThreadSafeProxy> GrContext::threadSafeProxy() { @@ -398,8 +386,7 @@ void GrContext::abandonContext() { fGpu->disconnect(GrGpu::DisconnectType::kAbandon); - fGlyphCache->freeAll(); - fFullAtlasManager->freeAll(); + fAtlasGlyphCache->freeAll(); fTextBlobCache->freeAll(); } @@ -418,8 +405,7 @@ void GrContext::releaseResourcesAndAbandonContext() { fGpu->disconnect(GrGpu::DisconnectType::kCleanup); - fGlyphCache->freeAll(); - fFullAtlasManager->freeAll(); + fAtlasGlyphCache->freeAll(); fTextBlobCache->freeAll(); } @@ -433,8 +419,7 @@ void GrContext::freeGpuResources() { this->flush(); - fGlyphCache->freeAll(); - fFullAtlasManager->freeAll(); + fAtlasGlyphCache->freeAll(); fDrawingManager->freeGpuResources(); diff --git a/src/gpu/GrContextPriv.h b/src/gpu/GrContextPriv.h index c2e525d9b9..a2a45b5007 100644 --- a/src/gpu/GrContextPriv.h +++ b/src/gpu/GrContextPriv.h @@ -10,7 +10,6 @@ #include "GrContext.h" #include "GrSurfaceContext.h" -#include "text/GrAtlasManager.h" class GrBackendRenderTarget; class GrOnFlushCallbackObject; @@ -188,19 +187,8 @@ public: GrGpu* getGpu() { return fContext->fGpu.get(); } const GrGpu* getGpu() const { return fContext->fGpu.get(); } - GrGlyphCache* getGlyphCache() { return fContext->fGlyphCache; } + GrAtlasGlyphCache* getAtlasGlyphCache() { return fContext->fAtlasGlyphCache; } GrTextBlobCache* getTextBlobCache() { return fContext->fTextBlobCache.get(); } - GrRestrictedAtlasManager* getRestrictedAtlasManager() { return fContext->fFullAtlasManager; } - - // This accessor should only ever be called by the GrOpFlushState. - GrAtlasManager* getFullAtlasManager() { - if (fContext->fResourceProvider) { - // Disallow access to the full atlasManager when recording DDLs - return fContext->fFullAtlasManager; - } - - return nullptr; - } void moveOpListsToDDL(SkDeferredDisplayList*); void copyOpListsFromDDL(const SkDeferredDisplayList*, GrRenderTargetProxy* newDest); diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp index 56dfcef56d..3fd3110dcc 100644 --- a/src/gpu/GrDrawOpAtlas.cpp +++ b/src/gpu/GrDrawOpAtlas.cpp @@ -14,7 +14,6 @@ #include "GrRectanizer.h" #include "GrProxyProvider.h" #include "GrResourceProvider.h" -#include "GrSurfaceProxyPriv.h" #include "GrTexture.h" #include "GrTracing.h" @@ -337,8 +336,8 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, // With c+14 we could move sk_sp into lambda to only ref once. sk_sp<Plot> plotsp(SkRef(newPlot.get())); + SkASSERT(fProxies[pageIdx]->priv().isInstantiated()); GrTextureProxy* proxy = fProxies[pageIdx].get(); - SkASSERT(proxy->priv().isInstantiated()); GrDeferredUploadToken lastUploadToken = target->addInlineUpload( [plotsp, proxy](GrDeferredTextureUploadWritePixelsFn& writePixels) { diff --git a/src/gpu/GrOpFlushState.cpp b/src/gpu/GrOpFlushState.cpp index 53986c5f6a..06a05c6bb3 100644 --- a/src/gpu/GrOpFlushState.cpp +++ b/src/gpu/GrOpFlushState.cpp @@ -7,7 +7,6 @@ #include "GrOpFlushState.h" -#include "GrContextPriv.h" #include "GrDrawOpAtlas.h" #include "GrGpu.h" #include "GrResourceProvider.h" @@ -192,11 +191,3 @@ void GrOpFlushState::putBackVertices(int vertices, size_t vertexStride) { GrAppliedClip GrOpFlushState::detachAppliedClip() { return fOpArgs->fAppliedClip ? std::move(*fOpArgs->fAppliedClip) : GrAppliedClip(); } - -GrGlyphCache* GrOpFlushState::glyphCache() const { - return fGpu->getContext()->contextPriv().getGlyphCache(); -} - -GrAtlasManager* GrOpFlushState::fullAtlasManager() const { - return fGpu->getContext()->contextPriv().getFullAtlasManager(); -} diff --git a/src/gpu/GrOpFlushState.h b/src/gpu/GrOpFlushState.h index ad33a98e2d..1f77c25cb7 100644 --- a/src/gpu/GrOpFlushState.h +++ b/src/gpu/GrOpFlushState.h @@ -90,12 +90,6 @@ public: const GrCaps& caps() const final; GrResourceProvider* resourceProvider() const final { return fResourceProvider; } - GrGlyphCache* glyphCache() const final; - - // At this point we know we're flushing so full access to the GrAtlasManager is required (and - // permissible). - GrAtlasManager* fullAtlasManager() const final; - private: /** GrMeshDrawOp::Target override. */ SkArenaAlloc* pipelineArena() override { return &fArena; } diff --git a/src/gpu/GrProxyProvider.h b/src/gpu/GrProxyProvider.h index 254686a613..dfd06dfe80 100644 --- a/src/gpu/GrProxyProvider.h +++ b/src/gpu/GrProxyProvider.h @@ -8,13 +8,13 @@ #ifndef GrProxyProvider_DEFINED #define GrProxyProvider_DEFINED -#include "GrCaps.h" #include "GrResourceKey.h" #include "GrTextureProxy.h" #include "GrTypes.h" #include "SkRefCnt.h" #include "SkTDynamicHash.h" +class GrCaps; class GrResourceProvider; class GrSingleOwner; class GrBackendRenderTarget; @@ -207,7 +207,6 @@ public: void processInvalidProxyUniqueKey(const GrUniqueKey&, GrTextureProxy*, bool invalidateSurface); const GrCaps* caps() const { return fCaps.get(); } - sk_sp<const GrCaps> refCaps() const { return fCaps; } void abandon() { fResourceCache = nullptr; diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 8f0c555295..952b3ba5ad 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -16,8 +16,7 @@ #include "SkPoint3.h" #include "effects/GrBitmapTextGeoProc.h" #include "effects/GrDistanceFieldGeoProc.h" -#include "text/GrAtlasManager.h" -#include "text/GrGlyphCache.h" +#include "text/GrAtlasGlyphCache.h" /////////////////////////////////////////////////////////////////////////////////////////////////// @@ -54,12 +53,9 @@ void GrAtlasTextOp::init() { void GrAtlasTextOp::visitProxies(const VisitProxyFunc& func) const { fProcessors.visitProxies(func); - // We need to visit the atlasManager's proxies because, although the atlasManager explicitly - // manages their lifetimes, if they fail to allocate the draws that reference them need to - // be dropped. unsigned int numProxies; - const sk_sp<GrTextureProxy>* proxies = fRestrictedAtlasManager->getProxies( - this->maskFormat(), &numProxies); + const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(this->maskFormat(), + &numProxies); for (unsigned int i = 0; i < numProxies; ++i) { if (proxies[i]) { func(proxies[i].get()); @@ -236,15 +232,10 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { return; } - GrAtlasManager* fullAtlasManager = target->fullAtlasManager(); - SkASSERT(fRestrictedAtlasManager == fullAtlasManager); - GrGlyphCache* glyphCache = target->glyphCache(); - GrMaskFormat maskFormat = this->maskFormat(); unsigned int atlasPageCount; - const sk_sp<GrTextureProxy>* proxies = fullAtlasManager->getProxies(maskFormat, - &atlasPageCount); + const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &atlasPageCount); if (!proxies[0]) { SkDebugf("Could not allocate backing texture for atlas\n"); return; @@ -255,7 +246,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { target->makePipeline(fSRGBFlags, std::move(fProcessors), target->detachAppliedClip()); SkDEBUGCODE(bool dfPerspective = false); if (this->usesDistanceFields()) { - flushInfo.fGeometryProcessor = this->setupDfProcessor(fullAtlasManager); + flushInfo.fGeometryProcessor = this->setupDfProcessor(); SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective()); } else { flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make( @@ -281,15 +272,14 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { char* currVertex = reinterpret_cast<char*>(vertices); - SkAutoGlyphCache autoGlyphCache; + SkAutoGlyphCache glyphCache; // each of these is a SubRun for (int i = 0; i < fGeoCount; i++) { const Geometry& args = fGeoData[i]; Blob* blob = args.fBlob; GrAtlasTextBlob::VertexRegenerator regenerator( resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, - args.fColor, target->deferredUploadTarget(), glyphCache, fullAtlasManager, - &autoGlyphCache); + args.fColor, target->deferredUploadTarget(), fFontCache, &glyphCache); GrAtlasTextBlob::VertexRegenerator::Result result; do { result = regenerator.regenerate(); @@ -329,14 +319,11 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { } void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const { - auto fullAtlasManager = target->fullAtlasManager(); - SkASSERT(fRestrictedAtlasManager == fullAtlasManager); - GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get(); GrMaskFormat maskFormat = this->maskFormat(); unsigned int numProxies; - const sk_sp<GrTextureProxy>* proxies = fullAtlasManager->getProxies(maskFormat, &numProxies); + const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &numProxies); if (gp->numTextureSamplers() != (int) numProxies) { // During preparation the number of atlas pages has increased. // Update the proxies used in the GP to match. @@ -440,11 +427,9 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) { // TODO trying to figure out why lcd is so whack // (see comments in GrAtlasTextContext::ComputeCanonicalColor) -sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor( - GrRestrictedAtlasManager* restrictedAtlasManager) const { +sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const { unsigned int numProxies; - const sk_sp<GrTextureProxy>* p = restrictedAtlasManager->getProxies(this->maskFormat(), - &numProxies); + const sk_sp<GrTextureProxy>* p = fFontCache->getProxies(this->maskFormat(), &numProxies); bool isLCD = this->isLCD(); SkMatrix localMatrix = SkMatrix::I(); diff --git a/src/gpu/ops/GrAtlasTextOp.h b/src/gpu/ops/GrAtlasTextOp.h index ae1c95b56e..dbdce387ec 100644 --- a/src/gpu/ops/GrAtlasTextOp.h +++ b/src/gpu/ops/GrAtlasTextOp.h @@ -11,7 +11,6 @@ #include "ops/GrMeshDrawOp.h" #include "text/GrAtlasTextContext.h" #include "text/GrDistanceFieldAdjustTable.h" -#include "text/GrGlyphCache.h" class SkAtlasTextTarget; @@ -40,12 +39,11 @@ public: GrColor fColor; }; - static std::unique_ptr<GrAtlasTextOp> MakeBitmap( - GrPaint&& paint, GrMaskFormat maskFormat, - int glyphCount, GrRestrictedAtlasManager* restrictedAtlasManager) { - std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(restrictedAtlasManager, - std::move(paint))); + static std::unique_ptr<GrAtlasTextOp> MakeBitmap(GrPaint&& paint, GrMaskFormat maskFormat, + int glyphCount, GrAtlasGlyphCache* fontCache) { + std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); + op->fFontCache = fontCache; switch (maskFormat) { case kA8_GrMaskFormat: op->fMaskType = kGrayscaleCoverageMask_MaskType; @@ -60,17 +58,18 @@ public: op->fNumGlyphs = glyphCount; op->fGeoCount = 1; op->fLuminanceColor = 0; + op->fFontCache = fontCache; return op; } static std::unique_ptr<GrAtlasTextOp> MakeDistanceField( - GrPaint&& paint, int glyphCount, GrRestrictedAtlasManager* restrictedAtlasManager, + GrPaint&& paint, int glyphCount, GrAtlasGlyphCache* fontCache, const GrDistanceFieldAdjustTable* distanceAdjustTable, bool useGammaCorrectDistanceTable, SkColor luminanceColor, bool isLCD, bool useBGR, bool isAntiAliased) { - std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(restrictedAtlasManager, - std::move(paint))); + std::unique_ptr<GrAtlasTextOp> op(new GrAtlasTextOp(std::move(paint))); + op->fFontCache = fontCache; op->fMaskType = !isAntiAliased ? kAliasedDistanceField_MaskType : isLCD ? (useBGR ? kLCDBGRDistanceField_MaskType : kLCDDistanceField_MaskType) @@ -121,9 +120,8 @@ private: // The minimum number of Geometry we will try to allocate. static constexpr auto kMinGeometryAllocated = 12; - GrAtlasTextOp(GrRestrictedAtlasManager* restrictedAtlasManager, GrPaint&& paint) + GrAtlasTextOp(GrPaint&& paint) : INHERITED(ClassID()) - , fRestrictedAtlasManager(restrictedAtlasManager) , fGeoDataAllocSize(kMinGeometryAllocated) , fSRGBFlags(GrPipeline::SRGBFlagsFromPaint(paint)) , fProcessors(std::move(paint)) {} @@ -176,9 +174,8 @@ private: bool onCombineIfPossible(GrOp* t, const GrCaps& caps) override; - sk_sp<GrGeometryProcessor> setupDfProcessor(GrRestrictedAtlasManager*) const; + sk_sp<GrGeometryProcessor> setupDfProcessor() const; - GrRestrictedAtlasManager* fRestrictedAtlasManager; SkAutoSTMalloc<kMinGeometryAllocated, Geometry> fGeoData; int fGeoDataAllocSize; uint32_t fSRGBFlags; @@ -188,6 +185,7 @@ private: int fGeoCount; int fNumGlyphs; MaskType fMaskType; + GrAtlasGlyphCache* fFontCache; // Distance field properties sk_sp<const GrDistanceFieldAdjustTable> fDistanceAdjustTable; SkColor fLuminanceColor; diff --git a/src/gpu/ops/GrMeshDrawOp.h b/src/gpu/ops/GrMeshDrawOp.h index 766fd23ce5..1b8831cfe8 100644 --- a/src/gpu/ops/GrMeshDrawOp.h +++ b/src/gpu/ops/GrMeshDrawOp.h @@ -15,9 +15,7 @@ #include "SkTLList.h" -class GrAtlasManager; class GrCaps; -class GrGlyphCache; class GrOpFlushState; /** @@ -154,9 +152,6 @@ public: virtual GrResourceProvider* resourceProvider() const = 0; - virtual GrGlyphCache* glyphCache() const = 0; - virtual GrAtlasManager* fullAtlasManager() const = 0; - virtual const GrCaps& caps() const = 0; virtual GrDeferredUploadTarget* deferredUploadTarget() = 0; diff --git a/src/gpu/text/GrGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp index d4440897bc..f7b1e1269a 100644 --- a/src/gpu/text/GrGlyphCache.cpp +++ b/src/gpu/text/GrAtlasGlyphCache.cpp @@ -5,19 +5,81 @@ * found in the LICENSE file. */ -#include "GrAtlasManager.h" +#include "GrAtlasGlyphCache.h" +#include "GrContext.h" #include "GrDistanceFieldGenFromVector.h" -#include "GrGlyphCache.h" +#include "GrGpu.h" +#include "GrProxyProvider.h" +#include "GrRectanizer.h" #include "SkAutoMalloc.h" #include "SkDistanceFieldGen.h" +#include "SkMathPriv.h" +#include "SkString.h" + +bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) { + int index = MaskFormatToAtlasIndex(format); + if (!fAtlases[index]) { + GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->caps()); + int width = fAtlasConfigs[index].fWidth; + int height = fAtlasConfigs[index].fHeight; + int numPlotsX = fAtlasConfigs[index].numPlotsX(); + int numPlotsY = fAtlasConfigs[index].numPlotsY(); + + fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height, + numPlotsX, numPlotsY, fAllowMultitexturing, + &GrAtlasGlyphCache::HandleEviction, (void*)this); + if (!fAtlases[index]) { + return false; + } + } + return true; +} -GrGlyphCache::GrGlyphCache() - : fPreserveStrike(nullptr) - , fGlyphSizeLimit(0) { +GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes, + GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) + : fProxyProvider(proxyProvider) + , fAllowMultitexturing(allowMultitexturing) + , fPreserveStrike(nullptr) { + // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2 + int log2MaxTextureSize = SkPrevLog2(fProxyProvider->caps()->maxTextureSize()); + int log2MaxDim = 9; + for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) { + int maxDim = 1 << log2MaxDim; + int minDim = 1 << (log2MaxDim - 1); + + if (maxDim * minDim * 4 >= maxTextureBytes) break; + } + + int log2MinDim = log2MaxDim - 1; + int maxDim = 1 << log2MaxDim; + int minDim = 1 << log2MinDim; + // Plots are either 256 or 512. + int maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2))); + int minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3))); + + // Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8 + // format is already very compact. + fAtlasConfigs[kA8_GrMaskFormat].fWidth = maxDim; + fAtlasConfigs[kA8_GrMaskFormat].fHeight = maxDim; + fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = maxPlot; + fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = minPlot; + + // A565 and ARGB use maxDim x minDim. + fAtlasConfigs[kA565_GrMaskFormat].fWidth = minDim; + fAtlasConfigs[kA565_GrMaskFormat].fHeight = maxDim; + fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = minPlot; + fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = minPlot; + + fAtlasConfigs[kARGB_GrMaskFormat].fWidth = minDim; + fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim; + fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot; + fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot; + + fGlyphSizeLimit = minPlot; } -GrGlyphCache::~GrGlyphCache() { +GrAtlasGlyphCache::~GrAtlasGlyphCache() { StrikeHash::Iter iter(&fCache); while (!iter.done()) { (*iter).fIsAbandoned = true; @@ -26,7 +88,7 @@ GrGlyphCache::~GrGlyphCache() { } } -void GrGlyphCache::freeAll() { +void GrAtlasGlyphCache::freeAll() { StrikeHash::Iter iter(&fCache); while (!iter.done()) { (*iter).fIsAbandoned = true; @@ -34,26 +96,120 @@ void GrGlyphCache::freeAll() { ++iter; } fCache.rewind(); + for (int i = 0; i < kMaskFormatCount; ++i) { + fAtlases[i] = nullptr; + } } -void GrGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) { - GrGlyphCache* glyphCache = reinterpret_cast<GrGlyphCache*>(ptr); +void GrAtlasGlyphCache::HandleEviction(GrDrawOpAtlas::AtlasID id, void* ptr) { + GrAtlasGlyphCache* fontCache = reinterpret_cast<GrAtlasGlyphCache*>(ptr); - StrikeHash::Iter iter(&glyphCache->fCache); + StrikeHash::Iter iter(&fontCache->fCache); for (; !iter.done(); ++iter) { GrAtlasTextStrike* strike = &*iter; strike->removeID(id); // clear out any empty strikes. We will preserve the strike whose call to addToAtlas // triggered the eviction - if (strike != glyphCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) { - glyphCache->fCache.remove(GrAtlasTextStrike::GetKey(*strike)); + if (strike != fontCache->fPreserveStrike && 0 == strike->fAtlasedGlyphs) { + fontCache->fCache.remove(GrAtlasTextStrike::GetKey(*strike)); strike->fIsAbandoned = true; strike->unref(); } } } +#ifdef SK_DEBUG +#include "GrContextPriv.h" +#include "GrSurfaceProxy.h" +#include "GrSurfaceContext.h" +#include "GrTextureProxy.h" + +#include "SkBitmap.h" +#include "SkImageEncoder.h" +#include "SkStream.h" +#include <stdio.h> + +/** + * Write the contents of the surface proxy to a PNG. Returns true if successful. + * @param filename Full path to desired file + */ +static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) { + if (!sProxy) { + return false; + } + + SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(), + kRGBA_8888_SkColorType, kPremul_SkAlphaType); + SkBitmap bm; + if (!bm.tryAllocPixels(ii)) { + return false; + } + + sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext( + sk_ref_sp(sProxy))); + if (!sContext || !sContext->asTextureProxy()) { + return false; + } + + bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0); + if (!result) { + SkDebugf("------ failed to read pixels for %s\n", filename); + return false; + } + + // remove any previous version of this file + remove(filename); + + SkFILEWStream file(filename); + if (!file.isValid()) { + SkDebugf("------ failed to create file: %s\n", filename); + remove(filename); // remove any partial file + return false; + } + + if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) { + SkDebugf("------ failed to encode %s\n", filename); + remove(filename); // remove any partial file + return false; + } + + return true; +} + +void GrAtlasGlyphCache::dump(GrContext* context) const { + static int gDumpCount = 0; + for (int i = 0; i < kMaskFormatCount; ++i) { + if (fAtlases[i]) { + const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies(); + for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) { + SkASSERT(proxies[pageIdx]); + SkString filename; +#ifdef SK_BUILD_FOR_ANDROID + filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx); +#else + filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx); +#endif + + save_pixels(context, proxies[pageIdx].get(), filename.c_str()); + } + } + } + ++gDumpCount; +} +#endif + +void GrAtlasGlyphCache::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) { + // Delete any old atlases. + // This should be safe to do as long as we are not in the middle of a flush. + for (int i = 0; i < kMaskFormatCount; i++) { + fAtlases[i] = nullptr; + } + memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs)); +} + +/////////////////////////////////////////////////////////////////////////////// + static inline GrMaskFormat get_packed_glyph_mask_format(const SkGlyph& glyph) { SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); switch (format) { @@ -294,8 +450,7 @@ void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) { bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider, GrDeferredUploadTarget* target, - GrGlyphCache* glyphCache, - GrAtlasManager* fullAtlasManager, + GrAtlasGlyphCache* atlasGlyphCache, GrGlyph* glyph, SkGlyphCache* cache, GrMaskFormat expectedMaskFormat) { @@ -322,10 +477,10 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider, } } - bool success = fullAtlasManager->addToAtlas(resourceProvider, glyphCache, this, - &glyph->fID, target, expectedMaskFormat, - glyph->width(), glyph->height(), - storage.get(), &glyph->fAtlasLocation); + bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target, + expectedMaskFormat, + glyph->width(), glyph->height(), + storage.get(), &glyph->fAtlasLocation); if (success) { SkASSERT(GrDrawOpAtlas::kInvalidAtlasID != glyph->fID); fAtlasedGlyphs++; diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h new file mode 100644 index 0000000000..84b7d1b249 --- /dev/null +++ b/src/gpu/text/GrAtlasGlyphCache.h @@ -0,0 +1,270 @@ +/* + * Copyright 2015 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef GrAtlasGlyphCache_DEFINED +#define GrAtlasGlyphCache_DEFINED + +#include "GrCaps.h" +#include "GrDrawOpAtlas.h" +#include "GrGlyph.h" +#include "GrOnFlushResourceProvider.h" +#include "SkArenaAlloc.h" +#include "SkGlyphCache.h" +#include "SkTDynamicHash.h" + +class GrAtlasGlyphCache; +class GrGpu; + +/** + * The GrAtlasTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory + * is indexed by a PackedID and SkGlyphCache. The SkGlyphCache is what actually creates the mask. + * The GrAtlasTextStrike may outlive the generating SkGlyphCache. However, it retains a copy + * of it's SkDescriptor as a key to access (or regenerate) the SkGlyphCache. GrAtlasTextStrike are + * created by and owned by a GrAtlasGlyphCache. + */ +class GrAtlasTextStrike : public SkNVRefCnt<GrAtlasTextStrike> { +public: + GrAtlasTextStrike(const SkDescriptor& fontScalerKey); + ~GrAtlasTextStrike(); + + inline GrGlyph* getGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed, + SkGlyphCache* cache) { + GrGlyph* glyph = fCache.find(packed); + if (nullptr == glyph) { + glyph = this->generateGlyph(skGlyph, packed, cache); + } + return glyph; + } + + // This variant of the above function is called by GrAtlasTextOp. At this point, it is possible + // that the maskformat of the glyph differs from what we expect. In these cases we will just + // draw a clear square. + // skbug:4143 crbug:510931 + inline GrGlyph* getGlyph(GrGlyph::PackedID packed, + GrMaskFormat expectedMaskFormat, + SkGlyphCache* cache) { + GrGlyph* glyph = fCache.find(packed); + if (nullptr == glyph) { + // We could return this to the caller, but in practice it adds code complexity for + // potentially little benefit(ie, if the glyph is not in our font cache, then its not + // in the atlas and we're going to be doing a texture upload anyways). + const SkGlyph& skGlyph = GrToSkGlyph(cache, packed); + glyph = this->generateGlyph(skGlyph, packed, cache); + glyph->fMaskFormat = expectedMaskFormat; + } + return glyph; + } + + // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's + // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never + // happen. + // TODO we can handle some of these cases if we really want to, but the long term solution is to + // get the actual glyph image itself when we get the glyph metrics. + bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, + SkGlyphCache*, GrMaskFormat expectedMaskFormat); + + // testing + int countGlyphs() const { return fCache.count(); } + + // remove any references to this plot + void removeID(GrDrawOpAtlas::AtlasID); + + // If a TextStrike is abandoned by the cache, then the caller must get a new strike + bool isAbandoned() const { return fIsAbandoned; } + + static const SkDescriptor& GetKey(const GrAtlasTextStrike& ts) { + return *ts.fFontScalerKey.getDesc(); + } + + static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); } + +private: + SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache; + SkAutoDescriptor fFontScalerKey; + SkArenaAlloc fPool{512}; + + int fAtlasedGlyphs; + bool fIsAbandoned; + + static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) { + return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id), + GrGlyph::UnpackFixedX(id), + GrGlyph::UnpackFixedY(id)); + } + + GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, SkGlyphCache*); + + friend class GrAtlasGlyphCache; +}; + +/** + * GrAtlasGlyphCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be + * used to generate individual Glyph Masks. The GrAtlasGlyphCache also manages GrDrawOpAtlases, + * though this is more or less transparent to the client(aside from atlasGeneration, described + * below). + */ +class GrAtlasGlyphCache : public GrOnFlushCallbackObject { +public: + GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes, + GrDrawOpAtlas::AllowMultitexturing); + ~GrAtlasGlyphCache() override; + // The user of the cache may hold a long-lived ref to the returned strike. However, actions by + // another client of the cache may cause the strike to be purged while it is still reffed. + // Therefore, the caller must check GrAtlasTextStrike::isAbandoned() if there are other + // interactions with the cache since the strike was received. + inline GrAtlasTextStrike* getStrike(const SkGlyphCache* cache) { + GrAtlasTextStrike* strike = fCache.find(cache->getDescriptor()); + if (nullptr == strike) { + strike = this->generateStrike(cache); + } + return strike; + } + + void freeAll(); + + // if getProxies returns nullptr, the client must not try to use other functions on the + // GrAtlasGlyphCache which use the atlas. This function *must* be called first, before other + // functions which use the atlas. + const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numProxies) { + SkASSERT(numProxies); + + if (this->initAtlas(format)) { + *numProxies = this->getAtlas(format)->numActivePages(); + return this->getAtlas(format)->getProxies(); + } + *numProxies = 0; + return nullptr; + } + + SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; } + + bool hasGlyph(GrGlyph* glyph) { + SkASSERT(glyph); + return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID); + } + + // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store, + // the client must pass in the current op token along with the GrGlyph. + // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas. + // For convenience, this function will also set the use token for the current glyph if required + // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration + void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater, GrGlyph* glyph, + GrDeferredUploadToken token) { + SkASSERT(glyph); + updater->add(glyph->fID); + this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token); + } + + void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater, + GrDeferredUploadToken token, + GrMaskFormat format) { + this->getAtlas(format)->setLastUseTokenBulk(updater, token); + } + + // add to texture atlas that matches this format + bool addToAtlas(GrResourceProvider* resourceProvider, GrAtlasTextStrike* strike, + GrDrawOpAtlas::AtlasID* id, + GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height, + const void* image, SkIPoint16* loc) { + fPreserveStrike = strike; + return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, + width, height, image, loc); + } + + // Some clients may wish to verify the integrity of the texture backing store of the + // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which + // changes every time something is removed from the texture backing store. + uint64_t atlasGeneration(GrMaskFormat format) const { + return this->getAtlas(format)->atlasGeneration(); + } + + // GrOnFlushCallbackObject overrides + + void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int, + SkTArray<sk_sp<GrRenderTargetContext>>*) override { + for (int i = 0; i < kMaskFormatCount; ++i) { + if (fAtlases[i]) { + fAtlases[i]->instantiate(onFlushResourceProvider); + } + } + } + + void postFlush(GrDeferredUploadToken startTokenForNextFlush, const uint32_t*, int) override { + for (int i = 0; i < kMaskFormatCount; ++i) { + if (fAtlases[i]) { + fAtlases[i]->compact(startTokenForNextFlush); + } + } + } + + // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active + // OnFlushCallbackObject list + bool retainOnFreeGpuResources() override { return true; } + + /////////////////////////////////////////////////////////////////////////// + // Functions intended debug only +#ifdef SK_DEBUG + void dump(GrContext*) const; +#endif + + void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]); + +private: + static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) { + switch (format) { + case kA8_GrMaskFormat: + return kAlpha_8_GrPixelConfig; + case kA565_GrMaskFormat: + return kRGB_565_GrPixelConfig; + case kARGB_GrMaskFormat: + return caps.srgbSupport() ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig; + default: + SkDEBUGFAIL("unsupported GrMaskFormat"); + return kAlpha_8_GrPixelConfig; + } + } + + // There is a 1:1 mapping between GrMaskFormats and atlas indices + static int MaskFormatToAtlasIndex(GrMaskFormat format) { + static const int sAtlasIndices[] = { + kA8_GrMaskFormat, + kA565_GrMaskFormat, + kARGB_GrMaskFormat, + }; + static_assert(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, "array_size_mismatch"); + + SkASSERT(sAtlasIndices[format] < kMaskFormatCount); + return sAtlasIndices[format]; + } + + bool initAtlas(GrMaskFormat); + + GrAtlasTextStrike* generateStrike(const SkGlyphCache* cache) { + GrAtlasTextStrike* strike = new GrAtlasTextStrike(cache->getDescriptor()); + fCache.add(strike); + return strike; + } + + GrDrawOpAtlas* getAtlas(GrMaskFormat format) const { + int atlasIndex = MaskFormatToAtlasIndex(format); + SkASSERT(fAtlases[atlasIndex]); + return fAtlases[atlasIndex].get(); + } + + static void HandleEviction(GrDrawOpAtlas::AtlasID, void*); + + using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>; + GrProxyProvider* fProxyProvider; + StrikeHash fCache; + GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; + std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount]; + GrAtlasTextStrike* fPreserveStrike; + GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount]; + SkScalar fGlyphSizeLimit; +}; + +#endif diff --git a/src/gpu/text/GrAtlasManager.cpp b/src/gpu/text/GrAtlasManager.cpp deleted file mode 100644 index 6e227a94a2..0000000000 --- a/src/gpu/text/GrAtlasManager.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#include "GrAtlasManager.h" - -#include "GrCaps.h" -#include "GrGlyph.h" -#include "GrGlyphCache.h" -#include "GrProxyProvider.h" - -GrRestrictedAtlasManager::GrRestrictedAtlasManager( - sk_sp<const GrCaps> caps, - float maxTextureBytes, - GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) - : fCaps(std::move(caps)) - , fAllowMultitexturing(allowMultitexturing) { - // Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2 - int log2MaxTextureSize = SkPrevLog2(fCaps->maxTextureSize()); - int log2MaxDim = 9; - for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) { - int maxDim = 1 << log2MaxDim; - int minDim = 1 << (log2MaxDim - 1); - - if (maxDim * minDim * 4 >= maxTextureBytes) break; - } - - int log2MinDim = log2MaxDim - 1; - int maxDim = 1 << log2MaxDim; - int minDim = 1 << log2MinDim; - // Plots are either 256 or 512. - int maxPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 2))); - int minPlot = SkTMin(512, SkTMax(256, 1 << (log2MaxDim - 3))); - - // Setup default atlas configs. The A8 atlas uses maxDim for both width and height, as the A8 - // format is already very compact. - fAtlasConfigs[kA8_GrMaskFormat].fWidth = maxDim; - fAtlasConfigs[kA8_GrMaskFormat].fHeight = maxDim; - fAtlasConfigs[kA8_GrMaskFormat].fPlotWidth = maxPlot; - fAtlasConfigs[kA8_GrMaskFormat].fPlotHeight = minPlot; - - // A565 and ARGB use maxDim x minDim. - fAtlasConfigs[kA565_GrMaskFormat].fWidth = minDim; - fAtlasConfigs[kA565_GrMaskFormat].fHeight = maxDim; - fAtlasConfigs[kA565_GrMaskFormat].fPlotWidth = minPlot; - fAtlasConfigs[kA565_GrMaskFormat].fPlotHeight = minPlot; - - fAtlasConfigs[kARGB_GrMaskFormat].fWidth = minDim; - fAtlasConfigs[kARGB_GrMaskFormat].fHeight = maxDim; - fAtlasConfigs[kARGB_GrMaskFormat].fPlotWidth = minPlot; - fAtlasConfigs[kARGB_GrMaskFormat].fPlotHeight = minPlot; - - fGlyphSizeLimit = minPlot; -} - -GrRestrictedAtlasManager::~GrRestrictedAtlasManager() { -} - -static GrPixelConfig mask_format_to_pixel_config(GrMaskFormat format, const GrCaps& caps) { - switch (format) { - case kA8_GrMaskFormat: - return kAlpha_8_GrPixelConfig; - case kA565_GrMaskFormat: - return kRGB_565_GrPixelConfig; - case kARGB_GrMaskFormat: - return caps.srgbSupport() ? kSRGBA_8888_GrPixelConfig : kRGBA_8888_GrPixelConfig; - default: - SkDEBUGFAIL("unsupported GrMaskFormat"); - return kAlpha_8_GrPixelConfig; - } -} - -////////////////////////////////////////////////////////////////////////////////////////////////// -GrAtlasManager::GrAtlasManager(GrProxyProvider* proxyProvider, GrGlyphCache* glyphCache, - float maxTextureBytes, - GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) - : INHERITED(proxyProvider->refCaps(), maxTextureBytes, allowMultitexturing) - , fProxyProvider(proxyProvider) - , fGlyphCache(glyphCache) { -} - -void GrAtlasManager::freeAll() { - for (int i = 0; i < kMaskFormatCount; ++i) { - fAtlases[i] = nullptr; - } -} - -bool GrAtlasManager::hasGlyph(GrGlyph* glyph) { - SkASSERT(glyph); - return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID); -} - -// add to texture atlas that matches this format -bool GrAtlasManager::addToAtlas(GrResourceProvider* resourceProvider, - GrGlyphCache* glyphCache, - GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id, - GrDeferredUploadTarget* target, GrMaskFormat format, - int width, int height, const void* image, SkIPoint16* loc) { - glyphCache->setStrikeToPreserve(strike); - return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, width, height, - image, loc); -} - -void GrAtlasManager::addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater* updater, - GrGlyph* glyph, - GrDeferredUploadToken token) { - SkASSERT(glyph); - updater->add(glyph->fID); - this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token); -} - -#ifdef SK_DEBUG -#include "GrContextPriv.h" -#include "GrSurfaceProxy.h" -#include "GrSurfaceContext.h" -#include "GrTextureProxy.h" - -#include "SkBitmap.h" -#include "SkImageEncoder.h" -#include "SkStream.h" -#include <stdio.h> - -/** - * Write the contents of the surface proxy to a PNG. Returns true if successful. - * @param filename Full path to desired file - */ -static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* filename) { - if (!sProxy) { - return false; - } - - SkImageInfo ii = SkImageInfo::Make(sProxy->width(), sProxy->height(), - kRGBA_8888_SkColorType, kPremul_SkAlphaType); - SkBitmap bm; - if (!bm.tryAllocPixels(ii)) { - return false; - } - - sk_sp<GrSurfaceContext> sContext(context->contextPriv().makeWrappedSurfaceContext( - sk_ref_sp(sProxy))); - if (!sContext || !sContext->asTextureProxy()) { - return false; - } - - bool result = sContext->readPixels(ii, bm.getPixels(), bm.rowBytes(), 0, 0); - if (!result) { - SkDebugf("------ failed to read pixels for %s\n", filename); - return false; - } - - // remove any previous version of this file - remove(filename); - - SkFILEWStream file(filename); - if (!file.isValid()) { - SkDebugf("------ failed to create file: %s\n", filename); - remove(filename); // remove any partial file - return false; - } - - if (!SkEncodeImage(&file, bm, SkEncodedImageFormat::kPNG, 100)) { - SkDebugf("------ failed to encode %s\n", filename); - remove(filename); // remove any partial file - return false; - } - - return true; -} - -void GrAtlasManager::dump(GrContext* context) const { - static int gDumpCount = 0; - for (int i = 0; i < kMaskFormatCount; ++i) { - if (fAtlases[i]) { - const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies(); - for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) { - SkASSERT(proxies[pageIdx]); - SkString filename; -#ifdef SK_BUILD_FOR_ANDROID - filename.printf("/sdcard/fontcache_%d%d%d.png", gDumpCount, i, pageIdx); -#else - filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx); -#endif - - save_pixels(context, proxies[pageIdx].get(), filename.c_str()); - } - } - } - ++gDumpCount; -} -#endif - -void GrAtlasManager::setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]) { - // Delete any old atlases. - // This should be safe to do as long as we are not in the middle of a flush. - for (int i = 0; i < kMaskFormatCount; i++) { - fAtlases[i] = nullptr; - } - memcpy(fAtlasConfigs, configs, sizeof(fAtlasConfigs)); -} - -bool GrAtlasManager::initAtlas(GrMaskFormat format) { - int index = MaskFormatToAtlasIndex(format); - if (!fAtlases[index]) { - GrPixelConfig config = mask_format_to_pixel_config(format, *fCaps); - int width = fAtlasConfigs[index].fWidth; - int height = fAtlasConfigs[index].fHeight; - int numPlotsX = fAtlasConfigs[index].numPlotsX(); - int numPlotsY = fAtlasConfigs[index].numPlotsY(); - - fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height, - numPlotsX, numPlotsY, fAllowMultitexturing, - &GrGlyphCache::HandleEviction, - fGlyphCache); - if (!fAtlases[index]) { - return false; - } - } - return true; -} diff --git a/src/gpu/text/GrAtlasManager.h b/src/gpu/text/GrAtlasManager.h deleted file mode 100644 index 4629cb173b..0000000000 --- a/src/gpu/text/GrAtlasManager.h +++ /dev/null @@ -1,155 +0,0 @@ -/* - * Copyright 2018 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrAtlasManager_DEFINED -#define GrAtlasManager_DEFINED - -#include "GrDrawOpAtlas.h" -#include "GrOnFlushResourceProvider.h" - -class GrAtlasGlypCache; -class GrAtlasTextStrike; -struct GrGlyph; - - /** The GrAtlasManager classes manage the lifetime of and access to GrDrawOpAtlases. - * The restricted version is available at op creation time and only allows basic access - * to the proxies (so the created ops can reference them). The full GrAtlasManager class - * is only available at flush time and only via the GrOpFlushState. - * - * This organization implies that all of the advanced atlasManager functionality (i.e., - * adding glyphs to the atlas) are only available at flush time. - */ -class GrRestrictedAtlasManager : public GrOnFlushCallbackObject { -public: - GrRestrictedAtlasManager(sk_sp<const GrCaps>, float maxTextureBytes, - GrDrawOpAtlas::AllowMultitexturing); - ~GrRestrictedAtlasManager() override; - - // if getProxies returns nullptr, the client must not try to use other functions on the - // GrGlyphCache which use the atlas. This function *must* be called first, before other - // functions which use the atlas. - const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numProxies) { - if (this->initAtlas(format)) { - *numProxies = this->getAtlas(format)->numActivePages(); - return this->getAtlas(format)->getProxies(); - } - *numProxies = 0; - return nullptr; - } - - SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; } - -protected: - // There is a 1:1 mapping between GrMaskFormats and atlas indices - static int MaskFormatToAtlasIndex(GrMaskFormat format) { - static const int sAtlasIndices[] = { - kA8_GrMaskFormat, - kA565_GrMaskFormat, - kARGB_GrMaskFormat, - }; - static_assert(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, "array_size_mismatch"); - - SkASSERT(sAtlasIndices[format] < kMaskFormatCount); - return sAtlasIndices[format]; - } - - GrDrawOpAtlas* getAtlas(GrMaskFormat format) const { - int atlasIndex = MaskFormatToAtlasIndex(format); - SkASSERT(fAtlases[atlasIndex]); - return fAtlases[atlasIndex].get(); - } - - sk_sp<const GrCaps> fCaps; - GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; - std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount]; - GrDrawOpAtlasConfig fAtlasConfigs[kMaskFormatCount]; - SkScalar fGlyphSizeLimit; - -private: - virtual bool initAtlas(GrMaskFormat) = 0; - - typedef GrOnFlushCallbackObject INHERITED; -}; - -////////////////////////////////////////////////////////////////////////////////////////////////// -class GrAtlasManager : public GrRestrictedAtlasManager { -public: - GrAtlasManager(GrProxyProvider*, GrGlyphCache*, - float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing); - - void freeAll(); - - bool hasGlyph(GrGlyph* glyph); - - // To ensure the GrDrawOpAtlas does not evict the Glyph Mask from its texture backing store, - // the client must pass in the current op token along with the GrGlyph. - // A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas. - // For convenience, this function will also set the use token for the current glyph if required - // NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration - void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*, - GrDeferredUploadToken); - - void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater, - GrDeferredUploadToken token, - GrMaskFormat format) { - this->getAtlas(format)->setLastUseTokenBulk(updater, token); - } - - // add to texture atlas that matches this format - bool addToAtlas(GrResourceProvider*, GrGlyphCache*, GrAtlasTextStrike*, - GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat, - int width, int height, const void* image, SkIPoint16* loc); - - // Some clients may wish to verify the integrity of the texture backing store of the - // GrDrawOpAtlas. The atlasGeneration returned below is a monotonically increasing number which - // changes every time something is removed from the texture backing store. - uint64_t atlasGeneration(GrMaskFormat format) const { - return this->getAtlas(format)->atlasGeneration(); - } - - // GrOnFlushCallbackObject overrides - - void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int, - SkTArray<sk_sp<GrRenderTargetContext>>*) override { - for (int i = 0; i < kMaskFormatCount; ++i) { - if (fAtlases[i]) { - fAtlases[i]->instantiate(onFlushResourceProvider); - } - } - } - - void postFlush(GrDeferredUploadToken startTokenForNextFlush, - const uint32_t* opListIDs, int numOpListIDs) override { - for (int i = 0; i < kMaskFormatCount; ++i) { - if (fAtlases[i]) { - fAtlases[i]->compact(startTokenForNextFlush); - } - } - } - - // The AtlasGlyph cache always survives freeGpuResources so we want it to remain in the active - // OnFlushCallbackObject list - bool retainOnFreeGpuResources() override { return true; } - - /////////////////////////////////////////////////////////////////////////// - // Functions intended debug only -#ifdef SK_DEBUG - void dump(GrContext* context) const; -#endif - - void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]); - -private: - bool initAtlas(GrMaskFormat) override; - - GrProxyProvider* fProxyProvider; - GrGlyphCache* fGlyphCache; - - typedef GrRestrictedAtlasManager INHERITED; -}; - -#endif // GrAtlasManager_DEFINED diff --git a/src/gpu/text/GrAtlasTextBlob.cpp b/src/gpu/text/GrAtlasTextBlob.cpp index 35e783019f..90bcf5a224 100644 --- a/src/gpu/text/GrAtlasTextBlob.cpp +++ b/src/gpu/text/GrAtlasTextBlob.cpp @@ -250,8 +250,8 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp( const Run::SubRunInfo& info, int glyphCount, uint16_t run, uint16_t subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect, const GrTextUtils::Paint& paint, const SkSurfaceProps& props, - const GrDistanceFieldAdjustTable* distanceAdjustTable, - GrRestrictedAtlasManager* restrictedAtlasManager, GrTextUtils::Target* target) { + const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache, + GrTextUtils::Target* target) { GrMaskFormat format = info.maskFormat(); GrPaint grPaint; @@ -260,12 +260,11 @@ inline std::unique_ptr<GrAtlasTextOp> GrAtlasTextBlob::makeOp( if (info.drawAsDistanceFields()) { bool useBGR = SkPixelGeometryIsBGR(props.pixelGeometry()); op = GrAtlasTextOp::MakeDistanceField( - std::move(grPaint), glyphCount, restrictedAtlasManager, distanceAdjustTable, + std::move(grPaint), glyphCount, cache, distanceAdjustTable, target->colorSpaceInfo().isGammaCorrect(), paint.luminanceColor(), info.hasUseLCDText(), useBGR, info.isAntiAliased()); } else { - op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, - glyphCount, restrictedAtlasManager); + op = GrAtlasTextOp::MakeBitmap(std::move(grPaint), format, glyphCount, cache); } GrAtlasTextOp::Geometry& geometry = op->geometry(); geometry.fViewMatrix = viewMatrix; @@ -301,8 +300,8 @@ static void calculate_translation(bool applyVM, } } -void GrAtlasTextBlob::flush(GrRestrictedAtlasManager* restrictedAtlasManager, - GrTextUtils::Target* target, const SkSurfaceProps& props, +void GrAtlasTextBlob::flush(GrAtlasGlyphCache* atlasGlyphCache, GrTextUtils::Target* target, + const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable, const GrTextUtils::Paint& paint, const GrClip& clip, const SkMatrix& viewMatrix, const SkIRect& clipBounds, @@ -377,7 +376,7 @@ void GrAtlasTextBlob::flush(GrRestrictedAtlasManager* restrictedAtlasManager, if (submitOp) { auto op = this->makeOp(info, glyphCount, runIndex, subRun, viewMatrix, x, y, clipRect, std::move(paint), props, distanceAdjustTable, - restrictedAtlasManager, target); + atlasGlyphCache, target); if (op) { if (skipClip) { target->addDrawOp(GrNoClip(), std::move(op)); @@ -395,12 +394,12 @@ void GrAtlasTextBlob::flush(GrRestrictedAtlasManager* restrictedAtlasManager, std::unique_ptr<GrDrawOp> GrAtlasTextBlob::test_makeOp( int glyphCount, uint16_t run, uint16_t subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint& paint, const SkSurfaceProps& props, - const GrDistanceFieldAdjustTable* distanceAdjustTable, - GrRestrictedAtlasManager* restrictedAtlasManager, GrTextUtils::Target* target) { + const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache, + GrTextUtils::Target* target) { const GrAtlasTextBlob::Run::SubRunInfo& info = fRuns[run].fSubRunInfo[subRun]; SkIRect emptyRect = SkIRect::MakeEmpty(); return this->makeOp(info, glyphCount, run, subRun, viewMatrix, x, y, emptyRect, paint, props, - distanceAdjustTable, restrictedAtlasManager, target); + distanceAdjustTable, cache, target); } void GrAtlasTextBlob::AssertEqual(const GrAtlasTextBlob& l, const GrAtlasTextBlob& r) { diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h index 9f91cae957..0fae3cd8c7 100644 --- a/src/gpu/text/GrAtlasTextBlob.h +++ b/src/gpu/text/GrAtlasTextBlob.h @@ -8,9 +8,9 @@ #ifndef GrAtlasTextBlob_DEFINED #define GrAtlasTextBlob_DEFINED +#include "GrAtlasGlyphCache.h" #include "GrColor.h" #include "GrDrawOpAtlas.h" -#include "GrGlyphCache.h" #include "GrMemoryPool.h" #include "GrTextUtils.h" #include "SkDescriptor.h" @@ -22,13 +22,8 @@ #include "SkSurfaceProps.h" #include "SkTInternalLList.h" -class GrAtlasManager; struct GrDistanceFieldAdjustTable; -struct GrGlyph; -class GrGlyphCache; class GrMemoryPool; -class GrRestrictedAtlasManager; - class SkDrawFilter; class SkTextBlob; class SkTextBlobRunIterator; @@ -206,7 +201,7 @@ public: bool mustRegenerate(const GrTextUtils::Paint&, const SkMaskFilterBase::BlurRec& blurRec, const SkMatrix& viewMatrix, SkScalar x, SkScalar y); - void flush(GrRestrictedAtlasManager*, GrTextUtils::Target*, const SkSurfaceProps& props, + void flush(GrAtlasGlyphCache*, GrTextUtils::Target*, const SkSurfaceProps& props, const GrDistanceFieldAdjustTable* distanceAdjustTable, const GrTextUtils::Paint& paint, const GrClip& clip, const SkMatrix& viewMatrix, const SkIRect& clipBounds, SkScalar x, @@ -281,8 +276,8 @@ public: std::unique_ptr<GrDrawOp> test_makeOp(int glyphCount, uint16_t run, uint16_t subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const GrTextUtils::Paint&, const SkSurfaceProps&, - const GrDistanceFieldAdjustTable*, - GrRestrictedAtlasManager*, GrTextUtils::Target*); + const GrDistanceFieldAdjustTable*, GrAtlasGlyphCache*, + GrTextUtils::Target*); private: GrAtlasTextBlob() @@ -511,8 +506,9 @@ private: inline std::unique_ptr<GrAtlasTextOp> makeOp( const Run::SubRunInfo& info, int glyphCount, uint16_t run, uint16_t subRun, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, const SkIRect& clipRect, - const GrTextUtils::Paint&, const SkSurfaceProps&, - const GrDistanceFieldAdjustTable*, GrRestrictedAtlasManager* , GrTextUtils::Target*); + const GrTextUtils::Paint& paint, const SkSurfaceProps& props, + const GrDistanceFieldAdjustTable* distanceAdjustTable, GrAtlasGlyphCache* cache, + GrTextUtils::Target*); struct StrokeInfo { SkScalar fFrameWidth; @@ -566,8 +562,7 @@ public: */ VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, - GrDeferredUploadTarget*, GrGlyphCache*, GrAtlasManager*, - SkAutoGlyphCache*); + GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*); struct Result { /** @@ -598,8 +593,7 @@ private: const SkMatrix& fViewMatrix; GrAtlasTextBlob* fBlob; GrDeferredUploadTarget* fUploadTarget; - GrGlyphCache* fGlyphCache; - GrAtlasManager* fFullAtlasManager; + GrAtlasGlyphCache* fGlyphCache; SkAutoGlyphCache* fLazyCache; Run* fRun; Run::SubRunInfo* fSubRun; diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp index 54001c2628..500ae31703 100644 --- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp +++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp @@ -5,7 +5,6 @@ * found in the LICENSE file. */ -#include "GrAtlasManager.h" #include "GrAtlasTextBlob.h" #include "GrTextUtils.h" #include "SkDistanceFieldGen.h" @@ -194,14 +193,13 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, - GrDeferredUploadTarget* uploadTarget, GrGlyphCache* glyphCache, - GrAtlasManager* fullAtlasManager, SkAutoGlyphCache* lazyCache) + GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache, + SkAutoGlyphCache* lazyCache) : fResourceProvider(resourceProvider) , fViewMatrix(viewMatrix) , fBlob(blob) , fUploadTarget(uploadTarget) , fGlyphCache(glyphCache) - , fFullAtlasManager(fullAtlasManager) , fLazyCache(lazyCache) , fRun(&blob->fRuns[runIdx]) , fSubRun(&blob->fRuns[runIdx].fSubRunInfo[subRunIdx]) @@ -209,7 +207,7 @@ Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasText // Compute translation if any fSubRun->computeTranslation(fViewMatrix, x, y, &fTransX, &fTransY); - // Because the GrGlyphCache may evict the strike a blob depends on using for + // Because the GrAtlasGlyphCache may evict the strike a blob depends on using for // generating its texture coords, we have to track whether or not the strike has // been abandoned. If it hasn't been abandoned, then we can use the GrGlyph*s as is // otherwise we have to get the new strike, and use that to get the correct glyphs. @@ -277,17 +275,16 @@ Regenerator::Result Regenerator::doRegen() { glyph = fBlob->fGlyphs[glyphOffset]; SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat()); - if (!fFullAtlasManager->hasGlyph(glyph) && - !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, - fFullAtlasManager, glyph, + if (!fGlyphCache->hasGlyph(glyph) && + !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph, fLazyCache->get(), fSubRun->maskFormat())) { fBrokenRun = glyphIdx > 0; result.fFinished = false; return result; } auto tokenTracker = fUploadTarget->tokenTracker(); - fFullAtlasManager->addGlyphToBulkAndSetUseToken(fSubRun->bulkUseToken(), glyph, - tokenTracker->nextDrawToken()); + fGlyphCache->addGlyphToBulkAndSetUseToken(fSubRun->bulkUseToken(), glyph, + tokenTracker->nextDrawToken()); } regen_vertices<regenPos, regenCol, regenTexCoords>(currVertex, glyph, vertexStride, @@ -305,14 +302,14 @@ Regenerator::Result Regenerator::doRegen() { fSubRun->setStrike(strike); } fSubRun->setAtlasGeneration(fBrokenRun - ? GrDrawOpAtlas::kInvalidAtlasGeneration - : fFullAtlasManager->atlasGeneration(fSubRun->maskFormat())); + ? GrDrawOpAtlas::kInvalidAtlasGeneration + : fGlyphCache->atlasGeneration(fSubRun->maskFormat())); } return result; } Regenerator::Result Regenerator::regenerate() { - uint64_t currentAtlasGen = fFullAtlasManager->atlasGeneration(fSubRun->maskFormat()); + uint64_t currentAtlasGen = fGlyphCache->atlasGeneration(fSubRun->maskFormat()); // If regenerate() is called multiple times then the atlas gen may have changed. So we check // this each time. if (fSubRun->atlasGeneration() != currentAtlasGen) { @@ -355,9 +352,9 @@ Regenerator::Result Regenerator::regenerate() { // set use tokens for all of the glyphs in our subrun. This is only valid if we // have a valid atlas generation - fFullAtlasManager->setUseTokenBulk(*fSubRun->bulkUseToken(), - fUploadTarget->tokenTracker()->nextDrawToken(), - fSubRun->maskFormat()); + fGlyphCache->setUseTokenBulk(*fSubRun->bulkUseToken(), + fUploadTarget->tokenTracker()->nextDrawToken(), + fSubRun->maskFormat()); return result; } } diff --git a/src/gpu/text/GrAtlasTextContext.cpp b/src/gpu/text/GrAtlasTextContext.cpp index aadc2dc0c1..06282e103e 100644 --- a/src/gpu/text/GrAtlasTextContext.cpp +++ b/src/gpu/text/GrAtlasTextContext.cpp @@ -118,8 +118,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t drawFilter); SkScalerContextFlags scalerContextFlags = ComputeScalerContextFlags(target->colorSpaceInfo()); - auto glyphCache = context->contextPriv().getGlyphCache(); - auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); + auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache(); GrTextBlobCache* textBlobCache = context->contextPriv().getTextBlobCache(); if (canCache) { @@ -152,7 +151,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t // but we'd have to clear the subrun information textBlobCache->remove(cacheBlob.get()); cacheBlob = textBlobCache->makeCachedBlob(blob, key, blurRec, skPaint); - this->regenerateTextBlob(cacheBlob.get(), glyphCache, + this->regenerateTextBlob(cacheBlob.get(), atlasGlyphCache, *context->caps()->shaderCaps(), paint, scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); } else { @@ -164,7 +163,7 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t GrTextBlobCache::BlobGlyphCount(&glyphCount, &runCount, blob); sk_sp<GrAtlasTextBlob> sanityBlob(textBlobCache->makeBlob(glyphCount, runCount)); sanityBlob->setupKey(key, blurRec, skPaint); - this->regenerateTextBlob(sanityBlob.get(), glyphCache, + this->regenerateTextBlob(sanityBlob.get(), atlasGlyphCache, *context->caps()->shaderCaps(), paint, scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); GrAtlasTextBlob::AssertEqual(*sanityBlob, *cacheBlob); @@ -176,17 +175,17 @@ void GrAtlasTextContext::drawTextBlob(GrContext* context, GrTextUtils::Target* t } else { cacheBlob = textBlobCache->makeBlob(blob); } - this->regenerateTextBlob(cacheBlob.get(), glyphCache, + this->regenerateTextBlob(cacheBlob.get(), atlasGlyphCache, *context->caps()->shaderCaps(), paint, scalerContextFlags, viewMatrix, props, blob, x, y, drawFilter); } - cacheBlob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, + cacheBlob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, clip, viewMatrix, clipBounds, x, y); } void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const GrShaderCaps& shaderCaps, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, @@ -212,21 +211,21 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, if (this->canDrawAsDistanceFields(runPaint, viewMatrix, props, shaderCaps)) { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: { - this->drawDFText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + this->drawDFText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), y + offset.y()); break; } case SkTextBlob::kHorizontal_Positioning: { SkPoint dfOffset = SkPoint::Make(x, y + offset.y()); - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, + this->drawDFPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, dfOffset); break; } case SkTextBlob::kFull_Positioning: { SkPoint dfOffset = SkPoint::Make(x, y); - this->drawDFPosText(cacheBlob, run, glyphCache, props, runPaint, + this->drawDFPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, dfOffset); break; @@ -235,17 +234,17 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, } else { switch (it.positioning()) { case SkTextBlob::kDefault_Positioning: - DrawBmpText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + DrawBmpText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, x + offset.x(), y + offset.y()); break; case SkTextBlob::kHorizontal_Positioning: - DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 1, SkPoint::Make(x, y + offset.y())); break; case SkTextBlob::kFull_Positioning: - DrawBmpPosText(cacheBlob, run, glyphCache, props, runPaint, scalerContextFlags, + DrawBmpPosText(cacheBlob, run, fontCache, props, runPaint, scalerContextFlags, viewMatrix, (const char*)it.glyphs(), textLen, it.pos(), 2, SkPoint::Make(x, y)); break; @@ -256,7 +255,7 @@ void GrAtlasTextContext::regenerateTextBlob(GrAtlasTextBlob* cacheBlob, inline sk_sp<GrAtlasTextBlob> GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const GrShaderCaps& shaderCaps, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, @@ -273,10 +272,10 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, blob->setRunPaintFlags(0, paint.skPaint().getFlags()); if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { - this->drawDFText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, + this->drawDFText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, x, y); } else { - DrawBmpText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, text, + DrawBmpText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, x, y); } return blob; @@ -284,7 +283,7 @@ GrAtlasTextContext::makeDrawTextBlob(GrTextBlobCache* blobCache, inline sk_sp<GrAtlasTextBlob> GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const GrShaderCaps& shaderCaps, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, @@ -303,11 +302,11 @@ GrAtlasTextContext::makeDrawPosTextBlob(GrTextBlobCache* blobCache, blob->setRunPaintFlags(0, paint.skPaint().getFlags()); if (this->canDrawAsDistanceFields(paint, viewMatrix, props, shaderCaps)) { - this->drawDFPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, + this->drawDFPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); } else { - DrawBmpPosText(blob.get(), 0, glyphCache, props, paint, scalerContextFlags, viewMatrix, - text, byteLength, pos, scalarsPerPosition, offset); + DrawBmpPosText(blob.get(), 0, fontCache, props, paint, scalerContextFlags, viewMatrix, text, + byteLength, pos, scalarsPerPosition, offset); } return blob; } @@ -321,18 +320,17 @@ void GrAtlasTextContext::drawText(GrContext* context, GrTextUtils::Target* targe return; } - auto glyphCache = context->contextPriv().getGlyphCache(); - auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); + auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache(); auto textBlobCache = context->contextPriv().getTextBlobCache(); GrTextUtils::Paint paint(&skPaint, &target->colorSpaceInfo()); sk_sp<GrAtlasTextBlob> blob( - this->makeDrawTextBlob(textBlobCache, glyphCache, + this->makeDrawTextBlob(textBlobCache, atlasGlyphCache, *context->caps()->shaderCaps(), paint, ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, byteLength, x, y)); if (blob) { - blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, + blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, clip, viewMatrix, regionClipBounds, x, y); } } @@ -348,23 +346,22 @@ void GrAtlasTextContext::drawPosText(GrContext* context, GrTextUtils::Target* ta return; } - auto glyphCache = context->contextPriv().getGlyphCache(); - auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); + auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache(); auto textBlobCache = context->contextPriv().getTextBlobCache(); sk_sp<GrAtlasTextBlob> blob(this->makeDrawPosTextBlob( - textBlobCache, glyphCache, + textBlobCache, atlasGlyphCache, *context->caps()->shaderCaps(), paint, ComputeScalerContextFlags(target->colorSpaceInfo()), viewMatrix, props, text, byteLength, pos, scalarsPerPosition, offset)); if (blob) { - blob->flush(restrictedAtlasManager, target, props, fDistanceAdjustTable.get(), paint, + blob->flush(atlasGlyphCache, target, props, fDistanceAdjustTable.get(), paint, clip, viewMatrix, regionClipBounds, offset.fX, offset.fY); } } void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, const SkSurfaceProps& props, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], @@ -380,7 +377,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, blob->setHasBitmap(); if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { - DrawBmpTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix, + DrawBmpTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, x, y); return; } @@ -390,7 +387,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, viewMatrix, paint.skPaint().getTextAlign(), cache, [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { position += rounding; - BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, + BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, SkScalarFloorToScalar(position.fX), SkScalarFloorToScalar(position.fY), paint.filteredPremulColor(), cache, @@ -401,7 +398,7 @@ void GrAtlasTextContext::DrawBmpText(GrAtlasTextBlob* blob, int runIndex, } void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, const SkSurfaceProps& props, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, @@ -419,7 +416,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, blob->setHasBitmap(); if (SkDraw::ShouldDrawTextAsPaths(paint, viewMatrix)) { - DrawBmpPosTextAsPaths(blob, runIndex, glyphCache, props, paint, scalerContextFlags, + DrawBmpPosTextAsPaths(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, pos, scalarsPerPosition, offset); return; } @@ -432,7 +429,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, scalarsPerPosition, paint.skPaint().getTextAlign(), cache, [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) { position += rounding; - BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, + BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, SkScalarFloorToScalar(position.fX), SkScalarFloorToScalar(position.fY), paint.filteredPremulColor(), cache, SK_Scalar1); @@ -442,7 +439,7 @@ void GrAtlasTextContext::DrawBmpPosText(GrAtlasTextBlob* blob, int runIndex, } void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& origPaint, SkScalerContextFlags scalerContextFlags, @@ -460,7 +457,7 @@ void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex, GrTextUtils::PathTextIter iter(text, byteLength, pathPaint, true); FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(), - glyphCache->getGlyphSizeLimit(), + fontCache->getGlyphSizeLimit(), iter.getPathScale()); const SkGlyph* iterGlyph; @@ -477,11 +474,11 @@ void GrAtlasTextContext::DrawBmpTextAsPaths(GrAtlasTextBlob* blob, int runIndex, lastText = iter.getText(); } - fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags); + fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags); } void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& origPaint, SkScalerContextFlags scalerContextFlags, @@ -500,7 +497,7 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd SkPaint pathPaint(origPaint); SkScalar matrixScale = pathPaint.setupForAsPaths(); FallbackTextHelper fallbackTextHelper(viewMatrix, pathPaint.getTextSize(), matrixScale, - glyphCache->getGlyphSizeLimit()); + fontCache->getGlyphSizeLimit()); // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache. pathPaint.setStyle(SkPaint::kFill_Style); @@ -537,23 +534,23 @@ void GrAtlasTextContext::DrawBmpPosTextAsPaths(GrAtlasTextBlob* blob, int runInd pos += scalarsPerPosition; } - fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, origPaint, scalerContextFlags); + fallbackTextHelper.drawText(blob, runIndex, fontCache, props, origPaint, scalerContextFlags); } void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* grGlyphCache, GrAtlasTextStrike** strike, + GrAtlasGlyphCache* fontCache, GrAtlasTextStrike** strike, const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, - GrColor color, SkGlyphCache* skGlyphCache, + GrColor color, SkGlyphCache* glyphCache, SkScalar textRatio) { if (!*strike) { - *strike = grGlyphCache->getStrike(skGlyphCache); + *strike = fontCache->getStrike(glyphCache); } GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), skGlyph.getSubXFixed(), skGlyph.getSubYFixed(), GrGlyph::kCoverage_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache); if (!glyph) { return; } @@ -573,7 +570,7 @@ void GrAtlasTextContext::BmpAppendGlyph(GrAtlasTextBlob* blob, int runIndex, SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height); - blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy, + blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx, sy, textRatio, true); } @@ -673,7 +670,7 @@ void GrAtlasTextContext::initDistanceFieldPaint(GrAtlasTextBlob* blob, } void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, const SkSurfaceProps& props, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], @@ -743,12 +740,12 @@ void GrAtlasTextContext::drawDFText(GrAtlasTextBlob* blob, int runIndex, y -= alignY; SkPoint offset = SkPoint::Make(x, y); - this->drawDFPosText(blob, runIndex, glyphCache, props, paint, scalerContextFlags, viewMatrix, + this->drawDFPosText(blob, runIndex, fontCache, props, paint, scalerContextFlags, viewMatrix, text, byteLength, positions.begin(), 2, offset); } void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, const SkSurfaceProps& props, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], @@ -774,7 +771,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, FallbackTextHelper fallbackTextHelper(viewMatrix, paint.skPaint().getTextSize(), - glyphCache->getGlyphSizeLimit(), + fontCache->getGlyphSizeLimit(), textRatio); GrAtlasTextStrike* currStrike = nullptr; @@ -803,7 +800,7 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, SkFloatToScalar(glyph.fAdvanceY) * alignMul * textRatio; if (glyph.fMaskFormat != SkMask::kARGB32_Format) { - DfAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, glyphPos.fX, + DfAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, glyphPos.fX, glyphPos.fY, paint.filteredPremulColor(), cache, textRatio); } else { // can't append color glyph to SDF batch, send to fallback @@ -815,24 +812,25 @@ void GrAtlasTextContext::drawDFPosText(GrAtlasTextBlob* blob, int runIndex, SkGlyphCache::AttachCache(cache); - fallbackTextHelper.drawText(blob, runIndex, glyphCache, props, paint, scalerContextFlags); + fallbackTextHelper.drawText(blob, runIndex, fontCache, props, paint, + scalerContextFlags); } // TODO: merge with BmpAppendGlyph void GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* grGlyphCache, GrAtlasTextStrike** strike, + GrAtlasGlyphCache* cache, GrAtlasTextStrike** strike, const SkGlyph& skGlyph, SkScalar sx, SkScalar sy, - GrColor color, SkGlyphCache* skGlyphCache, + GrColor color, SkGlyphCache* glyphCache, SkScalar textRatio) { if (!*strike) { - *strike = grGlyphCache->getStrike(skGlyphCache); + *strike = cache->getStrike(glyphCache); } GrGlyph::PackedID id = GrGlyph::Pack(skGlyph.getGlyphID(), skGlyph.getSubXFixed(), skGlyph.getSubYFixed(), GrGlyph::kDistance_MaskStyle); - GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, skGlyphCache); + GrGlyph* glyph = (*strike)->getGlyph(skGlyph, id, glyphCache); if (!glyph) { return; } @@ -848,7 +846,7 @@ void GrAtlasTextContext::DfAppendGlyph(GrAtlasTextBlob* blob, int runIndex, height *= textRatio; SkRect glyphRect = SkRect::MakeXYWH(sx + dx, sy + dy, width, height); - blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, skGlyphCache, skGlyph, sx, sy, + blob->appendGlyph(runIndex, glyphRect, color, *strike, glyph, glyphCache, skGlyph, sx, sy, textRatio, false); } @@ -873,7 +871,7 @@ void GrAtlasTextContext::FallbackTextHelper::appendText(const SkGlyph& glyph, in } void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int runIndex, - GrGlyphCache* glyphCache, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags) { @@ -911,7 +909,7 @@ void GrAtlasTextContext::FallbackTextHelper::drawText(GrAtlasTextBlob* blob, int SkPoint* glyphPos = fFallbackPos.begin(); while (text < stop) { const SkGlyph& glyph = glyphCacheProc(cache, &text); - GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, glyphCache, &currStrike, glyph, + GrAtlasTextContext::BmpAppendGlyph(blob, runIndex, fontCache, &currStrike, glyph, glyphPos->fX, glyphPos->fY, textColor, cache, textRatio); glyphPos++; @@ -964,19 +962,18 @@ GR_DRAW_OP_TEST_DEFINE(GrAtlasTextOp) { SkScalar x = SkIntToScalar(xInt); SkScalar y = SkIntToScalar(yInt); - auto glyphCache = context->contextPriv().getGlyphCache(); - auto restrictedAtlasManager = context->contextPriv().getRestrictedAtlasManager(); + auto atlasGlyphCache = context->contextPriv().getAtlasGlyphCache(); // right now we don't handle textblobs, nor do we handle drawPosText. Since we only intend to // test the text op with this unit test, that is okay. sk_sp<GrAtlasTextBlob> blob(gTextContext->makeDrawTextBlob( - context->contextPriv().getTextBlobCache(), glyphCache, + context->contextPriv().getTextBlobCache(), atlasGlyphCache, *context->caps()->shaderCaps(), utilsPaint, GrAtlasTextContext::kTextBlobOpScalerContextFlags, viewMatrix, gSurfaceProps, text, static_cast<size_t>(textLen), x, y)); return blob->test_makeOp(textLen, 0, 0, viewMatrix, x, y, utilsPaint, gSurfaceProps, - gTextContext->dfAdjustTable(), restrictedAtlasManager, + gTextContext->dfAdjustTable(), atlasGlyphCache, rtc->textTarget()); } diff --git a/src/gpu/text/GrAtlasTextContext.h b/src/gpu/text/GrAtlasTextContext.h index 37b7de5357..207dd67206 100644 --- a/src/gpu/text/GrAtlasTextContext.h +++ b/src/gpu/text/GrAtlasTextContext.h @@ -74,8 +74,9 @@ private: } void appendText(const SkGlyph& glyph, int count, const char* text, SkPoint glyphPos); - void drawText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&, - const GrTextUtils::Paint&, SkScalerContextFlags); + void drawText(GrAtlasTextBlob* blob, int runIndex, + GrAtlasGlyphCache* fontCache, const SkSurfaceProps& props, + const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags); private: SkTDArray<char> fFallbackTxt; @@ -95,7 +96,7 @@ private: // Determines if we need to use fake gamma (and contrast boost): static SkScalerContextFlags ComputeScalerContextFlags(const GrColorSpaceInfo&); void regenerateTextBlob(GrAtlasTextBlob* bmp, - GrGlyphCache*, + GrAtlasGlyphCache*, const GrShaderCaps&, const GrTextUtils::Paint&, SkScalerContextFlags scalerContextFlags, @@ -106,7 +107,7 @@ private: static bool HasLCD(const SkTextBlob*); - sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrGlyphCache*, + sk_sp<GrAtlasTextBlob> makeDrawTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*, const GrShaderCaps&, const GrTextUtils::Paint&, SkScalerContextFlags scalerContextFlags, @@ -115,7 +116,7 @@ private: const char text[], size_t byteLength, SkScalar x, SkScalar y) const; - sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrGlyphCache*, + sk_sp<GrAtlasTextBlob> makeDrawPosTextBlob(GrTextBlobCache*, GrAtlasGlyphCache*, const GrShaderCaps&, const GrTextUtils::Paint&, SkScalerContextFlags scalerContextFlags, @@ -127,24 +128,24 @@ private: const SkPoint& offset) const; // Functions for appending BMP text to GrAtlasTextBlob - static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void DrawBmpText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, SkScalar y); - static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void DrawBmpPosText(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, const SkScalar pos[], int scalarsPerPosition, const SkPoint& offset); - static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void DrawBmpTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, SkScalar y); - static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void DrawBmpPosTextAsPaths(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, @@ -156,12 +157,12 @@ private: bool canDrawAsDistanceFields(const SkPaint& skPaint, const SkMatrix& viewMatrix, const SkSurfaceProps& props, const GrShaderCaps& caps) const; - void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, const SkSurfaceProps&, + void drawDFText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], size_t byteLength, SkScalar x, SkScalar y) const; - void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrGlyphCache*, + void drawDFPosText(GrAtlasTextBlob* blob, int runIndex, GrAtlasGlyphCache*, const SkSurfaceProps&, const GrTextUtils::Paint& paint, SkScalerContextFlags scalerContextFlags, const SkMatrix& viewMatrix, const char text[], @@ -173,11 +174,11 @@ private: SkScalar* textRatio, const SkMatrix& viewMatrix) const; - static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void BmpAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy, GrColor color, SkGlyphCache*, SkScalar textRatio); - static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrGlyphCache*, + static void DfAppendGlyph(GrAtlasTextBlob*, int runIndex, GrAtlasGlyphCache*, GrAtlasTextStrike**, const SkGlyph&, SkScalar sx, SkScalar sy, GrColor color, SkGlyphCache* cache, SkScalar textRatio); diff --git a/src/gpu/text/GrGlyphCache.h b/src/gpu/text/GrGlyphCache.h deleted file mode 100644 index 169e4b30a5..0000000000 --- a/src/gpu/text/GrGlyphCache.h +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2015 Google Inc. - * - * Use of this source code is governed by a BSD-style license that can be - * found in the LICENSE file. - */ - -#ifndef GrAtlasGlyphCache_DEFINED -#define GrAtlasGlyphCache_DEFINED - -#include "GrDrawOpAtlas.h" -#include "GrGlyph.h" -#include "SkArenaAlloc.h" -#include "SkGlyphCache.h" -#include "SkTDynamicHash.h" - -class GrGlyphCache; -class GrAtlasManager; -class GrGpu; - -/** - * The GrAtlasTextStrike manages a pool of CPU backing memory for GrGlyphs. This backing memory - * is indexed by a PackedID and SkGlyphCache. The SkGlyphCache is what actually creates the mask. - * The GrAtlasTextStrike may outlive the generating SkGlyphCache. However, it retains a copy - * of it's SkDescriptor as a key to access (or regenerate) the SkGlyphCache. GrAtlasTextStrike are - * created by and owned by a GrGlyphCache. - */ -class GrAtlasTextStrike : public SkNVRefCnt<GrAtlasTextStrike> { -public: - GrAtlasTextStrike(const SkDescriptor& fontScalerKey); - ~GrAtlasTextStrike(); - - inline GrGlyph* getGlyph(const SkGlyph& skGlyph, GrGlyph::PackedID packed, - SkGlyphCache* cache) { - GrGlyph* glyph = fCache.find(packed); - if (nullptr == glyph) { - glyph = this->generateGlyph(skGlyph, packed, cache); - } - return glyph; - } - - // This variant of the above function is called by GrAtlasTextOp. At this point, it is possible - // that the maskformat of the glyph differs from what we expect. In these cases we will just - // draw a clear square. - // skbug:4143 crbug:510931 - inline GrGlyph* getGlyph(GrGlyph::PackedID packed, - GrMaskFormat expectedMaskFormat, - SkGlyphCache* cache) { - GrGlyph* glyph = fCache.find(packed); - if (nullptr == glyph) { - // We could return this to the caller, but in practice it adds code complexity for - // potentially little benefit(ie, if the glyph is not in our font cache, then its not - // in the atlas and we're going to be doing a texture upload anyways). - const SkGlyph& skGlyph = GrToSkGlyph(cache, packed); - glyph = this->generateGlyph(skGlyph, packed, cache); - glyph->fMaskFormat = expectedMaskFormat; - } - return glyph; - } - - // returns true if glyph successfully added to texture atlas, false otherwise. If the glyph's - // mask format has changed, then addGlyphToAtlas will draw a clear box. This will almost never - // happen. - // TODO we can handle some of these cases if we really want to, but the long term solution is to - // get the actual glyph image itself when we get the glyph metrics. - bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrGlyphCache*, - GrAtlasManager*, GrGlyph*, - SkGlyphCache*, GrMaskFormat expectedMaskFormat); - - // testing - int countGlyphs() const { return fCache.count(); } - - // remove any references to this plot - void removeID(GrDrawOpAtlas::AtlasID); - - // If a TextStrike is abandoned by the cache, then the caller must get a new strike - bool isAbandoned() const { return fIsAbandoned; } - - static const SkDescriptor& GetKey(const GrAtlasTextStrike& ts) { - return *ts.fFontScalerKey.getDesc(); - } - - static uint32_t Hash(const SkDescriptor& desc) { return desc.getChecksum(); } - -private: - SkTDynamicHash<GrGlyph, GrGlyph::PackedID> fCache; - SkAutoDescriptor fFontScalerKey; - SkArenaAlloc fPool{512}; - - int fAtlasedGlyphs; - bool fIsAbandoned; - - static const SkGlyph& GrToSkGlyph(SkGlyphCache* cache, GrGlyph::PackedID id) { - return cache->getGlyphIDMetrics(GrGlyph::UnpackID(id), - GrGlyph::UnpackFixedX(id), - GrGlyph::UnpackFixedY(id)); - } - - GrGlyph* generateGlyph(const SkGlyph&, GrGlyph::PackedID, SkGlyphCache*); - - friend class GrGlyphCache; -}; - -/** - * GrGlyphCache manages strikes which are indexed by a SkGlyphCache. These strikes can then be - * used to generate individual Glyph Masks. - */ -class GrGlyphCache { -public: - GrGlyphCache(); - ~GrGlyphCache(); - - void setGlyphSizeLimit(SkScalar sizeLimit) { fGlyphSizeLimit = sizeLimit; } - SkScalar getGlyphSizeLimit() const { return fGlyphSizeLimit; } - - void setStrikeToPreserve(GrAtlasTextStrike* strike) { fPreserveStrike = strike; } - - // The user of the cache may hold a long-lived ref to the returned strike. However, actions by - // another client of the cache may cause the strike to be purged while it is still reffed. - // Therefore, the caller must check GrAtlasTextStrike::isAbandoned() if there are other - // interactions with the cache since the strike was received. - inline GrAtlasTextStrike* getStrike(const SkGlyphCache* cache) { - GrAtlasTextStrike* strike = fCache.find(cache->getDescriptor()); - if (nullptr == strike) { - strike = this->generateStrike(cache); - } - return strike; - } - - void freeAll(); - - static void HandleEviction(GrDrawOpAtlas::AtlasID, void*); - -private: - GrAtlasTextStrike* generateStrike(const SkGlyphCache* cache) { - GrAtlasTextStrike* strike = new GrAtlasTextStrike(cache->getDescriptor()); - fCache.add(strike); - return strike; - } - - using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>; - - StrikeHash fCache; - GrAtlasTextStrike* fPreserveStrike; - SkScalar fGlyphSizeLimit; -}; - -#endif diff --git a/src/gpu/text/GrTextUtils.h b/src/gpu/text/GrTextUtils.h index 69421c2474..5fe38fe773 100644 --- a/src/gpu/text/GrTextUtils.h +++ b/src/gpu/text/GrTextUtils.h @@ -16,13 +16,13 @@ #include "SkTextToPathIter.h" #include "SkTLazy.h" +class GrAtlasGlyphCache; class GrAtlasTextBlob; class GrAtlasTextOp; class GrAtlasTextStrike; class GrClip; class GrColorSpaceXform; class GrContext; -class GrGlyphCache; class GrPaint; class GrShaderCaps; class SkColorSpace; |