| |
| /* |
| * Copyright 2010 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| |
| #ifndef GrLayerAtlas_DEFINED |
| #define GrLayerAtlas_DEFINED |
| |
| #include "GrTexture.h" |
| |
| #include "SkPoint.h" |
| #include "SkTDArray.h" |
| #include "SkTInternalLList.h" |
| |
| class GrLayerAtlas; |
| class GrTextureProvider; |
| class GrRectanizer; |
| |
| // The backing GrTexture for a GrLayerAtlas is broken into a spatial grid of Plots. When |
| // the atlas needs space on the texture (i.e., in response to an addToAtlas call), it |
| // iterates through the plots in use by the requesting client looking for space and, |
| // if no space is found, opens up a new Plot for that client. The Plots keep track of |
| // subimage placement via their GrRectanizer. |
| // |
| // If all Plots are full, the replacement strategy is up to the client. The Plot::reset |
| // call will remove a Plot's knowledge of any allocated rects - freeing its space for reuse. |
| |
| class GrLayerAtlas { |
| public: |
| class Plot { |
| SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot); // In an MRU llist |
| |
| public: |
| // This returns a plot ID unique to each plot in the atlas. They are |
| // consecutive and start at 0. |
| int id() const { return fID; } |
| |
| void reset(); |
| |
| private: |
| friend class GrLayerAtlas; |
| |
| Plot(); |
| ~Plot(); // does not try to delete the fNext field |
| |
| void init(int id, int offX, int offY, int width, int height); |
| |
| bool allocateRect(int width, int height, SkIPoint16*); |
| |
| int fID; |
| GrRectanizer* fRects; |
| SkIPoint16 fOffset; // the offset of the plot in the backing texture |
| }; |
| |
| // This class allows each client to independently track the Plots in |
| // which its data is stored. |
| // For example, multiple pictures may simultaneously store their layers in the |
| // layer atlas. When a picture goes away it can use the ClientPlotUsage to remove itself |
| // from those plots. |
| class ClientPlotUsage { |
| public: |
| ClientPlotUsage(int maxPlots) |
| SkDEBUGCODE(: fMaxPlots(maxPlots)) { |
| fPlots.setReserve(maxPlots); |
| } |
| |
| bool isEmpty() const { return 0 == fPlots.count(); } |
| |
| int numPlots() const { return fPlots.count(); } |
| Plot* plot(int index) { return fPlots[index]; } |
| |
| void appendPlot(Plot* plot) { |
| SkASSERT(fPlots.count() <= fMaxPlots); |
| SkASSERT(!fPlots.contains(plot)); |
| *fPlots.append() = plot; |
| } |
| |
| // remove reference to 'plot' |
| void removePlot(const Plot* plot) { |
| int index = fPlots.find(const_cast<Plot*>(plot)); |
| if (index >= 0) { |
| fPlots.remove(index); |
| } |
| } |
| |
| #ifdef SK_DEBUG |
| bool contains(const Plot* plot) const { |
| return fPlots.contains(const_cast<Plot*>(plot)); |
| } |
| #endif |
| |
| private: |
| SkTDArray<Plot*> fPlots; |
| SkDEBUGCODE(int fMaxPlots;) |
| }; |
| |
| GrLayerAtlas(GrTextureProvider*, GrPixelConfig, GrSurfaceFlags flags, |
| const SkISize& backingTextureSize, |
| int numPlotsX, int numPlotsY); |
| ~GrLayerAtlas(); |
| |
| // Requests a width x height block in the atlas. Upon success it returns |
| // the containing Plot and absolute location in the backing texture. |
| // nullptr is returned if there is no more space in the atlas. |
| Plot* addToAtlas(ClientPlotUsage*, int width, int height, SkIPoint16* loc); |
| |
| GrTexture* getTextureOrNull() const { |
| return fTexture; |
| } |
| |
| GrTexture* getTexture() const { |
| SkASSERT(fTexture); |
| return fTexture; |
| } |
| |
| bool reattachBackingTexture(); |
| |
| void detachBackingTexture() { |
| fTexture.reset(nullptr); |
| } |
| |
| void resetPlots(); |
| |
| enum IterOrder { |
| kLRUFirst_IterOrder, |
| kMRUFirst_IterOrder |
| }; |
| |
| typedef SkTInternalLList<Plot> PlotList; |
| typedef PlotList::Iter PlotIter; |
| Plot* iterInit(PlotIter* iter, IterOrder order) { |
| return iter->init(fPlotList, kLRUFirst_IterOrder == order |
| ? PlotList::Iter::kTail_IterStart |
| : PlotList::Iter::kHead_IterStart); |
| } |
| |
| private: |
| void createBackingTexture(); |
| |
| void makeMRU(Plot* plot); |
| |
| GrTextureProvider* fTexProvider; |
| GrPixelConfig fPixelConfig; |
| GrSurfaceFlags fFlags; |
| SkAutoTUnref<GrTexture> fTexture; |
| |
| SkISize fBackingTextureSize; |
| |
| // allocated array of Plots |
| Plot* fPlotArray; |
| // LRU list of Plots (MRU at head - LRU at tail) |
| PlotList fPlotList; |
| }; |
| |
| #endif |