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