Revert "Revert "Revert "Separate creation time & flush time behavior in GrDrawOpAtlas (take 2)"""
This reverts commit934c3d0c54
. Reason for revert: Chrome Original change's description: > Revert "Revert "Separate creation time & flush time behavior in GrDrawOpAtlas (take 2)"" > > This reverts commit84d823a5e2
. > > Reason for revert: The DFT diffs don't repro on Windows so I'm chalking it up to minor device differences > > Original change's description: > > Revert "Separate creation time & flush time behavior in GrDrawOpAtlas (take 2)" > > > > This reverts commit96165ebeaa
. > > > > Reason for revert: DFT GMs w/ LCD text are slightly different > > > > Original change's description: > > > 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> > > > > TBR=jvanverth@google.com,robertphillips@google.com > > > > Change-Id: I62efc61c8394477e54d6e79fa2f65180c91a4515 > > No-Presubmit: true > > No-Tree-Checks: true > > No-Try: true > > Reviewed-on: https://skia-review.googlesource.com/110220 > > Reviewed-by: Robert Phillips <robertphillips@google.com> > > Commit-Queue: Robert Phillips <robertphillips@google.com> > > TBR=jvanverth@google.com,robertphillips@google.com > > Change-Id: I7c87b4523f9b53285f0de5c2d741a25893522d9a > No-Presubmit: true > No-Tree-Checks: true > No-Try: true > Reviewed-on: https://skia-review.googlesource.com/110221 > Reviewed-by: Robert Phillips <robertphillips@google.com> > Commit-Queue: Robert Phillips <robertphillips@google.com> TBR=jvanverth@google.com,robertphillips@google.com # Not skipping CQ checks because original CL landed > 1 day ago. Change-Id: I7dd73ab0159f38595f21b21eef3becc10aa0934d Reviewed-on: https://skia-review.googlesource.com/111080 Reviewed-by: Robert Phillips <robertphillips@google.com>
This commit is contained in:
parent
3bd55bd59a
commit
ba7a165194
@ -60,7 +60,6 @@ tests_sources = [
|
||||
"$_tests/DiscardableMemoryTest.cpp",
|
||||
"$_tests/DrawBitmapRectTest.cpp",
|
||||
"$_tests/DrawFilterTest.cpp",
|
||||
"$_tests/DrawOpAtlasTest.cpp",
|
||||
"$_tests/DrawPathTest.cpp",
|
||||
"$_tests/DrawTextTest.cpp",
|
||||
"$_tests/DynamicHashTest.cpp",
|
||||
|
@ -57,17 +57,6 @@ public:
|
||||
}
|
||||
#endif
|
||||
|
||||
void release() {
|
||||
SkASSERT(1 == fRefCnt);
|
||||
SkASSERT(0 == fPendingReads);
|
||||
SkASSERT(0 == fPendingWrites);
|
||||
|
||||
SkASSERT(fTarget->internalHasUniqueRef());
|
||||
SkASSERT(!fTarget->internalHasPendingIO());
|
||||
fTarget->unref();
|
||||
fTarget = nullptr;
|
||||
}
|
||||
|
||||
void validate() const {
|
||||
#ifdef SK_DEBUG
|
||||
SkASSERT(fRefCnt >= 0);
|
||||
@ -140,7 +129,7 @@ protected:
|
||||
}
|
||||
virtual ~GrIORefProxy() {
|
||||
// We don't unref 'fTarget' here since the 'unref' method will already
|
||||
// have forwarded on the unref call that got us here.
|
||||
// have forwarded on the unref call that got use here.
|
||||
}
|
||||
|
||||
// This GrIORefProxy was deferred before but has just been instantiated. To
|
||||
@ -290,8 +279,6 @@ public:
|
||||
|
||||
virtual bool instantiate(GrResourceProvider* resourceProvider) = 0;
|
||||
|
||||
void deInstantiate();
|
||||
|
||||
/**
|
||||
* Helper that gets the width and height of the surface as a bounding rectangle.
|
||||
*/
|
||||
|
@ -183,18 +183,12 @@ void GrAtlasTextOp::executeForTextTarget(SkAtlasTextTarget* target) {
|
||||
FlushInfo flushInfo;
|
||||
SkAutoGlyphCache glyphCache;
|
||||
auto& context = target->context()->internal();
|
||||
auto atlasGlyphCache = context.grContext()->contextPriv().getAtlasGlyphCache();
|
||||
auto resourceProvider = context.grContext()->contextPriv().resourceProvider();
|
||||
auto drawingManager = context.grContext()->contextPriv().drawingManager();
|
||||
|
||||
GrOnFlushResourceProvider onFlushResourceProvider(drawingManager);
|
||||
atlasGlyphCache->preFlush(&onFlushResourceProvider, nullptr, 0, nullptr);
|
||||
|
||||
auto* atlasGlyphCache = context.grContext()->contextPriv().getAtlasGlyphCache();
|
||||
for (int i = 0; i < fGeoCount; ++i) {
|
||||
GrAtlasTextBlob::VertexRegenerator regenerator(
|
||||
resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun,
|
||||
fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor,
|
||||
&context, atlasGlyphCache, &glyphCache);
|
||||
fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fViewMatrix,
|
||||
fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, &context, atlasGlyphCache,
|
||||
&glyphCache);
|
||||
GrAtlasTextBlob::VertexRegenerator::Result result;
|
||||
do {
|
||||
result = regenerator.regenerate();
|
||||
|
@ -293,7 +293,7 @@ bool GrContext::init(const GrContextOptions& options) {
|
||||
} else {
|
||||
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
|
||||
}
|
||||
fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes,
|
||||
fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
|
||||
allowMultitexturing);
|
||||
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
|
||||
|
||||
|
@ -96,10 +96,9 @@ public:
|
||||
GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
|
||||
|
||||
private:
|
||||
// Only these three classes get to increment the token counters
|
||||
// Only these two classes get to increment the token counters
|
||||
friend class SkInternalAtlasTextContext;
|
||||
friend class GrOpFlushState;
|
||||
friend class TestingUploadTarget;
|
||||
|
||||
/** Issues the next token for a draw. */
|
||||
GrDeferredUploadToken issueDrawToken() { return ++fLastIssuedToken; }
|
||||
|
@ -26,20 +26,20 @@
|
||||
// must explicitly manage the lifetime of their backing proxies via the onFlushCallback system
|
||||
// (which calls this method).
|
||||
void GrDrawOpAtlas::instantiate(GrOnFlushResourceProvider* onFlushResourceProvider) {
|
||||
for (uint32_t i = 0; i < fNumActivePages; ++i) {
|
||||
// All the atlas pages are now instantiated at flush time in the activeNewPage method.
|
||||
SkASSERT(fProxies[i] && fProxies[i]->priv().isInstantiated());
|
||||
for (int i = 0; i < GrDrawOpAtlas::kMaxMultitexturePages; ++i) {
|
||||
if (fProxies[i] && !fProxies[i]->priv().isInstantiated()) {
|
||||
// If instantiation fails we expect the ops that rely on the atlas to be dropped
|
||||
onFlushResourceProvider->instatiateProxy(fProxies[i].get());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrProxyProvider* proxyProvider,
|
||||
GrPixelConfig config, int width,
|
||||
std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width,
|
||||
int height, int numPlotsX, int numPlotsY,
|
||||
AllowMultitexturing allowMultitexturing,
|
||||
GrDrawOpAtlas::EvictionFunc func, void* data) {
|
||||
std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(proxyProvider, config, width, height,
|
||||
numPlotsX, numPlotsY,
|
||||
allowMultitexturing));
|
||||
std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(ctx, config, width, height, numPlotsX,
|
||||
numPlotsY, allowMultitexturing));
|
||||
if (!atlas->getProxies()[0]) {
|
||||
return nullptr;
|
||||
}
|
||||
@ -53,6 +53,7 @@ static bool gDumpAtlasData = false;
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrDrawOpAtlas::Plot::Plot(int pageIndex, int plotIndex, uint64_t genID, int offX, int offY,
|
||||
int width, int height, GrPixelConfig config)
|
||||
: fLastUpload(GrDeferredUploadToken::AlreadyFlushedToken())
|
||||
@ -177,16 +178,16 @@ void GrDrawOpAtlas::Plot::resetRects() {
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
|
||||
GrPixelConfig config, int width, int height,
|
||||
GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height,
|
||||
int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
|
||||
: fPixelConfig(config)
|
||||
: fContext(context)
|
||||
, fPixelConfig(config)
|
||||
, fTextureWidth(width)
|
||||
, fTextureHeight(height)
|
||||
, fAtlasGeneration(kInvalidAtlasGeneration + 1)
|
||||
, fPrevFlushToken(GrDeferredUploadToken::AlreadyFlushedToken())
|
||||
, fAllowMultitexturing(allowMultitexturing)
|
||||
, fNumActivePages(0) {
|
||||
, fNumPages(0) {
|
||||
fPlotWidth = fTextureWidth / numPlotsX;
|
||||
fPlotHeight = fTextureHeight / numPlotsY;
|
||||
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
|
||||
@ -195,7 +196,7 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
|
||||
|
||||
fNumPlots = numPlotsX * numPlotsY;
|
||||
|
||||
this->createPages(proxyProvider);
|
||||
this->createNewPage();
|
||||
}
|
||||
|
||||
inline void GrDrawOpAtlas::processEviction(AtlasID id) {
|
||||
@ -216,8 +217,13 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i
|
||||
// With c+14 we could move sk_sp into lamba to only ref once.
|
||||
sk_sp<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) {
|
||||
@ -237,9 +243,8 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i
|
||||
// are rare; i.e., we are not continually refreshing the frame.
|
||||
static constexpr auto kRecentlyUsedCount = 256;
|
||||
|
||||
bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
AtlasID* id, GrDeferredUploadTarget* target,
|
||||
int width, int height, const void* image, SkIPoint16* loc) {
|
||||
bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int width, int height,
|
||||
const void* image, SkIPoint16* loc) {
|
||||
if (width > fPlotWidth || height > fPlotHeight) {
|
||||
return false;
|
||||
}
|
||||
@ -247,7 +252,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
// Look through each page to see if we can upload without having to flush
|
||||
// We prioritize this upload to the first pages, not the most recently used, to make it easier
|
||||
// to remove unused pages in reverse page order.
|
||||
for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
|
||||
for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) {
|
||||
SkASSERT(fProxies[pageIdx]);
|
||||
// look through all allocated plots for one we can share, in Most Recently Refed order
|
||||
PlotList::Iter plotIter;
|
||||
@ -267,10 +272,10 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
// We wait until we've grown to the full number of pages to begin evicting already flushed
|
||||
// plots so that we can maximize the opportunity for reuse.
|
||||
// As before we prioritize this upload to the first pages, not the most recently used.
|
||||
for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
|
||||
for (unsigned int pageIdx = 0; pageIdx < fNumPages; ++pageIdx) {
|
||||
Plot* plot = fPages[pageIdx].fPlotList.tail();
|
||||
SkASSERT(plot);
|
||||
if ((fNumActivePages == this->maxPages() &&
|
||||
if ((fNumPages == this->maxPages() &&
|
||||
plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) ||
|
||||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
|
||||
this->processEvictionAndResetRects(plot);
|
||||
@ -285,10 +290,9 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
}
|
||||
|
||||
// If the simple cases fail, try to create a new page and add to it
|
||||
if (this->activateNewPage(resourceProvider)) {
|
||||
unsigned int pageIdx = fNumActivePages-1;
|
||||
SkASSERT(fProxies[pageIdx] && fProxies[pageIdx]->priv().isInstantiated());
|
||||
|
||||
if (this->createNewPage()) {
|
||||
unsigned int pageIdx = fNumPages-1;
|
||||
SkASSERT(fProxies[pageIdx]);
|
||||
Plot* plot = fPages[pageIdx].fPlotList.head();
|
||||
SkASSERT(GrBytesPerPixel(fProxies[pageIdx]->config()) == plot->bpp());
|
||||
if (plot->addSubImage(width, height, image, loc)) {
|
||||
@ -303,7 +307,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
// Try to find a plot that we can perform an inline upload to.
|
||||
// We prioritize this upload in reverse order of pages to counterbalance the order above.
|
||||
Plot* plot = nullptr;
|
||||
for (int pageIdx = (int)(fNumActivePages-1); pageIdx >= 0; --pageIdx) {
|
||||
for (int pageIdx = (int)(fNumPages-1); pageIdx >= 0; --pageIdx) {
|
||||
Plot* currentPlot = fPages[pageIdx].fPlotList.tail();
|
||||
if (currentPlot->lastUseToken() != target->tokenTracker()->nextDrawToken()) {
|
||||
plot = currentPlot;
|
||||
@ -335,8 +339,11 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
// one it displaced most likely was uploaded ASAP.
|
||||
// With c+14 we could move sk_sp into lambda to only ref once.
|
||||
sk_sp<Plot> plotsp(SkRef(newPlot.get()));
|
||||
|
||||
SkASSERT(fProxies[pageIdx]->priv().isInstantiated());
|
||||
// MDB TODO: this is currently fine since the atlas' proxy is always pre-instantiated.
|
||||
// Once it is deferred more care must be taken upon instantiation failure.
|
||||
if (!fProxies[pageIdx]->instantiate(fContext->contextPriv().resourceProvider())) {
|
||||
return false;
|
||||
}
|
||||
GrTextureProxy* proxy = fProxies[pageIdx].get();
|
||||
|
||||
GrDeferredUploadToken lastUploadToken = target->addInlineUpload(
|
||||
@ -351,7 +358,7 @@ bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||
}
|
||||
|
||||
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
||||
if (fNumActivePages <= 1) {
|
||||
if (fNumPages <= 1) {
|
||||
fPrevFlushToken = startTokenForNextFlush;
|
||||
return;
|
||||
}
|
||||
@ -359,7 +366,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
||||
// For all plots, reset number of flushes since used if used this frame.
|
||||
PlotList::Iter plotIter;
|
||||
bool atlasUsedThisFlush = false;
|
||||
for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
|
||||
for (uint32_t pageIndex = 0; pageIndex < fNumPages; ++pageIndex) {
|
||||
plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
|
||||
while (Plot* plot = plotIter.get()) {
|
||||
// Reset number of flushes since used
|
||||
@ -378,7 +385,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
||||
// TODO: consider if we should also do this if it's been a long time since the last atlas use
|
||||
if (atlasUsedThisFlush) {
|
||||
SkTArray<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
|
||||
// if there are any in the first pages that the last page can safely upload to.
|
||||
@ -487,15 +494,19 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
||||
SkDebugf("delete %d\n", fNumPages-1);
|
||||
}
|
||||
#endif
|
||||
this->deactivateLastPage();
|
||||
this->deleteLastPage();
|
||||
}
|
||||
}
|
||||
|
||||
fPrevFlushToken = startTokenForNextFlush;
|
||||
}
|
||||
|
||||
bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) {
|
||||
SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight));
|
||||
bool GrDrawOpAtlas::createNewPage() {
|
||||
if (fNumPages == this->maxPages()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
|
||||
|
||||
GrSurfaceDesc desc;
|
||||
desc.fFlags = kNone_GrSurfaceFlags;
|
||||
@ -504,83 +515,47 @@ bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) {
|
||||
desc.fHeight = fTextureHeight;
|
||||
desc.fConfig = fPixelConfig;
|
||||
|
||||
SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight));
|
||||
fProxies[fNumPages] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes,
|
||||
GrResourceProvider::kNoPendingIO_Flag);
|
||||
if (!fProxies[fNumPages]) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int numPlotsX = fTextureWidth/fPlotWidth;
|
||||
int numPlotsY = fTextureHeight/fPlotHeight;
|
||||
|
||||
for (uint32_t i = 0; i < this->maxPages(); ++i) {
|
||||
fProxies[i] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes,
|
||||
GrResourceProvider::kNoPendingIO_Flag);
|
||||
if (!fProxies[i]) {
|
||||
return false;
|
||||
// set up allocated plots
|
||||
fPages[fNumPages].fPlotArray.reset(new sk_sp<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;
|
||||
}
|
||||
|
||||
// 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("activated page#: %d\n", fNumActivePages);
|
||||
SkDebugf("created %d\n", fNumPages);
|
||||
}
|
||||
#endif
|
||||
|
||||
++fNumActivePages;
|
||||
fNumPages++;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
inline void GrDrawOpAtlas::deactivateLastPage() {
|
||||
SkASSERT(fNumActivePages);
|
||||
|
||||
uint32_t lastPageIndex = fNumActivePages - 1;
|
||||
|
||||
int numPlotsX = fTextureWidth/fPlotWidth;
|
||||
int numPlotsY = fTextureHeight/fPlotHeight;
|
||||
|
||||
inline void GrDrawOpAtlas::deleteLastPage() {
|
||||
uint32_t lastPageIndex = fNumPages - 1;
|
||||
// clean out the plots
|
||||
fPages[lastPageIndex].fPlotList.reset();
|
||||
for (int y = numPlotsY - 1, r = 0; y >= 0; --y, ++r) {
|
||||
for (int x = numPlotsX - 1, c = 0; x >= 0; --x, ++c) {
|
||||
uint32_t plotIndex = r * numPlotsX + c;
|
||||
|
||||
Plot* currPlot = fPages[lastPageIndex].fPlotArray[plotIndex].get();
|
||||
currPlot->resetRects();
|
||||
currPlot->resetFlushesSinceLastUsed();
|
||||
|
||||
// rebuild the LRU list
|
||||
SkDEBUGCODE(currPlot->fPrev = currPlot->fNext = nullptr);
|
||||
SkDEBUGCODE(currPlot->fList = nullptr);
|
||||
fPages[lastPageIndex].fPlotList.addToHead(currPlot);
|
||||
}
|
||||
}
|
||||
|
||||
// remove ref to the backing texture
|
||||
fProxies[lastPageIndex]->deInstantiate();
|
||||
--fNumActivePages;
|
||||
fPages[lastPageIndex].fPlotArray.reset(nullptr);
|
||||
// remove ref to texture proxy
|
||||
fProxies[lastPageIndex].reset(nullptr);
|
||||
--fNumPages;
|
||||
}
|
||||
|
@ -91,8 +91,7 @@ public:
|
||||
* eviction occurs
|
||||
* @return An initialized GrDrawOpAtlas, or nullptr if creation fails
|
||||
*/
|
||||
static std::unique_ptr<GrDrawOpAtlas> Make(GrProxyProvider*, GrPixelConfig,
|
||||
int width, int height,
|
||||
static std::unique_ptr<GrDrawOpAtlas> Make(GrContext*, GrPixelConfig, int width, int height,
|
||||
int numPlotsX, int numPlotsY,
|
||||
AllowMultitexturing allowMultitexturing,
|
||||
GrDrawOpAtlas::EvictionFunc func, void* data);
|
||||
@ -109,21 +108,19 @@ public:
|
||||
* 'setUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to
|
||||
* addToAtlas might cause the previous data to be overwritten before it has been read.
|
||||
*/
|
||||
bool addToAtlas(GrResourceProvider*, AtlasID*, GrDeferredUploadTarget*, int width, int height,
|
||||
const void* image, SkIPoint16* loc);
|
||||
bool addToAtlas(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image,
|
||||
SkIPoint16* loc);
|
||||
|
||||
GrContext* context() const { return fContext; }
|
||||
const sk_sp<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 < fNumActivePages);
|
||||
SkASSERT(page < fNumPages);
|
||||
return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id);
|
||||
}
|
||||
|
||||
@ -133,7 +130,7 @@ public:
|
||||
uint32_t plotIdx = GetPlotIndexFromID(id);
|
||||
SkASSERT(plotIdx < fNumPlots);
|
||||
uint32_t pageIdx = GetPageIndexFromID(id);
|
||||
SkASSERT(pageIdx < fNumActivePages);
|
||||
SkASSERT(pageIdx < fNumPages);
|
||||
Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get();
|
||||
this->makeMRU(plot, pageIdx);
|
||||
plot->setLastUseToken(token);
|
||||
@ -145,7 +142,7 @@ public:
|
||||
data->fData = userData;
|
||||
}
|
||||
|
||||
uint32_t numActivePages() { return fNumActivePages; }
|
||||
uint32_t pageCount() { return fNumPages; }
|
||||
|
||||
/**
|
||||
* A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The
|
||||
@ -207,7 +204,7 @@ public:
|
||||
const BulkUseTokenUpdater::PlotData& pd = updater.fPlotsToUpdate[i];
|
||||
// it's possible we've added a plot to the updater and subsequently the plot's page
|
||||
// was deleted -- so we check to prevent a crash
|
||||
if (pd.fPageIndex < fNumActivePages) {
|
||||
if (pd.fPageIndex < fNumPages) {
|
||||
Plot* plot = fPages[pd.fPageIndex].fPlotArray[pd.fPlotIndex].get();
|
||||
this->makeMRU(plot, pd.fPageIndex);
|
||||
plot->setLastUseToken(token);
|
||||
@ -228,14 +225,12 @@ public:
|
||||
|
||||
void instantiate(GrOnFlushResourceProvider*);
|
||||
|
||||
private:
|
||||
uint32_t maxPages() const {
|
||||
return AllowMultitexturing::kYes == fAllowMultitexturing ? kMaxMultitexturePages : 1;
|
||||
}
|
||||
|
||||
int numAllocated_TestingOnly() const;
|
||||
|
||||
private:
|
||||
GrDrawOpAtlas(GrProxyProvider*, GrPixelConfig, int width, int height, int numPlotsX,
|
||||
GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX,
|
||||
int numPlotsY, AllowMultitexturing allowMultitexturing);
|
||||
|
||||
/**
|
||||
@ -359,9 +354,8 @@ private:
|
||||
// the front and remove from the back there is no need for MRU.
|
||||
}
|
||||
|
||||
bool createPages(GrProxyProvider*);
|
||||
bool activateNewPage(GrResourceProvider*);
|
||||
void deactivateLastPage();
|
||||
bool createNewPage();
|
||||
void deleteLastPage();
|
||||
|
||||
void processEviction(AtlasID);
|
||||
inline void processEvictionAndResetRects(Plot* plot) {
|
||||
@ -369,6 +363,7 @@ private:
|
||||
plot->resetRects();
|
||||
}
|
||||
|
||||
GrContext* fContext;
|
||||
GrPixelConfig fPixelConfig;
|
||||
int fTextureWidth;
|
||||
int fTextureHeight;
|
||||
@ -397,8 +392,7 @@ private:
|
||||
sk_sp<GrTextureProxy> fProxies[kMaxMultitexturePages];
|
||||
Page fPages[kMaxMultitexturePages];
|
||||
AllowMultitexturing fAllowMultitexturing;
|
||||
|
||||
uint32_t fNumActivePages;
|
||||
uint32_t fNumPages;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -66,8 +66,6 @@ public:
|
||||
*/
|
||||
class GrOnFlushResourceProvider {
|
||||
public:
|
||||
explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
|
||||
|
||||
sk_sp<GrRenderTargetContext> makeRenderTargetContext(const GrSurfaceDesc&,
|
||||
sk_sp<SkColorSpace>,
|
||||
const SkSurfaceProps*);
|
||||
@ -88,10 +86,13 @@ public:
|
||||
const GrCaps* caps() const;
|
||||
|
||||
private:
|
||||
explicit GrOnFlushResourceProvider(GrDrawingManager* drawingMgr) : fDrawingMgr(drawingMgr) {}
|
||||
GrOnFlushResourceProvider(const GrOnFlushResourceProvider&) = delete;
|
||||
GrOnFlushResourceProvider& operator=(const GrOnFlushResourceProvider&) = delete;
|
||||
|
||||
GrDrawingManager* fDrawingMgr;
|
||||
|
||||
friend class GrDrawingManager; // to construct this type.
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -208,13 +208,6 @@ bool GrSurfaceProxy::instantiateImpl(GrResourceProvider* resourceProvider, int s
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrSurfaceProxy::deInstantiate() {
|
||||
SkASSERT(this->priv().isInstantiated());
|
||||
|
||||
this->release();
|
||||
}
|
||||
|
||||
|
||||
void GrSurfaceProxy::computeScratchKey(GrScratchKey* key) const {
|
||||
SkASSERT(LazyState::kFully != this->lazyInstantiationState());
|
||||
const GrRenderTargetProxy* rtp = this->asRenderTargetProxy();
|
||||
|
@ -222,8 +222,6 @@ static void clip_quads(const SkIRect& clipRect, char* currVertex, const char* bl
|
||||
}
|
||||
|
||||
void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
||||
auto resourceProvider = target->resourceProvider();
|
||||
|
||||
// if we have RGB, then we won't have any SkShaders so no need to use a localmatrix.
|
||||
// TODO actually only invert if we don't have RGBA
|
||||
SkMatrix localMatrix;
|
||||
@ -236,7 +234,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
||||
|
||||
unsigned int atlasPageCount;
|
||||
const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &atlasPageCount);
|
||||
if (!proxies[0]) {
|
||||
if (!atlasPageCount || !proxies[0]) {
|
||||
SkDebugf("Could not allocate backing texture for atlas\n");
|
||||
return;
|
||||
}
|
||||
@ -278,8 +276,8 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
||||
const Geometry& args = fGeoData[i];
|
||||
Blob* blob = args.fBlob;
|
||||
GrAtlasTextBlob::VertexRegenerator regenerator(
|
||||
resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY,
|
||||
args.fColor, target->deferredUploadTarget(), fFontCache, &glyphCache);
|
||||
blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor,
|
||||
target->deferredUploadTarget(), fFontCache, &glyphCache);
|
||||
GrAtlasTextBlob::VertexRegenerator::Result result;
|
||||
do {
|
||||
result = regenerator.regenerate();
|
||||
|
@ -181,7 +181,7 @@ public:
|
||||
fHelper.visitProxies(func);
|
||||
|
||||
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]);
|
||||
func(proxies[i].get());
|
||||
}
|
||||
@ -222,6 +222,11 @@ private:
|
||||
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;
|
||||
@ -244,7 +249,7 @@ private:
|
||||
matrix = &SkMatrix::I();
|
||||
}
|
||||
flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(
|
||||
*matrix, fAtlas->getProxies(), GrSamplerState::ClampBilerp(), flags);
|
||||
*matrix, atlas->getProxies(), GrSamplerState::ClampBilerp(), flags);
|
||||
} else {
|
||||
SkMatrix invert;
|
||||
if (fHelper.usesLocalCoords()) {
|
||||
@ -255,7 +260,7 @@ private:
|
||||
}
|
||||
|
||||
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
|
||||
this->color(), fAtlas->getProxies(), GrSamplerState::ClampNearest(),
|
||||
this->color(), atlas->getProxies(), GrSamplerState::ClampNearest(),
|
||||
kA8_GrMaskFormat, invert, fHelper.usesLocalCoords());
|
||||
}
|
||||
|
||||
@ -330,7 +335,7 @@ private:
|
||||
// check to see if df path is cached
|
||||
ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension));
|
||||
shapeData = fShapeCache->find(key);
|
||||
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
|
||||
if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
|
||||
// Remove the stale cache entry
|
||||
if (shapeData) {
|
||||
fShapeCache->remove(shapeData->fKey);
|
||||
@ -342,7 +347,7 @@ private:
|
||||
shapeData = new ShapeData;
|
||||
if (!this->addDFPathToAtlas(target,
|
||||
&flushInfo,
|
||||
fAtlas,
|
||||
atlas,
|
||||
shapeData,
|
||||
args.fShape,
|
||||
SkScalarCeilToInt(desiredDimension),
|
||||
@ -355,7 +360,7 @@ private:
|
||||
// check to see if bitmap path is cached
|
||||
ShapeData::Key key(args.fShape, args.fViewMatrix);
|
||||
shapeData = fShapeCache->find(key);
|
||||
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
|
||||
if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
|
||||
// Remove the stale cache entry
|
||||
if (shapeData) {
|
||||
fShapeCache->remove(shapeData->fKey);
|
||||
@ -366,7 +371,7 @@ private:
|
||||
shapeData = new ShapeData;
|
||||
if (!this->addBMPathToAtlas(target,
|
||||
&flushInfo,
|
||||
fAtlas,
|
||||
atlas,
|
||||
shapeData,
|
||||
args.fShape,
|
||||
args.fViewMatrix)) {
|
||||
@ -377,9 +382,9 @@ private:
|
||||
}
|
||||
|
||||
auto uploadTarget = target->deferredUploadTarget();
|
||||
fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
|
||||
atlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
|
||||
|
||||
this->writePathVertices(fAtlas,
|
||||
this->writePathVertices(atlas,
|
||||
offset,
|
||||
args.fColor,
|
||||
vertexStride,
|
||||
@ -395,8 +400,6 @@ private:
|
||||
bool addDFPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
|
||||
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
|
||||
uint32_t dimension, SkScalar scale) const {
|
||||
auto resourceProvider = target->resourceProvider();
|
||||
|
||||
const SkRect& bounds = shape.bounds();
|
||||
|
||||
// generate bounding rect for bitmap draw
|
||||
@ -485,11 +488,10 @@ private:
|
||||
SkIPoint16 atlasLocation;
|
||||
GrDrawOpAtlas::AtlasID id;
|
||||
auto uploadTarget = target->deferredUploadTarget();
|
||||
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
|
||||
dfStorage.get(), &atlasLocation)) {
|
||||
if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) {
|
||||
this->flush(target, flushInfo);
|
||||
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
|
||||
dfStorage.get(), &atlasLocation)) {
|
||||
if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(),
|
||||
&atlasLocation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -528,8 +530,6 @@ private:
|
||||
bool addBMPathToAtlas(GrMeshDrawOp::Target* target, FlushInfo* flushInfo,
|
||||
GrDrawOpAtlas* atlas, ShapeData* shapeData, const GrShape& shape,
|
||||
const SkMatrix& ctm) const {
|
||||
auto resourceProvider = target->resourceProvider();
|
||||
|
||||
const SkRect& bounds = shape.bounds();
|
||||
if (bounds.isEmpty()) {
|
||||
return false;
|
||||
@ -590,11 +590,11 @@ private:
|
||||
SkIPoint16 atlasLocation;
|
||||
GrDrawOpAtlas::AtlasID id;
|
||||
auto uploadTarget = target->deferredUploadTarget();
|
||||
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
|
||||
dst.addr(), &atlasLocation)) {
|
||||
if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
|
||||
&atlasLocation)) {
|
||||
this->flush(target, flushInfo);
|
||||
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
|
||||
dst.addr(), &atlasLocation)) {
|
||||
if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
|
||||
&atlasLocation)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -696,7 +696,7 @@ private:
|
||||
|
||||
void flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) const {
|
||||
GrGeometryProcessor* gp = flushInfo->fGeometryProcessor.get();
|
||||
if (gp->numTextureSamplers() != (int)fAtlas->numActivePages()) {
|
||||
if (gp->numTextureSamplers() != (int)fAtlas->pageCount()) {
|
||||
// During preparation the number of atlas pages has increased.
|
||||
// Update the proxies used in the GP to match.
|
||||
if (fUsesDistanceField) {
|
||||
@ -788,7 +788,7 @@ bool GrSmallPathRenderer::onDrawPath(const DrawPathArgs& args) {
|
||||
SkASSERT(!args.fShape->isEmpty());
|
||||
SkASSERT(args.fShape->hasUnstyledKey());
|
||||
if (!fAtlas) {
|
||||
fAtlas = GrDrawOpAtlas::Make(args.fContext->contextPriv().proxyProvider(),
|
||||
fAtlas = GrDrawOpAtlas::Make(args.fContext,
|
||||
kAlpha_8_GrPixelConfig,
|
||||
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
|
||||
NUM_PLOTS_X, NUM_PLOTS_Y,
|
||||
@ -858,8 +858,7 @@ GR_DRAW_OP_TEST_DEFINE(SmallPathOp) {
|
||||
if (context->uniqueID() != gTestStruct.fContextID) {
|
||||
gTestStruct.fContextID = context->uniqueID();
|
||||
gTestStruct.reset();
|
||||
gTestStruct.fAtlas = GrDrawOpAtlas::Make(context->contextPriv().proxyProvider(),
|
||||
kAlpha_8_GrPixelConfig,
|
||||
gTestStruct.fAtlas = GrDrawOpAtlas::Make(context, kAlpha_8_GrPixelConfig,
|
||||
ATLAS_TEXTURE_WIDTH, ATLAS_TEXTURE_HEIGHT,
|
||||
NUM_PLOTS_X, NUM_PLOTS_Y,
|
||||
GrDrawOpAtlas::AllowMultitexturing::kYes,
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "GrContext.h"
|
||||
#include "GrDistanceFieldGenFromVector.h"
|
||||
#include "GrGpu.h"
|
||||
#include "GrProxyProvider.h"
|
||||
#include "GrRectanizer.h"
|
||||
|
||||
#include "SkAutoMalloc.h"
|
||||
@ -20,14 +19,14 @@
|
||||
bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
|
||||
int index = MaskFormatToAtlasIndex(format);
|
||||
if (!fAtlases[index]) {
|
||||
GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->caps());
|
||||
GrPixelConfig config = MaskFormatToPixelConfig(format, *fContext->caps());
|
||||
int width = fAtlasConfigs[index].fWidth;
|
||||
int height = fAtlasConfigs[index].fHeight;
|
||||
int numPlotsX = fAtlasConfigs[index].numPlotsX();
|
||||
int numPlotsY = fAtlasConfigs[index].numPlotsY();
|
||||
|
||||
fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
|
||||
numPlotsX, numPlotsY, fAllowMultitexturing,
|
||||
fAtlases[index] = GrDrawOpAtlas::Make(fContext, config, width, height, numPlotsX, numPlotsY,
|
||||
fAllowMultitexturing,
|
||||
&GrAtlasGlyphCache::HandleEviction, (void*)this);
|
||||
if (!fAtlases[index]) {
|
||||
return false;
|
||||
@ -36,13 +35,11 @@ bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
|
||||
return true;
|
||||
}
|
||||
|
||||
GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes,
|
||||
GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
|
||||
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
|
||||
: fProxyProvider(proxyProvider)
|
||||
, fAllowMultitexturing(allowMultitexturing)
|
||||
, fPreserveStrike(nullptr) {
|
||||
: fContext(context), fAllowMultitexturing(allowMultitexturing), fPreserveStrike(nullptr) {
|
||||
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
|
||||
int log2MaxTextureSize = SkPrevLog2(fProxyProvider->caps()->maxTextureSize());
|
||||
int log2MaxTextureSize = SkPrevLog2(context->caps()->maxTextureSize());
|
||||
int log2MaxDim = 9;
|
||||
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
|
||||
int maxDim = 1 << log2MaxDim;
|
||||
@ -177,12 +174,12 @@ static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char*
|
||||
return true;
|
||||
}
|
||||
|
||||
void GrAtlasGlyphCache::dump(GrContext* context) const {
|
||||
void GrAtlasGlyphCache::dump() const {
|
||||
static int gDumpCount = 0;
|
||||
for (int i = 0; i < kMaskFormatCount; ++i) {
|
||||
if (fAtlases[i]) {
|
||||
const sk_sp<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]);
|
||||
SkString filename;
|
||||
#ifdef SK_BUILD_FOR_ANDROID
|
||||
@ -191,7 +188,7 @@ void GrAtlasGlyphCache::dump(GrContext* context) const {
|
||||
filename.printf("fontcache_%d%d%d.png", gDumpCount, i, pageIdx);
|
||||
#endif
|
||||
|
||||
save_pixels(context, proxies[pageIdx].get(), filename.c_str());
|
||||
save_pixels(fContext, proxies[pageIdx].get(), filename.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -448,8 +445,7 @@ void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
|
||||
}
|
||||
}
|
||||
|
||||
bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
|
||||
GrDeferredUploadTarget* target,
|
||||
bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
|
||||
GrAtlasGlyphCache* atlasGlyphCache,
|
||||
GrGlyph* glyph,
|
||||
SkGlyphCache* cache,
|
||||
@ -477,8 +473,7 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
|
||||
}
|
||||
}
|
||||
|
||||
bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target,
|
||||
expectedMaskFormat,
|
||||
bool success = atlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat,
|
||||
glyph->width(), glyph->height(),
|
||||
storage.get(), &glyph->fAtlasLocation);
|
||||
if (success) {
|
||||
|
@ -64,8 +64,8 @@ public:
|
||||
// happen.
|
||||
// TODO we can handle some of these cases if we really want to, but the long term solution is to
|
||||
// get the actual glyph image itself when we get the glyph metrics.
|
||||
bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*,
|
||||
SkGlyphCache*, GrMaskFormat expectedMaskFormat);
|
||||
bool addGlyphToAtlas(GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, SkGlyphCache*,
|
||||
GrMaskFormat expectedMaskFormat);
|
||||
|
||||
// testing
|
||||
int countGlyphs() const { return fCache.count(); }
|
||||
@ -109,8 +109,7 @@ private:
|
||||
*/
|
||||
class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
|
||||
public:
|
||||
GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes,
|
||||
GrDrawOpAtlas::AllowMultitexturing);
|
||||
GrAtlasGlyphCache(GrContext*, float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
|
||||
~GrAtlasGlyphCache() override;
|
||||
// The user of the cache may hold a long-lived ref to the returned strike. However, actions by
|
||||
// another client of the cache may cause the strike to be purged while it is still reffed.
|
||||
@ -133,7 +132,7 @@ public:
|
||||
SkASSERT(numProxies);
|
||||
|
||||
if (this->initAtlas(format)) {
|
||||
*numProxies = this->getAtlas(format)->numActivePages();
|
||||
*numProxies = this->getAtlas(format)->pageCount();
|
||||
return this->getAtlas(format)->getProxies();
|
||||
}
|
||||
*numProxies = 0;
|
||||
@ -166,13 +165,11 @@ public:
|
||||
}
|
||||
|
||||
// add to texture atlas that matches this format
|
||||
bool addToAtlas(GrResourceProvider* resourceProvider, GrAtlasTextStrike* strike,
|
||||
GrDrawOpAtlas::AtlasID* id,
|
||||
bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
|
||||
GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height,
|
||||
const void* image, SkIPoint16* loc) {
|
||||
fPreserveStrike = strike;
|
||||
return this->getAtlas(format)->addToAtlas(resourceProvider, id, target,
|
||||
width, height, image, loc);
|
||||
return this->getAtlas(format)->addToAtlas(id, target, width, height, image, loc);
|
||||
}
|
||||
|
||||
// Some clients may wish to verify the integrity of the texture backing store of the
|
||||
@ -193,7 +190,8 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void postFlush(GrDeferredUploadToken startTokenForNextFlush, const uint32_t*, int) override {
|
||||
void postFlush(GrDeferredUploadToken startTokenForNextFlush,
|
||||
const uint32_t* opListIDs, int numOpListIDs) override {
|
||||
for (int i = 0; i < kMaskFormatCount; ++i) {
|
||||
if (fAtlases[i]) {
|
||||
fAtlases[i]->compact(startTokenForNextFlush);
|
||||
@ -208,11 +206,13 @@ public:
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Functions intended debug only
|
||||
#ifdef SK_DEBUG
|
||||
void dump(GrContext*) const;
|
||||
void dump() const;
|
||||
#endif
|
||||
|
||||
void setAtlasSizes_ForTesting(const GrDrawOpAtlasConfig configs[3]);
|
||||
|
||||
GrContext* context() const { return fContext; }
|
||||
|
||||
private:
|
||||
static GrPixelConfig MaskFormatToPixelConfig(GrMaskFormat format, const GrCaps& caps) {
|
||||
switch (format) {
|
||||
@ -258,7 +258,7 @@ private:
|
||||
static void HandleEviction(GrDrawOpAtlas::AtlasID, void*);
|
||||
|
||||
using StrikeHash = SkTDynamicHash<GrAtlasTextStrike, SkDescriptor>;
|
||||
GrProxyProvider* fProxyProvider;
|
||||
GrContext* fContext;
|
||||
StrikeHash fCache;
|
||||
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
|
||||
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
|
||||
|
@ -560,9 +560,9 @@ public:
|
||||
* SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
|
||||
* SkGlyphCache.
|
||||
*/
|
||||
VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
||||
GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*);
|
||||
VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix,
|
||||
SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget*,
|
||||
GrAtlasGlyphCache*, SkAutoGlyphCache*);
|
||||
|
||||
struct Result {
|
||||
/**
|
||||
@ -589,7 +589,6 @@ private:
|
||||
template <bool regenPos, bool regenCol, bool regenTexCoords, bool regenGlyphs>
|
||||
Result doRegen();
|
||||
|
||||
GrResourceProvider* fResourceProvider;
|
||||
const SkMatrix& fViewMatrix;
|
||||
GrAtlasTextBlob* fBlob;
|
||||
GrDeferredUploadTarget* fUploadTarget;
|
||||
|
@ -190,13 +190,11 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
|
||||
}
|
||||
}
|
||||
|
||||
Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob,
|
||||
int runIdx, int subRunIdx,
|
||||
Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx,
|
||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
||||
GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
|
||||
SkAutoGlyphCache* lazyCache)
|
||||
: fResourceProvider(resourceProvider)
|
||||
, fViewMatrix(viewMatrix)
|
||||
: fViewMatrix(viewMatrix)
|
||||
, fBlob(blob)
|
||||
, fUploadTarget(uploadTarget)
|
||||
, fGlyphCache(glyphCache)
|
||||
@ -276,8 +274,8 @@ Regenerator::Result Regenerator::doRegen() {
|
||||
SkASSERT(glyph && glyph->fMaskFormat == fSubRun->maskFormat());
|
||||
|
||||
if (!fGlyphCache->hasGlyph(glyph) &&
|
||||
!strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph,
|
||||
fLazyCache->get(), fSubRun->maskFormat())) {
|
||||
!strike->addGlyphToAtlas(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(),
|
||||
fSubRun->maskFormat())) {
|
||||
fBrokenRun = glyphIdx > 0;
|
||||
result.fFinished = false;
|
||||
return result;
|
||||
|
@ -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
|
Loading…
Reference in New Issue
Block a user