Line data Source code
1 : /* This Source Code Form is subject to the terms of the Mozilla Public
2 : * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 : * You can obtain one at http://mozilla.org/MPL/2.0/. */
4 :
5 : #ifndef GFX_TILEDLAYERBUFFER_H
6 : #define GFX_TILEDLAYERBUFFER_H
7 :
8 : // Debug defines
9 : //#define GFX_TILEDLAYER_DEBUG_OVERLAY
10 : //#define GFX_TILEDLAYER_PREF_WARNINGS
11 : //#define GFX_TILEDLAYER_RETAINING_LOG
12 :
13 : #include <stdint.h> // for uint16_t, uint32_t
14 : #include <sys/types.h> // for int32_t
15 : #include "LayersLogging.h" // for print_stderr
16 : #include "mozilla/gfx/gfxVars.h"
17 : #include "mozilla/gfx/Logging.h" // for gfxCriticalError
18 : #include "mozilla/layers/LayersTypes.h" // for TextureDumpMode
19 : #include "nsDebug.h" // for NS_ASSERTION
20 : #include "nsPoint.h" // for nsIntPoint
21 : #include "nsRect.h" // for mozilla::gfx::IntRect
22 : #include "nsRegion.h" // for nsIntRegion
23 : #include "nsTArray.h" // for nsTArray
24 :
25 : namespace mozilla {
26 :
27 0 : struct TileUnit {};
28 : template<> struct IsPixel<TileUnit> : mozilla::TrueType {};
29 :
30 : namespace layers {
31 :
32 : // You can enable all the TILING_LOG print statements by
33 : // changing the 0 to a 1 in the following #define.
34 : #define ENABLE_TILING_LOG 0
35 :
36 : #if ENABLE_TILING_LOG
37 : # define TILING_LOG(...) printf_stderr(__VA_ARGS__);
38 : #else
39 : # define TILING_LOG(...)
40 : #endif
41 :
42 : // Normal integer division truncates towards zero,
43 : // we instead want to floor to hangle negative numbers.
44 0 : static inline int floor_div(int a, int b)
45 : {
46 0 : int rem = a % b;
47 0 : int div = a/b;
48 0 : if (rem == 0) {
49 0 : return div;
50 : } else {
51 : // If the signs are different substract 1.
52 : int sub;
53 0 : sub = a ^ b;
54 : // The results of this shift is either 0 or -1.
55 0 : sub >>= 8*sizeof(int)-1;
56 0 : return div+sub;
57 : }
58 : }
59 :
60 : // Tiles are aligned to a grid with one of the grid points at (0,0) and other
61 : // grid points spaced evenly in the x- and y-directions by GetTileSize()
62 : // multiplied by mResolution. GetScaledTileSize() provides convenience for
63 : // accessing these values.
64 : //
65 : // This tile buffer stores a valid region, which defines the areas that have
66 : // up-to-date content. The contents of tiles within this region will be reused
67 : // from paint to paint. It also stores the region that was modified in the last
68 : // paint operation; this is useful when one tiled layer buffer shadows another
69 : // (as in an off-main-thread-compositing scenario), so that the shadow tiled
70 : // layer buffer can correctly reflect the updates of the master layer buffer.
71 : //
72 : // The associated Tile may be of any type as long as the derived class can
73 : // validate and return tiles of that type. Tiles will be frequently copied, so
74 : // the tile type should be a reference or some other type with an efficient
75 : // copy constructor.
76 : //
77 : // The contents of the tile buffer will be rendered at the resolution specified
78 : // in mResolution, which can be altered with SetResolution. The resolution
79 : // should always be a factor of the tile length, to avoid tiles covering
80 : // non-integer amounts of pixels.
81 :
82 : // Size and Point in number of tiles rather than in pixels
83 : typedef gfx::IntSizeTyped<TileUnit> TileIntSize;
84 : typedef gfx::IntPointTyped<TileUnit> TileIntPoint;
85 :
86 : /**
87 : * Stores the origin and size of a tile buffer and handles switching between
88 : * tile indices and tile positions.
89 : *
90 : * Tile positions in TileIntPoint take the first tile offset into account which
91 : * means that two TilesPlacement of the same layer and resolution give tile
92 : * positions in the same coordinate space (useful when changing the offset and/or
93 : * size of a tile buffer).
94 : */
95 : struct TilesPlacement {
96 : // in tiles
97 : TileIntPoint mFirst;
98 : TileIntSize mSize;
99 :
100 0 : TilesPlacement(int aFirstX, int aFirstY,
101 : int aRetainedWidth, int aRetainedHeight)
102 0 : : mFirst(aFirstX, aFirstY)
103 0 : , mSize(aRetainedWidth, aRetainedHeight)
104 0 : {}
105 :
106 0 : int TileIndex(TileIntPoint aPosition) const {
107 0 : return (aPosition.x - mFirst.x) * mSize.height + aPosition.y - mFirst.y;
108 : }
109 :
110 0 : TileIntPoint TilePosition(size_t aIndex) const {
111 0 : return TileIntPoint(
112 0 : mFirst.x + aIndex / mSize.height,
113 0 : mFirst.y + aIndex % mSize.height
114 0 : );
115 : }
116 :
117 0 : bool HasTile(TileIntPoint aPosition) const {
118 0 : return aPosition.x >= mFirst.x && aPosition.x < mFirst.x + mSize.width &&
119 0 : aPosition.y >= mFirst.y && aPosition.y < mFirst.y + mSize.height;
120 : }
121 : };
122 :
123 :
124 : // Given a position i, this function returns the position inside the current tile.
125 0 : inline int GetTileStart(int i, int aTileLength) {
126 0 : return (i >= 0) ? (i % aTileLength)
127 0 : : ((aTileLength - (-i % aTileLength)) %
128 0 : aTileLength);
129 : }
130 :
131 : // Rounds the given coordinate down to the nearest tile boundary.
132 0 : inline int RoundDownToTileEdge(int aX, int aTileLength) { return aX - GetTileStart(aX, aTileLength); }
133 :
134 : template<typename Derived, typename Tile>
135 : class TiledLayerBuffer
136 : {
137 : public:
138 0 : TiledLayerBuffer()
139 : : mTiles(0, 0, 0, 0)
140 : , mResolution(1)
141 0 : , mTileSize(mozilla::gfx::gfxVars::TileSize())
142 0 : {}
143 :
144 0 : ~TiledLayerBuffer() {}
145 :
146 0 : gfx::IntPoint GetTileOffset(TileIntPoint aPosition) const {
147 0 : gfx::IntSize scaledTileSize = GetScaledTileSize();
148 0 : return gfx::IntPoint(aPosition.x * scaledTileSize.width,
149 0 : aPosition.y * scaledTileSize.height) + mTileOrigin;
150 : }
151 :
152 0 : const TilesPlacement& GetPlacement() const { return mTiles; }
153 :
154 0 : const gfx::IntSize& GetTileSize() const { return mTileSize; }
155 :
156 0 : gfx::IntSize GetScaledTileSize() const { return gfx::IntSize::Round(gfx::Size(mTileSize) / mResolution); }
157 :
158 0 : unsigned int GetTileCount() const { return mRetainedTiles.Length(); }
159 :
160 0 : Tile& GetTile(size_t i) { return mRetainedTiles[i]; }
161 :
162 0 : const nsIntRegion& GetValidRegion() const { return mValidRegion; }
163 : const nsIntRegion& GetPaintedRegion() const { return mPaintedRegion; }
164 0 : void ClearPaintedRegion() { mPaintedRegion.SetEmpty(); }
165 :
166 : // Get and set draw scaling. mResolution affects the resolution at which the
167 : // contents of the buffer are drawn. mResolution has no effect on the
168 : // coordinate space of the valid region, but does affect the size of an
169 : // individual tile's rect in relation to the valid region.
170 : // Setting the resolution will invalidate the buffer.
171 0 : float GetResolution() const { return mResolution; }
172 0 : bool IsLowPrecision() const { return mResolution < 1; }
173 :
174 : void Dump(std::stringstream& aStream, const char* aPrefix, bool aDumpHtml,
175 : TextureDumpMode aCompress);
176 :
177 : protected:
178 :
179 : nsIntRegion mValidRegion;
180 : nsIntRegion mPaintedRegion;
181 :
182 : /**
183 : * mRetainedTiles is a rectangular buffer of mTiles.mSize.width x mTiles.mSize.height
184 : * stored as column major with the same origin as mValidRegion.GetBounds().
185 : * Any tile that does not intersect mValidRegion is a PlaceholderTile.
186 : * Only the region intersecting with mValidRegion should be read from a tile,
187 : * another other region is assumed to be uninitialized. The contents of the
188 : * tiles is scaled by mResolution.
189 : */
190 : nsTArray<Tile> mRetainedTiles;
191 : TilesPlacement mTiles;
192 : float mResolution;
193 : gfx::IntSize mTileSize;
194 : gfx::IntPoint mTileOrigin;
195 : };
196 :
197 : template<typename Derived, typename Tile> void
198 0 : TiledLayerBuffer<Derived, Tile>::Dump(std::stringstream& aStream,
199 : const char* aPrefix,
200 : bool aDumpHtml,
201 : TextureDumpMode aCompress)
202 : {
203 0 : for (size_t i = 0; i < mRetainedTiles.Length(); ++i) {
204 0 : const TileIntPoint tilePosition = mTiles.TilePosition(i);
205 0 : gfx::IntPoint tileOffset = GetTileOffset(tilePosition);
206 :
207 0 : aStream << "\n" << aPrefix << "Tile (x=" <<
208 0 : tileOffset.x << ", y=" << tileOffset.y << "): ";
209 0 : if (!mRetainedTiles[i].IsPlaceholderTile()) {
210 0 : mRetainedTiles[i].DumpTexture(aStream, aCompress);
211 : } else {
212 0 : aStream << "empty tile";
213 : }
214 : }
215 0 : }
216 :
217 : } // namespace layers
218 : } // namespace mozilla
219 :
220 : #endif // GFX_TILEDLAYERBUFFER_H
|