32#if defined(DUMP_ATLAS_DATA)
39void DrawAtlas::validate(
const AtlasLocator& atlasLocator)
const {
41 int numPlotsX = fTextureWidth / fPlotWidth;
42 int numPlotsY = fTextureHeight / fPlotHeight;
45 auto topLeft = atlasLocator.
topLeft();
46 int plotX = topLeft.
x() / fPlotWidth;
47 int plotY = topLeft.y() / fPlotHeight;
48 SkASSERT(plotIndex == (numPlotsY - plotY - 1) * numPlotsX + (numPlotsX - plotX - 1));
53 int height,
int plotWidth,
int plotHeight,
58 std::string_view label) {
60 plotWidth, plotHeight, generationCounter,
61 allowMultitexturing, useStorageTextures, label));
63 if (evictor !=
nullptr) {
64 atlas->fEvictionCallbacks.emplace_back(evictor);
71 static std::atomic<uint32_t> nextID{1};
74 id = nextID.fetch_add(1, std::memory_order_relaxed);
80 AllowMultitexturing allowMultitexturing,
81 UseStorageTextures useStorageTextures,
82 std::string_view label)
85 , fTextureWidth(
width)
87 , fPlotWidth(plotWidth)
88 , fPlotHeight(plotHeight)
89 , fUseStorageTextures(useStorageTextures)
92 , fGenerationCounter(generationCounter)
93 , fAtlasGeneration(fGenerationCounter->
next())
95 , fFlushesSinceLastUse(0)
96 , fMaxPages(allowMultitexturing == AllowMultitexturing::
kYes ?
98 , fNumActivePages(0) {
99 int numPlotsX =
width/plotWidth;
100 int numPlotsY =
height/plotHeight;
102 SkASSERTF(fPlotWidth * numPlotsX == fTextureWidth,
103 "Invalid DrawAtlas. Plot width: %d, texture width %d", fPlotWidth, fTextureWidth);
104 SkASSERTF(fPlotHeight * numPlotsY == fTextureHeight,
105 "Invalid DrawAtlas. Plot height: %d, texture height %d", fPlotHeight, fTextureHeight);
107 fNumPlots = numPlotsX * numPlotsY;
109 this->createPages(generationCounter);
112inline void DrawAtlas::processEviction(
PlotLocator plotLocator) {
113 for (PlotEvictionCallback* evictor : fEvictionCallbacks) {
114 evictor->evict(plotLocator);
117 fAtlasGeneration = fGenerationCounter->next();
121 int pageIdx =
plot->pageIndex();
122 this->makeMRU(
plot, pageIdx);
130bool DrawAtlas::addRectToPage(
unsigned int pageIdx,
int width,
int height,
135 PlotList::Iter plotIter;
136 plotIter.init(fPages[pageIdx].fPlotList, PlotList::Iter::kHead_IterStart);
140 this->updatePlot(
plot, atlasLocator);
150 for (uint32_t pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
151 PlotList::Iter plotIter;
152 plotIter.init(fPages[pageIdx].fPlotList, PlotList::Iter::kHead_IterStart);
154 if (
plot->needsUpload()) {
160 std::tie(dataPtr, dstRect) =
plot->prepareForUpload();
165 std::vector<MipLevel> levels;
166 levels.push_back({dataPtr, fBytesPerPixel*fPlotWidth});
201 if (fNumActivePages == 0) {
203 this->activateNewPage(recorder);
208 return ErrorCode::kSucceeded;
214 for (
unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
215 if (this->addRectToPage(pageIdx,
width,
height, atlasLocator)) {
216 return ErrorCode::kSucceeded;
225 if (fNumActivePages == this->maxPages()) {
226 for (
unsigned int pageIdx = 0; pageIdx < fNumActivePages; ++pageIdx) {
227 Plot*
plot = fPages[pageIdx].fPlotList.tail();
230 this->processEvictionAndResetRects(
plot);
233 this->updatePlot(
plot, atlasLocator);
234 return ErrorCode::kSucceeded;
239 if (!this->activateNewPage(recorder)) {
243 if (this->addRectToPage(fNumActivePages-1,
width,
height, atlasLocator)) {
244 return ErrorCode::kSucceeded;
252 if (!fNumActivePages) {
260 return ErrorCode::kTryAgain;
267 if (ec == ErrorCode::kSucceeded) {
268 Plot*
plot = this->findPlot(*atlasLocator);
269 plot->copySubImage(*atlasLocator,
image);
276 Plot*
plot = this->findPlot(locator);
277 return plot->prepForRender(locator, pixmap);
281 if (fNumActivePages < 1) {
282 fPrevFlushToken = startTokenForNextFlush;
287 PlotList::Iter plotIter;
288 bool atlasUsedThisFlush =
false;
289 for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
290 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
291 while (
Plot*
plot = plotIter.get()) {
293 if (
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
294 plot->resetFlushesSinceLastUsed();
295 atlasUsedThisFlush =
true;
302 if (atlasUsedThisFlush) {
303 fFlushesSinceLastUse = 0;
305 ++fFlushesSinceLastUse;
314 uint32_t lastPageIndex = fNumActivePages - 1;
318 for (uint32_t pageIndex = 0; pageIndex < lastPageIndex; ++pageIndex) {
323 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
324 while (
Plot*
plot = plotIter.get()) {
329 if (!
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
330 plot->incFlushesSinceLastUsed();
354 plotIter.init(fPages[lastPageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
355 unsigned int usedPlots = 0;
357 SkDebugf(
"page %u: ", lastPageIndex);
359 while (
Plot*
plot = plotIter.get()) {
361 if (!
plot->lastUseToken().inInterval(fPrevFlushToken, startTokenForNextFlush)) {
362 plot->incFlushesSinceLastUsed();
374 this->processEvictionAndResetRects(
plot);
387 if (availablePlots.
size() && usedPlots && usedPlots <= fNumPlots / 4) {
388 plotIter.init(fPages[lastPageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
389 while (
Plot*
plot = plotIter.get()) {
395 if (availablePlots.
size() > 0) {
396 this->processEvictionAndResetRects(
plot);
397 this->processEvictionAndResetRects(availablePlots.
back());
401 if (!usedPlots || !availablePlots.
size()) {
412 SkDebugf(
"delete %u\n", fNumActivePages-1);
415 this->deactivateLastPage();
416 fFlushesSinceLastUse = 0;
420 fPrevFlushToken = startTokenForNextFlush;
426 int numPlotsX = fTextureWidth/fPlotWidth;
427 int numPlotsY = fTextureHeight/fPlotHeight;
429 for (uint32_t
i = 0;
i < this->maxPages(); ++
i) {
431 fProxies[
i] =
nullptr;
434 fPages[
i].fPlotArray = std::make_unique<sk_sp<Plot>[]>(numPlotsX * numPlotsY);
437 for (
int y = numPlotsY - 1, r = 0;
y >= 0; --
y, ++r) {
438 for (
int x = numPlotsX - 1, c = 0;
x >= 0; --
x, ++c) {
439 uint32_t plotIndex = r * numPlotsX + c;
440 currPlot->reset(
new Plot(
441 i, plotIndex, generationCounter,
x,
y, fPlotWidth, fPlotHeight,
fColorType,
445 fPages[
i].fPlotList.addToHead(currPlot->get());
454bool DrawAtlas::activateNewPage(
Recorder* recorder) {
455 SkASSERT(fNumActivePages < this->maxPages());
456 SkASSERT(!fProxies[fNumActivePages]);
458 const Caps* caps = recorder->
priv().
caps();
459 auto textureInfo = fUseStorageTextures == UseStorageTextures::kYes
461 : caps->getDefaultSampledTextureInfo(
fColorType,
467 {fTextureWidth, fTextureHeight},
471 if (!fProxies[fNumActivePages]) {
476 SkDebugf(
"activated page#: %u\n", fNumActivePages);
483inline void DrawAtlas::deactivateLastPage() {
486 uint32_t lastPageIndex = fNumActivePages - 1;
488 int numPlotsX = fTextureWidth/fPlotWidth;
489 int numPlotsY = fTextureHeight/fPlotHeight;
491 fPages[lastPageIndex].fPlotList.reset();
492 for (
int r = 0; r < numPlotsY; ++r) {
493 for (
int c = 0; c < numPlotsX; ++c) {
494 uint32_t plotIndex = r * numPlotsX + c;
496 Plot* currPlot = fPages[lastPageIndex].fPlotArray[plotIndex].get();
502 fPages[lastPageIndex].fPlotList.addToHead(currPlot);
507 fProxies[lastPageIndex].reset();
511void DrawAtlas::markUsedPlotsAsFull() {
512 PlotList::Iter plotIter;
513 for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
514 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
515 while (
Plot*
plot = plotIter.get()) {
516 plot->markFullIfUsed();
522void DrawAtlas::evictAllPlots() {
523 PlotList::Iter plotIter;
524 for (uint32_t pageIndex = 0; pageIndex < fNumActivePages; ++pageIndex) {
525 plotIter.init(fPages[pageIndex].fPlotList, PlotList::Iter::kHead_IterStart);
526 while (
Plot*
plot = plotIter.get()) {
527 this->processEvictionAndResetRects(
plot);
533DrawAtlasConfig::DrawAtlasConfig(
int maxTextureSize,
size_t maxBytes) {
534 static const SkISize kARGBDimensions[] = {
546 int index = maxBytes > 0
552 fARGBDimensions.set(std::min<int>(kARGBDimensions[index].
width(), maxTextureSize),
553 std::min<int>(kARGBDimensions[index].
height(), maxTextureSize));
554 fMaxTextureSize = std::min<int>(maxTextureSize, kMaxAtlasDim);
560 return { std::min<int>(2 * fARGBDimensions.width(), fMaxTextureSize),
561 std::min<int>(2 * fARGBDimensions.height(), fMaxTextureSize) };
563 return fARGBDimensions;
569 SkISize atlasDimensions = this->atlasDimensions(
type);
576 int plotWidth = atlasDimensions.
width() >= 2048 ? 512 : 256;
577 int plotHeight = atlasDimensions.
height() >= 2048 ? 512 : 256;
579 return { plotWidth, plotHeight };
static constexpr auto kPlotRecentlyUsedCount
static constexpr auto kAtlasRecentlyUsedCount
static const constexpr bool kDumpAtlasData
static float next(float f)
@ kUnknown_SkAlphaType
uninitialized
#define SkASSERTF(cond, fmt,...)
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.
sk_sp< T > sk_ref_sp(T *obj)
SkDEBUGCODE(SK_SPI) SkThreadID SkGetThreadID()
static constexpr uint32_t SK_InvalidGenID
uint32_t plotIndex() const
void updateRect(skgpu::IRect16 rect)
void updatePlotLocator(PlotLocator p)
static AtlasToken InvalidToken()
static constexpr int kMaxPlots
void resetFlushesSinceLastUsed()
AtlasToken nextFlushToken() const
virtual TextureInfo getDefaultStorageTextureInfo(SkColorType) const =0
static std::unique_ptr< DrawAtlas > Make(SkColorType ct, size_t bpp, int width, int height, int plotWidth, int plotHeight, AtlasGenerationCounter *generationCounter, AllowMultitexturing allowMultitexturing, UseStorageTextures useStorageTextures, PlotEvictionCallback *evictor, std::string_view label)
bool recordUpload(Recorder *recorder, sk_sp< TextureProxy > targetProxy, const SkColorInfo &srcColorInfo, const SkColorInfo &dstColorInfo, const std::vector< MipLevel > &levels, const SkIRect &dstRect, std::unique_ptr< ConditionalUploadContext >)
TokenTracker * tokenTracker()
Protected isProtected() const
const Caps * caps() const
ResourceProvider * resourceProvider()
SK_API sk_sp< SkDocument > Make(SkWStream *dst, const SkSerialProcs *=nullptr, std::function< void(const SkPicture *)> onEndPage=nullptr)
sk_sp< const SkImage > atlas
sk_sp< const SkImage > image
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
static const constexpr bool kDumpAtlasData
static uint32_t next_id()
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
constexpr int32_t height() const
static IRect16 MakeXYWH(int16_t x, int16_t y, int16_t w, int16_t h)
#define TRACE_EVENT0(category_group, name)