Source code

Revision control

Other Tools

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