mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 754233 - Handle negative layer coordinate in Tiled layers. r=ajuma
This commit is contained in:
parent
e00a607d2a
commit
1f9de263ac
@ -107,8 +107,14 @@ public:
|
||||
mLastPaintRegion = aLastPaintRegion;
|
||||
}
|
||||
|
||||
// Given a position i, this function returns the position inside the current tile.
|
||||
int GetTileStart(int i) const {
|
||||
return (i >= 0) ? (i % GetTileLength())
|
||||
: ((GetTileLength() - (-i % GetTileLength())) % GetTileLength());
|
||||
}
|
||||
|
||||
// Rounds the given coordinate down to the nearest tile boundary.
|
||||
int RoundDownToTileEdge(int aX) const { return aX - aX % GetTileLength(); }
|
||||
int RoundDownToTileEdge(int aX) const { return aX - GetTileStart(aX); }
|
||||
|
||||
protected:
|
||||
// The implementor should call Update() to change
|
||||
@ -154,16 +160,34 @@ public:
|
||||
virtual void PaintedTiledLayerBuffer(const BasicTiledLayerBuffer* aTiledBuffer) = 0;
|
||||
};
|
||||
|
||||
// Normal integer division truncates towards zero,
|
||||
// we instead want to floor to hangle negative numbers.
|
||||
static int floor_div(int a, int b)
|
||||
{
|
||||
int rem = a % b;
|
||||
int div = a/b;
|
||||
if (rem == 0) {
|
||||
return div;
|
||||
} else {
|
||||
// If the signs are different substract 1.
|
||||
int sub;
|
||||
sub = a ^ b;
|
||||
// The results of this shift is either 0 or -1.
|
||||
sub >>= 8*sizeof(int)-1;
|
||||
return div+sub;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> Tile
|
||||
TiledLayerBuffer<Derived, Tile>::GetTile(const nsIntPoint& aTileOrigin) const
|
||||
{
|
||||
// TODO Cache firstTileOriginX/firstTileOriginY
|
||||
// Find the tile x/y of the first tile and the target tile relative to the (0, 0)
|
||||
// origin, the difference is the tile x/y relative to the start of the tile buffer.
|
||||
int firstTileX = mValidRegion.GetBounds().x / GetTileLength();
|
||||
int firstTileY = mValidRegion.GetBounds().y / GetTileLength();
|
||||
return GetTile(aTileOrigin.x / GetTileLength() - firstTileX,
|
||||
aTileOrigin.y / GetTileLength() - firstTileY);
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
|
||||
return GetTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY);
|
||||
}
|
||||
|
||||
template<typename Derived, typename Tile> Tile
|
||||
@ -177,10 +201,10 @@ template<typename Derived, typename Tile> bool
|
||||
TiledLayerBuffer<Derived, Tile>::RemoveTile(const nsIntPoint& aTileOrigin,
|
||||
Tile& aRemovedTile)
|
||||
{
|
||||
int firstTileX = mValidRegion.GetBounds().x / GetTileLength();
|
||||
int firstTileY = mValidRegion.GetBounds().y / GetTileLength();
|
||||
return RemoveTile(aTileOrigin.x / GetTileLength() - firstTileX,
|
||||
aTileOrigin.y / GetTileLength() - firstTileY,
|
||||
int firstTileX = floor_div(mValidRegion.GetBounds().x, GetTileLength());
|
||||
int firstTileY = floor_div(mValidRegion.GetBounds().y, GetTileLength());
|
||||
return RemoveTile(floor_div(aTileOrigin.x, GetTileLength()) - firstTileX,
|
||||
floor_div(aTileOrigin.y, GetTileLength()) - firstTileY,
|
||||
aRemovedTile);
|
||||
}
|
||||
|
||||
@ -221,17 +245,17 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
int tileX = 0;
|
||||
int tileY;
|
||||
// Iterate over the new drawing bounds in steps of tiles.
|
||||
for (int x = newBound.x; x < newBound.XMost(); tileX++) {
|
||||
for (int32_t x = newBound.x; x < newBound.XMost(); tileX++) {
|
||||
// Compute tileRect(x,y,width,height) in layer space coordinate
|
||||
// giving us the rect of the tile that hits the newBounds.
|
||||
int width = GetTileLength() - x % GetTileLength();
|
||||
int width = GetTileLength() - GetTileStart(x);
|
||||
if (x + width > newBound.XMost()) {
|
||||
width = newBound.x + newBound.width - x;
|
||||
}
|
||||
|
||||
tileY = 0;
|
||||
for (int y = newBound.y; y < newBound.YMost(); tileY++) {
|
||||
int height = GetTileLength() - y % GetTileLength();
|
||||
for (int32_t y = newBound.y; y < newBound.YMost(); tileY++) {
|
||||
int height = GetTileLength() - GetTileStart(y);
|
||||
if (y + height > newBound.y + newBound.height) {
|
||||
height = newBound.y + newBound.height - y;
|
||||
}
|
||||
@ -241,8 +265,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
// This old tiles contains some valid area so move it to the new tile
|
||||
// buffer. Replace the tile in the old buffer with a placeholder
|
||||
// to leave the old buffer index unaffected.
|
||||
int tileX = (x - oldBufferOrigin.x) / GetTileLength();
|
||||
int tileY = (y - oldBufferOrigin.y) / GetTileLength();
|
||||
int tileX = floor_div(x - oldBufferOrigin.x, GetTileLength());
|
||||
int tileY = floor_div(y - oldBufferOrigin.y, GetTileLength());
|
||||
int index = tileX * oldRetainedHeight + tileY;
|
||||
|
||||
// The tile may have been removed, skip over it in this case.
|
||||
@ -294,18 +318,21 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
// We also know that any place holder tile in the new buffer must be
|
||||
// allocated.
|
||||
tileX = 0;
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Update %i, %i, %i, %i\n", newBound.x, newBound.y, newBound.width, newBound.height);
|
||||
#endif
|
||||
for (int x = newBound.x; x < newBound.x + newBound.width; tileX++) {
|
||||
// Compute tileRect(x,y,width,height) in layer space coordinate
|
||||
// giving us the rect of the tile that hits the newBounds.
|
||||
int tileStartX = RoundDownToTileEdge(x);
|
||||
int width = GetTileLength() - x % GetTileLength();
|
||||
int width = GetTileLength() - GetTileStart(x);
|
||||
if (x + width > newBound.XMost())
|
||||
width = newBound.XMost() - x;
|
||||
|
||||
tileY = 0;
|
||||
for (int y = newBound.y; y < newBound.y + newBound.height; tileY++) {
|
||||
int tileStartY = RoundDownToTileEdge(y);
|
||||
int height = GetTileLength() - y % GetTileLength();
|
||||
int height = GetTileLength() - GetTileStart(y);
|
||||
if (y + height > newBound.YMost()) {
|
||||
height = newBound.YMost() - y;
|
||||
}
|
||||
@ -320,8 +347,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
// because we can reuse all of the content from the
|
||||
// previous buffer.
|
||||
#ifdef DEBUG
|
||||
int currTileX = (x - newBufferOrigin.x) / GetTileLength();
|
||||
int currTileY = (y - newBufferOrigin.y) / GetTileLength();
|
||||
int currTileX = floor_div(x - newBufferOrigin.x, GetTileLength());
|
||||
int currTileY = floor_div(y - newBufferOrigin.y, GetTileLength());
|
||||
int index = currTileX * mRetainedHeight + currTileY;
|
||||
NS_ABORT_IF_FALSE(!newValidRegion.Intersects(tileRect) ||
|
||||
!IsPlaceholder(newRetainedTiles.
|
||||
@ -332,8 +359,8 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
continue;
|
||||
}
|
||||
|
||||
int tileX = (x - newBufferOrigin.x) / GetTileLength();
|
||||
int tileY = (y - newBufferOrigin.y) / GetTileLength();
|
||||
int tileX = floor_div(x - newBufferOrigin.x, GetTileLength());
|
||||
int tileY = floor_div(y - newBufferOrigin.y, GetTileLength());
|
||||
int index = tileX * mRetainedHeight + tileY;
|
||||
NS_ABORT_IF_FALSE(index >= 0 && index < newRetainedTiles.Length(), "index out of range");
|
||||
Tile newTile = newRetainedTiles[index];
|
||||
@ -349,6 +376,9 @@ TiledLayerBuffer<Derived, Tile>::Update(const nsIntRegion& aNewValidRegion,
|
||||
newTile = AsDerived().ValidateTile(newTile, nsIntPoint(tileStartX, tileStartY),
|
||||
tileDrawRegion);
|
||||
NS_ABORT_IF_FALSE(!IsPlaceholder(newTile), "index out of range");
|
||||
#ifdef GFX_TILEDLAYER_PREF_WARNINGS
|
||||
printf_stderr("Store Validate tile %i, %i -> %i\n", tileStartX, tileStartY, index);
|
||||
#endif
|
||||
newRetainedTiles[index] = newTile;
|
||||
|
||||
y += height;
|
||||
|
@ -125,12 +125,12 @@ ReusableTileStoreOGL::HarvestTiles(TiledThebesLayerOGL* aLayer,
|
||||
uint16_t tileSize = aVideoMemoryTiledBuffer->GetTileLength();
|
||||
nsIntRect validBounds = aOldValidRegion.GetBounds();
|
||||
for (int x = validBounds.x; x < validBounds.XMost();) {
|
||||
int w = tileSize - x % tileSize;
|
||||
int w = tileSize - aVideoMemoryTiledBuffer->GetTileStart(x);
|
||||
if (x + w > validBounds.x + validBounds.width)
|
||||
w = validBounds.x + validBounds.width - x;
|
||||
|
||||
for (int y = validBounds.y; y < validBounds.YMost();) {
|
||||
int h = tileSize - y % tileSize;
|
||||
int h = tileSize - aVideoMemoryTiledBuffer->GetTileStart(y);
|
||||
if (y + h > validBounds.y + validBounds.height)
|
||||
h = validBounds.y + validBounds.height - y;
|
||||
|
||||
@ -273,8 +273,18 @@ ReusableTileStoreOGL::DrawTiles(TiledThebesLayerOGL* aLayer,
|
||||
|
||||
// XXX If we have multiple tiles covering the same area, we will
|
||||
// end up with rendering artifacts if the aLayer isn't opaque.
|
||||
uint16_t tileStartX = tile->mTileOrigin.x % tile->mTileSize;
|
||||
uint16_t tileStartY = tile->mTileOrigin.y % tile->mTileSize;
|
||||
int32_t tileStartX;
|
||||
int32_t tileStartY;
|
||||
if (tile->mTileOrigin.x >= 0) {
|
||||
tileStartX = tile->mTileOrigin.x % tile->mTileSize;
|
||||
} else {
|
||||
tileStartX = (tile->mTileSize - (-tile->mTileOrigin.x % tile->mTileSize)) % tile->mTileSize;
|
||||
}
|
||||
if (tile->mTileOrigin.y >= 0) {
|
||||
tileStartY = tile->mTileOrigin.y % tile->mTileSize;
|
||||
} else {
|
||||
tileStartY = (tile->mTileSize - (-tile->mTileOrigin.y % tile->mTileSize)) % tile->mTileSize;
|
||||
}
|
||||
nsIntPoint tileOffset(tile->mTileOrigin.x - tileStartX, tile->mTileOrigin.y - tileStartY);
|
||||
nsIntSize textureSize(tile->mTileSize, tile->mTileSize);
|
||||
aLayer->RenderTile(tile->mTexture, transform, aRenderOffset, tileRegion, tileOffset, textureSize, aMaskLayer);
|
||||
|
@ -237,18 +237,18 @@ TiledThebesLayerOGL::RenderLayer(int aPreviousFrameBuffer, const nsIntPoint& aOf
|
||||
const nsIntRegion& visibleRegion = GetEffectiveVisibleRegion();
|
||||
const nsIntRect visibleRect = visibleRegion.GetBounds();
|
||||
|
||||
unsigned int rowCount = 0;
|
||||
int tileX = 0;
|
||||
for (size_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
|
||||
uint32_t rowCount = 0;
|
||||
uint32_t tileX = 0;
|
||||
for (int32_t x = visibleRect.x; x < visibleRect.x + visibleRect.width;) {
|
||||
rowCount++;
|
||||
uint16_t tileStartX = x % mVideoMemoryTiledBuffer.GetTileLength();
|
||||
uint16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
|
||||
int32_t tileStartX = mVideoMemoryTiledBuffer.GetTileStart(x);
|
||||
int16_t w = mVideoMemoryTiledBuffer.GetTileLength() - tileStartX;
|
||||
if (x + w > visibleRect.x + visibleRect.width)
|
||||
w = visibleRect.x + visibleRect.width - x;
|
||||
int tileY = 0;
|
||||
for (size_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
|
||||
uint16_t tileStartY = y % mVideoMemoryTiledBuffer.GetTileLength();
|
||||
uint16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
|
||||
for (int32_t y = visibleRect.y; y < visibleRect.y + visibleRect.height;) {
|
||||
int32_t tileStartY = mVideoMemoryTiledBuffer.GetTileStart(y);
|
||||
int16_t h = mVideoMemoryTiledBuffer.GetTileLength() - tileStartY;
|
||||
if (y + h > visibleRect.y + visibleRect.height)
|
||||
h = visibleRect.y + visibleRect.height - y;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user