From 59ddc6d5ee39c026e78bf39361cc788e30ca0afa Mon Sep 17 00:00:00 2001 From: Robert Phillips Date: Wed, 21 Feb 2018 21:56:35 +0000 Subject: [PATCH] Revert "Separate creation time & flush time behavior in GrDrawOpAtlas" This reverts commit 056c1a821afcfbe606615ad1a7d1b554549d0846. Reason for revert: GM issues Original change's description: > Separate creation time & flush time behavior in GrDrawOpAtlas > > This CL clarifies what is going on in the GrDrawOpAtlas and GrAtlasGlyphCache. > > For the GrDrawOpAtlas: > At creation time all the allowed pages are created (with their backing GrTextureProxies) but they aren't instantiated. > > The GrDrawOpAtlas::instantiate call is called in preFlushCB and allocates any pages known to be needed at the start of flush > > GrDrawOpAtlas::addToAtlas is called at flush time and, if a new page is activated, will instantiated it at that time. > > During compaction, an unused page will be deInstantiated but its Plots and backing GrTextureProxy will remain alive. > > The GrAtlasGlyphCache reflects the changes to the GrDrawOpAtlas > It now carries a GrProxyProvider for when it needs to create an atlas > It passes in a GrResourceProvider* at flush time to allow instantiation. > > It does not, yet, allocate that GrDrawOpAtlases it might ever require. > > Change-Id: I54909b7a3ba4bec2db5f1218f6a2a3a1636f66d6 > Reviewed-on: https://skia-review.googlesource.com/108520 > Commit-Queue: Robert Phillips > Reviewed-by: Jim Van Verth TBR=jvanverth@google.com,bsalomon@google.com,robertphillips@google.com Change-Id: I36eafe46209380f533aa84e831d1c9d18844b6be No-Presubmit: true No-Tree-Checks: true No-Try: true Reviewed-on: https://skia-review.googlesource.com/109280 Reviewed-by: Robert Phillips Commit-Queue: Robert Phillips --- gn/tests.gni | 1 - include/private/GrSurfaceProxy.h | 15 +- src/atlastext/SkAtlasTextTarget.cpp | 14 +- src/gpu/GrContext.cpp | 2 +- src/gpu/GrDeferredUpload.h | 3 +- src/gpu/GrDrawOpAtlas.cpp | 171 ++++++++---------- src/gpu/GrDrawOpAtlas.h | 34 ++-- src/gpu/GrOnFlushResourceProvider.h | 5 +- src/gpu/GrSurfaceProxy.cpp | 7 - src/gpu/ops/GrAtlasTextOp.cpp | 6 +- src/gpu/ops/GrSmallPathRenderer.cpp | 30 ++- src/gpu/text/GrAtlasGlyphCache.cpp | 27 ++- src/gpu/text/GrAtlasGlyphCache.h | 24 +-- src/gpu/text/GrAtlasTextBlob.h | 7 +- .../text/GrAtlasTextBlobVertexRegenerator.cpp | 10 +- tests/DrawOpAtlasTest.cpp | 132 -------------- 16 files changed, 141 insertions(+), 347 deletions(-) delete mode 100644 tests/DrawOpAtlasTest.cpp diff --git a/gn/tests.gni b/gn/tests.gni index 02293a0b48..58b1ff05c6 100644 --- a/gn/tests.gni +++ b/gn/tests.gni @@ -60,7 +60,6 @@ tests_sources = [ "$_tests/DiscardableMemoryTest.cpp", "$_tests/DrawBitmapRectTest.cpp", "$_tests/DrawFilterTest.cpp", - "$_tests/DrawOpAtlasTest.cpp", "$_tests/DrawPathTest.cpp", "$_tests/DrawTextTest.cpp", "$_tests/DynamicHashTest.cpp", diff --git a/include/private/GrSurfaceProxy.h b/include/private/GrSurfaceProxy.h index 6beb11e46f..cb8c46e78f 100644 --- a/include/private/GrSurfaceProxy.h +++ b/include/private/GrSurfaceProxy.h @@ -57,17 +57,6 @@ public: } #endif - void release() { - SkASSERT(1 == fRefCnt); - SkASSERT(0 == fPendingReads); - SkASSERT(0 == fPendingWrites); - - SkASSERT(fTarget->internalHasUniqueRef()); - SkASSERT(!fTarget->internalHasPendingIO()); - fTarget->unref(); - fTarget = nullptr; - } - void validate() const { #ifdef SK_DEBUG SkASSERT(fRefCnt >= 0); @@ -140,7 +129,7 @@ protected: } virtual ~GrIORefProxy() { // We don't unref 'fTarget' here since the 'unref' method will already - // have forwarded on the unref call that got us here. + // have forwarded on the unref call that got use here. } // This GrIORefProxy was deferred before but has just been instantiated. To @@ -290,8 +279,6 @@ public: virtual bool instantiate(GrResourceProvider* resourceProvider) = 0; - void deInstantiate(); - /** * Helper that gets the width and height of the surface as a bounding rectangle. */ diff --git a/src/atlastext/SkAtlasTextTarget.cpp b/src/atlastext/SkAtlasTextTarget.cpp index f553ffad96..d80c7a45d7 100644 --- a/src/atlastext/SkAtlasTextTarget.cpp +++ b/src/atlastext/SkAtlasTextTarget.cpp @@ -183,18 +183,12 @@ void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) { FlushInfo flushInfo; SkAutoGlyphCache glyphCache; auto& context = target->context()->internal(); - auto atlasGlyphCache = context.grContext()->contextPriv().getAtlasGlyphCache(); - auto resourceProvider = context.grContext()->contextPriv().resourceProvider(); - auto drawingManager = context.grContext()->contextPriv().drawingManager(); - - GrOnFlushResourceProvider onFlushResourceProvider(drawingManager); - atlasGlyphCache->preFlush(&onFlushResourceProvider, nullptr, 0, nullptr); - + auto* atlasGlyphCache = context.grContext()->contextPriv().getAtlasGlyphCache(); for (int i = 0; i < fGeoCount; ++i) { GrAtlasTextBlob::VertexRegenerator regenerator( - resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, - fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, - &context, atlasGlyphCache, &glyphCache); + fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fViewMatrix, + fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, &context, atlasGlyphCache, + &glyphCache); GrAtlasTextBlob::VertexRegenerator::Result result; do { result = regenerator.regenerate(); diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp index 0af319715b..3fb7a9c837 100644 --- a/src/gpu/GrContext.cpp +++ b/src/gpu/GrContext.cpp @@ -295,7 +295,7 @@ bool GrContext::init(const GrContextOptions& options) { } else { allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; } - fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes, + fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes, allowMultitexturing); this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache); diff --git a/src/gpu/GrDeferredUpload.h b/src/gpu/GrDeferredUpload.h index d78363136d..fad5e930a1 100644 --- a/src/gpu/GrDeferredUpload.h +++ b/src/gpu/GrDeferredUpload.h @@ -96,10 +96,9 @@ public: GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); } private: - // Only these three classes get to increment the token counters + // Only these two classes get to increment the token counters friend class SkInternalAtlasTextContext; friend class GrOpFlushState; - friend class TestingUploadTarget; /** Issues the next token for a draw. */ GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; } diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp index 7539a7a05e..622aa229bd 100644 --- a/src/gpu/GrDrawOpAtlas.cpp +++ b/src/gpu/GrDrawOpAtlas.cpp @@ -26,20 +26,20 @@ // must explicitly manage the lifetime of their backing proxies via the onFlushCallback system // (which calls this method). void GrDrawOpAtlas::instantiate(GrOnFlushResourceProvider* onFlushResourceProvider) { - for (uint32_t i = 0; i < fNumActivePages; ++i) { - // All the atlas pages are now instantiated at flush time in the activeNewPage method. - SkASSERT(fProxies[i] && fProxies[i]->priv().isInstantiated()); + for (int i = 0; i < GrDrawOpAtlas::kMaxMultitexturePages; ++i) { + if (fProxies[i] && !fProxies[i]->priv().isInstantiated()) { + // If instantiation fails we expect the ops that rely on the atlas to be dropped + onFlushResourceProvider->instatiateProxy(fProxies[i].get()); + } } } -std::unique_ptr GrDrawOpAtlas::Make(GrProxyProvider* proxyProvider, - GrPixelConfig config, int width, +std::unique_ptr GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width, int height, int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing, GrDrawOpAtlas::EvictionFunc func, void* data) { - std::unique_ptr atlas(new GrDrawOpAtlas(proxyProvider, config, width, height, - numPlotsX, numPlotsY, - allowMultitexturing)); + std::unique_ptr atlas(new GrDrawOpAtlas(ctx, config, width, height, numPlotsX, + numPlotsY, allowMultitexturing)); if (!atlas->getProxies()[0]) { return nullptr; } @@ -53,6 +53,7 @@ static bool gDumpAtlasData = false; #endif //////////////////////////////////////////////////////////////////////////////// + GrDrawOpAtlas::Plot::Plot(int pageIndex, int plotIndex, uint64_t genID, int offX, int offY, int width, int height, GrPixelConfig config) : fLastUpload(GrDeferredUploadToken::AlreadyFlushedToken()) @@ -177,16 +178,16 @@ void GrDrawOpAtlas::Plot::resetRects() { /////////////////////////////////////////////////////////////////////////////// -GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider, - GrPixelConfig config, int width, int height, +GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height, int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing) - : fPixelConfig(config) + : fContext(context) + , fPixelConfig(config) , fTextureWidth(width) , fTextureHeight(height) , fAtlasGeneration(kInvalidAtlasGeneration + 1) , fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken()) , fAllowMultitexturing(allowMultitexturing) - , fNumActivePages(0) { + , fNumPages(0) { fPlotWidth = fTextureWidth / numPlotsX; fPlotHeight = fTextureHeight / numPlotsY; SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots); @@ -195,7 +196,7 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider, fNumPlots = numPlotsX * numPlotsY; - this->createPages(proxyProvider); + this->createNewPage(); } inline void GrDrawOpAtlas::processEviction(AtlasID id) { @@ -216,8 +217,13 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i // With c+14 we could move sk_sp into lamba to only ref once. sk_sp plotsp(SkRef(plot)); + // MDB TODO: this is currently fine since the atlas' proxy is always pre-instantiated. + // Once it is deferred more care must be taken upon instantiation failure. + if (!fProxies[pageIdx]->instantiate(fContext->contextPriv().resourceProvider())) { + return false; + } + GrTextureProxy* proxy = fProxies[pageIdx].get(); - SkASSERT(proxy->priv().isInstantiated()); // This is occurring at flush time GrDeferredUploadToken lastUploadToken = target->addASAPUpload( [plotsp, proxy](GrDeferredTextureUploadWritePixelsFn& writePixels) { @@ -237,9 +243,8 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i // are rare; i.e., we are not continually refreshing the frame. static constexpr auto kRecentlyUsedCount = 256; -bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, - AtlasID* id, GrDeferredUploadTarget* target, - int width, int height, const void* image, SkIPoint16* loc) { +bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int width, int height, + const void* image, SkIPoint16* loc) { if (width > fPlotWidth || height > fPlotHeight) { return false; } @@ -247,7 +252,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, // Look through each page to see if we can upload without having to flush // We prioritize this upload to the first pages, not the most recently used, to make it easier // to remove unused pages in reverse page order. - for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) { + for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) { SkASSERT(fProxies[pageIdx]); // look through all allocated plots for one we can share, in Most Recently Refed order PlotList::Iter plotIter; @@ -267,10 +272,10 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, // We wait until we've grown to the full number of pages to begin evicting already flushed // plots so that we can maximize the opportunity for reuse. // As before we prioritize this upload to the first pages, not the most recently used. - for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) { + for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) { Plot* plot = fPages[pageIdx].fPlotList.tail(); SkASSERT(plot); - if ((fNumActivePages == this->maxPages() && + if ((fNumPages == this->maxPages() && plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) || plot->flushesSinceLastUsed() >= kRecentlyUsedCount) { this->processEvictionAndResetRects(plot); @@ -285,10 +290,9 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, } // If the simple cases fail, try to create a new page and add to it - if (this->activateNewPage(resourceProvider)) { - unsigned int pageIdx = fNumActivePages-1; - SkASSERT(fProxies[pageIdx] && fProxies[pageIdx]->priv().isInstantiated()); - + if (this->createNewPage()) { + unsigned int pageIdx = fNumPages-1; + SkASSERT(fProxies[pageIdx]); Plot* plot = fPages[pageIdx].fPlotList.head(); SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp()); if (plot->addSubImage(width, height, image, loc)) { @@ -303,7 +307,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, // Try to find a plot that we can perform an inline upload to. // We prioritize this upload in reverse order of pages to counterbalance the order above. Plot* plot = nullptr; - for (int pageIdx = (int)(fNumActivePages-1); pageIdx >= 0; --pageIdx) { + for (int pageIdx = (int)(fNumPages-1); pageIdx >= 0; --pageIdx) { Plot* currentPlot = fPages[pageIdx].fPlotList.tail(); if (currentPlot->lastUseToken() != target->tokenTracker()->nextDrawToken()) { plot = currentPlot; @@ -335,8 +339,11 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, // one it displaced most likely was uploaded ASAP. // With c+14 we could move sk_sp into lambda to only ref once. sk_sp plotsp(SkRef(newPlot.get())); - - SkASSERT(fProxies[pageIdx]->priv().isInstantiated()); + // MDB TODO: this is currently fine since the atlas' proxy is always pre-instantiated. + // Once it is deferred more care must be taken upon instantiation failure. + if (!fProxies[pageIdx]->instantiate(fContext->contextPriv().resourceProvider())) { + return false; + } GrTextureProxy* proxy = fProxies[pageIdx].get(); GrDeferredUploadToken lastUploadToken = target->addInlineUpload( @@ -351,7 +358,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, } void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) { - if (fNumActivePages <= 1) { + if (fNumPages <= 1) { fPrevFlushToken = startTokenForNextFlush; return; } @@ -359,7 +366,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) { // For all plots, reset number of flushes since used if used this frame. PlotList::Iter plotIter; bool atlasUsedThisFlush = false; - for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) { + for (uint32_t pageIndex = 0; pageIndex < fNumPages; ++pageIndex) { plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart); while (Plot* plot = plotIter.get()) { // Reset number of flushes since used @@ -378,7 +385,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) { // TODO: consider if we should also do this if it's been a long time since the last atlas use if (atlasUsedThisFlush) { SkTArray availablePlots; - uint32_t lastPageIndex = fNumActivePages - 1; + uint32_t lastPageIndex = fNumPages - 1; // For all plots but the last one, update number of flushes since used, and check to see // if there are any in the first pages that the last page can safely upload to. @@ -487,15 +494,19 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) { SkDebugf("delete %d\n", fNumPages-1); } #endif - this->deactivateLastPage(); + this->deleteLastPage(); } } fPrevFlushToken = startTokenForNextFlush; } -bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) { - SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight)); +bool GrDrawOpAtlas::createNewPage() { + if (fNumPages == this->maxPages()) { + return false; + } + + GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider(); GrSurfaceDesc desc; desc.fFlags = kNone_GrSurfaceFlags; @@ -504,83 +515,47 @@ bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) { desc.fHeight = fTextureHeight; desc.fConfig = fPixelConfig; + SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight)); + fProxies[fNumPages] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes, + GrResourceProvider::kNoPendingIO_Flag); + if (!fProxies[fNumPages]) { + return false; + } + int numPlotsX = fTextureWidth/fPlotWidth; int numPlotsY = fTextureHeight/fPlotHeight; - for (uint32_t i = 0; i < this->maxPages(); ++i) { - fProxies[i] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes, - GrResourceProvider::kNoPendingIO_Flag); - if (!fProxies[i]) { - return false; + // set up allocated plots + fPages[fNumPages].fPlotArray.reset(new sk_sp[ numPlotsX * numPlotsY ]); + + sk_sp* currPlot = fPages[fNumPages].fPlotArray.get(); + for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) { + for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) { + uint32_t plotIndex = r * numPlotsX + c; + currPlot->reset(new Plot(fNumPages, plotIndex, 1, x, y, fPlotWidth, fPlotHeight, + fPixelConfig)); + + // build LRU list + fPages[fNumPages].fPlotList.addToHead(currPlot->get()); + ++currPlot; } - - // set up allocated plots - fPages[i].fPlotArray.reset(new sk_sp[ numPlotsX * numPlotsY ]); - - sk_sp* currPlot = fPages[i].fPlotArray.get(); - for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) { - for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) { - uint32_t plotIndex = r * numPlotsX + c; - currPlot->reset(new Plot(i, plotIndex, 1, x, y, fPlotWidth, fPlotHeight, - fPixelConfig)); - - // build LRU list - fPages[i].fPlotList.addToHead(currPlot->get()); - ++currPlot; - } - } - - } - - return true; -} - - -bool GrDrawOpAtlas::activateNewPage(GrResourceProvider* resourceProvider) { - if (fNumActivePages >= this->maxPages()) { - return false; - } - - if (!fProxies[fNumActivePages]->instantiate(resourceProvider)) { - return false; } #ifdef DUMP_ATLAS_DATA if (gDumpAtlasData) { - SkDebugf("activated page#: %d\n", fNumActivePages); + SkDebugf("created %d\n", fNumPages); } #endif - - ++fNumActivePages; + fNumPages++; return true; } - -inline void GrDrawOpAtlas::deactivateLastPage() { - SkASSERT(fNumActivePages); - - uint32_t lastPageIndex = fNumActivePages - 1; - - int numPlotsX = fTextureWidth/fPlotWidth; - int numPlotsY = fTextureHeight/fPlotHeight; - +inline void GrDrawOpAtlas::deleteLastPage() { + uint32_t lastPageIndex = fNumPages - 1; + // clean out the plots fPages[lastPageIndex].fPlotList.reset(); - for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) { - for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) { - uint32_t plotIndex = r * numPlotsX + c; - - Plot* currPlot = fPages[lastPageIndex].fPlotArray[plotIndex].get(); - currPlot->resetRects(); - currPlot->resetFlushesSinceLastUsed(); - - // rebuild the LRU list - SkDEBUGCODE(currPlot->fPrev = currPlot->fNext = nullptr); - SkDEBUGCODE(currPlot->fList = nullptr); - fPages[lastPageIndex].fPlotList.addToHead(currPlot); - } - } - - // remove ref to the backing texture - fProxies[lastPageIndex]->deInstantiate(); - --fNumActivePages; + fPages[lastPageIndex].fPlotArray.reset(nullptr); + // remove ref to texture proxy + fProxies[lastPageIndex].reset(nullptr); + --fNumPages; } diff --git a/src/gpu/GrDrawOpAtlas.h b/src/gpu/GrDrawOpAtlas.h index b849d9e067..a2c985928d 100644 --- a/src/gpu/GrDrawOpAtlas.h +++ b/src/gpu/GrDrawOpAtlas.h @@ -91,8 +91,7 @@ public: * eviction occurs * @return An initialized GrDrawOpAtlas, or nullptr if creation fails */ - static std::unique_ptr Make(GrProxyProvider*, GrPixelConfig, - int width, int height, + static std::unique_ptr Make(GrContext*, GrPixelConfig, int width, int height, int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing, GrDrawOpAtlas::EvictionFunc func, void* data); @@ -109,21 +108,19 @@ public: * 'setUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to * addToAtlas might cause the previous data to be overwritten before it has been read. */ - bool addToAtlas(GrResourceProvider*, AtlasID*, GrDeferredUploadTarget*, int width, int height, - const void* image, SkIPoint16* loc); + bool addToAtlas(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image, + SkIPoint16* loc); + GrContext* context() const { return fContext; } const sk_sp* getProxies() const { return fProxies; } uint64_t atlasGeneration() const { return fAtlasGeneration; } inline bool hasID(AtlasID id) { - if (kInvalidAtlasID == id) { - return false; - } uint32_t plot = GetPlotIndexFromID(id); SkASSERT(plot < fNumPlots); uint32_t page = GetPageIndexFromID(id); - SkASSERT(page < fNumActivePages); + SkASSERT(page < fNumPages); return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id); } @@ -133,7 +130,7 @@ public: uint32_t plotIdx = GetPlotIndexFromID(id); SkASSERT(plotIdx < fNumPlots); uint32_t pageIdx = GetPageIndexFromID(id); - SkASSERT(pageIdx < fNumActivePages); + SkASSERT(pageIdx < fNumPages); Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get(); this->makeMRU(plot, pageIdx); plot->setLastUseToken(token); @@ -145,7 +142,7 @@ public: data->fData = userData; } - uint32_t numActivePages() { return fNumActivePages; } + uint32_t pageCount() { return fNumPages; } /** * A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The @@ -207,7 +204,7 @@ public: const BulkUseTokenUpdater::PlotData& pd = updater.fPlotsToUpdate[i]; // it's possible we've added a plot to the updater and subsequently the plot's page // was deleted -- so we check to prevent a crash - if (pd.fPageIndex < fNumActivePages) { + if (pd.fPageIndex < fNumPages) { Plot* plot = fPages[pd.fPageIndex].fPlotArray[pd.fPlotIndex].get(); this->makeMRU(plot, pd.fPageIndex); plot->setLastUseToken(token); @@ -228,14 +225,12 @@ public: void instantiate(GrOnFlushResourceProvider*); +private: uint32_t maxPages() const { return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1; } - int numAllocated_TestingOnly() const; - -private: - GrDrawOpAtlas(GrProxyProvider*, GrPixelConfig, int width, int height, int numPlotsX, + GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing); /** @@ -359,9 +354,8 @@ private: // the front and remove from the back there is no need for MRU. } - bool createPages(GrProxyProvider*); - bool activateNewPage(GrResourceProvider*); - void deactivateLastPage(); + bool createNewPage(); + void deleteLastPage(); void processEviction(AtlasID); inline void processEvictionAndResetRects(Plot* plot) { @@ -369,6 +363,7 @@ private: plot->resetRects(); } + GrContext* fContext; GrPixelConfig fPixelConfig; int fTextureWidth; int fTextureHeight; @@ -397,8 +392,7 @@ private: sk_sp fProxies[kMaxMultitexturePages]; Page fPages[kMaxMultitexturePages]; AllowMultitexturing fAllowMultitexturing; - - uint32_t fNumActivePages; + uint32_t fNumPages; }; #endif diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h index 75b9b0c2b1..456b1ce82f 100644 --- a/src/gpu/GrOnFlushResourceProvider.h +++ b/src/gpu/GrOnFlushResourceProvider.h @@ -66,8 +66,6 @@ public: */ class GrOnFlushResourceProvider { public: - explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {} - sk_sp makeRenderTargetContext(const GrSurfaceDesc&, sk_sp, const SkSurfaceProps*); @@ -88,10 +86,13 @@ public: const GrCaps* caps() const; private: + explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {} GrOnFlushResourceProvider(const GrOnFlushResourceProvider&) = delete; GrOnFlushResourceProvider& operator=(const GrOnFlushResourceProvider&) = delete; GrDrawingManager* fDrawingMgr; + + friend class GrDrawingManager; // to construct this type. }; #endif diff --git a/src/gpu/GrSurfaceProxy.cpp b/src/gpu/GrSurfaceProxy.cpp index 7acc03b05a..800b44723c 100644 --- a/src/gpu/GrSurfaceProxy.cpp +++ b/src/gpu/GrSurfaceProxy.cpp @@ -208,13 +208,6 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s return true; } -void GrSurfaceProxy::deInstantiate() { - SkASSERT(this->priv().isInstantiated()); - - this->release(); -} - - void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const { SkASSERT(LazyState::kFully != this->lazyInstantiationState()); const GrRenderTargetProxy* rtp = this->asRenderTargetProxy(); diff --git a/src/gpu/ops/GrAtlasTextOp.cpp b/src/gpu/ops/GrAtlasTextOp.cpp index 891564e586..46f38099ec 100644 --- a/src/gpu/ops/GrAtlasTextOp.cpp +++ b/src/gpu/ops/GrAtlasTextOp.cpp @@ -222,8 +222,6 @@ static void clip_quads(const SkIRect& clipRect, char* currVertex, const char* bl } void GrAtlasTextOp::onPrepareDraws(Target* target) { - auto resourceProvider = target->resourceProvider(); - // if we have RGB, then we won't have any SkShaders so no need to use a localmatrix. // TODO actually only invert if we don't have RGBA SkMatrix localMatrix; @@ -278,8 +276,8 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) { 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(), fFontCache, &glyphCache); + blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor, + target->deferredUploadTarget(), fFontCache, &glyphCache); GrAtlasTextBlob::VertexRegenerator::Result result; do { result = regenerator.regenerate(); diff --git a/src/gpu/ops/GrSmallPathRenderer.cpp b/src/gpu/ops/GrSmallPathRenderer.cpp index 563fbd3de3..3e7da52230 100644 --- a/src/gpu/ops/GrSmallPathRenderer.cpp +++ b/src/gpu/ops/GrSmallPathRenderer.cpp @@ -181,7 +181,7 @@ public: fHelper.visitProxies(func); const sk_sp* proxies = fAtlas->getProxies(); - for (uint32_t i = 0; i < fAtlas->numActivePages(); ++i) { + for (uint32_t i = 0; i < fAtlas->pageCount(); ++i) { SkASSERT(proxies[i]); func(proxies[i].get()); } @@ -223,7 +223,7 @@ private: flushInfo.fPipeline = fHelper.makePipeline(target); // Setup GrGeometryProcessor GrDrawOpAtlas* atlas = fAtlas; - uint32_t atlasPageCount = atlas->numActivePages(); + uint32_t atlasPageCount = atlas->pageCount(); if (!atlasPageCount) { return; } @@ -400,8 +400,6 @@ private: bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape, uint32_t dimension, SkScalar scale) const { - auto resourceProvider = target->resourceProvider(); - const SkRect& bounds = shape.bounds(); // generate bounding rect for bitmap draw @@ -490,11 +488,10 @@ private: SkIPoint16 atlasLocation; GrDrawOpAtlas::AtlasID id; auto uploadTarget = target->deferredUploadTarget(); - if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height, - dfStorage.get(), &atlasLocation)) { + if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) { this->flush(target, flushInfo); - if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height, - dfStorage.get(), &atlasLocation)) { + if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), + &atlasLocation)) { return false; } } @@ -533,8 +530,6 @@ private: bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape, const SkMatrix& ctm) const { - auto resourceProvider = target->resourceProvider(); - const SkRect& bounds = shape.bounds(); if (bounds.isEmpty()) { return false; @@ -595,11 +590,11 @@ private: SkIPoint16 atlasLocation; GrDrawOpAtlas::AtlasID id; auto uploadTarget = target->deferredUploadTarget(); - if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(), - dst.addr(), &atlasLocation)) { + if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(), + &atlasLocation)) { this->flush(target, flushInfo); - if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(), - dst.addr(), &atlasLocation)) { + if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(), + &atlasLocation)) { return false; } } @@ -701,7 +696,7 @@ private: void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const { GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get(); - if (gp->numTextureSamplers() != (int)fAtlas->numActivePages()) { + if (gp->numTextureSamplers() != (int)fAtlas->pageCount()) { // During preparation the number of atlas pages has increased. // Update the proxies used in the GP to match. if (fUsesDistanceField) { @@ -793,7 +788,7 @@ bool GrSmallPathRenderer::onDrawPath(const DrawPathArgs& args) { SkASSERT(!args.fShape->isEmpty()); SkASSERT(args.fShape->hasUnstyledKey()); if (!fAtlas) { - fAtlas = GrDrawOpAtlas::Make(args.fContext->contextPriv().proxyProvider(), + fAtlas = GrDrawOpAtlas::Make(args.fContext, kAlpha_8_GrPixelConfig, ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT, NUM_PLOTS_X, NUM_PLOTS_Y, @@ -863,8 +858,7 @@ GR_DRAW_OP_TEST_DEFINE(SmallPathOp) { if (context->uniqueID() != gTestStruct.fContextID) { gTestStruct.fContextID = context->uniqueID(); gTestStruct.reset(); - gTestStruct.fAtlas = GrDrawOpAtlas::Make(context->contextPriv().proxyProvider(), - kAlpha_8_GrPixelConfig, + gTestStruct.fAtlas = GrDrawOpAtlas::Make(context, kAlpha_8_GrPixelConfig, ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT, NUM_PLOTS_X, NUM_PLOTS_Y, GrDrawOpAtlas::AllowMultitexturing::kYes, diff --git a/src/gpu/text/GrAtlasGlyphCache.cpp b/src/gpu/text/GrAtlasGlyphCache.cpp index f7b1e1269a..fb52250781 100644 --- a/src/gpu/text/GrAtlasGlyphCache.cpp +++ b/src/gpu/text/GrAtlasGlyphCache.cpp @@ -9,7 +9,6 @@ #include "GrContext.h" #include "GrDistanceFieldGenFromVector.h" #include "GrGpu.h" -#include "GrProxyProvider.h" #include "GrRectanizer.h" #include "SkAutoMalloc.h" @@ -20,14 +19,14 @@ bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) { int index = MaskFormatToAtlasIndex(format); if (!fAtlases[index]) { - GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->caps()); + GrPixelConfig config = MaskFormatToPixelConfig(format, *fContext->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, + fAtlases[index] = GrDrawOpAtlas::Make(fContext, config, width, height, numPlotsX, numPlotsY, + fAllowMultitexturing, &GrAtlasGlyphCache::HandleEviction, (void*)this); if (!fAtlases[index]) { return false; @@ -36,13 +35,11 @@ bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) { return true; } -GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes, +GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) - : fProxyProvider(proxyProvider) - , fAllowMultitexturing(allowMultitexturing) - , fPreserveStrike(nullptr) { + : fContext(context), 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 log2MaxTextureSize = SkPrevLog2(context->caps()->maxTextureSize()); int log2MaxDim = 9; for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) { int maxDim = 1 << log2MaxDim; @@ -177,12 +174,12 @@ static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char* return true; } -void GrAtlasGlyphCache::dump(GrContext* context) const { +void GrAtlasGlyphCache::dump() const { static int gDumpCount = 0; for (int i = 0; i < kMaskFormatCount; ++i) { if (fAtlases[i]) { const sk_sp* proxies = fAtlases[i]->getProxies(); - for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) { + for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->pageCount(); ++pageIdx) { SkASSERT(proxies[pageIdx]); SkString filename; #ifdef SK_BUILD_FOR_ANDROID @@ -191,7 +188,7 @@ void GrAtlasGlyphCache::dump(GrContext* context) const { filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx); #endif - save_pixels(context, proxies[pageIdx].get(), filename.c_str()); + save_pixels(fContext, proxies[pageIdx].get(), filename.c_str()); } } } @@ -448,8 +445,7 @@ void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) { } } -bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider, - GrDeferredUploadTarget* target, +bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target, GrAtlasGlyphCache* atlasGlyphCache, GrGlyph* glyph, SkGlyphCache* cache, @@ -477,8 +473,7 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider, } } - bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target, - expectedMaskFormat, + bool success = atlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat, glyph->width(), glyph->height(), storage.get(), &glyph->fAtlasLocation); if (success) { diff --git a/src/gpu/text/GrAtlasGlyphCache.h b/src/gpu/text/GrAtlasGlyphCache.h index 84b7d1b249..6175342c26 100644 --- a/src/gpu/text/GrAtlasGlyphCache.h +++ b/src/gpu/text/GrAtlasGlyphCache.h @@ -64,8 +64,8 @@ public: // 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); + bool addGlyphToAtlas(GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, SkGlyphCache*, + GrMaskFormat expectedMaskFormat); // testing int countGlyphs() const { return fCache.count(); } @@ -109,8 +109,7 @@ private: */ class GrAtlasGlyphCache : public GrOnFlushCallbackObject { public: - GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes, - GrDrawOpAtlas::AllowMultitexturing); + GrAtlasGlyphCache(GrContext*, 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. @@ -133,7 +132,7 @@ public: SkASSERT(numProxies); if (this->initAtlas(format)) { - *numProxies = this->getAtlas(format)->numActivePages(); + *numProxies = this->getAtlas(format)->pageCount(); return this->getAtlas(format)->getProxies(); } *numProxies = 0; @@ -166,13 +165,11 @@ public: } // add to texture atlas that matches this format - bool addToAtlas(GrResourceProvider* resourceProvider, GrAtlasTextStrike* strike, - GrDrawOpAtlas::AtlasID* id, + bool addToAtlas(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); + return this->getAtlas(format)->addToAtlas(id, target, width, height, image, loc); } // Some clients may wish to verify the integrity of the texture backing store of the @@ -193,7 +190,8 @@ public: } } - void postFlush(GrDeferredUploadToken startTokenForNextFlush, const uint32_t*, int) override { + 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); @@ -208,11 +206,13 @@ public: /////////////////////////////////////////////////////////////////////////// // Functions intended debug only #ifdef SK_DEBUG - void dump(GrContext*) const; + void dump() const; #endif void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]); + GrContext* context() const { return fContext; } + private: static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) { switch (format) { @@ -258,7 +258,7 @@ private: static void HandleEviction(GrDrawOpAtlas::AtlasID, void*); using StrikeHash = SkTDynamicHash; - GrProxyProvider* fProxyProvider; + GrContext* fContext; StrikeHash fCache; GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; std::unique_ptr fAtlases[kMaskFormatCount]; diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h index 0fae3cd8c7..6e1d0b1bde 100644 --- a/src/gpu/text/GrAtlasTextBlob.h +++ b/src/gpu/text/GrAtlasTextBlob.h @@ -560,9 +560,9 @@ public: * SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of * SkGlyphCache. */ - VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx, - const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, - GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*); + VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix, + SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget*, + GrAtlasGlyphCache*, SkAutoGlyphCache*); struct Result { /** @@ -589,7 +589,6 @@ private: template Result doRegen(); - GrResourceProvider* fResourceProvider; const SkMatrix& fViewMatrix; GrAtlasTextBlob* fBlob; GrDeferredUploadTarget* fUploadTarget; diff --git a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp index 500ae31703..1a9c3d73e4 100644 --- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp +++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp @@ -190,13 +190,11 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri } } -Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob, - int runIdx, int subRunIdx, +Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache, SkAutoGlyphCache* lazyCache) - : fResourceProvider(resourceProvider) - , fViewMatrix(viewMatrix) + : fViewMatrix(viewMatrix) , fBlob(blob) , fUploadTarget(uploadTarget) , fGlyphCache(glyphCache) @@ -276,8 +274,8 @@ Regenerator::Result Regenerator::doRegen() { SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat()); if (!fGlyphCache->hasGlyph(glyph) && - !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph, - fLazyCache->get(), fSubRun->maskFormat())) { + !strike->addGlyphToAtlas(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(), + fSubRun->maskFormat())) { fBrokenRun = glyphIdx > 0; result.fFinished = false; return result; diff --git a/tests/DrawOpAtlasTest.cpp b/tests/DrawOpAtlasTest.cpp deleted file mode 100644 index a34618e38f..0000000000 --- a/tests/DrawOpAtlasTest.cpp +++ /dev/null @@ -1,132 +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 "SkTypes.h" - -#if SK_SUPPORT_GPU - -#include "GrContextPriv.h" -#include "Test.h" -#include "text/GrAtlasGlyphCache.h" - -static const int kNumPlots = 2; -static const int kPlotSize = 32; -static const int kAtlasSize = kNumPlots * kPlotSize; - -int GrDrawOpAtlas::numAllocated_TestingOnly() const { - int count = 0; - for (uint32_t i = 0; i < this->maxPages(); ++i) { - if (fProxies[i]->priv().isInstantiated()) { - ++count; - } - } - - return count; -} - -void EvictionFunc(GrDrawOpAtlas::AtlasID atlasID, void*) { - SkASSERT(0); // The unit test shouldn't exercise this code path -} - -static void check(skiatest::Reporter* r, GrDrawOpAtlas* atlas, - uint32_t expectedActive, uint32_t expectedMax, int expectedAlloced) { - REPORTER_ASSERT(r, expectedActive == atlas->numActivePages()); - REPORTER_ASSERT(r, expectedMax == atlas->maxPages()); - REPORTER_ASSERT(r, expectedAlloced == atlas->numAllocated_TestingOnly()); -} - -class TestingUploadTarget : public GrDeferredUploadTarget { -public: - TestingUploadTarget() { } - - const GrTokenTracker* tokenTracker() final { - return &fTokenTracker; - } - - GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final { - SkASSERT(0); // this test shouldn't invoke this code path - return fTokenTracker.nextDrawToken(); - } - - virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) final { - return fTokenTracker.nextTokenToFlush(); - } - - void issueDrawToken() { fTokenTracker.issueDrawToken(); } - void flushToken() { fTokenTracker.flushToken(); } - -private: - GrTokenTracker fTokenTracker; - - typedef GrDeferredUploadTarget INHERITED; -}; - -static bool fill_plot(GrDrawOpAtlas* atlas, - GrResourceProvider* resourceProvider, - GrDeferredUploadTarget* target, - GrDrawOpAtlas::AtlasID* atlasID, - int alpha) { - SkImageInfo ii = SkImageInfo::MakeA8(kPlotSize, kPlotSize); - - SkBitmap data; - data.allocPixels(ii); - data.eraseARGB(alpha, 0, 0, 0); - - SkIPoint16 loc; - bool result = atlas->addToAtlas(resourceProvider, atlasID, target, kPlotSize, kPlotSize, - data.getAddr(0, 0), &loc); - return result; -} - - -DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DrawOpAtlas, reporter, ctxInfo) { - auto context = ctxInfo.grContext(); - auto proxyProvider = context->contextPriv().proxyProvider(); - auto resourceProvider = context->contextPriv().resourceProvider(); - auto drawingManager = context->contextPriv().drawingManager(); - - GrOnFlushResourceProvider onFlushResourceProvider(drawingManager); - TestingUploadTarget uploadTarget; - - std::unique_ptr atlas = GrDrawOpAtlas::Make( - proxyProvider, - kAlpha_8_GrPixelConfig, - kAtlasSize, kAtlasSize, - kNumPlots, kNumPlots, - GrDrawOpAtlas::AllowMultitexturing::kYes, - EvictionFunc, nullptr); - check(reporter, atlas.get(), 0, 4, 0); - - // Fill up the first level - GrDrawOpAtlas::AtlasID atlasIDs[kNumPlots * kNumPlots]; - for (int i = 0; i < kNumPlots * kNumPlots; ++i) { - bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasIDs[i], i*32); - REPORTER_ASSERT(reporter, result); - check(reporter, atlas.get(), 1, 4, 1); - } - - atlas->instantiate(&onFlushResourceProvider); - check(reporter, atlas.get(), 1, 4, 1); - - // Force allocation of a second level - GrDrawOpAtlas::AtlasID atlasID; - bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasID, 4*32); - REPORTER_ASSERT(reporter, result); - check(reporter, atlas.get(), 2, 4, 2); - - // Simulate a lot of draws using only the first plot. The last texture should be compacted. - for (int i = 0; i < 512; ++i) { - atlas->setLastUseToken(atlasIDs[0], uploadTarget.tokenTracker()->nextDrawToken()); - uploadTarget.issueDrawToken(); - uploadTarget.flushToken(); - atlas->compact(uploadTarget.tokenTracker()->nextTokenToFlush()); - } - - check(reporter, atlas.get(), 1, 4, 1); -} - -#endif