35#if defined(DUMP_ATLAS_DATA)
42void GrDrawOpAtlas::validate(
const AtlasLocator& atlasLocator)
const {
44 int numPlotsX = fTextureWidth / fPlotWidth;
45 int numPlotsY = fTextureHeight / fPlotHeight;
48 auto topLeft = atlasLocator.
topLeft();
49 int plotX = topLeft.
x() / fPlotWidth;
50 int plotY = topLeft.y() / fPlotHeight;
51 SkASSERT(plotIndex == (numPlotsY - plotY - 1) * numPlotsX + (numPlotsX - plotX - 1));
64 for (uint32_t i = 0; i < fNumActivePages; ++i) {
66 SkASSERT(fViews[i].proxy() && fViews[i].proxy()->isInstantiated());
73 int height,
int plotWidth,
int plotHeight,
77 std::string_view label) {
85 allowMultitexturing, label));
86 if (!atlas->createPages(proxyProvider, generationCounter) || !atlas->getViews()[0].proxy()) {
90 if (evictor !=
nullptr) {
91 atlas->fEvictionCallbacks.emplace_back(evictor);
101 AllowMultitexturing allowMultitexturing, std::string_view label)
104 , fBytesPerPixel(bpp)
105 , fTextureWidth(
width)
107 , fPlotWidth(plotWidth)
108 , fPlotHeight(plotHeight)
110 , fGenerationCounter(generationCounter)
111 , fAtlasGeneration(fGenerationCounter->
next())
113 , fFlushesSinceLastUse(0)
114 , fMaxPages(AllowMultitexturing::
kYes == allowMultitexturing ?
116 , fNumActivePages(0) {
117 int numPlotsX =
width/plotWidth;
118 int numPlotsY =
height/plotHeight;
120 SkASSERT(fPlotWidth * numPlotsX == fTextureWidth);
121 SkASSERT(fPlotHeight * numPlotsY == fTextureHeight);
123 fNumPlots = numPlotsX * numPlotsY;
126inline void GrDrawOpAtlas::processEviction(
PlotLocator plotLocator) {
128 evictor->evict(plotLocator);
131 fAtlasGeneration = fGenerationCounter->
next();
142 std::tie(dataPtr, rect) =
plot->prepareForUpload();
148 fBytesPerPixel*fPlotWidth);
153 uint32_t pageIdx =
plot->pageIndex();
154 if (pageIdx >= fNumActivePages) {
157 this->makeMRU(
plot, pageIdx);
162 if (
plot->lastUploadToken() <
target->tokenTracker()->nextFlushToken()) {
171 this->uploadPlotToTexture(writePixels, proxy, plotsp.get());
173 plot->setLastUploadToken(lastUploadToken);
182 SkASSERT(fViews[pageIdx].proxy() && fViews[pageIdx].proxy()->isInstantiated());
185 PlotList::Iter plotIter;
186 plotIter.init(fPages[pageIdx].fPlotList, PlotList::Iter::kHead_IterStart);
193 return this->updatePlot(
target, atlasLocator,
plot);
220 for (
unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
231 if (fNumActivePages == this->
maxPages()) {
232 for (
unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
233 Plot*
plot = fPages[pageIdx].fPlotList.tail();
235 if (
plot->lastUseToken() <
target->tokenTracker()->nextFlushToken()) {
236 this->processEvictionAndResetRects(
plot);
241 if (!this->updatePlot(
target, atlasLocator,
plot)) {
249 if (!this->activateNewPage(resourceProvider)) {
262 if (!fNumActivePages) {
269 for (
int pageIdx = ((
int)fNumActivePages)-1; pageIdx >= 0; --pageIdx) {
270 Plot* currentPlot = fPages[pageIdx].fPlotList.tail();
286 this->processEviction(
plot->plotLocator());
287 int pageIdx =
plot->pageIndex();
288 fPages[pageIdx].fPlotList.remove(
plot);
290 newPlot =
plot->clone();
292 fPages[pageIdx].fPlotList.addToHead(newPlot.
get());
308 this->uploadPlotToTexture(writePixels, proxy, plotsp.
get());
310 newPlot->setLastUploadToken(lastUploadToken);
319 if (fNumActivePages < 1) {
320 fPrevFlushToken = startTokenForNextFlush;
325 PlotList::Iter plotIter;
326 bool atlasUsedThisFlush =
false;
327 for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
328 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
329 while (
Plot*
plot = plotIter.get()) {
331 if (
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
332 plot->resetFlushesSinceLastUsed();
333 atlasUsedThisFlush =
true;
340 if (atlasUsedThisFlush) {
341 fFlushesSinceLastUse = 0;
343 ++fFlushesSinceLastUse;
352 uint32_t lastPageIndex = fNumActivePages - 1;
356 for (uint32_t pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex) {
361 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
362 while (
Plot*
plot = plotIter.get()) {
367 if (!
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
368 plot->incFlushesSinceLastUsed();
392 plotIter.init(fPages[lastPageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
393 unsigned int usedPlots = 0;
395 SkDebugf(
"page %u: ", lastPageIndex);
398 while (
Plot*
plot = plotIter.get()) {
400 if (!
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
401 plot->incFlushesSinceLastUsed();
413 this->processEvictionAndResetRects(
plot);
426 if (!availablePlots.
empty() && usedPlots && usedPlots <= fNumPlots / 4) {
427 plotIter.init(fPages[lastPageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
428 while (
Plot*
plot = plotIter.get()) {
434 if (!availablePlots.
empty()) {
435 this->processEvictionAndResetRects(
plot);
436 this->processEvictionAndResetRects(availablePlots.
back());
440 if (!usedPlots || availablePlots.
empty()) {
451 SkDebugf(
"delete %u\n", fNumActivePages - 1);
454 this->deactivateLastPage();
455 fFlushesSinceLastUse = 0;
459 fPrevFlushToken = startTokenForNextFlush;
462bool GrDrawOpAtlas::createPages(
466 SkISize dims = {fTextureWidth, fTextureHeight};
468 int numPlotsX = fTextureWidth/fPlotWidth;
469 int numPlotsY = fTextureHeight/fPlotHeight;
473 for (uint32_t i = 0; i < this->
maxPages(); ++i) {
482 skgpu::Mipmapped::kNo,
495 fPages[i].fPlotArray = std::make_unique<sk_sp<Plot>[]>(numPlotsX * numPlotsY);
497 sk_sp<Plot>* currPlot = fPages[i].fPlotArray.get();
498 for (
int y = numPlotsY - 1, r = 0;
y >= 0; --
y, ++r) {
499 for (
int x = numPlotsX - 1, c = 0;
x >= 0; --
x, ++c) {
500 uint32_t plotIndex = r * numPlotsX + c;
501 currPlot->reset(
new Plot(
502 i, plotIndex, generationCounter,
x,
y, fPlotWidth, fPlotHeight, fColorType,
506 fPages[i].fPlotList.addToHead(currPlot->get());
519 if (!fViews[fNumActivePages].proxy()->
instantiate(resourceProvider)) {
524 SkDebugf(
"activated page#: %u\n", fNumActivePages);
531inline void GrDrawOpAtlas::deactivateLastPage() {
534 uint32_t lastPageIndex = fNumActivePages - 1;
536 int numPlotsX = fTextureWidth/fPlotWidth;
537 int numPlotsY = fTextureHeight/fPlotHeight;
539 fPages[lastPageIndex].fPlotList.reset();
540 for (
int r = 0; r < numPlotsY; ++r) {
541 for (
int c = 0; c < numPlotsX; ++c) {
542 uint32_t plotIndex = r * numPlotsX + c;
544 Plot* currPlot = fPages[lastPageIndex].fPlotArray[plotIndex].get();
550 fPages[lastPageIndex].fPlotList.addToHead(currPlot);
560 static const SkISize kARGBDimensions[] = {
572 int index = maxBytes > 0
573 ? SkTPin<int>(
SkPrevLog2(maxBytes), 0, std::size(kARGBDimensions) - 1)
578 fARGBDimensions.
set(std::min<int>(kARGBDimensions[index].
width(), maxTextureSize),
579 std::min<int>(kARGBDimensions[index].
height(), maxTextureSize));
580 fMaxTextureSize = std::min<int>(maxTextureSize, kMaxAtlasDim);
584 if (MaskFormat::kA8 ==
type) {
586 return { std::min<int>(2 * fARGBDimensions.
width(), fMaxTextureSize),
587 std::min<int>(2 * fARGBDimensions.
height(), fMaxTextureSize) };
589 return fARGBDimensions;
594 if (MaskFormat::kA8 ==
type) {
605 return { plotWidth, plotHeight };
size_t GrBackendFormatBytesPerPixel(const GrBackendFormat &format)
std::function< bool(GrTextureProxy *, SkIRect, GrColorType srcColorType, const void *, size_t rowBytes)> GrDeferredTextureUploadWritePixelsFn
static constexpr auto kPlotRecentlyUsedCount
static constexpr auto kAtlasRecentlyUsedCount
static const constexpr bool kDumpAtlasData
static constexpr bool GrColorTypeIsAlphaOnly(GrColorType ct)
static constexpr GrColorType SkColorTypeToGrColorType(SkColorType ct)
@ kTopLeft_GrSurfaceOrigin
static float next(float f)
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static SkColorType colorType(AImageDecoder *decoder, const AImageDecoderHeaderInfo *headerInfo)
static int SkPrevLog2(uint32_t value)
constexpr bool SkIsPow2(T value)
@ kYes
Do pre-clip the geometry before applying the (perspective) matrix.
skgpu::Swizzle getReadSwizzle(const GrBackendFormat &format, GrColorType colorType) const
SkISize atlasDimensions(skgpu::MaskFormat type) const
SkISize plotDimensions(skgpu::MaskFormat type) const
void compact(skgpu::AtlasToken startTokenForNextFlush)
static std::unique_ptr< GrDrawOpAtlas > Make(GrProxyProvider *proxyProvider, const GrBackendFormat &format, SkColorType ct, size_t bpp, int width, int height, int plotWidth, int plotHeight, skgpu::AtlasGenerationCounter *generationCounter, AllowMultitexturing allowMultitexturing, skgpu::PlotEvictionCallback *evictor, std::string_view label)
ErrorCode addToAtlas(GrResourceProvider *, GrDeferredUploadTarget *, int width, int height, const void *image, skgpu::AtlasLocator *)
void instantiate(GrOnFlushResourceProvider *)
uint32_t maxPages() const
sk_sp< GrTextureProxy > createProxy(const GrBackendFormat &, SkISize dimensions, GrRenderable, int renderTargetSampleCnt, skgpu::Mipmapped, SkBackingFit, skgpu::Budgeted, GrProtected, std::string_view label, GrInternalSurfaceFlags=GrInternalSurfaceFlags::kNone, UseAllocator useAllocator=UseAllocator::kYes)
const GrCaps * caps() const
GrTextureProxy * asTextureProxy() const
GrSurfaceProxy * proxy() const
GrTexture * peekTexture() const
bool isInstantiated() const
uint32_t plotIndex() const
void updatePlotLocator(PlotLocator p)
static AtlasToken InvalidToken()
static constexpr int kMaxPlots
skgpu::AtlasToken lastUseToken() const
void resetFlushesSinceLastUsed()
static constexpr Swizzle Concat(const Swizzle &a, const Swizzle &b)
uint32_t uint32_t * format
sk_sp< SkBlender > blender SkRect rect
SkTInternalLList< Plot > PlotList
static void plot(SkCanvas *canvas, const char *fn, float xMin, float xMax, float yMin, float yMax, const char *label=nullptr, bool requireES3=false)
constexpr int32_t x() const
constexpr int32_t width() const
void set(int32_t w, int32_t h)
constexpr int32_t height() const
#define TRACE_EVENT0(category_group, name)