Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 #ifndef GrLayerAtlas_DEFINED
     10 #define GrLayerAtlas_DEFINED
     11 
     12 #include "GrTexture.h"
     13 
     14 #include "SkPoint.h"
     15 #include "SkTDArray.h"
     16 #include "SkTInternalLList.h"
     17 
     18 class GrLayerAtlas;
     19 class GrTextureProvider;
     20 class GrRectanizer;
     21 
     22 // The backing GrTexture for a GrLayerAtlas is broken into a spatial grid of Plots. When
     23 // the atlas needs space on the texture (i.e., in response to an addToAtlas call), it
     24 // iterates through the plots in use by the requesting client looking for space and,
     25 // if no space is found, opens up a new Plot for that client. The Plots keep track of
     26 // subimage placement via their GrRectanizer.
     27 //
     28 // If all Plots are full, the replacement strategy is up to the client. The Plot::reset
     29 // call will remove a Plot's knowledge of any allocated rects - freeing its space for reuse.
     30 
     31 class GrLayerAtlas {
     32 public:
     33     class Plot {
     34         SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot); // In an MRU llist
     35 
     36     public:
     37         // This returns a plot ID unique to each plot in the atlas. They are
     38         // consecutive and start at 0.
     39         int id() const { return fID; }
     40 
     41         void reset();
     42 
     43     private:
     44         friend class GrLayerAtlas;
     45 
     46         Plot();
     47         ~Plot(); // does not try to delete the fNext field
     48 
     49         void init(int id, int offX, int offY, int width, int height);
     50 
     51         bool allocateRect(int width, int height, SkIPoint16*);
     52 
     53         int                     fID;
     54         GrRectanizer*           fRects;
     55         SkIPoint16              fOffset;        // the offset of the plot in the backing texture
     56     };
     57 
     58     // This class allows each client to independently track the Plots in
     59     // which its data is stored.
     60     // For example, multiple pictures may simultaneously store their layers in the
     61     // layer atlas. When a picture goes away it can use the ClientPlotUsage to remove itself
     62     // from those plots.
     63     class ClientPlotUsage {
     64     public:
     65         ClientPlotUsage(int maxPlots)
     66             SkDEBUGCODE(: fMaxPlots(maxPlots)) {
     67             fPlots.setReserve(maxPlots);
     68         }
     69 
     70         bool isEmpty() const { return 0 == fPlots.count(); }
     71 
     72         int numPlots() const { return fPlots.count(); }
     73         Plot* plot(int index) { return fPlots[index]; }
     74 
     75         void appendPlot(Plot* plot) {
     76             SkASSERT(fPlots.count() <= fMaxPlots);
     77             SkASSERT(!fPlots.contains(plot));
     78             *fPlots.append() = plot;
     79         }
     80 
     81         // remove reference to 'plot'
     82         void removePlot(const Plot* plot) {
     83             int index = fPlots.find(const_cast<Plot*>(plot));
     84             if (index >= 0) {
     85                 fPlots.remove(index);
     86             }
     87         }
     88 
     89 #ifdef SK_DEBUG
     90         bool contains(const Plot* plot) const {
     91             return fPlots.contains(const_cast<Plot*>(plot));
     92         }
     93 #endif
     94 
     95     private:
     96         SkTDArray<Plot*> fPlots;
     97         SkDEBUGCODE(int fMaxPlots;)
     98     };
     99 
    100     GrLayerAtlas(GrTextureProvider*, GrPixelConfig, GrSurfaceFlags flags,
    101                  const SkISize& backingTextureSize,
    102                  int numPlotsX, int numPlotsY);
    103     ~GrLayerAtlas();
    104 
    105     // Requests a width x height block in the atlas. Upon success it returns
    106     // the containing Plot and absolute location in the backing texture.
    107     // nullptr is returned if there is no more space in the atlas.
    108     Plot* addToAtlas(ClientPlotUsage*, int width, int height, SkIPoint16* loc);
    109 
    110     GrTexture* getTextureOrNull() const {
    111         return fTexture;
    112     }
    113 
    114     GrTexture* getTexture() const {
    115         SkASSERT(fTexture);
    116         return fTexture;
    117     }
    118 
    119     bool reattachBackingTexture();
    120 
    121     void detachBackingTexture() {
    122         fTexture.reset(nullptr);
    123     }
    124 
    125     void resetPlots();
    126 
    127     enum IterOrder {
    128         kLRUFirst_IterOrder,
    129         kMRUFirst_IterOrder
    130     };
    131 
    132     typedef SkTInternalLList<Plot> PlotList;
    133     typedef PlotList::Iter PlotIter;
    134     Plot* iterInit(PlotIter* iter, IterOrder order) {
    135         return iter->init(fPlotList, kLRUFirst_IterOrder == order
    136                                                        ? PlotList::Iter::kTail_IterStart
    137                                                        : PlotList::Iter::kHead_IterStart);
    138     }
    139 
    140 private:
    141     void createBackingTexture();
    142 
    143     void makeMRU(Plot* plot);
    144 
    145     GrTextureProvider* fTexProvider;
    146     GrPixelConfig      fPixelConfig;
    147     GrSurfaceFlags     fFlags;
    148     SkAutoTUnref<GrTexture> fTexture;
    149 
    150     SkISize            fBackingTextureSize;
    151 
    152     // allocated array of Plots
    153     Plot*              fPlotArray;
    154     // LRU list of Plots (MRU at head - LRU at tail)
    155     PlotList           fPlotList;
    156 };
    157 
    158 #endif
    159