blob: ae08e4527ba6738cba02b2a73986028d2a3d832d [file] [log] [blame]
robertphillipse51fa4a2015-11-03 07:04:47 -08001
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
robertphillipscf1d1982015-11-06 05:59:14 -080012#include "GrTypes.h"
robertphillipse51fa4a2015-11-03 07:04:47 -080013
14#include "SkPoint.h"
robertphillipscf1d1982015-11-06 05:59:14 -080015#include "SkSize.h"
robertphillipse51fa4a2015-11-03 07:04:47 -080016#include "SkTDArray.h"
17#include "SkTInternalLList.h"
18
19class GrLayerAtlas;
robertphillipscf1d1982015-11-06 05:59:14 -080020class GrTexture;
robertphillipse51fa4a2015-11-03 07:04:47 -080021class GrTextureProvider;
22class GrRectanizer;
23
24// The backing GrTexture for a GrLayerAtlas is broken into a spatial grid of Plots. When
25// the atlas needs space on the texture (i.e., in response to an addToAtlas call), it
26// iterates through the plots in use by the requesting client looking for space and,
27// if no space is found, opens up a new Plot for that client. The Plots keep track of
28// subimage placement via their GrRectanizer.
29//
30// If all Plots are full, the replacement strategy is up to the client. The Plot::reset
31// call will remove a Plot's knowledge of any allocated rects - freeing its space for reuse.
32
33class GrLayerAtlas {
34public:
35 class Plot {
36 SK_DECLARE_INTERNAL_LLIST_INTERFACE(Plot); // In an MRU llist
37
38 public:
39 // This returns a plot ID unique to each plot in the atlas. They are
40 // consecutive and start at 0.
41 int id() const { return fID; }
42
43 void reset();
44
45 private:
46 friend class GrLayerAtlas;
47
48 Plot();
49 ~Plot(); // does not try to delete the fNext field
50
51 void init(int id, int offX, int offY, int width, int height);
52
53 bool allocateRect(int width, int height, SkIPoint16*);
54
55 int fID;
56 GrRectanizer* fRects;
57 SkIPoint16 fOffset; // the offset of the plot in the backing texture
58 };
59
60 // This class allows each client to independently track the Plots in
61 // which its data is stored.
62 // For example, multiple pictures may simultaneously store their layers in the
63 // layer atlas. When a picture goes away it can use the ClientPlotUsage to remove itself
64 // from those plots.
65 class ClientPlotUsage {
66 public:
67 ClientPlotUsage(int maxPlots)
68 SkDEBUGCODE(: fMaxPlots(maxPlots)) {
69 fPlots.setReserve(maxPlots);
70 }
71
72 bool isEmpty() const { return 0 == fPlots.count(); }
73
74 int numPlots() const { return fPlots.count(); }
75 Plot* plot(int index) { return fPlots[index]; }
76
77 void appendPlot(Plot* plot) {
78 SkASSERT(fPlots.count() <= fMaxPlots);
79 SkASSERT(!fPlots.contains(plot));
80 *fPlots.append() = plot;
81 }
82
83 // remove reference to 'plot'
84 void removePlot(const Plot* plot) {
85 int index = fPlots.find(const_cast<Plot*>(plot));
86 if (index >= 0) {
87 fPlots.remove(index);
88 }
89 }
90
91#ifdef SK_DEBUG
92 bool contains(const Plot* plot) const {
93 return fPlots.contains(const_cast<Plot*>(plot));
94 }
95#endif
96
97 private:
98 SkTDArray<Plot*> fPlots;
99 SkDEBUGCODE(int fMaxPlots;)
100 };
101
102 GrLayerAtlas(GrTextureProvider*, GrPixelConfig, GrSurfaceFlags flags,
103 const SkISize& backingTextureSize,
104 int numPlotsX, int numPlotsY);
105 ~GrLayerAtlas();
106
107 // Requests a width x height block in the atlas. Upon success it returns
108 // the containing Plot and absolute location in the backing texture.
109 // nullptr is returned if there is no more space in the atlas.
110 Plot* addToAtlas(ClientPlotUsage*, int width, int height, SkIPoint16* loc);
111
robertphillips42597bc2015-11-06 04:14:55 -0800112 GrTexture* getTexture() const {
robertphillips42597bc2015-11-06 04:14:55 -0800113 return fTexture;
114 }
115
robertphillipse51fa4a2015-11-03 07:04:47 -0800116 enum IterOrder {
117 kLRUFirst_IterOrder,
118 kMRUFirst_IterOrder
119 };
120
121 typedef SkTInternalLList<Plot> PlotList;
122 typedef PlotList::Iter PlotIter;
123 Plot* iterInit(PlotIter* iter, IterOrder order) {
124 return iter->init(fPlotList, kLRUFirst_IterOrder == order
125 ? PlotList::Iter::kTail_IterStart
126 : PlotList::Iter::kHead_IterStart);
127 }
128
129private:
130 void makeMRU(Plot* plot);
131
132 GrTextureProvider* fTexProvider;
133 GrPixelConfig fPixelConfig;
134 GrSurfaceFlags fFlags;
robertphillipscf1d1982015-11-06 05:59:14 -0800135 GrTexture* fTexture;
robertphillipse51fa4a2015-11-03 07:04:47 -0800136
137 SkISize fBackingTextureSize;
138
139 // allocated array of Plots
140 Plot* fPlotArray;
141 // LRU list of Plots (MRU at head - LRU at tail)
142 PlotList fPlotList;
143};
144
145#endif