aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrDrawOpAtlas.cpp
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-02-21 14:17:08 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-02-21 19:46:56 +0000
commit056c1a821afcfbe606615ad1a7d1b554549d0846 (patch)
tree33ed26319e742379d7630065dc1ef165296df35d /src/gpu/GrDrawOpAtlas.cpp
parent9ce9507a7f66634eeb06fc34aebdfb6c4f1a1d11 (diff)
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 <robertphillips@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
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;
}