Revert "Separate creation time & flush time behavior in GrDrawOpAtlas"

This reverts commit 056c1a821a.

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 <robertphillips@google.com>
> Reviewed-by: Jim Van Verth <jvanverth@google.com>

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 <robertphillips@google.com>
Commit-Queue: Robert Phillips <robertphillips@google.com>
This commit is contained in:
Robert Phillips 2018-02-21 21:56:35 +00:00 committed by Skia Commit-Bot
parent 7630dcd794
commit 59ddc6d5ee
16 changed files with 141 additions and 347 deletions

View File

@ -60,7 +60,6 @@ tests_sources = [
"$_tests/DiscardableMemoryTest.cpp", "$_tests/DiscardableMemoryTest.cpp",
"$_tests/DrawBitmapRectTest.cpp", "$_tests/DrawBitmapRectTest.cpp",
"$_tests/DrawFilterTest.cpp", "$_tests/DrawFilterTest.cpp",
"$_tests/DrawOpAtlasTest.cpp",
"$_tests/DrawPathTest.cpp", "$_tests/DrawPathTest.cpp",
"$_tests/DrawTextTest.cpp", "$_tests/DrawTextTest.cpp",
"$_tests/DynamicHashTest.cpp", "$_tests/DynamicHashTest.cpp",

View File

@ -57,17 +57,6 @@ public:
} }
#endif #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 { void validate() const {
#ifdef SK_DEBUG #ifdef SK_DEBUG
SkASSERT(fRefCnt >= 0); SkASSERT(fRefCnt >= 0);
@ -140,7 +129,7 @@ protected:
} }
virtual ~GrIORefProxy() { virtual ~GrIORefProxy() {
// We don't unref 'fTarget' here since the 'unref' method will already // 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 // This GrIORefProxy was deferred before but has just been instantiated. To
@ -290,8 +279,6 @@ public:
virtual bool instantiate(GrResourceProvider* resourceProvider) = 0; virtual bool instantiate(GrResourceProvider* resourceProvider) = 0;
void deInstantiate();
/** /**
* Helper that gets the width and height of the surface as a bounding rectangle. * Helper that gets the width and height of the surface as a bounding rectangle.
*/ */

View File

@ -183,18 +183,12 @@ void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
FlushInfo flushInfo; FlushInfo flushInfo;
SkAutoGlyphCache glyphCache; SkAutoGlyphCache glyphCache;
auto& context = target->context()->internal(); 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) { for (int i = 0; i < fGeoCount; ++i) {
GrAtlasTextBlob::VertexRegenerator regenerator( GrAtlasTextBlob::VertexRegenerator regenerator(
resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fViewMatrix,
fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, &context, atlasGlyphCache,
&context, atlasGlyphCache, &glyphCache); &glyphCache);
GrAtlasTextBlob::VertexRegenerator::Result result; GrAtlasTextBlob::VertexRegenerator::Result result;
do { do {
result = regenerator.regenerate(); result = regenerator.regenerate();

View File

@ -295,7 +295,7 @@ bool GrContext::init(const GrContextOptions& options) {
} else { } else {
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes; allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
} }
fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes, fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
allowMultitexturing); allowMultitexturing);
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache); this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);

View File

@ -96,10 +96,9 @@ public:
GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); } GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
private: 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 SkInternalAtlasTextContext;
friend class GrOpFlushState; friend class GrOpFlushState;
friend class TestingUploadTarget;
/** Issues the next token for a draw. */ /** Issues the next token for a draw. */
GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; } GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; }

View File

@ -26,20 +26,20 @@
// must explicitly manage the lifetime of their backing proxies via the onFlushCallback system // must explicitly manage the lifetime of their backing proxies via the onFlushCallback system
// (which calls this method). // (which calls this method).
void GrDrawOpAtlas::instantiate(GrOnFlushResourceProvider* onFlushResourceProvider) { void GrDrawOpAtlas::instantiate(GrOnFlushResourceProvider* onFlushResourceProvider) {
for (uint32_t i = 0; i < fNumActivePages; ++i) { for (int i = 0; i < GrDrawOpAtlas::kMaxMultitexturePages; ++i) {
// All the atlas pages are now instantiated at flush time in the activeNewPage method. if (fProxies[i] && !fProxies[i]->priv().isInstantiated()) {
SkASSERT(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> GrDrawOpAtlas::Make(GrProxyProvider* proxyProvider, std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width,
GrPixelConfig config, int width,
int height, int numPlotsX, int numPlotsY, int height, int numPlotsX, int numPlotsY,
AllowMultitexturing allowMultitexturing, AllowMultitexturing allowMultitexturing,
GrDrawOpAtlas::EvictionFunc func, void* data) { GrDrawOpAtlas::EvictionFunc func, void* data) {
std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(proxyProvider, config, width, height, std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(ctx, config, width, height, numPlotsX,
numPlotsX, numPlotsY, numPlotsY, allowMultitexturing));
allowMultitexturing));
if (!atlas->getProxies()[0]) { if (!atlas->getProxies()[0]) {
return nullptr; return nullptr;
} }
@ -53,6 +53,7 @@ static bool gDumpAtlasData = false;
#endif #endif
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
GrDrawOpAtlas::Plot::Plot(int pageIndex, int plotIndex, uint64_t genID, int offX, int offY, GrDrawOpAtlas::Plot::Plot(int pageIndex, int plotIndex, uint64_t genID, int offX, int offY,
int width, int height, GrPixelConfig config) int width, int height, GrPixelConfig config)
: fLastUpload(GrDeferredUploadToken::AlreadyFlushedToken()) : fLastUpload(GrDeferredUploadToken::AlreadyFlushedToken())
@ -177,16 +178,16 @@ void GrDrawOpAtlas::Plot::resetRects() {
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider, GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height,
GrPixelConfig config, int width, int height,
int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing) int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
: fPixelConfig(config) : fContext(context)
, fPixelConfig(config)
, fTextureWidth(width) , fTextureWidth(width)
, fTextureHeight(height) , fTextureHeight(height)
, fAtlasGeneration(kInvalidAtlasGeneration + 1) , fAtlasGeneration(kInvalidAtlasGeneration + 1)
, fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken()) , fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken())
, fAllowMultitexturing(allowMultitexturing) , fAllowMultitexturing(allowMultitexturing)
, fNumActivePages(0) { , fNumPages(0) {
fPlotWidth = fTextureWidth / numPlotsX; fPlotWidth = fTextureWidth / numPlotsX;
fPlotHeight = fTextureHeight / numPlotsY; fPlotHeight = fTextureHeight / numPlotsY;
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots); SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
@ -195,7 +196,7 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
fNumPlots = numPlotsX * numPlotsY; fNumPlots = numPlotsX * numPlotsY;
this->createPages(proxyProvider); this->createNewPage();
} }
inline void GrDrawOpAtlas::processEviction(AtlasID id) { 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. // With c+14 we could move sk_sp into lamba to only ref once.
sk_sp<Plot> plotsp(SkRef(plot)); 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(); GrTextureProxy* proxy = fProxies[pageIdx].get();
SkASSERT(proxy->priv().isInstantiated()); // This is occurring at flush time
GrDeferredUploadToken lastUploadToken = target->addASAPUpload( GrDeferredUploadToken lastUploadToken = target->addASAPUpload(
[plotsp, proxy](GrDeferredTextureUploadWritePixelsFn& writePixels) { [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. // are rare; i.e., we are not continually refreshing the frame.
static constexpr auto kRecentlyUsedCount = 256; static constexpr auto kRecentlyUsedCount = 256;
bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider, bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int width, int height,
AtlasID* id, GrDeferredUploadTarget* target, const void* image, SkIPoint16* loc) {
int width, int height, const void* image, SkIPoint16* loc) {
if (width > fPlotWidth || height > fPlotHeight) { if (width > fPlotWidth || height > fPlotHeight) {
return false; 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 // 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 // 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. // 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]); SkASSERT(fProxies[pageIdx]);
// look through all allocated plots for one we can share, in Most Recently Refed order // look through all allocated plots for one we can share, in Most Recently Refed order
PlotList::Iter plotIter; 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 // 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. // 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. // 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(); Plot* plot = fPages[pageIdx].fPlotList.tail();
SkASSERT(plot); SkASSERT(plot);
if ((fNumActivePages == this->maxPages() && if ((fNumPages == this->maxPages() &&
plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) || plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) ||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) { plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
this->processEvictionAndResetRects(plot); 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 the simple cases fail, try to create a new page and add to it
if (this->activateNewPage(resourceProvider)) { if (this->createNewPage()) {
unsigned int pageIdx = fNumActivePages-1; unsigned int pageIdx = fNumPages-1;
SkASSERT(fProxies[pageIdx] && fProxies[pageIdx]->priv().isInstantiated()); SkASSERT(fProxies[pageIdx]);
Plot* plot = fPages[pageIdx].fPlotList.head(); Plot* plot = fPages[pageIdx].fPlotList.head();
SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp()); SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp());
if (plot->addSubImage(width, height, image, loc)) { 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. // 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. // We prioritize this upload in reverse order of pages to counterbalance the order above.
Plot* plot = nullptr; 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(); Plot* currentPlot = fPages[pageIdx].fPlotList.tail();
if (currentPlot->lastUseToken() != target->tokenTracker()->nextDrawToken()) { if (currentPlot->lastUseToken() != target->tokenTracker()->nextDrawToken()) {
plot = currentPlot; plot = currentPlot;
@ -335,8 +339,11 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
// one it displaced most likely was uploaded ASAP. // one it displaced most likely was uploaded ASAP.
// With c+14 we could move sk_sp into lambda to only ref once. // With c+14 we could move sk_sp into lambda to only ref once.
sk_sp<Plot> plotsp(SkRef(newPlot.get())); sk_sp<Plot> plotsp(SkRef(newPlot.get()));
// MDB TODO: this is currently fine since the atlas' proxy is always pre-instantiated.
SkASSERT(fProxies[pageIdx]->priv().isInstantiated()); // 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(); GrTextureProxy* proxy = fProxies[pageIdx].get();
GrDeferredUploadToken lastUploadToken = target->addInlineUpload( GrDeferredUploadToken lastUploadToken = target->addInlineUpload(
@ -351,7 +358,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
} }
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) { void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
if (fNumActivePages <= 1) { if (fNumPages <= 1) {
fPrevFlushToken = startTokenForNextFlush; fPrevFlushToken = startTokenForNextFlush;
return; return;
} }
@ -359,7 +366,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
// For all plots, reset number of flushes since used if used this frame. // For all plots, reset number of flushes since used if used this frame.
PlotList::Iter plotIter; PlotList::Iter plotIter;
bool atlasUsedThisFlush = false; 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); plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
while (Plot* plot = plotIter.get()) { while (Plot* plot = plotIter.get()) {
// Reset number of flushes since used // 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 // TODO: consider if we should also do this if it's been a long time since the last atlas use
if (atlasUsedThisFlush) { if (atlasUsedThisFlush) {
SkTArray<Plot*> availablePlots; SkTArray<Plot*> 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 // 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. // 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); SkDebugf("delete %d\n", fNumPages-1);
} }
#endif #endif
this->deactivateLastPage(); this->deleteLastPage();
} }
} }
fPrevFlushToken = startTokenForNextFlush; fPrevFlushToken = startTokenForNextFlush;
} }
bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) { bool GrDrawOpAtlas::createNewPage() {
SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight)); if (fNumPages == this->maxPages()) {
return false;
}
GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
GrSurfaceDesc desc; GrSurfaceDesc desc;
desc.fFlags = kNone_GrSurfaceFlags; desc.fFlags = kNone_GrSurfaceFlags;
@ -504,83 +515,47 @@ bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) {
desc.fHeight = fTextureHeight; desc.fHeight = fTextureHeight;
desc.fConfig = fPixelConfig; desc.fConfig = fPixelConfig;
int numPlotsX = fTextureWidth/fPlotWidth; SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight));
int numPlotsY = fTextureHeight/fPlotHeight; fProxies[fNumPages] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes,
for (uint32_t i = 0; i < this->maxPages(); ++i) {
fProxies[i] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes,
GrResourceProvider::kNoPendingIO_Flag); GrResourceProvider::kNoPendingIO_Flag);
if (!fProxies[i]) { if (!fProxies[fNumPages]) {
return false; return false;
} }
// set up allocated plots int numPlotsX = fTextureWidth/fPlotWidth;
fPages[i].fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]); int numPlotsY = fTextureHeight/fPlotHeight;
sk_sp<Plot>* currPlot = fPages[i].fPlotArray.get(); // 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 y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) {
for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) { for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) {
uint32_t plotIndex = r * numPlotsX + c; uint32_t plotIndex = r * numPlotsX + c;
currPlot->reset(new Plot(i, plotIndex, 1, x, y, fPlotWidth, fPlotHeight, currPlot->reset(new Plot(fNumPages, plotIndex, 1, x, y, fPlotWidth, fPlotHeight,
fPixelConfig)); fPixelConfig));
// build LRU list // build LRU list
fPages[i].fPlotList.addToHead(currPlot->get()); fPages[fNumPages].fPlotList.addToHead(currPlot->get());
++currPlot; ++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 #ifdef DUMP_ATLAS_DATA
if (gDumpAtlasData) { if (gDumpAtlasData) {
SkDebugf("activated page#: %d\n", fNumActivePages); SkDebugf("created %d\n", fNumPages);
} }
#endif #endif
fNumPages++;
++fNumActivePages;
return true; return true;
} }
inline void GrDrawOpAtlas::deleteLastPage() {
inline void GrDrawOpAtlas::deactivateLastPage() { uint32_t lastPageIndex = fNumPages - 1;
SkASSERT(fNumActivePages); // clean out the plots
uint32_t lastPageIndex = fNumActivePages - 1;
int numPlotsX = fTextureWidth/fPlotWidth;
int numPlotsY = fTextureHeight/fPlotHeight;
fPages[lastPageIndex].fPlotList.reset(); fPages[lastPageIndex].fPlotList.reset();
for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) { fPages[lastPageIndex].fPlotArray.reset(nullptr);
for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) { // remove ref to texture proxy
uint32_t plotIndex = r * numPlotsX + c; fProxies[lastPageIndex].reset(nullptr);
--fNumPages;
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;
} }

View File

@ -91,8 +91,7 @@ public:
* eviction occurs * eviction occurs
* @return An initialized GrDrawOpAtlas, or nullptr if creation fails * @return An initialized GrDrawOpAtlas, or nullptr if creation fails
*/ */
static std::unique_ptr<GrDrawOpAtlas> Make(GrProxyProvider*, GrPixelConfig, static std::unique_ptr<GrDrawOpAtlas> Make(GrContext*, GrPixelConfig, int width, int height,
int width, int height,
int numPlotsX, int numPlotsY, int numPlotsX, int numPlotsY,
AllowMultitexturing allowMultitexturing, AllowMultitexturing allowMultitexturing,
GrDrawOpAtlas::EvictionFunc func, void* data); GrDrawOpAtlas::EvictionFunc func, void* data);
@ -109,21 +108,19 @@ public:
* 'setUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to * '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. * addToAtlas might cause the previous data to be overwritten before it has been read.
*/ */
bool addToAtlas(GrResourceProvider*, AtlasID*, GrDeferredUploadTarget*, int width, int height, bool addToAtlas(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image,
const void* image, SkIPoint16* loc); SkIPoint16* loc);
GrContext* context() const { return fContext; }
const sk_sp<GrTextureProxy>* getProxies() const { return fProxies; } const sk_sp<GrTextureProxy>* getProxies() const { return fProxies; }
uint64_t atlasGeneration() const { return fAtlasGeneration; } uint64_t atlasGeneration() const { return fAtlasGeneration; }
inline bool hasID(AtlasID id) { inline bool hasID(AtlasID id) {
if (kInvalidAtlasID == id) {
return false;
}
uint32_t plot = GetPlotIndexFromID(id); uint32_t plot = GetPlotIndexFromID(id);
SkASSERT(plot < fNumPlots); SkASSERT(plot < fNumPlots);
uint32_t page = GetPageIndexFromID(id); uint32_t page = GetPageIndexFromID(id);
SkASSERT(page < fNumActivePages); SkASSERT(page < fNumPages);
return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id); return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id);
} }
@ -133,7 +130,7 @@ public:
uint32_t plotIdx = GetPlotIndexFromID(id); uint32_t plotIdx = GetPlotIndexFromID(id);
SkASSERT(plotIdx < fNumPlots); SkASSERT(plotIdx < fNumPlots);
uint32_t pageIdx = GetPageIndexFromID(id); uint32_t pageIdx = GetPageIndexFromID(id);
SkASSERT(pageIdx < fNumActivePages); SkASSERT(pageIdx < fNumPages);
Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get(); Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get();
this->makeMRU(plot, pageIdx); this->makeMRU(plot, pageIdx);
plot->setLastUseToken(token); plot->setLastUseToken(token);
@ -145,7 +142,7 @@ public:
data->fData = userData; 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 * 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]; const BulkUseTokenUpdater::PlotData& pd = updater.fPlotsToUpdate[i];
// it's possible we've added a plot to the updater and subsequently the plot's page // 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 // 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(); Plot* plot = fPages[pd.fPageIndex].fPlotArray[pd.fPlotIndex].get();
this->makeMRU(plot, pd.fPageIndex); this->makeMRU(plot, pd.fPageIndex);
plot->setLastUseToken(token); plot->setLastUseToken(token);
@ -228,14 +225,12 @@ public:
void instantiate(GrOnFlushResourceProvider*); void instantiate(GrOnFlushResourceProvider*);
private:
uint32_t maxPages() const { uint32_t maxPages() const {
return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1; return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1;
} }
int numAllocated_TestingOnly() const; GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX,
private:
GrDrawOpAtlas(GrProxyProvider*, GrPixelConfig, int width, int height, int numPlotsX,
int numPlotsY, AllowMultitexturing allowMultitexturing); int numPlotsY, AllowMultitexturing allowMultitexturing);
/** /**
@ -359,9 +354,8 @@ private:
// the front and remove from the back there is no need for MRU. // the front and remove from the back there is no need for MRU.
} }
bool createPages(GrProxyProvider*); bool createNewPage();
bool activateNewPage(GrResourceProvider*); void deleteLastPage();
void deactivateLastPage();
void processEviction(AtlasID); void processEviction(AtlasID);
inline void processEvictionAndResetRects(Plot* plot) { inline void processEvictionAndResetRects(Plot* plot) {
@ -369,6 +363,7 @@ private:
plot->resetRects(); plot->resetRects();
} }
GrContext* fContext;
GrPixelConfig fPixelConfig; GrPixelConfig fPixelConfig;
int fTextureWidth; int fTextureWidth;
int fTextureHeight; int fTextureHeight;
@ -397,8 +392,7 @@ private:
sk_sp<GrTextureProxy> fProxies[kMaxMultitexturePages]; sk_sp<GrTextureProxy> fProxies[kMaxMultitexturePages];
Page fPages[kMaxMultitexturePages]; Page fPages[kMaxMultitexturePages];
AllowMultitexturing fAllowMultitexturing; AllowMultitexturing fAllowMultitexturing;
uint32_t fNumPages;
uint32_t fNumActivePages;
}; };
#endif #endif

View File

@ -66,8 +66,6 @@ public:
*/ */
class GrOnFlushResourceProvider { class GrOnFlushResourceProvider {
public: public:
explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
sk_sp<GrRenderTargetContext> makeRenderTargetContext(const GrSurfaceDesc&, sk_sp<GrRenderTargetContext> makeRenderTargetContext(const GrSurfaceDesc&,
sk_sp<SkColorSpace>, sk_sp<SkColorSpace>,
const SkSurfaceProps*); const SkSurfaceProps*);
@ -88,10 +86,13 @@ public:
const GrCaps* caps() const; const GrCaps* caps() const;
private: private:
explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
GrOnFlushResourceProvider(const GrOnFlushResourceProvider&) = delete; GrOnFlushResourceProvider(const GrOnFlushResourceProvider&) = delete;
GrOnFlushResourceProvider& operator=(const GrOnFlushResourceProvider&) = delete; GrOnFlushResourceProvider& operator=(const GrOnFlushResourceProvider&) = delete;
GrDrawingManager* fDrawingMgr; GrDrawingManager* fDrawingMgr;
friend class GrDrawingManager; // to construct this type.
}; };
#endif #endif

View File

@ -208,13 +208,6 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s
return true; return true;
} }
void GrSurfaceProxy::deInstantiate() {
SkASSERT(this->priv().isInstantiated());
this->release();
}
void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const { void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
SkASSERT(LazyState::kFully != this->lazyInstantiationState()); SkASSERT(LazyState::kFully != this->lazyInstantiationState());
const GrRenderTargetProxy* rtp = this->asRenderTargetProxy(); const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();

View File

@ -222,8 +222,6 @@ static void clip_quads(const SkIRect& clipRect, char* currVertex, const char* bl
} }
void GrAtlasTextOp::onPrepareDraws(Target* target) { 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. // 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 // TODO actually only invert if we don't have RGBA
SkMatrix localMatrix; SkMatrix localMatrix;
@ -278,8 +276,8 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
const Geometry& args = fGeoData[i]; const Geometry& args = fGeoData[i];
Blob* blob = args.fBlob; Blob* blob = args.fBlob;
GrAtlasTextBlob::VertexRegenerator regenerator( GrAtlasTextBlob::VertexRegenerator regenerator(
resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor,
args.fColor, target->deferredUploadTarget(), fFontCache, &glyphCache); target->deferredUploadTarget(), fFontCache, &glyphCache);
GrAtlasTextBlob::VertexRegenerator::Result result; GrAtlasTextBlob::VertexRegenerator::Result result;
do { do {
result = regenerator.regenerate(); result = regenerator.regenerate();

View File

@ -181,7 +181,7 @@ public:
fHelper.visitProxies(func); fHelper.visitProxies(func);
const sk_sp<GrTextureProxy>* proxies = fAtlas->getProxies(); const sk_sp<GrTextureProxy>* proxies = fAtlas->getProxies();
for (uint32_t i = 0; i < fAtlas->numActivePages(); ++i) { for (uint32_t i = 0; i < fAtlas->pageCount(); ++i) {
SkASSERT(proxies[i]); SkASSERT(proxies[i]);
func(proxies[i].get()); func(proxies[i].get());
} }
@ -223,7 +223,7 @@ private:
flushInfo.fPipeline = fHelper.makePipeline(target); flushInfo.fPipeline = fHelper.makePipeline(target);
// Setup GrGeometryProcessor // Setup GrGeometryProcessor
GrDrawOpAtlas* atlas = fAtlas; GrDrawOpAtlas* atlas = fAtlas;
uint32_t atlasPageCount = atlas->numActivePages(); uint32_t atlasPageCount = atlas->pageCount();
if (!atlasPageCount) { if (!atlasPageCount) {
return; return;
} }
@ -400,8 +400,6 @@ private:
bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape, GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
uint32_t dimension, SkScalar scale) const { uint32_t dimension, SkScalar scale) const {
auto resourceProvider = target->resourceProvider();
const SkRect& bounds = shape.bounds(); const SkRect& bounds = shape.bounds();
// generate bounding rect for bitmap draw // generate bounding rect for bitmap draw
@ -490,11 +488,10 @@ private:
SkIPoint16 atlasLocation; SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id; GrDrawOpAtlas::AtlasID id;
auto uploadTarget = target->deferredUploadTarget(); auto uploadTarget = target->deferredUploadTarget();
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height, if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) {
dfStorage.get(), &atlasLocation)) {
this->flush(target, flushInfo); this->flush(target, flushInfo);
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height, if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(),
dfStorage.get(), &atlasLocation)) { &atlasLocation)) {
return false; return false;
} }
} }
@ -533,8 +530,6 @@ private:
bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo, bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape, GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
const SkMatrix& ctm) const { const SkMatrix& ctm) const {
auto resourceProvider = target->resourceProvider();
const SkRect& bounds = shape.bounds(); const SkRect& bounds = shape.bounds();
if (bounds.isEmpty()) { if (bounds.isEmpty()) {
return false; return false;
@ -595,11 +590,11 @@ private:
SkIPoint16 atlasLocation; SkIPoint16 atlasLocation;
GrDrawOpAtlas::AtlasID id; GrDrawOpAtlas::AtlasID id;
auto uploadTarget = target->deferredUploadTarget(); auto uploadTarget = target->deferredUploadTarget();
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(), if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
dst.addr(), &atlasLocation)) { &atlasLocation)) {
this->flush(target, flushInfo); this->flush(target, flushInfo);
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(), if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
dst.addr(), &atlasLocation)) { &atlasLocation)) {
return false; return false;
} }
} }
@ -701,7 +696,7 @@ private:
void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const { void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get(); 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. // During preparation the number of atlas pages has increased.
// Update the proxies used in the GP to match. // Update the proxies used in the GP to match.
if (fUsesDistanceField) { if (fUsesDistanceField) {
@ -793,7 +788,7 @@ bool GrSmallPathRenderer::onDrawPath(const DrawPathArgs& args) {
SkASSERT(!args.fShape->isEmpty()); SkASSERT(!args.fShape->isEmpty());
SkASSERT(args.fShape->hasUnstyledKey()); SkASSERT(args.fShape->hasUnstyledKey());
if (!fAtlas) { if (!fAtlas) {
fAtlas = GrDrawOpAtlas::Make(args.fContext->contextPriv().proxyProvider(), fAtlas = GrDrawOpAtlas::Make(args.fContext,
kAlpha_8_GrPixelConfig, kAlpha_8_GrPixelConfig,
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT, ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
NUM_PLOTS_X, NUM_PLOTS_Y, NUM_PLOTS_X, NUM_PLOTS_Y,
@ -863,8 +858,7 @@ GR_DRAW_OP_TEST_DEFINE(SmallPathOp) {
if (context->uniqueID() != gTestStruct.fContextID) { if (context->uniqueID() != gTestStruct.fContextID) {
gTestStruct.fContextID = context->uniqueID(); gTestStruct.fContextID = context->uniqueID();
gTestStruct.reset(); gTestStruct.reset();
gTestStruct.fAtlas = GrDrawOpAtlas::Make(context->contextPriv().proxyProvider(), gTestStruct.fAtlas = GrDrawOpAtlas::Make(context, kAlpha_8_GrPixelConfig,
kAlpha_8_GrPixelConfig,
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT, ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
NUM_PLOTS_X, NUM_PLOTS_Y, NUM_PLOTS_X, NUM_PLOTS_Y,
GrDrawOpAtlas::AllowMultitexturing::kYes, GrDrawOpAtlas::AllowMultitexturing::kYes,

View File

@ -9,7 +9,6 @@
#include "GrContext.h" #include "GrContext.h"
#include "GrDistanceFieldGenFromVector.h" #include "GrDistanceFieldGenFromVector.h"
#include "GrGpu.h" #include "GrGpu.h"
#include "GrProxyProvider.h"
#include "GrRectanizer.h" #include "GrRectanizer.h"
#include "SkAutoMalloc.h" #include "SkAutoMalloc.h"
@ -20,14 +19,14 @@
bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) { bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
int index = MaskFormatToAtlasIndex(format); int index = MaskFormatToAtlasIndex(format);
if (!fAtlases[index]) { if (!fAtlases[index]) {
GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->caps()); GrPixelConfig config = MaskFormatToPixelConfig(format, *fContext->caps());
int width = fAtlasConfigs[index].fWidth; int width = fAtlasConfigs[index].fWidth;
int height = fAtlasConfigs[index].fHeight; int height = fAtlasConfigs[index].fHeight;
int numPlotsX = fAtlasConfigs[index].numPlotsX(); int numPlotsX = fAtlasConfigs[index].numPlotsX();
int numPlotsY = fAtlasConfigs[index].numPlotsY(); int numPlotsY = fAtlasConfigs[index].numPlotsY();
fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height, fAtlases[index] = GrDrawOpAtlas::Make(fContext, config, width, height, numPlotsX, numPlotsY,
numPlotsX, numPlotsY, fAllowMultitexturing, fAllowMultitexturing,
&GrAtlasGlyphCache::HandleEviction, (void*)this); &GrAtlasGlyphCache::HandleEviction, (void*)this);
if (!fAtlases[index]) { if (!fAtlases[index]) {
return false; return false;
@ -36,13 +35,11 @@ bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
return true; return true;
} }
GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes, GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing) GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
: fProxyProvider(proxyProvider) : fContext(context), fAllowMultitexturing(allowMultitexturing), fPreserveStrike(nullptr) {
, fAllowMultitexturing(allowMultitexturing)
, fPreserveStrike(nullptr) {
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2 // 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; int log2MaxDim = 9;
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) { for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
int maxDim = 1 << log2MaxDim; int maxDim = 1 << log2MaxDim;
@ -177,12 +174,12 @@ static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char*
return true; return true;
} }
void GrAtlasGlyphCache::dump(GrContext* context) const { void GrAtlasGlyphCache::dump() const {
static int gDumpCount = 0; static int gDumpCount = 0;
for (int i = 0; i < kMaskFormatCount; ++i) { for (int i = 0; i < kMaskFormatCount; ++i) {
if (fAtlases[i]) { if (fAtlases[i]) {
const sk_sp<GrTextureProxy>* proxies = fAtlases[i]->getProxies(); const sk_sp<GrTextureProxy>* 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]); SkASSERT(proxies[pageIdx]);
SkString filename; SkString filename;
#ifdef SK_BUILD_FOR_ANDROID #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); filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
#endif #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, bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
GrDeferredUploadTarget* target,
GrAtlasGlyphCache* atlasGlyphCache, GrAtlasGlyphCache* atlasGlyphCache,
GrGlyph* glyph, GrGlyph* glyph,
SkGlyphCache* cache, SkGlyphCache* cache,
@ -477,8 +473,7 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
} }
} }
bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target, bool success = atlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat,
expectedMaskFormat,
glyph->width(), glyph->height(), glyph->width(), glyph->height(),
storage.get(), &glyph->fAtlasLocation); storage.get(), &glyph->fAtlasLocation);
if (success) { if (success) {

View File

@ -64,8 +64,8 @@ public:
// happen. // happen.
// TODO we can handle some of these cases if we really want to, but the long term solution is to // 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. // get the actual glyph image itself when we get the glyph metrics.
bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, bool addGlyphToAtlas(GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, SkGlyphCache*,
SkGlyphCache*, GrMaskFormat expectedMaskFormat); GrMaskFormat expectedMaskFormat);
// testing // testing
int countGlyphs() const { return fCache.count(); } int countGlyphs() const { return fCache.count(); }
@ -109,8 +109,7 @@ private:
*/ */
class GrAtlasGlyphCache : public GrOnFlushCallbackObject { class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
public: public:
GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes, GrAtlasGlyphCache(GrContext*, float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
GrDrawOpAtlas::AllowMultitexturing);
~GrAtlasGlyphCache() override; ~GrAtlasGlyphCache() override;
// The user of the cache may hold a long-lived ref to the returned strike. However, actions by // 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. // another client of the cache may cause the strike to be purged while it is still reffed.
@ -133,7 +132,7 @@ public:
SkASSERT(numProxies); SkASSERT(numProxies);
if (this->initAtlas(format)) { if (this->initAtlas(format)) {
*numProxies = this->getAtlas(format)->numActivePages(); *numProxies = this->getAtlas(format)->pageCount();
return this->getAtlas(format)->getProxies(); return this->getAtlas(format)->getProxies();
} }
*numProxies = 0; *numProxies = 0;
@ -166,13 +165,11 @@ public:
} }
// add to texture atlas that matches this format // add to texture atlas that matches this format
bool addToAtlas(GrResourceProvider* resourceProvider, GrAtlasTextStrike* strike, bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
GrDrawOpAtlas::AtlasID* id,
GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height, GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height,
const void* image, SkIPoint16* loc) { const void* image, SkIPoint16* loc) {
fPreserveStrike = strike; fPreserveStrike = strike;
return this->getAtlas(format)->addToAtlas(resourceProvider, id, target, return this->getAtlas(format)->addToAtlas(id, target, width, height, image, loc);
width, height, image, loc);
} }
// Some clients may wish to verify the integrity of the texture backing store of the // 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) { for (int i = 0; i < kMaskFormatCount; ++i) {
if (fAtlases[i]) { if (fAtlases[i]) {
fAtlases[i]->compact(startTokenForNextFlush); fAtlases[i]->compact(startTokenForNextFlush);
@ -208,11 +206,13 @@ public:
/////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////
// Functions intended debug only // Functions intended debug only
#ifdef SK_DEBUG #ifdef SK_DEBUG
void dump(GrContext*) const; void dump() const;
#endif #endif
void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]); void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
GrContext* context() const { return fContext; }
private: private:
static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) { static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) {
switch (format) { switch (format) {
@ -258,7 +258,7 @@ private:
static void HandleEviction(GrDrawOpAtlas::AtlasID, void*); static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>; using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
GrProxyProvider* fProxyProvider; GrContext* fContext;
StrikeHash fCache; StrikeHash fCache;
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing; GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount]; std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];

View File

@ -560,9 +560,9 @@ public:
* SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of * SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
* SkGlyphCache. * SkGlyphCache.
*/ */
VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx, VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget*,
GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*); GrAtlasGlyphCache*, SkAutoGlyphCache*);
struct Result { struct Result {
/** /**
@ -589,7 +589,6 @@ private:
template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs> template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
Result doRegen(); Result doRegen();
GrResourceProvider* fResourceProvider;
const SkMatrix& fViewMatrix; const SkMatrix& fViewMatrix;
GrAtlasTextBlob* fBlob; GrAtlasTextBlob* fBlob;
GrDeferredUploadTarget* fUploadTarget; GrDeferredUploadTarget* fUploadTarget;

View File

@ -190,13 +190,11 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
} }
} }
Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob, Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx,
int runIdx, int subRunIdx,
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color, const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache, GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
SkAutoGlyphCache* lazyCache) SkAutoGlyphCache* lazyCache)
: fResourceProvider(resourceProvider) : fViewMatrix(viewMatrix)
, fViewMatrix(viewMatrix)
, fBlob(blob) , fBlob(blob)
, fUploadTarget(uploadTarget) , fUploadTarget(uploadTarget)
, fGlyphCache(glyphCache) , fGlyphCache(glyphCache)
@ -276,8 +274,8 @@ Regenerator::Result Regenerator::doRegen() {
SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat()); SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat());
if (!fGlyphCache->hasGlyph(glyph) && if (!fGlyphCache->hasGlyph(glyph) &&
!strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph, !strike->addGlyphToAtlas(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(),
fLazyCache->get(), fSubRun->maskFormat())) { fSubRun->maskFormat())) {
fBrokenRun = glyphIdx > 0; fBrokenRun = glyphIdx > 0;
result.fFinished = false; result.fFinished = false;
return result; return result;

View File

@ -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<GrDrawOpAtlas> 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