Separate creation time & flush time behavior in GrDrawOpAtlas (take 3)
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. TBR=bsalomon@google.com Change-Id: I276d339d81e7b709140e082a7b58c5584f73ab70 Reviewed-on: https://skia-review.googlesource.com/111100 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
This commit is contained in:
parent
a63d6900d3
commit
4bc7011802
@ -60,6 +60,7 @@ 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",
|
||||||
|
@ -57,6 +57,17 @@ 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);
|
||||||
@ -129,7 +140,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 use here.
|
// have forwarded on the unref call that got us here.
|
||||||
}
|
}
|
||||||
|
|
||||||
// This GrIORefProxy was deferred before but has just been instantiated. To
|
// This GrIORefProxy was deferred before but has just been instantiated. To
|
||||||
@ -279,6 +290,8 @@ 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.
|
||||||
*/
|
*/
|
||||||
|
@ -183,12 +183,18 @@ 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(
|
||||||
fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun, fGeoData[i].fViewMatrix,
|
resourceProvider, fGeoData[i].fBlob, fGeoData[i].fRun, fGeoData[i].fSubRun,
|
||||||
fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor, &context, atlasGlyphCache,
|
fGeoData[i].fViewMatrix, fGeoData[i].fX, fGeoData[i].fY, fGeoData[i].fColor,
|
||||||
&glyphCache);
|
&context, atlasGlyphCache, &glyphCache);
|
||||||
GrAtlasTextBlob::VertexRegenerator::Result result;
|
GrAtlasTextBlob::VertexRegenerator::Result result;
|
||||||
do {
|
do {
|
||||||
result = regenerator.regenerate();
|
result = regenerator.regenerate();
|
||||||
|
@ -293,7 +293,7 @@ bool GrContext::init(const GrContextOptions& options) {
|
|||||||
} else {
|
} else {
|
||||||
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
|
allowMultitexturing = GrDrawOpAtlas::AllowMultitexturing::kYes;
|
||||||
}
|
}
|
||||||
fAtlasGlyphCache = new GrAtlasGlyphCache(this, options.fGlyphCacheTextureMaximumBytes,
|
fAtlasGlyphCache = new GrAtlasGlyphCache(fProxyProvider, options.fGlyphCacheTextureMaximumBytes,
|
||||||
allowMultitexturing);
|
allowMultitexturing);
|
||||||
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
|
this->contextPriv().addOnFlushCallbackObject(fAtlasGlyphCache);
|
||||||
|
|
||||||
|
@ -96,9 +96,10 @@ public:
|
|||||||
GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
|
GrDeferredUploadToken nextDrawToken() const { return fLastIssuedToken.next(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Only these two classes get to increment the token counters
|
// Only these three classes get to increment the token counters
|
||||||
friend class SkInternalAtlasTextContext;
|
friend class 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; }
|
||||||
|
@ -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 (int i = 0; i < GrDrawOpAtlas::kMaxMultitexturePages; ++i) {
|
for (uint32_t i = 0; i < fNumActivePages; ++i) {
|
||||||
if (fProxies[i] && !fProxies[i]->priv().isInstantiated()) {
|
// All the atlas pages are now instantiated at flush time in the activeNewPage method.
|
||||||
// If instantiation fails we expect the ops that rely on the atlas to be dropped
|
SkASSERT(fProxies[i] && fProxies[i]->priv().isInstantiated());
|
||||||
onFlushResourceProvider->instatiateProxy(fProxies[i].get());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrContext* ctx, GrPixelConfig config, int width,
|
std::unique_ptr<GrDrawOpAtlas> GrDrawOpAtlas::Make(GrProxyProvider* proxyProvider,
|
||||||
|
GrPixelConfig config, int width,
|
||||||
int height, int numPlotsX, int numPlotsY,
|
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(ctx, config, width, height, numPlotsX,
|
std::unique_ptr<GrDrawOpAtlas> atlas(new GrDrawOpAtlas(proxyProvider, config, width, height,
|
||||||
numPlotsY, allowMultitexturing));
|
numPlotsX, numPlotsY,
|
||||||
|
allowMultitexturing));
|
||||||
if (!atlas->getProxies()[0]) {
|
if (!atlas->getProxies()[0]) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
@ -53,7 +53,6 @@ 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())
|
||||||
@ -178,16 +177,16 @@ void GrDrawOpAtlas::Plot::resetRects() {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width, int height,
|
GrDrawOpAtlas::GrDrawOpAtlas(GrProxyProvider* proxyProvider,
|
||||||
|
GrPixelConfig config, int width, int height,
|
||||||
int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
|
int numPlotsX, int numPlotsY, AllowMultitexturing allowMultitexturing)
|
||||||
: fContext(context)
|
: fPixelConfig(config)
|
||||||
, 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)
|
||||||
, fNumPages(0) {
|
, fNumActivePages(0) {
|
||||||
fPlotWidth = fTextureWidth / numPlotsX;
|
fPlotWidth = fTextureWidth / numPlotsX;
|
||||||
fPlotHeight = fTextureHeight / numPlotsY;
|
fPlotHeight = fTextureHeight / numPlotsY;
|
||||||
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
|
SkASSERT(numPlotsX * numPlotsY <= BulkUseTokenUpdater::kMaxPlots);
|
||||||
@ -196,7 +195,7 @@ GrDrawOpAtlas::GrDrawOpAtlas(GrContext* context, GrPixelConfig config, int width
|
|||||||
|
|
||||||
fNumPlots = numPlotsX * numPlotsY;
|
fNumPlots = numPlotsX * numPlotsY;
|
||||||
|
|
||||||
this->createNewPage();
|
this->createPages(proxyProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void GrDrawOpAtlas::processEviction(AtlasID id) {
|
inline void GrDrawOpAtlas::processEviction(AtlasID id) {
|
||||||
@ -217,13 +216,8 @@ inline bool GrDrawOpAtlas::updatePlot(GrDeferredUploadTarget* target, AtlasID* i
|
|||||||
// With c+14 we could move sk_sp into lamba to only ref once.
|
// 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) {
|
||||||
@ -243,8 +237,9 @@ 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(AtlasID* id, GrDeferredUploadTarget* target, int width, int height,
|
bool GrDrawOpAtlas::addToAtlas(GrResourceProvider* resourceProvider,
|
||||||
const void* image, SkIPoint16* loc) {
|
AtlasID* id, GrDeferredUploadTarget* target,
|
||||||
|
int width, int height, const void* image, SkIPoint16* loc) {
|
||||||
if (width > fPlotWidth || height > fPlotHeight) {
|
if (width > fPlotWidth || height > fPlotHeight) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -252,7 +247,7 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
// Look through each page to see if we can upload without having to flush
|
// 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 < fNumPages; ++pageIdx) {
|
for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++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;
|
||||||
@ -272,10 +267,10 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
// We wait until we've grown to the full number of pages to begin evicting already flushed
|
// 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 < fNumPages; ++pageIdx) {
|
for (unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
|
||||||
Plot* plot = fPages[pageIdx].fPlotList.tail();
|
Plot* plot = fPages[pageIdx].fPlotList.tail();
|
||||||
SkASSERT(plot);
|
SkASSERT(plot);
|
||||||
if ((fNumPages == this->maxPages() &&
|
if ((fNumActivePages == this->maxPages() &&
|
||||||
plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) ||
|
plot->lastUseToken() < target->tokenTracker()->nextTokenToFlush()) ||
|
||||||
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
|
plot->flushesSinceLastUsed() >= kRecentlyUsedCount) {
|
||||||
this->processEvictionAndResetRects(plot);
|
this->processEvictionAndResetRects(plot);
|
||||||
@ -290,9 +285,10 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the simple cases fail, try to create a new page and add to it
|
// If the simple cases fail, try to create a new page and add to it
|
||||||
if (this->createNewPage()) {
|
if (this->activateNewPage(resourceProvider)) {
|
||||||
unsigned int pageIdx = fNumPages-1;
|
unsigned int pageIdx = fNumActivePages-1;
|
||||||
SkASSERT(fProxies[pageIdx]);
|
SkASSERT(fProxies[pageIdx] && fProxies[pageIdx]->priv().isInstantiated());
|
||||||
|
|
||||||
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)) {
|
||||||
@ -307,7 +303,7 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
// Try to find a plot that we can perform an inline upload to.
|
// 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)(fNumPages-1); pageIdx >= 0; --pageIdx) {
|
for (int pageIdx = (int)(fNumActivePages-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;
|
||||||
@ -339,11 +335,8 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
// 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.
|
|
||||||
// Once it is deferred more care must be taken upon instantiation failure.
|
SkASSERT(fProxies[pageIdx]->priv().isInstantiated());
|
||||||
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(
|
||||||
@ -358,7 +351,7 @@ bool GrDrawOpAtlas::addToAtlas(AtlasID* id, GrDeferredUploadTarget* target, int
|
|||||||
}
|
}
|
||||||
|
|
||||||
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
||||||
if (fNumPages <= 1) {
|
if (fNumActivePages <= 1) {
|
||||||
fPrevFlushToken = startTokenForNextFlush;
|
fPrevFlushToken = startTokenForNextFlush;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -366,7 +359,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 < fNumPages; ++pageIndex) {
|
for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++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
|
||||||
@ -385,7 +378,7 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
|||||||
// TODO: consider if we should also do this if it's been a long time since the last atlas use
|
// 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 = fNumPages - 1;
|
uint32_t lastPageIndex = fNumActivePages - 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.
|
||||||
@ -494,19 +487,15 @@ void GrDrawOpAtlas::compact(GrDeferredUploadToken startTokenForNextFlush) {
|
|||||||
SkDebugf("delete %d\n", fNumPages-1);
|
SkDebugf("delete %d\n", fNumPages-1);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
this->deleteLastPage();
|
this->deactivateLastPage();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fPrevFlushToken = startTokenForNextFlush;
|
fPrevFlushToken = startTokenForNextFlush;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrDrawOpAtlas::createNewPage() {
|
bool GrDrawOpAtlas::createPages(GrProxyProvider* proxyProvider) {
|
||||||
if (fNumPages == this->maxPages()) {
|
SkASSERT(SkIsPow2(fTextureWidth) && SkIsPow2(fTextureHeight));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GrProxyProvider* proxyProvider = fContext->contextPriv().proxyProvider();
|
|
||||||
|
|
||||||
GrSurfaceDesc desc;
|
GrSurfaceDesc desc;
|
||||||
desc.fFlags = kNone_GrSurfaceFlags;
|
desc.fFlags = kNone_GrSurfaceFlags;
|
||||||
@ -515,47 +504,83 @@ bool GrDrawOpAtlas::createNewPage() {
|
|||||||
desc.fHeight = fTextureHeight;
|
desc.fHeight = fTextureHeight;
|
||||||
desc.fConfig = fPixelConfig;
|
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 numPlotsX = fTextureWidth/fPlotWidth;
|
||||||
int numPlotsY = fTextureHeight/fPlotHeight;
|
int numPlotsY = fTextureHeight/fPlotHeight;
|
||||||
|
|
||||||
// set up allocated plots
|
for (uint32_t i = 0; i < this->maxPages(); ++i) {
|
||||||
fPages[fNumPages].fPlotArray.reset(new sk_sp<Plot>[ numPlotsX * numPlotsY ]);
|
fProxies[i] = proxyProvider->createProxy(desc, SkBackingFit::kExact, SkBudgeted::kYes,
|
||||||
|
GrResourceProvider::kNoPendingIO_Flag);
|
||||||
|
if (!fProxies[i]) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
sk_sp<Plot>* currPlot = fPages[fNumPages].fPlotArray.get();
|
// 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 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(fNumPages, plotIndex, 1, x, y, fPlotWidth, fPlotHeight,
|
currPlot->reset(new Plot(i, plotIndex, 1, x, y, fPlotWidth, fPlotHeight,
|
||||||
fPixelConfig));
|
fPixelConfig));
|
||||||
|
|
||||||
// build LRU list
|
// build LRU list
|
||||||
fPages[fNumPages].fPlotList.addToHead(currPlot->get());
|
fPages[i].fPlotList.addToHead(currPlot->get());
|
||||||
++currPlot;
|
++currPlot;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DUMP_ATLAS_DATA
|
|
||||||
if (gDumpAtlasData) {
|
|
||||||
SkDebugf("created %d\n", fNumPages);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
fNumPages++;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void GrDrawOpAtlas::deleteLastPage() {
|
|
||||||
uint32_t lastPageIndex = fNumPages - 1;
|
bool GrDrawOpAtlas::activateNewPage(GrResourceProvider* resourceProvider) {
|
||||||
// clean out the plots
|
if (fNumActivePages >= this->maxPages()) {
|
||||||
fPages[lastPageIndex].fPlotList.reset();
|
return false;
|
||||||
fPages[lastPageIndex].fPlotArray.reset(nullptr);
|
}
|
||||||
// remove ref to texture proxy
|
|
||||||
fProxies[lastPageIndex].reset(nullptr);
|
if (!fProxies[fNumActivePages]->instantiate(resourceProvider)) {
|
||||||
--fNumPages;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DUMP_ATLAS_DATA
|
||||||
|
if (gDumpAtlasData) {
|
||||||
|
SkDebugf("activated page#: %d\n", fNumActivePages);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
++fNumActivePages;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void GrDrawOpAtlas::deactivateLastPage() {
|
||||||
|
SkASSERT(fNumActivePages);
|
||||||
|
|
||||||
|
uint32_t lastPageIndex = fNumActivePages - 1;
|
||||||
|
|
||||||
|
int numPlotsX = fTextureWidth/fPlotWidth;
|
||||||
|
int numPlotsY = fTextureHeight/fPlotHeight;
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,8 @@ 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(GrContext*, GrPixelConfig, int width, int height,
|
static std::unique_ptr<GrDrawOpAtlas> Make(GrProxyProvider*, GrPixelConfig,
|
||||||
|
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);
|
||||||
@ -108,19 +109,21 @@ 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(AtlasID*, GrDeferredUploadTarget*, int width, int height, const void* image,
|
bool addToAtlas(GrResourceProvider*, AtlasID*, GrDeferredUploadTarget*, int width, int height,
|
||||||
SkIPoint16* loc);
|
const void* image, 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 < fNumPages);
|
SkASSERT(page < fNumActivePages);
|
||||||
return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id);
|
return fPages[page].fPlotArray[plot]->genID() == GetGenerationFromID(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -130,7 +133,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 < fNumPages);
|
SkASSERT(pageIdx < fNumActivePages);
|
||||||
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);
|
||||||
@ -142,7 +145,7 @@ public:
|
|||||||
data->fData = userData;
|
data->fData = userData;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t pageCount() { return fNumPages; }
|
uint32_t numActivePages() { return fNumActivePages; }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The
|
* A class which can be handed back to GrDrawOpAtlas for updating last use tokens in bulk. The
|
||||||
@ -204,7 +207,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 < fNumPages) {
|
if (pd.fPageIndex < fNumActivePages) {
|
||||||
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);
|
||||||
@ -225,12 +228,14 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrDrawOpAtlas(GrContext*, GrPixelConfig config, int width, int height, int numPlotsX,
|
int numAllocated_TestingOnly() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
GrDrawOpAtlas(GrProxyProvider*, GrPixelConfig, int width, int height, int numPlotsX,
|
||||||
int numPlotsY, AllowMultitexturing allowMultitexturing);
|
int numPlotsY, AllowMultitexturing allowMultitexturing);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -354,8 +359,9 @@ 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 createNewPage();
|
bool createPages(GrProxyProvider*);
|
||||||
void deleteLastPage();
|
bool activateNewPage(GrResourceProvider*);
|
||||||
|
void deactivateLastPage();
|
||||||
|
|
||||||
void processEviction(AtlasID);
|
void processEviction(AtlasID);
|
||||||
inline void processEvictionAndResetRects(Plot* plot) {
|
inline void processEvictionAndResetRects(Plot* plot) {
|
||||||
@ -363,7 +369,6 @@ private:
|
|||||||
plot->resetRects();
|
plot->resetRects();
|
||||||
}
|
}
|
||||||
|
|
||||||
GrContext* fContext;
|
|
||||||
GrPixelConfig fPixelConfig;
|
GrPixelConfig fPixelConfig;
|
||||||
int fTextureWidth;
|
int fTextureWidth;
|
||||||
int fTextureHeight;
|
int fTextureHeight;
|
||||||
@ -392,7 +397,8 @@ 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
|
||||||
|
@ -66,6 +66,8 @@ 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*);
|
||||||
@ -86,13 +88,10 @@ 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
|
||||||
|
@ -208,6 +208,13 @@ 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();
|
||||||
|
@ -121,7 +121,8 @@ private:
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color,
|
GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color,
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params, GrMaskFormat format,
|
const GrSamplerState& params, GrMaskFormat format,
|
||||||
const SkMatrix& localMatrix, bool usesLocalCoords)
|
const SkMatrix& localMatrix, bool usesLocalCoords)
|
||||||
: INHERITED(kGrBitmapTextGeoProc_ClassID)
|
: INHERITED(kGrBitmapTextGeoProc_ClassID)
|
||||||
@ -130,6 +131,8 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color,
|
|||||||
, fUsesLocalCoords(usesLocalCoords)
|
, fUsesLocalCoords(usesLocalCoords)
|
||||||
, fInColor(nullptr)
|
, fInColor(nullptr)
|
||||||
, fMaskFormat(format) {
|
, fMaskFormat(format) {
|
||||||
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
|
|
||||||
fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
|
fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
|
||||||
|
|
||||||
bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
|
bool hasVertexColor = kA8_GrMaskFormat == fMaskFormat ||
|
||||||
@ -139,18 +142,23 @@ GrBitmapTextGeoProc::GrBitmapTextGeoProc(GrColor color,
|
|||||||
}
|
}
|
||||||
|
|
||||||
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
if (proxies[i]) {
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrBitmapTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
void GrBitmapTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params) {
|
const GrSamplerState& params) {
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
if (proxies[i] && !fTextureSamplers[i].isInitialized()) {
|
|
||||||
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
|
if (!fTextureSamplers[i].isInitialized()) {
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
@ -201,7 +209,7 @@ sk_sp<GrGeometryProcessor> GrBitmapTextGeoProc::TestCreate(GrProcessorTestData*
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GrBitmapTextGeoProc::Make(GrRandomColor(d->fRandom), proxies, samplerState,
|
return GrBitmapTextGeoProc::Make(GrRandomColor(d->fRandom), proxies, 1, samplerState,
|
||||||
format, GrTest::TestMatrix(d->fRandom),
|
format, GrTest::TestMatrix(d->fRandom),
|
||||||
d->fRandom->nextBool());
|
d->fRandom->nextBool());
|
||||||
}
|
}
|
||||||
|
@ -21,14 +21,14 @@ class GrInvariantOutput;
|
|||||||
*/
|
*/
|
||||||
class GrBitmapTextGeoProc : public GrGeometryProcessor {
|
class GrBitmapTextGeoProc : public GrGeometryProcessor {
|
||||||
public:
|
public:
|
||||||
static constexpr int kMaxTextures = 4;
|
|
||||||
|
|
||||||
static sk_sp<GrGeometryProcessor> Make(GrColor color,
|
static sk_sp<GrGeometryProcessor> Make(GrColor color,
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& p, GrMaskFormat format,
|
const GrSamplerState& p, GrMaskFormat format,
|
||||||
const SkMatrix& localMatrix, bool usesLocalCoords) {
|
const SkMatrix& localMatrix, bool usesLocalCoords) {
|
||||||
return sk_sp<GrGeometryProcessor>(
|
return sk_sp<GrGeometryProcessor>(
|
||||||
new GrBitmapTextGeoProc(color, proxies, p, format,
|
new GrBitmapTextGeoProc(color, proxies, numProxies, p, format,
|
||||||
localMatrix, usesLocalCoords));
|
localMatrix, usesLocalCoords));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,14 +45,16 @@ public:
|
|||||||
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
||||||
bool usesLocalCoords() const { return fUsesLocalCoords; }
|
bool usesLocalCoords() const { return fUsesLocalCoords; }
|
||||||
|
|
||||||
void addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures], const GrSamplerState& p);
|
void addNewProxies(const sk_sp<GrTextureProxy>* proxies, int numProxies, const GrSamplerState&);
|
||||||
|
|
||||||
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
|
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps& caps) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrBitmapTextGeoProc(GrColor, const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
static constexpr int kMaxTextures = 4;
|
||||||
|
|
||||||
|
GrBitmapTextGeoProc(GrColor, const sk_sp<GrTextureProxy>* proxies, int numProxies,
|
||||||
const GrSamplerState& params, GrMaskFormat format,
|
const GrSamplerState& params, GrMaskFormat format,
|
||||||
const SkMatrix& localMatrix, bool usesLocalCoords);
|
const SkMatrix& localMatrix, bool usesLocalCoords);
|
||||||
|
|
||||||
|
@ -207,7 +207,8 @@ private:
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
|
GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params,
|
const GrSamplerState& params,
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
float distanceAdjust,
|
float distanceAdjust,
|
||||||
@ -221,6 +222,8 @@ GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
|
|||||||
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
|
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
|
||||||
, fInColor(nullptr)
|
, fInColor(nullptr)
|
||||||
, fLocalMatrix(localMatrix) {
|
, fLocalMatrix(localMatrix) {
|
||||||
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
|
|
||||||
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
|
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
|
||||||
if (flags & kPerspective_DistanceFieldEffectFlag) {
|
if (flags & kPerspective_DistanceFieldEffectFlag) {
|
||||||
fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
|
fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
|
||||||
@ -229,18 +232,23 @@ GrDistanceFieldA8TextGeoProc::GrDistanceFieldA8TextGeoProc(
|
|||||||
}
|
}
|
||||||
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
||||||
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
if (proxies[i]) {
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrDistanceFieldA8TextGeoProc::addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
void GrDistanceFieldA8TextGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params) {
|
const GrSamplerState& params) {
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
if (proxies[i] && !fTextureSamplers[i].isInitialized()) {
|
|
||||||
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
|
if (!fTextureSamplers[i].isInitialized()) {
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
@ -287,7 +295,7 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldA8TextGeoProc::TestCreate(GrProcessorT
|
|||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
float lum = d->fRandom->nextF();
|
float lum = d->fRandom->nextF();
|
||||||
#endif
|
#endif
|
||||||
return GrDistanceFieldA8TextGeoProc::Make(proxies,
|
return GrDistanceFieldA8TextGeoProc::Make(proxies, 1,
|
||||||
samplerState,
|
samplerState,
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
lum,
|
lum,
|
||||||
@ -493,29 +501,37 @@ private:
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
|
GrDistanceFieldPathGeoProc::GrDistanceFieldPathGeoProc(
|
||||||
const SkMatrix& matrix,
|
const SkMatrix& matrix,
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params,
|
const GrSamplerState& params,
|
||||||
uint32_t flags)
|
uint32_t flags)
|
||||||
: INHERITED(kGrDistanceFieldPathGeoProc_ClassID)
|
: INHERITED(kGrDistanceFieldPathGeoProc_ClassID)
|
||||||
, fMatrix(matrix)
|
, fMatrix(matrix)
|
||||||
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
|
, fFlags(flags & kNonLCD_DistanceFieldEffectMask)
|
||||||
, fInColor(nullptr) {
|
, fInColor(nullptr) {
|
||||||
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
|
|
||||||
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
|
SkASSERT(!(flags & ~kNonLCD_DistanceFieldEffectMask));
|
||||||
fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
|
fInPosition = &this->addVertexAttrib("inPosition", kFloat2_GrVertexAttribType);
|
||||||
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
||||||
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
if (proxies[i]) {
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrDistanceFieldPathGeoProc::addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
void GrDistanceFieldPathGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params) {
|
const GrSamplerState& params) {
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
if (proxies[i] && !fTextureSamplers[i].isInitialized()) {
|
|
||||||
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
|
if (!fTextureSamplers[i].isInitialized()) {
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
@ -560,7 +576,7 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldPathGeoProc::TestCreate(GrProcessorTes
|
|||||||
}
|
}
|
||||||
|
|
||||||
return GrDistanceFieldPathGeoProc::Make(GrTest::TestMatrix(d->fRandom),
|
return GrDistanceFieldPathGeoProc::Make(GrTest::TestMatrix(d->fRandom),
|
||||||
proxies,
|
proxies, 1,
|
||||||
samplerState,
|
samplerState,
|
||||||
flags);
|
flags);
|
||||||
}
|
}
|
||||||
@ -787,7 +803,8 @@ private:
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
|
GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params,
|
const GrSamplerState& params,
|
||||||
DistanceAdjust distanceAdjust,
|
DistanceAdjust distanceAdjust,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
@ -796,6 +813,8 @@ GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
|
|||||||
, fDistanceAdjust(distanceAdjust)
|
, fDistanceAdjust(distanceAdjust)
|
||||||
, fFlags(flags & kLCD_DistanceFieldEffectMask)
|
, fFlags(flags & kLCD_DistanceFieldEffectMask)
|
||||||
, fLocalMatrix(localMatrix) {
|
, fLocalMatrix(localMatrix) {
|
||||||
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
|
|
||||||
SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
|
SkASSERT(!(flags & ~kLCD_DistanceFieldEffectMask) && (flags & kUseLCD_DistanceFieldEffectFlag));
|
||||||
if (fFlags & kPerspective_DistanceFieldEffectFlag) {
|
if (fFlags & kPerspective_DistanceFieldEffectFlag) {
|
||||||
fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
|
fInPosition = &this->addVertexAttrib("inPosition", kFloat3_GrVertexAttribType);
|
||||||
@ -804,19 +823,24 @@ GrDistanceFieldLCDTextGeoProc::GrDistanceFieldLCDTextGeoProc(
|
|||||||
}
|
}
|
||||||
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
fInColor = &this->addVertexAttrib("inColor", kUByte4_norm_GrVertexAttribType);
|
||||||
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
fInTextureCoords = &this->addVertexAttrib("inTextureCoords", kUShort2_GrVertexAttribType);
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
if (proxies[i]) {
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrDistanceFieldLCDTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy> prox[kMaxTextures],
|
void GrDistanceFieldLCDTextGeoProc::addNewProxies(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params) {
|
const GrSamplerState& params) {
|
||||||
for (int i = 0; i < kMaxTextures; ++i) {
|
SkASSERT(numProxies <= kMaxTextures);
|
||||||
if (prox[i] && !fTextureSamplers[i].isInitialized()) {
|
|
||||||
fTextureSamplers[i].reset(std::move(prox[i]), params);
|
for (int i = 0; i < numProxies; ++i) {
|
||||||
|
SkASSERT(proxies[i]);
|
||||||
|
|
||||||
|
if (!fTextureSamplers[i].isInitialized()) {
|
||||||
|
fTextureSamplers[i].reset(std::move(proxies[i]), params);
|
||||||
this->addTextureSampler(&fTextureSamplers[i]);
|
this->addTextureSampler(&fTextureSamplers[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -859,6 +883,6 @@ sk_sp<GrGeometryProcessor> GrDistanceFieldLCDTextGeoProc::TestCreate(GrProcessor
|
|||||||
}
|
}
|
||||||
flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
|
flags |= d->fRandom->nextBool() ? kBGR_DistanceFieldEffectFlag : 0;
|
||||||
SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
|
SkMatrix localMatrix = GrTest::TestMatrix(d->fRandom);
|
||||||
return GrDistanceFieldLCDTextGeoProc::Make(proxies, samplerState, wa, flags, localMatrix);
|
return GrDistanceFieldLCDTextGeoProc::Make(proxies, 1, samplerState, wa, flags, localMatrix);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -53,22 +53,22 @@ enum GrDistanceFieldEffectFlags {
|
|||||||
*/
|
*/
|
||||||
class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
|
class GrDistanceFieldA8TextGeoProc : public GrGeometryProcessor {
|
||||||
public:
|
public:
|
||||||
static constexpr int kMaxTextures = 4;
|
|
||||||
|
|
||||||
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
|
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params, float lum, uint32_t flags,
|
const GrSamplerState& params, float lum, uint32_t flags,
|
||||||
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
||||||
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
|
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
|
||||||
proxies, params, lum, flags, localMatrixIfUsesLocalCoords));
|
proxies, numProxies, params, lum, flags, localMatrixIfUsesLocalCoords));
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params, uint32_t flags,
|
const GrSamplerState& params, uint32_t flags,
|
||||||
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
||||||
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
|
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldA8TextGeoProc(
|
||||||
proxies, params, flags, localMatrixIfUsesLocalCoords));
|
proxies, numProxies, params, flags, localMatrixIfUsesLocalCoords));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -85,20 +85,23 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
uint32_t getFlags() const { return fFlags; }
|
uint32_t getFlags() const { return fFlags; }
|
||||||
|
|
||||||
void addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures], const GrSamplerState& p);
|
void addNewProxies(const sk_sp<GrTextureProxy>* proxies, int numProxies, const GrSamplerState&);
|
||||||
|
|
||||||
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrDistanceFieldA8TextGeoProc(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
GrDistanceFieldA8TextGeoProc(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params,
|
const GrSamplerState& params,
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
float distanceAdjust,
|
float distanceAdjust,
|
||||||
#endif
|
#endif
|
||||||
uint32_t flags, const SkMatrix& localMatrix);
|
uint32_t flags, const SkMatrix& localMatrix);
|
||||||
|
|
||||||
|
static constexpr int kMaxTextures = 4;
|
||||||
|
|
||||||
TextureSampler fTextureSamplers[kMaxTextures];
|
TextureSampler fTextureSamplers[kMaxTextures];
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
float fDistanceAdjust;
|
float fDistanceAdjust;
|
||||||
@ -122,14 +125,14 @@ private:
|
|||||||
*/
|
*/
|
||||||
class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
|
class GrDistanceFieldPathGeoProc : public GrGeometryProcessor {
|
||||||
public:
|
public:
|
||||||
static constexpr int kMaxTextures = 4;
|
|
||||||
|
|
||||||
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
|
/** The local matrix should be identity if local coords are not required by the GrPipeline. */
|
||||||
static sk_sp<GrGeometryProcessor> Make(const SkMatrix& matrix,
|
static sk_sp<GrGeometryProcessor> Make(const SkMatrix& matrix,
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState& params, uint32_t flags) {
|
const GrSamplerState& params, uint32_t flags) {
|
||||||
return sk_sp<GrGeometryProcessor>(
|
return sk_sp<GrGeometryProcessor>(
|
||||||
new GrDistanceFieldPathGeoProc(matrix, proxies, params, flags));
|
new GrDistanceFieldPathGeoProc(matrix, proxies, numProxies, params, flags));
|
||||||
}
|
}
|
||||||
|
|
||||||
~GrDistanceFieldPathGeoProc() override {}
|
~GrDistanceFieldPathGeoProc() override {}
|
||||||
@ -142,15 +145,18 @@ public:
|
|||||||
const SkMatrix& matrix() const { return fMatrix; }
|
const SkMatrix& matrix() const { return fMatrix; }
|
||||||
uint32_t getFlags() const { return fFlags; }
|
uint32_t getFlags() const { return fFlags; }
|
||||||
|
|
||||||
void addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures], const GrSamplerState& p);
|
void addNewProxies(const sk_sp<GrTextureProxy>* proxies, int numProxies, const GrSamplerState&);
|
||||||
|
|
||||||
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static constexpr int kMaxTextures = 4;
|
||||||
|
|
||||||
GrDistanceFieldPathGeoProc(const SkMatrix& matrix,
|
GrDistanceFieldPathGeoProc(const SkMatrix& matrix,
|
||||||
const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
const GrSamplerState&, uint32_t flags);
|
const GrSamplerState&, uint32_t flags);
|
||||||
|
|
||||||
SkMatrix fMatrix; // view matrix if perspective, local matrix otherwise
|
SkMatrix fMatrix; // view matrix if perspective, local matrix otherwise
|
||||||
@ -188,15 +194,14 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr int kMaxTextures = 4;
|
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy>* proxies,
|
||||||
|
int numProxies,
|
||||||
static sk_sp<GrGeometryProcessor> Make(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
|
||||||
const GrSamplerState& params,
|
const GrSamplerState& params,
|
||||||
DistanceAdjust distanceAdjust,
|
DistanceAdjust distanceAdjust,
|
||||||
uint32_t flags,
|
uint32_t flags,
|
||||||
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
const SkMatrix& localMatrixIfUsesLocalCoords) {
|
||||||
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldLCDTextGeoProc(
|
return sk_sp<GrGeometryProcessor>(new GrDistanceFieldLCDTextGeoProc(
|
||||||
proxies, params, distanceAdjust, flags, localMatrixIfUsesLocalCoords));
|
proxies, numProxies, params, distanceAdjust, flags, localMatrixIfUsesLocalCoords));
|
||||||
}
|
}
|
||||||
|
|
||||||
~GrDistanceFieldLCDTextGeoProc() override {}
|
~GrDistanceFieldLCDTextGeoProc() override {}
|
||||||
@ -210,17 +215,19 @@ public:
|
|||||||
uint32_t getFlags() const { return fFlags; }
|
uint32_t getFlags() const { return fFlags; }
|
||||||
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
const SkMatrix& localMatrix() const { return fLocalMatrix; }
|
||||||
|
|
||||||
void addNewProxies(const sk_sp<GrTextureProxy> proxies[kMaxTextures], const GrSamplerState& p);
|
void addNewProxies(const sk_sp<GrTextureProxy>* proxies, int numProxies, const GrSamplerState&);
|
||||||
|
|
||||||
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
void getGLSLProcessorKey(const GrShaderCaps& caps, GrProcessorKeyBuilder* b) const override;
|
||||||
|
|
||||||
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
GrGLSLPrimitiveProcessor* createGLSLInstance(const GrShaderCaps&) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
GrDistanceFieldLCDTextGeoProc(const sk_sp<GrTextureProxy> proxies[kMaxTextures],
|
GrDistanceFieldLCDTextGeoProc(const sk_sp<GrTextureProxy>* proxies, int numProxies,
|
||||||
const GrSamplerState& params, DistanceAdjust wa, uint32_t flags,
|
const GrSamplerState& params, DistanceAdjust wa, uint32_t flags,
|
||||||
const SkMatrix& localMatrix);
|
const SkMatrix& localMatrix);
|
||||||
|
|
||||||
|
static constexpr int kMaxTextures = 4;
|
||||||
|
|
||||||
TextureSampler fTextureSamplers[kMaxTextures];
|
TextureSampler fTextureSamplers[kMaxTextures];
|
||||||
DistanceAdjust fDistanceAdjust;
|
DistanceAdjust fDistanceAdjust;
|
||||||
uint32_t fFlags;
|
uint32_t fFlags;
|
||||||
|
@ -222,6 +222,8 @@ 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;
|
||||||
@ -234,7 +236,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
|||||||
|
|
||||||
unsigned int atlasPageCount;
|
unsigned int atlasPageCount;
|
||||||
const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &atlasPageCount);
|
const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(maskFormat, &atlasPageCount);
|
||||||
if (!atlasPageCount || !proxies[0]) {
|
if (!proxies[0]) {
|
||||||
SkDebugf("Could not allocate backing texture for atlas\n");
|
SkDebugf("Could not allocate backing texture for atlas\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -248,7 +250,7 @@ void GrAtlasTextOp::onPrepareDraws(Target* target) {
|
|||||||
SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective());
|
SkDEBUGCODE(dfPerspective = fGeoData[0].fViewMatrix.hasPerspective());
|
||||||
} else {
|
} else {
|
||||||
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
|
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
|
||||||
this->color(), proxies, GrSamplerState::ClampNearest(), maskFormat,
|
this->color(), proxies, atlasPageCount, GrSamplerState::ClampNearest(), maskFormat,
|
||||||
localMatrix, this->usesLocalCoords());
|
localMatrix, this->usesLocalCoords());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,8 +278,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(
|
||||||
blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY, args.fColor,
|
resourceProvider, blob, args.fRun, args.fSubRun, args.fViewMatrix, args.fX, args.fY,
|
||||||
target->deferredUploadTarget(), fFontCache, &glyphCache);
|
args.fColor, target->deferredUploadTarget(), fFontCache, &glyphCache);
|
||||||
GrAtlasTextBlob::VertexRegenerator::Result result;
|
GrAtlasTextBlob::VertexRegenerator::Result result;
|
||||||
do {
|
do {
|
||||||
result = regenerator.regenerate();
|
result = regenerator.regenerate();
|
||||||
@ -328,14 +330,14 @@ void GrAtlasTextOp::flush(GrMeshDrawOp::Target* target, FlushInfo* flushInfo) co
|
|||||||
if (this->usesDistanceFields()) {
|
if (this->usesDistanceFields()) {
|
||||||
if (this->isLCD()) {
|
if (this->isLCD()) {
|
||||||
reinterpret_cast<GrDistanceFieldLCDTextGeoProc*>(gp)->addNewProxies(
|
reinterpret_cast<GrDistanceFieldLCDTextGeoProc*>(gp)->addNewProxies(
|
||||||
proxies, GrSamplerState::ClampBilerp());
|
proxies, numProxies, GrSamplerState::ClampBilerp());
|
||||||
} else {
|
} else {
|
||||||
reinterpret_cast<GrDistanceFieldA8TextGeoProc*>(gp)->addNewProxies(
|
reinterpret_cast<GrDistanceFieldA8TextGeoProc*>(gp)->addNewProxies(
|
||||||
proxies, GrSamplerState::ClampBilerp());
|
proxies, numProxies, GrSamplerState::ClampBilerp());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(
|
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(
|
||||||
proxies, GrSamplerState::ClampNearest());
|
proxies, numProxies, GrSamplerState::ClampNearest());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -427,7 +429,7 @@ bool GrAtlasTextOp::onCombineIfPossible(GrOp* t, const GrCaps& caps) {
|
|||||||
// (see comments in GrAtlasTextContext::ComputeCanonicalColor)
|
// (see comments in GrAtlasTextContext::ComputeCanonicalColor)
|
||||||
sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
|
sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
|
||||||
unsigned int numProxies;
|
unsigned int numProxies;
|
||||||
const sk_sp<GrTextureProxy>* p = fFontCache->getProxies(this->maskFormat(), &numProxies);
|
const sk_sp<GrTextureProxy>* proxies = fFontCache->getProxies(this->maskFormat(), &numProxies);
|
||||||
bool isLCD = this->isLCD();
|
bool isLCD = this->isLCD();
|
||||||
|
|
||||||
SkMatrix localMatrix = SkMatrix::I();
|
SkMatrix localMatrix = SkMatrix::I();
|
||||||
@ -451,7 +453,8 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
|
|||||||
GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
|
GrDistanceFieldLCDTextGeoProc::DistanceAdjust widthAdjust =
|
||||||
GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(
|
GrDistanceFieldLCDTextGeoProc::DistanceAdjust::Make(
|
||||||
redCorrection, greenCorrection, blueCorrection);
|
redCorrection, greenCorrection, blueCorrection);
|
||||||
return GrDistanceFieldLCDTextGeoProc::Make(p, GrSamplerState::ClampBilerp(), widthAdjust,
|
return GrDistanceFieldLCDTextGeoProc::Make(proxies, numProxies,
|
||||||
|
GrSamplerState::ClampBilerp(), widthAdjust,
|
||||||
fDFGPFlags, localMatrix);
|
fDFGPFlags, localMatrix);
|
||||||
} else {
|
} else {
|
||||||
#ifdef SK_GAMMA_APPLY_TO_A8
|
#ifdef SK_GAMMA_APPLY_TO_A8
|
||||||
@ -462,10 +465,12 @@ sk_sp<GrGeometryProcessor> GrAtlasTextOp::setupDfProcessor() const {
|
|||||||
correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift,
|
correction = fDistanceAdjustTable->getAdjustment(lum >> kDistanceAdjustLumShift,
|
||||||
fUseGammaCorrectDistanceTable);
|
fUseGammaCorrectDistanceTable);
|
||||||
}
|
}
|
||||||
return GrDistanceFieldA8TextGeoProc::Make(p, GrSamplerState::ClampBilerp(),
|
return GrDistanceFieldA8TextGeoProc::Make(proxies, numProxies,
|
||||||
|
GrSamplerState::ClampBilerp(),
|
||||||
correction, fDFGPFlags, localMatrix);
|
correction, fDFGPFlags, localMatrix);
|
||||||
#else
|
#else
|
||||||
return GrDistanceFieldA8TextGeoProc::Make(p, GrSamplerState::ClampBilerp(),
|
return GrDistanceFieldA8TextGeoProc::Make(proxies, numProxies,
|
||||||
|
GrSamplerState::ClampBilerp(),
|
||||||
fDFGPFlags, localMatrix);
|
fDFGPFlags, localMatrix);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -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->pageCount(); ++i) {
|
for (uint32_t i = 0; i < fAtlas->numActivePages(); ++i) {
|
||||||
SkASSERT(proxies[i]);
|
SkASSERT(proxies[i]);
|
||||||
func(proxies[i].get());
|
func(proxies[i].get());
|
||||||
}
|
}
|
||||||
@ -222,11 +222,6 @@ private:
|
|||||||
FlushInfo flushInfo;
|
FlushInfo flushInfo;
|
||||||
flushInfo.fPipeline = fHelper.makePipeline(target);
|
flushInfo.fPipeline = fHelper.makePipeline(target);
|
||||||
// Setup GrGeometryProcessor
|
// Setup GrGeometryProcessor
|
||||||
GrDrawOpAtlas* atlas = fAtlas;
|
|
||||||
uint32_t atlasPageCount = atlas->pageCount();
|
|
||||||
if (!atlasPageCount) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const SkMatrix& ctm = fShapes[0].fViewMatrix;
|
const SkMatrix& ctm = fShapes[0].fViewMatrix;
|
||||||
if (fUsesDistanceField) {
|
if (fUsesDistanceField) {
|
||||||
uint32_t flags = 0;
|
uint32_t flags = 0;
|
||||||
@ -249,7 +244,8 @@ private:
|
|||||||
matrix = &SkMatrix::I();
|
matrix = &SkMatrix::I();
|
||||||
}
|
}
|
||||||
flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(
|
flushInfo.fGeometryProcessor = GrDistanceFieldPathGeoProc::Make(
|
||||||
*matrix, atlas->getProxies(), GrSamplerState::ClampBilerp(), flags);
|
*matrix, fAtlas->getProxies(), fAtlas->numActivePages(),
|
||||||
|
GrSamplerState::ClampBilerp(), flags);
|
||||||
} else {
|
} else {
|
||||||
SkMatrix invert;
|
SkMatrix invert;
|
||||||
if (fHelper.usesLocalCoords()) {
|
if (fHelper.usesLocalCoords()) {
|
||||||
@ -260,8 +256,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
|
flushInfo.fGeometryProcessor = GrBitmapTextGeoProc::Make(
|
||||||
this->color(), atlas->getProxies(), GrSamplerState::ClampNearest(),
|
this->color(), fAtlas->getProxies(), fAtlas->numActivePages(),
|
||||||
kA8_GrMaskFormat, invert, fHelper.usesLocalCoords());
|
GrSamplerState::ClampNearest(), kA8_GrMaskFormat, invert,
|
||||||
|
fHelper.usesLocalCoords());
|
||||||
}
|
}
|
||||||
|
|
||||||
// allocate vertices
|
// allocate vertices
|
||||||
@ -335,7 +332,7 @@ private:
|
|||||||
// check to see if df path is cached
|
// check to see if df path is cached
|
||||||
ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension));
|
ShapeData::Key key(args.fShape, SkScalarCeilToInt(desiredDimension));
|
||||||
shapeData = fShapeCache->find(key);
|
shapeData = fShapeCache->find(key);
|
||||||
if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
|
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
|
||||||
// Remove the stale cache entry
|
// Remove the stale cache entry
|
||||||
if (shapeData) {
|
if (shapeData) {
|
||||||
fShapeCache->remove(shapeData->fKey);
|
fShapeCache->remove(shapeData->fKey);
|
||||||
@ -347,7 +344,7 @@ private:
|
|||||||
shapeData = new ShapeData;
|
shapeData = new ShapeData;
|
||||||
if (!this->addDFPathToAtlas(target,
|
if (!this->addDFPathToAtlas(target,
|
||||||
&flushInfo,
|
&flushInfo,
|
||||||
atlas,
|
fAtlas,
|
||||||
shapeData,
|
shapeData,
|
||||||
args.fShape,
|
args.fShape,
|
||||||
SkScalarCeilToInt(desiredDimension),
|
SkScalarCeilToInt(desiredDimension),
|
||||||
@ -360,7 +357,7 @@ private:
|
|||||||
// check to see if bitmap path is cached
|
// check to see if bitmap path is cached
|
||||||
ShapeData::Key key(args.fShape, args.fViewMatrix);
|
ShapeData::Key key(args.fShape, args.fViewMatrix);
|
||||||
shapeData = fShapeCache->find(key);
|
shapeData = fShapeCache->find(key);
|
||||||
if (nullptr == shapeData || !atlas->hasID(shapeData->fID)) {
|
if (nullptr == shapeData || !fAtlas->hasID(shapeData->fID)) {
|
||||||
// Remove the stale cache entry
|
// Remove the stale cache entry
|
||||||
if (shapeData) {
|
if (shapeData) {
|
||||||
fShapeCache->remove(shapeData->fKey);
|
fShapeCache->remove(shapeData->fKey);
|
||||||
@ -371,7 +368,7 @@ private:
|
|||||||
shapeData = new ShapeData;
|
shapeData = new ShapeData;
|
||||||
if (!this->addBMPathToAtlas(target,
|
if (!this->addBMPathToAtlas(target,
|
||||||
&flushInfo,
|
&flushInfo,
|
||||||
atlas,
|
fAtlas,
|
||||||
shapeData,
|
shapeData,
|
||||||
args.fShape,
|
args.fShape,
|
||||||
args.fViewMatrix)) {
|
args.fViewMatrix)) {
|
||||||
@ -382,9 +379,9 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto uploadTarget = target->deferredUploadTarget();
|
auto uploadTarget = target->deferredUploadTarget();
|
||||||
atlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
|
fAtlas->setLastUseToken(shapeData->fID, uploadTarget->tokenTracker()->nextDrawToken());
|
||||||
|
|
||||||
this->writePathVertices(atlas,
|
this->writePathVertices(fAtlas,
|
||||||
offset,
|
offset,
|
||||||
args.fColor,
|
args.fColor,
|
||||||
vertexStride,
|
vertexStride,
|
||||||
@ -400,6 +397,8 @@ 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
|
||||||
@ -488,10 +487,11 @@ private:
|
|||||||
SkIPoint16 atlasLocation;
|
SkIPoint16 atlasLocation;
|
||||||
GrDrawOpAtlas::AtlasID id;
|
GrDrawOpAtlas::AtlasID id;
|
||||||
auto uploadTarget = target->deferredUploadTarget();
|
auto uploadTarget = target->deferredUploadTarget();
|
||||||
if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(), &atlasLocation)) {
|
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
|
||||||
|
dfStorage.get(), &atlasLocation)) {
|
||||||
this->flush(target, flushInfo);
|
this->flush(target, flushInfo);
|
||||||
if (!atlas->addToAtlas(&id, uploadTarget, width, height, dfStorage.get(),
|
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, width, height,
|
||||||
&atlasLocation)) {
|
dfStorage.get(), &atlasLocation)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -530,6 +530,8 @@ 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;
|
||||||
@ -590,11 +592,11 @@ private:
|
|||||||
SkIPoint16 atlasLocation;
|
SkIPoint16 atlasLocation;
|
||||||
GrDrawOpAtlas::AtlasID id;
|
GrDrawOpAtlas::AtlasID id;
|
||||||
auto uploadTarget = target->deferredUploadTarget();
|
auto uploadTarget = target->deferredUploadTarget();
|
||||||
if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
|
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
|
||||||
&atlasLocation)) {
|
dst.addr(), &atlasLocation)) {
|
||||||
this->flush(target, flushInfo);
|
this->flush(target, flushInfo);
|
||||||
if (!atlas->addToAtlas(&id, uploadTarget, dst.width(), dst.height(), dst.addr(),
|
if (!atlas->addToAtlas(resourceProvider, &id, uploadTarget, dst.width(), dst.height(),
|
||||||
&atlasLocation)) {
|
dst.addr(), &atlasLocation)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -696,15 +698,15 @@ 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->pageCount()) {
|
if (gp->numTextureSamplers() != (int)fAtlas->numActivePages()) {
|
||||||
// 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) {
|
||||||
reinterpret_cast<GrDistanceFieldPathGeoProc*>(gp)->addNewProxies(
|
reinterpret_cast<GrDistanceFieldPathGeoProc*>(gp)->addNewProxies(
|
||||||
fAtlas->getProxies(), GrSamplerState::ClampBilerp());
|
fAtlas->getProxies(), fAtlas->numActivePages(), GrSamplerState::ClampBilerp());
|
||||||
} else {
|
} else {
|
||||||
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(
|
reinterpret_cast<GrBitmapTextGeoProc*>(gp)->addNewProxies(
|
||||||
fAtlas->getProxies(), GrSamplerState::ClampNearest());
|
fAtlas->getProxies(), fAtlas->numActivePages(), GrSamplerState::ClampNearest());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -788,7 +790,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,
|
fAtlas = GrDrawOpAtlas::Make(args.fContext->contextPriv().proxyProvider(),
|
||||||
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,
|
||||||
@ -858,7 +860,8 @@ 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, kAlpha_8_GrPixelConfig,
|
gTestStruct.fAtlas = GrDrawOpAtlas::Make(context->contextPriv().proxyProvider(),
|
||||||
|
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,
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#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"
|
||||||
@ -19,14 +20,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, *fContext->caps());
|
GrPixelConfig config = MaskFormatToPixelConfig(format, *fProxyProvider->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(fContext, config, width, height, numPlotsX, numPlotsY,
|
fAtlases[index] = GrDrawOpAtlas::Make(fProxyProvider, config, width, height,
|
||||||
fAllowMultitexturing,
|
numPlotsX, numPlotsY, fAllowMultitexturing,
|
||||||
&GrAtlasGlyphCache::HandleEviction, (void*)this);
|
&GrAtlasGlyphCache::HandleEviction, (void*)this);
|
||||||
if (!fAtlases[index]) {
|
if (!fAtlases[index]) {
|
||||||
return false;
|
return false;
|
||||||
@ -35,11 +36,13 @@ bool GrAtlasGlyphCache::initAtlas(GrMaskFormat format) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
GrAtlasGlyphCache::GrAtlasGlyphCache(GrContext* context, float maxTextureBytes,
|
GrAtlasGlyphCache::GrAtlasGlyphCache(GrProxyProvider* proxyProvider, float maxTextureBytes,
|
||||||
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
|
GrDrawOpAtlas::AllowMultitexturing allowMultitexturing)
|
||||||
: fContext(context), fAllowMultitexturing(allowMultitexturing), fPreserveStrike(nullptr) {
|
: fProxyProvider(proxyProvider)
|
||||||
|
, fAllowMultitexturing(allowMultitexturing)
|
||||||
|
, fPreserveStrike(nullptr) {
|
||||||
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
|
// Calculate RGBA size. Must be between 512 x 256 and MaxTextureSize x MaxTextureSize / 2
|
||||||
int log2MaxTextureSize = SkPrevLog2(context->caps()->maxTextureSize());
|
int log2MaxTextureSize = SkPrevLog2(fProxyProvider->caps()->maxTextureSize());
|
||||||
int log2MaxDim = 9;
|
int log2MaxDim = 9;
|
||||||
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
|
for (; log2MaxDim <= log2MaxTextureSize; ++log2MaxDim) {
|
||||||
int maxDim = 1 << log2MaxDim;
|
int maxDim = 1 << log2MaxDim;
|
||||||
@ -174,12 +177,12 @@ static bool save_pixels(GrContext* context, GrSurfaceProxy* sProxy, const char*
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GrAtlasGlyphCache::dump() const {
|
void GrAtlasGlyphCache::dump(GrContext* context) 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]->pageCount(); ++pageIdx) {
|
for (uint32_t pageIdx = 0; pageIdx < fAtlases[i]->numActivePages(); ++pageIdx) {
|
||||||
SkASSERT(proxies[pageIdx]);
|
SkASSERT(proxies[pageIdx]);
|
||||||
SkString filename;
|
SkString filename;
|
||||||
#ifdef SK_BUILD_FOR_ANDROID
|
#ifdef SK_BUILD_FOR_ANDROID
|
||||||
@ -188,7 +191,7 @@ void GrAtlasGlyphCache::dump() 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(fContext, proxies[pageIdx].get(), filename.c_str());
|
save_pixels(context, proxies[pageIdx].get(), filename.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -445,7 +448,8 @@ void GrAtlasTextStrike::removeID(GrDrawOpAtlas::AtlasID id) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
|
bool GrAtlasTextStrike::addGlyphToAtlas(GrResourceProvider* resourceProvider,
|
||||||
|
GrDeferredUploadTarget* target,
|
||||||
GrAtlasGlyphCache* atlasGlyphCache,
|
GrAtlasGlyphCache* atlasGlyphCache,
|
||||||
GrGlyph* glyph,
|
GrGlyph* glyph,
|
||||||
SkGlyphCache* cache,
|
SkGlyphCache* cache,
|
||||||
@ -473,7 +477,8 @@ bool GrAtlasTextStrike::addGlyphToAtlas(GrDeferredUploadTarget* target,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool success = atlasGlyphCache->addToAtlas(this, &glyph->fID, target, expectedMaskFormat,
|
bool success = atlasGlyphCache->addToAtlas(resourceProvider, this, &glyph->fID, target,
|
||||||
|
expectedMaskFormat,
|
||||||
glyph->width(), glyph->height(),
|
glyph->width(), glyph->height(),
|
||||||
storage.get(), &glyph->fAtlasLocation);
|
storage.get(), &glyph->fAtlasLocation);
|
||||||
if (success) {
|
if (success) {
|
||||||
|
@ -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(GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*, SkGlyphCache*,
|
bool addGlyphToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, GrAtlasGlyphCache*, GrGlyph*,
|
||||||
GrMaskFormat expectedMaskFormat);
|
SkGlyphCache*, GrMaskFormat expectedMaskFormat);
|
||||||
|
|
||||||
// testing
|
// testing
|
||||||
int countGlyphs() const { return fCache.count(); }
|
int countGlyphs() const { return fCache.count(); }
|
||||||
@ -109,7 +109,8 @@ private:
|
|||||||
*/
|
*/
|
||||||
class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
|
class GrAtlasGlyphCache : public GrOnFlushCallbackObject {
|
||||||
public:
|
public:
|
||||||
GrAtlasGlyphCache(GrContext*, float maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing);
|
GrAtlasGlyphCache(GrProxyProvider*, float maxTextureBytes,
|
||||||
|
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.
|
||||||
@ -132,7 +133,7 @@ public:
|
|||||||
SkASSERT(numProxies);
|
SkASSERT(numProxies);
|
||||||
|
|
||||||
if (this->initAtlas(format)) {
|
if (this->initAtlas(format)) {
|
||||||
*numProxies = this->getAtlas(format)->pageCount();
|
*numProxies = this->getAtlas(format)->numActivePages();
|
||||||
return this->getAtlas(format)->getProxies();
|
return this->getAtlas(format)->getProxies();
|
||||||
}
|
}
|
||||||
*numProxies = 0;
|
*numProxies = 0;
|
||||||
@ -165,11 +166,13 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// add to texture atlas that matches this format
|
// add to texture atlas that matches this format
|
||||||
bool addToAtlas(GrAtlasTextStrike* strike, GrDrawOpAtlas::AtlasID* id,
|
bool addToAtlas(GrResourceProvider* resourceProvider, GrAtlasTextStrike* strike,
|
||||||
|
GrDrawOpAtlas::AtlasID* id,
|
||||||
GrDeferredUploadTarget* target, GrMaskFormat format, int width, int height,
|
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(id, target, width, height, image, loc);
|
return this->getAtlas(format)->addToAtlas(resourceProvider, id, target,
|
||||||
|
width, height, image, loc);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Some clients may wish to verify the integrity of the texture backing store of the
|
// Some clients may wish to verify the integrity of the texture backing store of the
|
||||||
@ -190,8 +193,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void postFlush(GrDeferredUploadToken startTokenForNextFlush,
|
void postFlush(GrDeferredUploadToken startTokenForNextFlush, const uint32_t*, int) override {
|
||||||
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);
|
||||||
@ -206,13 +208,11 @@ public:
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// Functions intended debug only
|
// Functions intended debug only
|
||||||
#ifdef SK_DEBUG
|
#ifdef SK_DEBUG
|
||||||
void dump() const;
|
void dump(GrContext*) 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>;
|
||||||
GrContext* fContext;
|
GrProxyProvider* fProxyProvider;
|
||||||
StrikeHash fCache;
|
StrikeHash fCache;
|
||||||
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
|
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
|
||||||
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
|
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
|
* SkAutoGlyphCache is reused then it can save the cost of multiple detach/attach operations of
|
||||||
* SkGlyphCache.
|
* SkGlyphCache.
|
||||||
*/
|
*/
|
||||||
VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx, const SkMatrix& viewMatrix,
|
VertexRegenerator(GrResourceProvider*, GrAtlasTextBlob*, int runIdx, int subRunIdx,
|
||||||
SkScalar x, SkScalar y, GrColor color, GrDeferredUploadTarget*,
|
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
||||||
GrAtlasGlyphCache*, SkAutoGlyphCache*);
|
GrDeferredUploadTarget*, GrAtlasGlyphCache*, SkAutoGlyphCache*);
|
||||||
|
|
||||||
struct Result {
|
struct Result {
|
||||||
/**
|
/**
|
||||||
@ -589,6 +589,7 @@ 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;
|
||||||
|
@ -190,11 +190,13 @@ inline void regen_vertices(char* vertex, const GrGlyph* glyph, size_t vertexStri
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Regenerator::VertexRegenerator(GrAtlasTextBlob* blob, int runIdx, int subRunIdx,
|
Regenerator::VertexRegenerator(GrResourceProvider* resourceProvider, GrAtlasTextBlob* blob,
|
||||||
|
int runIdx, int subRunIdx,
|
||||||
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
const SkMatrix& viewMatrix, SkScalar x, SkScalar y, GrColor color,
|
||||||
GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
|
GrDeferredUploadTarget* uploadTarget, GrAtlasGlyphCache* glyphCache,
|
||||||
SkAutoGlyphCache* lazyCache)
|
SkAutoGlyphCache* lazyCache)
|
||||||
: fViewMatrix(viewMatrix)
|
: fResourceProvider(resourceProvider)
|
||||||
|
, fViewMatrix(viewMatrix)
|
||||||
, fBlob(blob)
|
, fBlob(blob)
|
||||||
, fUploadTarget(uploadTarget)
|
, fUploadTarget(uploadTarget)
|
||||||
, fGlyphCache(glyphCache)
|
, fGlyphCache(glyphCache)
|
||||||
@ -274,8 +276,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(fUploadTarget, fGlyphCache, glyph, fLazyCache->get(),
|
!strike->addGlyphToAtlas(fResourceProvider, fUploadTarget, fGlyphCache, glyph,
|
||||||
fSubRun->maskFormat())) {
|
fLazyCache->get(), fSubRun->maskFormat())) {
|
||||||
fBrokenRun = glyphIdx > 0;
|
fBrokenRun = glyphIdx > 0;
|
||||||
result.fFinished = false;
|
result.fFinished = false;
|
||||||
return result;
|
return result;
|
||||||
|
132
tests/DrawOpAtlasTest.cpp
Normal file
132
tests/DrawOpAtlasTest.cpp
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
/*
|
||||||
|
* 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