1*c8dee2aaSAndroid Build Coastguard Worker /* 2*c8dee2aaSAndroid Build Coastguard Worker * Copyright 2015 Google Inc. 3*c8dee2aaSAndroid Build Coastguard Worker * 4*c8dee2aaSAndroid Build Coastguard Worker * Use of this source code is governed by a BSD-style license that can be 5*c8dee2aaSAndroid Build Coastguard Worker * found in the LICENSE file. 6*c8dee2aaSAndroid Build Coastguard Worker */ 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker #ifndef GrDrawOpAtlas_DEFINED 9*c8dee2aaSAndroid Build Coastguard Worker #define GrDrawOpAtlas_DEFINED 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h" 12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h" 13*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h" 14*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkAssert.h" 15*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/base/SkDebug.h" 16*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/AtlasTypes.h" 17*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDeferredUpload.h" 18*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h" 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Worker #include <cstddef> 21*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint> 22*c8dee2aaSAndroid Build Coastguard Worker #include <memory> 23*c8dee2aaSAndroid Build Coastguard Worker #include <string> 24*c8dee2aaSAndroid Build Coastguard Worker #include <string_view> 25*c8dee2aaSAndroid Build Coastguard Worker #include <vector> 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker class GrOnFlushResourceProvider; 28*c8dee2aaSAndroid Build Coastguard Worker class GrProxyProvider; 29*c8dee2aaSAndroid Build Coastguard Worker class GrResourceProvider; 30*c8dee2aaSAndroid Build Coastguard Worker class GrTextureProxy; 31*c8dee2aaSAndroid Build Coastguard Worker enum SkColorType : int; 32*c8dee2aaSAndroid Build Coastguard Worker 33*c8dee2aaSAndroid Build Coastguard Worker /** 34*c8dee2aaSAndroid Build Coastguard Worker * This class manages one or more atlas textures on behalf of GrDrawOps. The draw ops that use the 35*c8dee2aaSAndroid Build Coastguard Worker * atlas perform texture uploads when preparing their draws during flush. The class provides 36*c8dee2aaSAndroid Build Coastguard Worker * facilities for using GrDrawOpUploadToken to detect data hazards. Op's uploads are performed in 37*c8dee2aaSAndroid Build Coastguard Worker * "ASAP" mode until it is impossible to add data without overwriting texels read by draws that 38*c8dee2aaSAndroid Build Coastguard Worker * have not yet executed on the gpu. At that point, the atlas will attempt to allocate a new 39*c8dee2aaSAndroid Build Coastguard Worker * atlas texture (or "page") of the same size, up to a maximum number of textures, and upload 40*c8dee2aaSAndroid Build Coastguard Worker * to that texture. If that's not possible, the uploads are performed "inline" between draws. If a 41*c8dee2aaSAndroid Build Coastguard Worker * single draw would use enough subimage space to overflow the atlas texture then the atlas will 42*c8dee2aaSAndroid Build Coastguard Worker * fail to add a subimage. This gives the op the chance to end the draw and begin a new one. 43*c8dee2aaSAndroid Build Coastguard Worker * Additional uploads will then succeed in inline mode. 44*c8dee2aaSAndroid Build Coastguard Worker * 45*c8dee2aaSAndroid Build Coastguard Worker * When the atlas has multiple pages, new uploads are prioritized to the lower index pages, i.e., 46*c8dee2aaSAndroid Build Coastguard Worker * it will try to upload to page 0 before page 1 or 2. To keep the atlas from continually using 47*c8dee2aaSAndroid Build Coastguard Worker * excess space, periodic garbage collection is needed to shift data from the higher index pages to 48*c8dee2aaSAndroid Build Coastguard Worker * the lower ones, and then eventually remove any pages that are no longer in use. "In use" is 49*c8dee2aaSAndroid Build Coastguard Worker * determined by using the GrDrawUploadToken system: After a flush each subarea of the page 50*c8dee2aaSAndroid Build Coastguard Worker * is checked to see whether it was used in that flush. If less than a quarter of the plots have 51*c8dee2aaSAndroid Build Coastguard Worker * been used recently (within kPlotRecentlyUsedCount iterations) and there are available 52*c8dee2aaSAndroid Build Coastguard Worker * plots in lower index pages, the higher index page will be deactivated, and its glyphs will 53*c8dee2aaSAndroid Build Coastguard Worker * gradually migrate to other pages via the usual upload system. 54*c8dee2aaSAndroid Build Coastguard Worker * 55*c8dee2aaSAndroid Build Coastguard Worker * Garbage collection is initiated by the GrDrawOpAtlas's client via the compact() method. One 56*c8dee2aaSAndroid Build Coastguard Worker * solution is to make the client a subclass of GrOnFlushCallbackObject, register it with the 57*c8dee2aaSAndroid Build Coastguard Worker * GrContext via addOnFlushCallbackObject(), and the client's postFlush() method calls compact() 58*c8dee2aaSAndroid Build Coastguard Worker * and passes in the given GrDrawUploadToken. 59*c8dee2aaSAndroid Build Coastguard Worker */ 60*c8dee2aaSAndroid Build Coastguard Worker class GrDrawOpAtlas { 61*c8dee2aaSAndroid Build Coastguard Worker public: 62*c8dee2aaSAndroid Build Coastguard Worker /** Is the atlas allowed to use more than one texture? */ 63*c8dee2aaSAndroid Build Coastguard Worker enum class AllowMultitexturing : bool { kNo, kYes }; 64*c8dee2aaSAndroid Build Coastguard Worker 65*c8dee2aaSAndroid Build Coastguard Worker /** 66*c8dee2aaSAndroid Build Coastguard Worker * Returns a GrDrawOpAtlas. This function can be called anywhere, but the returned atlas 67*c8dee2aaSAndroid Build Coastguard Worker * should only be used inside of GrMeshDrawOp::onPrepareDraws. 68*c8dee2aaSAndroid Build Coastguard Worker * @param proxyProvider Used to create the atlas's texture proxies. 69*c8dee2aaSAndroid Build Coastguard Worker * @param format Backend format for the atlas's textures. 70*c8dee2aaSAndroid Build Coastguard Worker * Should be compatible with ct. 71*c8dee2aaSAndroid Build Coastguard Worker * @param ct The colorType which this atlas will store. 72*c8dee2aaSAndroid Build Coastguard Worker * @param bpp Size in bytes of each pixel. 73*c8dee2aaSAndroid Build Coastguard Worker * @param width Width in pixels of the atlas. 74*c8dee2aaSAndroid Build Coastguard Worker * @param height Height in pixels of the atlas. 75*c8dee2aaSAndroid Build Coastguard Worker * @param plotWidth The width of each plot. width/plotWidth should be an integer. 76*c8dee2aaSAndroid Build Coastguard Worker * @param plotWidth The height of each plot. height/plotHeight should be an integer. 77*c8dee2aaSAndroid Build Coastguard Worker * @param generationCounter A pointer to the context's generation counter. 78*c8dee2aaSAndroid Build Coastguard Worker * @param allowMultitexturing Can the atlas use more than one texture. 79*c8dee2aaSAndroid Build Coastguard Worker * @param evictor A pointer to an eviction callback class. 80*c8dee2aaSAndroid Build Coastguard Worker * @param label A label for the atlas texture. 81*c8dee2aaSAndroid Build Coastguard Worker * 82*c8dee2aaSAndroid Build Coastguard Worker * @return An initialized DrawAtlas, or nullptr if creation fails. 83*c8dee2aaSAndroid Build Coastguard Worker */ 84*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<GrDrawOpAtlas> Make(GrProxyProvider* proxyProvider, 85*c8dee2aaSAndroid Build Coastguard Worker const GrBackendFormat& format, 86*c8dee2aaSAndroid Build Coastguard Worker SkColorType ct, size_t bpp, 87*c8dee2aaSAndroid Build Coastguard Worker int width, int height, 88*c8dee2aaSAndroid Build Coastguard Worker int plotWidth, int plotHeight, 89*c8dee2aaSAndroid Build Coastguard Worker skgpu::AtlasGenerationCounter* generationCounter, 90*c8dee2aaSAndroid Build Coastguard Worker AllowMultitexturing allowMultitexturing, 91*c8dee2aaSAndroid Build Coastguard Worker skgpu::PlotEvictionCallback* evictor, 92*c8dee2aaSAndroid Build Coastguard Worker std::string_view label); 93*c8dee2aaSAndroid Build Coastguard Worker 94*c8dee2aaSAndroid Build Coastguard Worker /** 95*c8dee2aaSAndroid Build Coastguard Worker * Adds a width x height subimage to the atlas. Upon success it returns 'kSucceeded' and returns 96*c8dee2aaSAndroid Build Coastguard Worker * the ID and the subimage's coordinates in the backing texture. 'kTryAgain' is returned if 97*c8dee2aaSAndroid Build Coastguard Worker * the subimage cannot fit in the atlas without overwriting texels that will be read in the 98*c8dee2aaSAndroid Build Coastguard Worker * current draw. This indicates that the op should end its current draw and begin another 99*c8dee2aaSAndroid Build Coastguard Worker * before adding more data. Upon success, an upload of the provided image data will have 100*c8dee2aaSAndroid Build Coastguard Worker * been added to the GrDrawOp::Target, in "asap" mode if possible, otherwise in "inline" mode. 101*c8dee2aaSAndroid Build Coastguard Worker * Successive uploads in either mode may be consolidated. 102*c8dee2aaSAndroid Build Coastguard Worker * 'kError' will be returned when some unrecoverable error was encountered while trying to 103*c8dee2aaSAndroid Build Coastguard Worker * add the subimage. In this case the op being created should be discarded. 104*c8dee2aaSAndroid Build Coastguard Worker * 105*c8dee2aaSAndroid Build Coastguard Worker * NOTE: When the GrDrawOp prepares a draw that reads from the atlas, it must immediately call 106*c8dee2aaSAndroid Build Coastguard Worker * 'setLastUseToken' with the currentToken from the GrDrawOp::Target, otherwise the next call to 107*c8dee2aaSAndroid Build Coastguard Worker * addToAtlas might cause the previous data to be overwritten before it has been read. 108*c8dee2aaSAndroid Build Coastguard Worker */ 109*c8dee2aaSAndroid Build Coastguard Worker 110*c8dee2aaSAndroid Build Coastguard Worker enum class ErrorCode { 111*c8dee2aaSAndroid Build Coastguard Worker kError, 112*c8dee2aaSAndroid Build Coastguard Worker kSucceeded, 113*c8dee2aaSAndroid Build Coastguard Worker kTryAgain 114*c8dee2aaSAndroid Build Coastguard Worker }; 115*c8dee2aaSAndroid Build Coastguard Worker 116*c8dee2aaSAndroid Build Coastguard Worker ErrorCode addToAtlas(GrResourceProvider*, GrDeferredUploadTarget*, 117*c8dee2aaSAndroid Build Coastguard Worker int width, int height, const void* image, skgpu::AtlasLocator*); 118*c8dee2aaSAndroid Build Coastguard Worker getViews()119*c8dee2aaSAndroid Build Coastguard Worker const GrSurfaceProxyView* getViews() const { return fViews; } 120*c8dee2aaSAndroid Build Coastguard Worker atlasGeneration()121*c8dee2aaSAndroid Build Coastguard Worker uint64_t atlasGeneration() const { return fAtlasGeneration; } 122*c8dee2aaSAndroid Build Coastguard Worker hasID(const skgpu::PlotLocator & plotLocator)123*c8dee2aaSAndroid Build Coastguard Worker bool hasID(const skgpu::PlotLocator& plotLocator) { 124*c8dee2aaSAndroid Build Coastguard Worker if (!plotLocator.isValid()) { 125*c8dee2aaSAndroid Build Coastguard Worker return false; 126*c8dee2aaSAndroid Build Coastguard Worker } 127*c8dee2aaSAndroid Build Coastguard Worker 128*c8dee2aaSAndroid Build Coastguard Worker uint32_t plot = plotLocator.plotIndex(); 129*c8dee2aaSAndroid Build Coastguard Worker uint32_t page = plotLocator.pageIndex(); 130*c8dee2aaSAndroid Build Coastguard Worker uint64_t plotGeneration = fPages[page].fPlotArray[plot]->genID(); 131*c8dee2aaSAndroid Build Coastguard Worker uint64_t locatorGeneration = plotLocator.genID(); 132*c8dee2aaSAndroid Build Coastguard Worker return plot < fNumPlots && page < fNumActivePages && plotGeneration == locatorGeneration; 133*c8dee2aaSAndroid Build Coastguard Worker } 134*c8dee2aaSAndroid Build Coastguard Worker 135*c8dee2aaSAndroid Build Coastguard Worker /** To ensure the atlas does not evict a given entry, the client must set the last use token. */ setLastUseToken(const skgpu::AtlasLocator & atlasLocator,skgpu::AtlasToken token)136*c8dee2aaSAndroid Build Coastguard Worker void setLastUseToken(const skgpu::AtlasLocator& atlasLocator, skgpu::AtlasToken token) { 137*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(this->hasID(atlasLocator.plotLocator())); 138*c8dee2aaSAndroid Build Coastguard Worker uint32_t plotIdx = atlasLocator.plotIndex(); 139*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(plotIdx < fNumPlots); 140*c8dee2aaSAndroid Build Coastguard Worker uint32_t pageIdx = atlasLocator.pageIndex(); 141*c8dee2aaSAndroid Build Coastguard Worker SkASSERT(pageIdx < fNumActivePages); 142*c8dee2aaSAndroid Build Coastguard Worker skgpu::Plot* plot = fPages[pageIdx].fPlotArray[plotIdx].get(); 143*c8dee2aaSAndroid Build Coastguard Worker this->makeMRU(plot, pageIdx); 144*c8dee2aaSAndroid Build Coastguard Worker plot->setLastUseToken(token); 145*c8dee2aaSAndroid Build Coastguard Worker } 146*c8dee2aaSAndroid Build Coastguard Worker numActivePages()147*c8dee2aaSAndroid Build Coastguard Worker uint32_t numActivePages() { return fNumActivePages; } 148*c8dee2aaSAndroid Build Coastguard Worker setLastUseTokenBulk(const skgpu::BulkUsePlotUpdater & updater,skgpu::AtlasToken token)149*c8dee2aaSAndroid Build Coastguard Worker void setLastUseTokenBulk(const skgpu::BulkUsePlotUpdater& updater, 150*c8dee2aaSAndroid Build Coastguard Worker skgpu::AtlasToken token) { 151*c8dee2aaSAndroid Build Coastguard Worker int count = updater.count(); 152*c8dee2aaSAndroid Build Coastguard Worker for (int i = 0; i < count; i++) { 153*c8dee2aaSAndroid Build Coastguard Worker const skgpu::BulkUsePlotUpdater::PlotData& pd = updater.plotData(i); 154*c8dee2aaSAndroid Build Coastguard Worker // it's possible we've added a plot to the updater and subsequently the plot's page 155*c8dee2aaSAndroid Build Coastguard Worker // was deleted -- so we check to prevent a crash 156*c8dee2aaSAndroid Build Coastguard Worker if (pd.fPageIndex < fNumActivePages) { 157*c8dee2aaSAndroid Build Coastguard Worker skgpu::Plot* plot = fPages[pd.fPageIndex].fPlotArray[pd.fPlotIndex].get(); 158*c8dee2aaSAndroid Build Coastguard Worker this->makeMRU(plot, pd.fPageIndex); 159*c8dee2aaSAndroid Build Coastguard Worker plot->setLastUseToken(token); 160*c8dee2aaSAndroid Build Coastguard Worker } 161*c8dee2aaSAndroid Build Coastguard Worker } 162*c8dee2aaSAndroid Build Coastguard Worker } 163*c8dee2aaSAndroid Build Coastguard Worker 164*c8dee2aaSAndroid Build Coastguard Worker void compact(skgpu::AtlasToken startTokenForNextFlush); 165*c8dee2aaSAndroid Build Coastguard Worker 166*c8dee2aaSAndroid Build Coastguard Worker void instantiate(GrOnFlushResourceProvider*); 167*c8dee2aaSAndroid Build Coastguard Worker maxPages()168*c8dee2aaSAndroid Build Coastguard Worker uint32_t maxPages() const { 169*c8dee2aaSAndroid Build Coastguard Worker return fMaxPages; 170*c8dee2aaSAndroid Build Coastguard Worker } 171*c8dee2aaSAndroid Build Coastguard Worker 172*c8dee2aaSAndroid Build Coastguard Worker private: 173*c8dee2aaSAndroid Build Coastguard Worker friend class GrDrawOpAtlasTools; 174*c8dee2aaSAndroid Build Coastguard Worker 175*c8dee2aaSAndroid Build Coastguard Worker GrDrawOpAtlas(GrProxyProvider*, const GrBackendFormat& format, SkColorType, size_t bpp, 176*c8dee2aaSAndroid Build Coastguard Worker int width, int height, int plotWidth, int plotHeight, 177*c8dee2aaSAndroid Build Coastguard Worker skgpu::AtlasGenerationCounter* generationCounter, 178*c8dee2aaSAndroid Build Coastguard Worker AllowMultitexturing allowMultitexturing, std::string_view label); 179*c8dee2aaSAndroid Build Coastguard Worker 180*c8dee2aaSAndroid Build Coastguard Worker inline bool updatePlot(GrDeferredUploadTarget*, skgpu::AtlasLocator*, skgpu::Plot*); 181*c8dee2aaSAndroid Build Coastguard Worker makeMRU(skgpu::Plot * plot,uint32_t pageIdx)182*c8dee2aaSAndroid Build Coastguard Worker inline void makeMRU(skgpu::Plot* plot, uint32_t pageIdx) { 183*c8dee2aaSAndroid Build Coastguard Worker if (fPages[pageIdx].fPlotList.head() == plot) { 184*c8dee2aaSAndroid Build Coastguard Worker return; 185*c8dee2aaSAndroid Build Coastguard Worker } 186*c8dee2aaSAndroid Build Coastguard Worker 187*c8dee2aaSAndroid Build Coastguard Worker fPages[pageIdx].fPlotList.remove(plot); 188*c8dee2aaSAndroid Build Coastguard Worker fPages[pageIdx].fPlotList.addToHead(plot); 189*c8dee2aaSAndroid Build Coastguard Worker 190*c8dee2aaSAndroid Build Coastguard Worker // No MRU update for pages -- since we will always try to add from 191*c8dee2aaSAndroid Build Coastguard Worker // the front and remove from the back there is no need for MRU. 192*c8dee2aaSAndroid Build Coastguard Worker } 193*c8dee2aaSAndroid Build Coastguard Worker 194*c8dee2aaSAndroid Build Coastguard Worker bool uploadToPage(unsigned int pageIdx, GrDeferredUploadTarget*, int width, int height, 195*c8dee2aaSAndroid Build Coastguard Worker const void* image, skgpu::AtlasLocator*); 196*c8dee2aaSAndroid Build Coastguard Worker 197*c8dee2aaSAndroid Build Coastguard Worker void uploadPlotToTexture(GrDeferredTextureUploadWritePixelsFn& writePixels, 198*c8dee2aaSAndroid Build Coastguard Worker GrTextureProxy* proxy, 199*c8dee2aaSAndroid Build Coastguard Worker skgpu::Plot* plot); 200*c8dee2aaSAndroid Build Coastguard Worker 201*c8dee2aaSAndroid Build Coastguard Worker bool createPages(GrProxyProvider*, skgpu::AtlasGenerationCounter*); 202*c8dee2aaSAndroid Build Coastguard Worker bool activateNewPage(GrResourceProvider*); 203*c8dee2aaSAndroid Build Coastguard Worker void deactivateLastPage(); 204*c8dee2aaSAndroid Build Coastguard Worker 205*c8dee2aaSAndroid Build Coastguard Worker void processEviction(skgpu::PlotLocator); processEvictionAndResetRects(skgpu::Plot * plot)206*c8dee2aaSAndroid Build Coastguard Worker inline void processEvictionAndResetRects(skgpu::Plot* plot) { 207*c8dee2aaSAndroid Build Coastguard Worker this->processEviction(plot->plotLocator()); 208*c8dee2aaSAndroid Build Coastguard Worker plot->resetRects(); 209*c8dee2aaSAndroid Build Coastguard Worker } 210*c8dee2aaSAndroid Build Coastguard Worker 211*c8dee2aaSAndroid Build Coastguard Worker GrBackendFormat fFormat; 212*c8dee2aaSAndroid Build Coastguard Worker SkColorType fColorType; 213*c8dee2aaSAndroid Build Coastguard Worker size_t fBytesPerPixel; 214*c8dee2aaSAndroid Build Coastguard Worker int fTextureWidth; 215*c8dee2aaSAndroid Build Coastguard Worker int fTextureHeight; 216*c8dee2aaSAndroid Build Coastguard Worker int fPlotWidth; 217*c8dee2aaSAndroid Build Coastguard Worker int fPlotHeight; 218*c8dee2aaSAndroid Build Coastguard Worker unsigned int fNumPlots; 219*c8dee2aaSAndroid Build Coastguard Worker const std::string fLabel; 220*c8dee2aaSAndroid Build Coastguard Worker 221*c8dee2aaSAndroid Build Coastguard Worker // A counter to track the atlas eviction state for Glyphs. Each Glyph has a PlotLocator 222*c8dee2aaSAndroid Build Coastguard Worker // which contains its current generation. When the atlas evicts a plot, it increases 223*c8dee2aaSAndroid Build Coastguard Worker // the generation counter. If a Glyph's generation is less than the atlas's 224*c8dee2aaSAndroid Build Coastguard Worker // generation, then it knows it's been evicted and is either free to be deleted or 225*c8dee2aaSAndroid Build Coastguard Worker // re-added to the atlas if necessary. 226*c8dee2aaSAndroid Build Coastguard Worker skgpu::AtlasGenerationCounter* const fGenerationCounter; 227*c8dee2aaSAndroid Build Coastguard Worker uint64_t fAtlasGeneration; 228*c8dee2aaSAndroid Build Coastguard Worker 229*c8dee2aaSAndroid Build Coastguard Worker // nextFlushToken() value at the end of the previous flush 230*c8dee2aaSAndroid Build Coastguard Worker skgpu::AtlasToken fPrevFlushToken; 231*c8dee2aaSAndroid Build Coastguard Worker 232*c8dee2aaSAndroid Build Coastguard Worker // the number of flushes since this atlas has been last used 233*c8dee2aaSAndroid Build Coastguard Worker int fFlushesSinceLastUse; 234*c8dee2aaSAndroid Build Coastguard Worker 235*c8dee2aaSAndroid Build Coastguard Worker std::vector<skgpu::PlotEvictionCallback*> fEvictionCallbacks; 236*c8dee2aaSAndroid Build Coastguard Worker 237*c8dee2aaSAndroid Build Coastguard Worker struct Page { 238*c8dee2aaSAndroid Build Coastguard Worker // allocated array of Plots 239*c8dee2aaSAndroid Build Coastguard Worker std::unique_ptr<sk_sp<skgpu::Plot>[]> fPlotArray; 240*c8dee2aaSAndroid Build Coastguard Worker // LRU list of Plots (MRU at head - LRU at tail) 241*c8dee2aaSAndroid Build Coastguard Worker skgpu::PlotList fPlotList; 242*c8dee2aaSAndroid Build Coastguard Worker }; 243*c8dee2aaSAndroid Build Coastguard Worker // proxies kept separate to make it easier to pass them up to client 244*c8dee2aaSAndroid Build Coastguard Worker GrSurfaceProxyView fViews[skgpu::PlotLocator::kMaxMultitexturePages]; 245*c8dee2aaSAndroid Build Coastguard Worker Page fPages[skgpu::PlotLocator::kMaxMultitexturePages]; 246*c8dee2aaSAndroid Build Coastguard Worker uint32_t fMaxPages; 247*c8dee2aaSAndroid Build Coastguard Worker 248*c8dee2aaSAndroid Build Coastguard Worker uint32_t fNumActivePages; 249*c8dee2aaSAndroid Build Coastguard Worker 250*c8dee2aaSAndroid Build Coastguard Worker SkDEBUGCODE(void validate(const skgpu::AtlasLocator& atlasLocator) const;) 251*c8dee2aaSAndroid Build Coastguard Worker }; 252*c8dee2aaSAndroid Build Coastguard Worker 253*c8dee2aaSAndroid Build Coastguard Worker // There are three atlases (A8, 565, ARGB) that are kept in relation with one another. In 254*c8dee2aaSAndroid Build Coastguard Worker // general, because A8 is the most frequently used mask format its dimensions are 2x the 565 and 255*c8dee2aaSAndroid Build Coastguard Worker // ARGB dimensions, with the constraint that an atlas size will always contain at least one plot. 256*c8dee2aaSAndroid Build Coastguard Worker // Since the ARGB atlas takes the most space, its dimensions are used to size the other two atlases. 257*c8dee2aaSAndroid Build Coastguard Worker class GrDrawOpAtlasConfig { 258*c8dee2aaSAndroid Build Coastguard Worker public: 259*c8dee2aaSAndroid Build Coastguard Worker // The capabilities of the GPU define maxTextureSize. The client provides maxBytes, and this 260*c8dee2aaSAndroid Build Coastguard Worker // represents the largest they want a single atlas texture to be. Due to multitexturing, we 261*c8dee2aaSAndroid Build Coastguard Worker // may expand temporarily to use more space as needed. 262*c8dee2aaSAndroid Build Coastguard Worker GrDrawOpAtlasConfig(int maxTextureSize, size_t maxBytes); 263*c8dee2aaSAndroid Build Coastguard Worker 264*c8dee2aaSAndroid Build Coastguard Worker // For testing only - make minimum sized atlases -- a single plot for ARGB, four for A8 GrDrawOpAtlasConfig()265*c8dee2aaSAndroid Build Coastguard Worker GrDrawOpAtlasConfig() : GrDrawOpAtlasConfig(kMaxAtlasDim, 0) {} 266*c8dee2aaSAndroid Build Coastguard Worker 267*c8dee2aaSAndroid Build Coastguard Worker SkISize atlasDimensions(skgpu::MaskFormat type) const; 268*c8dee2aaSAndroid Build Coastguard Worker SkISize plotDimensions(skgpu::MaskFormat type) const; 269*c8dee2aaSAndroid Build Coastguard Worker 270*c8dee2aaSAndroid Build Coastguard Worker private: 271*c8dee2aaSAndroid Build Coastguard Worker // On some systems texture coordinates are represented using half-precision floating point 272*c8dee2aaSAndroid Build Coastguard Worker // with 11 significant bits, which limits the largest atlas dimensions to 2048x2048. 273*c8dee2aaSAndroid Build Coastguard Worker // For simplicity we'll use this constraint for all of our atlas textures. 274*c8dee2aaSAndroid Build Coastguard Worker // This can be revisited later if we need larger atlases. 275*c8dee2aaSAndroid Build Coastguard Worker inline static constexpr int kMaxAtlasDim = 2048; 276*c8dee2aaSAndroid Build Coastguard Worker 277*c8dee2aaSAndroid Build Coastguard Worker SkISize fARGBDimensions; 278*c8dee2aaSAndroid Build Coastguard Worker int fMaxTextureSize; 279*c8dee2aaSAndroid Build Coastguard Worker }; 280*c8dee2aaSAndroid Build Coastguard Worker 281*c8dee2aaSAndroid Build Coastguard Worker #endif 282