aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrDrawOpAtlas.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu/GrDrawOpAtlas.cpp')
-rw-r--r--src/gpu/GrDrawOpAtlas.cpp167
1 files changed, 96 insertions, 71 deletions
diff --git a/src/gpu/GrDrawOpAtlas.cpp b/src/gpu/GrDrawOpAtlas.cpp
index 622aa229bd..7539a7a05e 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 @@ 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())
@@ -178,16 +177,16 @@ void GrDrawOpAtlas::Plot::resetRects() {
///////////////////////////////////////////////////////////////////////////////
-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 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width
fNumPlots = numPlotsX * numPlotsY;
- this->createNewPage();
+ this->createPages(proxyProvider);
}
inline void GrDrawOpAtlas::processEviction(AtlasID id) {
@@ -217,13 +216,8 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i
// 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 @@ 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(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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
// 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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
// 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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
}
// 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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
// 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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
// 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 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
}
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
- if (fNumPages <= 1) {
+ if (fNumActivePages <= 1) {
fPrevFlushToken = startTokenForNextFlush;
return;
}
@@ -366,7 +359,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 < 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 @@ 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<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 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
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 @@ bool GrDrawOpAtlas::createNewPage() {
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 ]);
+ 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;
+ }
- 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));
+ // set up allocated plots
+ fPages[i].fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]);
- // build LRU list
- fPages[fNumPages].fPlotList.addToHead(currPlot->get());
- ++currPlot;
+ 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;
}