Home | History | Annotate | Download | only in gpu
      1 /*
      2  * Copyright 2015 Google Inc.
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef GrBatchAtlas_DEFINED
      9 #define GrBatchAtlas_DEFINED
     10 
     11 #include "GrTexture.h"
     12 #include "SkPoint.h"
     13 #include "SkTDArray.h"
     14 #include "SkTInternalLList.h"
     15 
     16 class BatchPlot;
     17 class GrBatchTarget;
     18 class GrRectanizer;
     19 
     20 typedef SkTInternalLList<BatchPlot> GrBatchPlotList;
     21 
     22 class GrBatchAtlas {
     23 public:
     24     typedef uint64_t BatchToken;
     25     // An AtlasID is an opaque handle which callers can use to determine if the atlas contains
     26     // a specific piece of data
     27     typedef uint32_t AtlasID;
     28     static const uint32_t kInvalidAtlasID = 0;
     29     static const uint64_t kInvalidAtlasGeneration = 0;
     30 
     31     // A function pointer for use as a callback during eviction.  Whenever GrBatchAtlas evicts a
     32     // specific AtlasID, it will call all of the registered listeners so they can optionally process
     33     // the eviction
     34     typedef void (*EvictionFunc)(GrBatchAtlas::AtlasID, void*);
     35 
     36     GrBatchAtlas(GrTexture*, int numPlotsX, int numPlotsY);
     37     ~GrBatchAtlas();
     38 
     39     // Adds a width x height subimage to the atlas. Upon success it returns
     40     // the containing GrPlot and absolute location in the backing texture.
     41     // NULL is returned if the subimage cannot fit in the atlas.
     42     // If provided, the image data will be written to the CPU-side backing bitmap.
     43     // NOTE: If the client intends to refer to the atlas, they should immediately call 'setUseToken'
     44     // with the currentToken from the batch target, otherwise the next call to addToAtlas might
     45     // cause an eviction
     46     bool addToAtlas(AtlasID*, GrBatchTarget*, int width, int height, const void* image,
     47                     SkIPoint16* loc);
     48 
     49     GrTexture* getTexture() const { return fTexture; }
     50 
     51     uint64_t atlasGeneration() const { return fAtlasGeneration; }
     52     bool hasID(AtlasID id);
     53 
     54     // To ensure the atlas does not evict a given entry, the client must set the last use token
     55     void setLastUseToken(AtlasID id, BatchToken batchToken);
     56     void registerEvictionCallback(EvictionFunc func, void* userData) {
     57         EvictionData* data = fEvictionCallbacks.append();
     58         data->fFunc = func;
     59         data->fData = userData;
     60     }
     61 
     62     /*
     63      * A class which can be handed back to GrBatchAtlas for updating in bulk last use tokens.  The
     64      * current max number of plots the GrBatchAtlas can handle is 32, if in the future this is
     65      * insufficient then we can move to a 64 bit int
     66      */
     67     class BulkUseTokenUpdater {
     68     public:
     69         BulkUseTokenUpdater() : fPlotAlreadyUpdated(0) {}
     70         void add(AtlasID id) {
     71             int index = GrBatchAtlas::GetIndexFromID(id);
     72             if (!this->find(index)) {
     73                 this->set(index);
     74             }
     75         }
     76 
     77         void reset() {
     78             fPlotsToUpdate.reset();
     79             fPlotAlreadyUpdated = 0;
     80         }
     81 
     82     private:
     83         bool find(int index) const {
     84             SkASSERT(index < kMaxPlots);
     85             return (fPlotAlreadyUpdated >> index) & 1;
     86         }
     87 
     88         void set(int index) {
     89             SkASSERT(!this->find(index));
     90             fPlotAlreadyUpdated = fPlotAlreadyUpdated | (1 << index);
     91             fPlotsToUpdate.push_back(index);
     92         }
     93 
     94         static const int kMinItems = 4;
     95         static const int kMaxPlots = 32;
     96         SkSTArray<kMinItems, int, true> fPlotsToUpdate;
     97         uint32_t fPlotAlreadyUpdated;
     98 
     99         friend class GrBatchAtlas;
    100     };
    101 
    102     void setLastUseTokenBulk(const BulkUseTokenUpdater& reffer, BatchToken);
    103 
    104     static const int kGlyphMaxDim = 256;
    105     static bool GlyphTooLargeForAtlas(int width, int height) {
    106         return width > kGlyphMaxDim || height > kGlyphMaxDim;
    107     }
    108 
    109 private:
    110     static int GetIndexFromID(AtlasID id) {
    111         return id & 0xffff;
    112     }
    113 
    114     static int GetGenerationFromID(AtlasID id) {
    115         return (id >> 16) & 0xffff;
    116     }
    117 
    118     inline void updatePlot(GrBatchTarget*, AtlasID*, BatchPlot*);
    119 
    120     inline void makeMRU(BatchPlot* plot);
    121 
    122     inline void processEviction(AtlasID);
    123 
    124     GrTexture* fTexture;
    125     int fNumPlotsX;
    126     int fNumPlotsY;
    127     int fPlotWidth;
    128     int fPlotHeight;
    129     size_t fBPP;
    130     uint64_t fAtlasGeneration;
    131 
    132     struct EvictionData {
    133         EvictionFunc fFunc;
    134         void* fData;
    135     };
    136 
    137     SkTDArray<EvictionData> fEvictionCallbacks;
    138     // allocated array of GrBatchPlots
    139     SkAutoTUnref<BatchPlot>* fPlotArray;
    140     // LRU list of GrPlots (MRU at head - LRU at tail)
    141     GrBatchPlotList fPlotList;
    142 };
    143 
    144 #endif
    145