Separate creation time & flush time behavior in GrDrawOpAtlas (take 2)
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: Ie9b64b13e261b01ee14be09fbf7e17841b7781dc
Reviewed-on: https://skia-review.googlesource.com/109749
Reviewed-by: Jim Van Verth <jvanverth@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
diff --git a/src/atlastext/SkAtlasTextTarget.cpp b/src/atlastext/SkAtlasTextTarget.cpp
index d80c7a4..f553ffa 100644
--- a/src/atlastext/SkAtlasTextTarget.cpp
+++ b/src/atlastext/SkAtlasTextTarget.cpp
@@ -183,12 +183,18 @@
FlushInfo flushInfo;
SkAutoGlyphCache glyphCache;
auto& context = target->context()->internal();
- auto* atlasGlyphCache = context.grContext()->contextPriv().getAtlasGlyphCache();
+ 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);
+
for (int i = 0; i < fGeoCount; ++i) {
GrAtlasTextBlob::VertexRegenerator regenerator(
- fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fViewMatrix,
- fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, &context, atlasGlyphCache,
- &glyphCache);
+ 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);
GrAtlasTextBlob::VertexRegenerator::Result result;
do {
result = regenerator.regenerate();
diff --git a/src/gpu/GrContext.cpp b/src/gpu/GrContext.cpp
index 3fb7a9c..0af3197 100644
--- a/src/gpu/GrContext.cpp
+++ b/src/gpu/GrContext.cpp
@@ -295,7 +295,7 @@
} else {
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
}
- fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
+ fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes,
allowMultitexturing);
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
diff --git a/src/gpu/GrDeferredUpload.h b/src/gpu/GrDeferredUpload.h
index fad5e93..d783631 100644
--- a/src/gpu/GrDeferredUpload.h
+++ b/src/gpu/GrDeferredUpload.h
@@ -96,9 +96,10 @@
GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
private:
- // Only these two classes get to increment the token counters
+ // Only these three 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 622aa22..7539a7a 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 (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());
- }
+ 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());
}
}
-std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width,
+std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrProxyProvider* proxyProvider,
+ GrPixelConfig config, int width,
int height, int numPlotsX, int numPlotsY,
AllowMultitexturing allowMultitexturing,
GrDrawOpAtlas::EvictionFunc func, void* data) {
- std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(ctx, config, width, height, numPlotsX,
- numPlotsY, allowMultitexturing));
+ std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(proxyProvider, config, width, height,
+ numPlotsX, numPlotsY,
+ allowMultitexturing));
if (!atlas->getProxies()[0]) {
return nullptr;
}
@@ -53,7 +53,6 @@
#endif
////////////////////////////////////////////////////////////////////////////////
-
GrDrawOpAtlas::Plot::Plot(int pageIndex, int plotIndex, uint64_t genID, int offX, int offY,
int width, int height, GrPixelConfig config)
: fLastUpload(GrDeferredUploadToken::AlreadyFlushedToken())
@@ -178,16 +177,16 @@
///////////////////////////////////////////////////////////////////////////////
-GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height,
+GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
+ GrPixelConfig config, int width, int height,
int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
- : fContext(context)
- , fPixelConfig(config)
+ : fPixelConfig(config)
, fTextureWidth(width)
, fTextureHeight(height)
, fAtlasGeneration(kInvalidAtlasGeneration + 1)
, fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken())
, fAllowMultitexturing(allowMultitexturing)
- , fNumPages(0) {
+ , fNumActivePages(0) {
fPlotWidth = fTextureWidth / numPlotsX;
fPlotHeight = fTextureHeight / numPlotsY;
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
@@ -196,7 +195,7 @@
fNumPlots = numPlotsX * numPlotsY;
- this->createNewPage();
+ this->createPages(proxyProvider);
}
inline void GrDrawOpAtlas::processEviction(AtlasID id) {
@@ -217,13 +216,8 @@
// With c+14 we could move sk_sp into lamba to only ref once.
sk_sp<Plot> 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) {
@@ -243,8 +237,9 @@
// are rare; i.e., we are not continually refreshing the frame.
static constexpr auto kRecentlyUsedCount = 256;
-bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int width, int height,
- const void* image, SkIPoint16* loc) {
+bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
+ AtlasID* id, GrDeferredUploadTarget* target,
+ int width, int height, const void* image, SkIPoint16* loc) {
if (width > fPlotWidth || height > fPlotHeight) {
return false;
}
@@ -252,7 +247,7 @@
// 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 < fNumPages; ++pageIdx) {
+ for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
SkASSERT(fProxies[pageIdx]);
// look through all allocated plots for one we can share, in Most Recently Refed order
PlotList::Iter plotIter;
@@ -272,10 +267,10 @@
// 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 < fNumPages; ++pageIdx) {
+ for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
Plot* plot = fPages[pageIdx].fPlotList.tail();
SkASSERT(plot);
- if ((fNumPages == this->maxPages() &&
+ if ((fNumActivePages == this->maxPages() &&
plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) ||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
this->processEvictionAndResetRects(plot);
@@ -290,9 +285,10 @@
}
// If the simple cases fail, try to create a new page and add to it
- if (this->createNewPage()) {
- unsigned int pageIdx = fNumPages-1;
- SkASSERT(fProxies[pageIdx]);
+ if (this->activateNewPage(resourceProvider)) {
+ unsigned int pageIdx = fNumActivePages-1;
+ SkASSERT(fProxies[pageIdx] && fProxies[pageIdx]->priv().isInstantiated());
+
Plot* plot = fPages[pageIdx].fPlotList.head();
SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp());
if (plot->addSubImage(width, height, image, loc)) {
@@ -307,7 +303,7 @@
// 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)(fNumPages-1); pageIdx >= 0; --pageIdx) {
+ for (int pageIdx = (int)(fNumActivePages-1); pageIdx >= 0; --pageIdx) {
Plot* currentPlot = fPages[pageIdx].fPlotList.tail();
if (currentPlot->lastUseToken() != target->tokenTracker()->nextDrawToken()) {
plot = currentPlot;
@@ -339,11 +335,8 @@
// one it displaced most likely was uploaded ASAP.
// With c+14 we could move sk_sp into lambda to only ref once.
sk_sp<Plot> plotsp(SkRef(newPlot.get()));
- // 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;
- }
+
+ SkASSERT(fProxies[pageIdx]->priv().isInstantiated());
GrTextureProxy* proxy = fProxies[pageIdx].get();
GrDeferredUploadToken lastUploadToken = target->addInlineUpload(
@@ -358,7 +351,7 @@
}
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
- if (fNumPages <= 1) {
+ if (fNumActivePages <= 1) {
fPrevFlushToken = startTokenForNextFlush;
return;
}
@@ -366,7 +359,7 @@
// 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 < fNumPages; ++pageIndex) {
+ for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
while (Plot* plot = plotIter.get()) {
// Reset number of flushes since used
@@ -385,7 +378,7 @@
// TODO: consider if we should also do this if it's been a long time since the last atlas use
if (atlasUsedThisFlush) {
SkTArray<Plot*> availablePlots;
- uint32_t lastPageIndex = fNumPages - 1;
+ uint32_t lastPageIndex = fNumActivePages - 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.
@@ -494,19 +487,15 @@
SkDebugf("delete %d\n", fNumPages-1);
}
#endif
- this->deleteLastPage();
+ this->deactivateLastPage();
}
}
fPrevFlushToken = startTokenForNextFlush;
}
-bool GrDrawOpAtlas::createNewPage() {
- if (fNumPages == this->maxPages()) {
- return false;
- }
-
- GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
+bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) {
+ SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight));
GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags;
@@ -515,47 +504,83 @@
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;
- // set up allocated plots
- fPages[fNumPages].fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]);
-
- sk_sp<Plot>* 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;
+ 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[i].fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]);
+
+ sk_sp<Plot>* 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("created %d\n", fNumPages);
+ SkDebugf("activated page#: %d\n", fNumActivePages);
}
#endif
- fNumPages++;
+
+ ++fNumActivePages;
return true;
}
-inline void GrDrawOpAtlas::deleteLastPage() {
- uint32_t lastPageIndex = fNumPages - 1;
- // clean out the plots
+
+inline void GrDrawOpAtlas::deactivateLastPage() {
+ SkASSERT(fNumActivePages);
+
+ uint32_t lastPageIndex = fNumActivePages - 1;
+
+ int numPlotsX = fTextureWidth/fPlotWidth;
+ int numPlotsY = fTextureHeight/fPlotHeight;
+
fPages[lastPageIndex].fPlotList.reset();
- fPages[lastPageIndex].fPlotArray.reset(nullptr);
- // remove ref to texture proxy
- fProxies[lastPageIndex].reset(nullptr);
- --fNumPages;
+ 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;
}
diff --git a/src/gpu/GrDrawOpAtlas.h b/src/gpu/GrDrawOpAtlas.h
index a2c9859..b849d9e 100644
--- a/src/gpu/GrDrawOpAtlas.h
+++ b/src/gpu/GrDrawOpAtlas.h
@@ -91,7 +91,8 @@
* eviction occurs
* @return An initialized GrDrawOpAtlas, or nullptr if creation fails
*/
- static std::unique_ptr<GrDrawOpAtlas> Make(GrContext*, GrPixelConfig, int width, int height,
+ static std::unique_ptr<GrDrawOpAtlas> Make(GrProxyProvider*, GrPixelConfig,
+ int width, int height,
int numPlotsX, int numPlotsY,
AllowMultitexturing allowMultitexturing,
GrDrawOpAtlas::EvictionFunc func, void* data);
@@ -108,19 +109,21 @@
* '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(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image,
- SkIPoint16* loc);
+ bool addToAtlas(GrResourceProvider*, AtlasID*, GrDeferredUploadTarget*, int width, int height,
+ const void* image, SkIPoint16* loc);
- GrContext* context() const { return fContext; }
const sk_sp<GrTextureProxy>* 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 < fNumPages);
+ SkASSERT(page < fNumActivePages);
return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id);
}
@@ -130,7 +133,7 @@
uint32_t plotIdx = GetPlotIndexFromID(id);
SkASSERT(plotIdx < fNumPlots);
uint32_t pageIdx = GetPageIndexFromID(id);
- SkASSERT(pageIdx < fNumPages);
+ SkASSERT(pageIdx < fNumActivePages);
Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get();
this->makeMRU(plot, pageIdx);
plot->setLastUseToken(token);
@@ -142,7 +145,7 @@
data->fData = userData;
}
- uint32_t pageCount() { return fNumPages; }
+ uint32_t numActivePages() { return fNumActivePages; }
/**
* A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The
@@ -204,7 +207,7 @@
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 < fNumPages) {
+ if (pd.fPageIndex < fNumActivePages) {
Plot* plot = fPages[pd.fPageIndex].fPlotArray[pd.fPlotIndex].get();
this->makeMRU(plot, pd.fPageIndex);
plot->setLastUseToken(token);
@@ -225,12 +228,14 @@
void instantiate(GrOnFlushResourceProvider*);
-private:
uint32_t maxPages() const {
return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1;
}
- GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX,
+ int numAllocated_TestingOnly() const;
+
+private:
+ GrDrawOpAtlas(GrProxyProvider*, GrPixelConfig, int width, int height, int numPlotsX,
int numPlotsY, AllowMultitexturing allowMultitexturing);
/**
@@ -354,8 +359,9 @@
// the front and remove from the back there is no need for MRU.
}
- bool createNewPage();
- void deleteLastPage();
+ bool createPages(GrProxyProvider*);
+ bool activateNewPage(GrResourceProvider*);
+ void deactivateLastPage();
void processEviction(AtlasID);
inline void processEvictionAndResetRects(Plot* plot) {
@@ -363,7 +369,6 @@
plot->resetRects();
}
- GrContext* fContext;
GrPixelConfig fPixelConfig;
int fTextureWidth;
int fTextureHeight;
@@ -392,7 +397,8 @@
sk_sp<GrTextureProxy> fProxies[kMaxMultitexturePages];
Page fPages[kMaxMultitexturePages];
AllowMultitexturing fAllowMultitexturing;
- uint32_t fNumPages;
+
+ uint32_t fNumActivePages;
};
#endif
diff --git a/src/gpu/GrOnFlushResourceProvider.h b/src/gpu/GrOnFlushResourceProvider.h
index 456b1ce..75b9b0c 100644
--- a/src/gpu/GrOnFlushResourceProvider.h
+++ b/src/gpu/GrOnFlushResourceProvider.h
@@ -66,6 +66,8 @@
*/
class GrOnFlushResourceProvider {
public:
+ explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
+
sk_sp<GrRenderTargetContext> makeRenderTargetContext(const GrSurfaceDesc&,
sk_sp<SkColorSpace>,
const SkSurfaceProps*);
@@ -86,13 +88,10 @@
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 800b447..7acc03b 100644
--- a/src/gpu/GrSurfaceProxy.cpp
+++ b/src/gpu/GrSurfaceProxy.cpp
@@ -208,6 +208,13 @@
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 46f3809..952b3ba 100644
--- a/src/gpu/ops/GrAtlasTextOp.cpp
+++ b/src/gpu/ops/GrAtlasTextOp.cpp
@@ -222,6 +222,8 @@
}
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;
@@ -234,7 +236,7 @@
unsigned int atlasPageCount;
const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &atlasPageCount);
- if (!atlasPageCount || !proxies[0]) {
+ if (!proxies[0]) {
SkDebugf("Could not allocate backing texture for atlas\n");
return;
}
@@ -276,8 +278,8 @@
const Geometry& args = fGeoData[i];
Blob* blob = args.fBlob;
GrAtlasTextBlob::VertexRegenerator regenerator(
- blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor,
- target->deferredUploadTarget(), fFontCache, &glyphCache);
+ resourceProvider, 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 3e7da52..c4201d7 100644
--- a/src/gpu/ops/GrSmallPathRenderer.cpp
+++ b/src/gpu/ops/GrSmallPathRenderer.cpp
@@ -181,7 +181,7 @@
fHelper.visitProxies(func);
const sk_sp<GrTextureProxy>* proxies = fAtlas->getProxies();
- for (uint32_t i = 0; i < fAtlas->pageCount(); ++i) {
+ for (uint32_t i = 0; i < fAtlas->numActivePages(); ++i) {
SkASSERT(proxies[i]);
func(proxies[i].get());
}
@@ -222,11 +222,6 @@
FlushInfo flushInfo;
flushInfo.fPipeline = fHelper.makePipeline(target);
// Setup GrGeometryProcessor
- GrDrawOpAtlas* atlas = fAtlas;
- uint32_t atlasPageCount = atlas->pageCount();
- if (!atlasPageCount) {
- return;
- }
const SkMatrix& ctm = fShapes[0].fViewMatrix;
if (fUsesDistanceField) {
uint32_t flags = 0;
@@ -249,7 +244,7 @@
matrix = &SkMatrix::I();
}
flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(
- *matrix, atlas->getProxies(), GrSamplerState::ClampBilerp(), flags);
+ *matrix, fAtlas->getProxies(), GrSamplerState::ClampBilerp(), flags);
} else {
SkMatrix invert;
if (fHelper.usesLocalCoords()) {
@@ -260,7 +255,7 @@
}
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
- this->color(), atlas->getProxies(), GrSamplerState::ClampNearest(),
+ this->color(), fAtlas->getProxies(), GrSamplerState::ClampNearest(),
kA8_GrMaskFormat, invert, fHelper.usesLocalCoords());
}
@@ -335,7 +330,7 @@
// check to see if df path is cached
ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension));
shapeData = fShapeCache->find(key);
- if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
+ if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
// Remove the stale cache entry
if (shapeData) {
fShapeCache->remove(shapeData->fKey);
@@ -347,7 +342,7 @@
shapeData = new ShapeData;
if (!this->addDFPathToAtlas(target,
&flushInfo,
- atlas,
+ fAtlas,
shapeData,
args.fShape,
SkScalarCeilToInt(desiredDimension),
@@ -360,7 +355,7 @@
// check to see if bitmap path is cached
ShapeData::Key key(args.fShape, args.fViewMatrix);
shapeData = fShapeCache->find(key);
- if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
+ if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
// Remove the stale cache entry
if (shapeData) {
fShapeCache->remove(shapeData->fKey);
@@ -371,7 +366,7 @@
shapeData = new ShapeData;
if (!this->addBMPathToAtlas(target,
&flushInfo,
- atlas,
+ fAtlas,
shapeData,
args.fShape,
args.fViewMatrix)) {
@@ -382,9 +377,9 @@
}
auto uploadTarget = target->deferredUploadTarget();
- atlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
+ fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
- this->writePathVertices(atlas,
+ this->writePathVertices(fAtlas,
offset,
args.fColor,
vertexStride,
@@ -400,6 +395,8 @@
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
@@ -488,10 +485,11 @@
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
auto uploadTarget = target->deferredUploadTarget();
- if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) {
+ if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
+ dfStorage.get(), &atlasLocation)) {
this->flush(target, flushInfo);
- if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(),
- &atlasLocation)) {
+ if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
+ dfStorage.get(), &atlasLocation)) {
return false;
}
}
@@ -530,6 +528,8 @@
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;
@@ -590,11 +590,11 @@
SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id;
auto uploadTarget = target->deferredUploadTarget();
- if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
- &atlasLocation)) {
+ if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
+ dst.addr(), &atlasLocation)) {
this->flush(target, flushInfo);
- if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
- &atlasLocation)) {
+ if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
+ dst.addr(), &atlasLocation)) {
return false;
}
}
@@ -696,7 +696,7 @@
void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get();
- if (gp->numTextureSamplers() != (int)fAtlas->pageCount()) {
+ if (gp->numTextureSamplers() != (int)fAtlas->numActivePages()) {
// During preparation the number of atlas pages has increased.
// Update the proxies used in the GP to match.
if (fUsesDistanceField) {
@@ -788,7 +788,7 @@
SkASSERT(!args.fShape->isEmpty());
SkASSERT(args.fShape->hasUnstyledKey());
if (!fAtlas) {
- fAtlas = GrDrawOpAtlas::Make(args.fContext,
+ fAtlas = GrDrawOpAtlas::Make(args.fContext->contextPriv().proxyProvider(),
kAlpha_8_GrPixelConfig,
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
NUM_PLOTS_X, NUM_PLOTS_Y,
@@ -858,7 +858,8 @@
if (context->uniqueID() != gTestStruct.fContextID) {
gTestStruct.fContextID = context->uniqueID();
gTestStruct.reset();
- gTestStruct.fAtlas = GrDrawOpAtlas::Make(context, kAlpha_8_GrPixelConfig,
+ gTestStruct.fAtlas = GrDrawOpAtlas::Make(context->contextPriv().proxyProvider(),
+ 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 fb52250..f7b1e12 100644
--- a/src/gpu/text/GrAtlasGlyphCache.cpp
+++ b/src/gpu/text/GrAtlasGlyphCache.cpp
@@ -9,6 +9,7 @@
#include "GrContext.h"
#include "GrDistanceFieldGenFromVector.h"
#include "GrGpu.h"
+#include "GrProxyProvider.h"
#include "GrRectanizer.h"
#include "SkAutoMalloc.h"
@@ -19,14 +20,14 @@
bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
int index = MaskFormatToAtlasIndex(format);
if (!fAtlases[index]) {
- GrPixelConfig config = MaskFormatToPixelConfig(format, *fContext->caps());
+ 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(fContext, config, width, height, numPlotsX, numPlotsY,
- fAllowMultitexturing,
+ fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
+ numPlotsX, numPlotsY, fAllowMultitexturing,
&GrAtlasGlyphCache::HandleEviction, (void*)this);
if (!fAtlases[index]) {
return false;
@@ -35,11 +36,13 @@
return true;
}
-GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
+GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes,
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
- : fContext(context), fAllowMultitexturing(allowMultitexturing), fPreserveStrike(nullptr) {
+ : fProxyProvider(proxyProvider)
+ , fAllowMultitexturing(allowMultitexturing)
+ , fPreserveStrike(nullptr) {
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
- int log2MaxTextureSize = SkPrevLog2(context->caps()->maxTextureSize());
+ int log2MaxTextureSize = SkPrevLog2(fProxyProvider->caps()->maxTextureSize());
int log2MaxDim = 9;
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
int maxDim = 1 << log2MaxDim;
@@ -174,12 +177,12 @@
return true;
}
-void GrAtlasGlyphCache::dump() const {
+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]->pageCount(); ++pageIdx) {
+ for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
SkASSERT(proxies[pageIdx]);
SkString filename;
#ifdef SK_BUILD_FOR_ANDROID
@@ -188,7 +191,7 @@
filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
#endif
- save_pixels(fContext, proxies[pageIdx].get(), filename.c_str());
+ save_pixels(context, proxies[pageIdx].get(), filename.c_str());
}
}
}
@@ -445,7 +448,8 @@
}
}
-bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
+bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
+ GrDeferredUploadTarget* target,
GrAtlasGlyphCache* atlasGlyphCache,
GrGlyph* glyph,
SkGlyphCache* cache,
@@ -473,7 +477,8 @@
}
}
- bool success = atlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat,
+ bool success = atlasGlyphCache->addToAtlas(resourceProvider, 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 6175342..84b7d1b 100644
--- a/src/gpu/text/GrAtlasGlyphCache.h
+++ b/src/gpu/text/GrAtlasGlyphCache.h
@@ -64,8 +64,8 @@
// 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(GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, SkGlyphCache*,
- GrMaskFormat expectedMaskFormat);
+ bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*,
+ SkGlyphCache*, GrMaskFormat expectedMaskFormat);
// testing
int countGlyphs() const { return fCache.count(); }
@@ -109,7 +109,8 @@
*/
class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
public:
- GrAtlasGlyphCache(GrContext*, float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
+ 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.
@@ -132,7 +133,7 @@
SkASSERT(numProxies);
if (this->initAtlas(format)) {
- *numProxies = this->getAtlas(format)->pageCount();
+ *numProxies = this->getAtlas(format)->numActivePages();
return this->getAtlas(format)->getProxies();
}
*numProxies = 0;
@@ -165,11 +166,13 @@
}
// add to texture atlas that matches this format
- bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
+ 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(id, target, width, height, image, loc);
+ 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
@@ -190,8 +193,7 @@
}
}
- void postFlush(GrDeferredUploadToken startTokenForNextFlush,
- const uint32_t* opListIDs, int numOpListIDs) override {
+ void postFlush(GrDeferredUploadToken startTokenForNextFlush, const uint32_t*, int) override {
for (int i = 0; i < kMaskFormatCount; ++i) {
if (fAtlases[i]) {
fAtlases[i]->compact(startTokenForNextFlush);
@@ -206,13 +208,11 @@
///////////////////////////////////////////////////////////////////////////
// Functions intended debug only
#ifdef SK_DEBUG
- void dump() const;
+ void dump(GrContext*) 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 @@
static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
- GrContext* fContext;
+ GrProxyProvider* fProxyProvider;
StrikeHash fCache;
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
diff --git a/src/gpu/text/GrAtlasTextBlob.h b/src/gpu/text/GrAtlasTextBlob.h
index 6e1d0b1..0fae3cd 100644
--- a/src/gpu/text/GrAtlasTextBlob.h
+++ b/src/gpu/text/GrAtlasTextBlob.h
@@ -560,9 +560,9 @@
* SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
* SkGlyphCache.
*/
- VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix,
- SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget*,
- GrAtlasGlyphCache*, SkAutoGlyphCache*);
+ VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx,
+ const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
+ GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*);
struct Result {
/**
@@ -589,6 +589,7 @@
template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
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 1a9c3d7..500ae31 100644
--- a/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
+++ b/src/gpu/text/GrAtlasTextBlobVertexRegenerator.cpp
@@ -190,11 +190,13 @@
}
}
-Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx,
+Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob,
+ int runIdx, int subRunIdx,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
SkAutoGlyphCache* lazyCache)
- : fViewMatrix(viewMatrix)
+ : fResourceProvider(resourceProvider)
+ , fViewMatrix(viewMatrix)
, fBlob(blob)
, fUploadTarget(uploadTarget)
, fGlyphCache(glyphCache)
@@ -274,8 +276,8 @@
SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat());
if (!fGlyphCache->hasGlyph(glyph) &&
- !strike->addGlyphToAtlas(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(),
- fSubRun->maskFormat())) {
+ !strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph,
+ fLazyCache->get(), fSubRun->maskFormat())) {
fBrokenRun = glyphIdx > 0;
result.fFinished = false;
return result;