Index: src/gpu/GrLayerAtlas.h |
diff --git a/src/gpu/GrLayerAtlas.h b/src/gpu/GrLayerAtlas.h |
new file mode 100644 |
index 0000000000000000000000000000000000000000..ae08e4527ba6738cba02b2a73986028d2a3d832d |
--- /dev/null |
+++ b/src/gpu/GrLayerAtlas.h |
@@ -0,0 +1,145 @@ |
+ |
+/* |
+ * 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 "GrTypes.h" |
+ |
+#include "SkPoint.h" |
+#include "SkSize.h" |
+#include "SkTDArray.h" |
+#include "SkTInternalLList.h" |
+ |
+class GrLayerAtlas; |
+class GrTexture; |
+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* getTexture() const { |
+ return fTexture; |
+ } |
+ |
+ 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 makeMRU(Plot* plot); |
+ |
+ GrTextureProvider* fTexProvider; |
+ GrPixelConfig fPixelConfig; |
+ GrSurfaceFlags fFlags; |
+ GrTexture* fTexture; |
+ |
+ SkISize fBackingTextureSize; |
+ |
+ // allocated array of Plots |
+ Plot* fPlotArray; |
+ // LRU list of Plots (MRU at head - LRU at tail) |
+ PlotList fPlotList; |
+}; |
+ |
+#endif |