mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Fix drawing of GL Thebes layers with rotation when using tiled textures
Drawing of rotated buffers relies on texture-wrapping, but in the case of tiled textures, this would cause each individual tile to wrap instead of wrapping the compound texture. Add a special case for tiled textures that manually does the wrapping.
This commit is contained in:
parent
085e4aff4d
commit
9f3d985c52
@ -191,40 +191,96 @@ ThebesLayerBufferOGL::RenderTo(const nsIntPoint& aOffset,
|
||||
renderRegion = &visibleRegion;
|
||||
}
|
||||
|
||||
mTexImage->BeginTileIteration();
|
||||
if (mTexImageOnWhite) {
|
||||
mTexImageOnWhite->BeginTileIteration();
|
||||
NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
|
||||
}
|
||||
nsIntRegion region(*renderRegion);
|
||||
nsIntPoint origin = GetOriginOffset();
|
||||
region.MoveBy(-origin); // translate into TexImage space, buffer origin might not be at texture (0,0)
|
||||
|
||||
// Figure out the intersecting draw region
|
||||
nsIntSize texSize = mTexImage->GetSize();
|
||||
nsIntRect textureRect = nsIntRect(0, 0, texSize.width, texSize.height);
|
||||
textureRect.MoveBy(region.GetBounds().TopLeft());
|
||||
nsIntRegion subregion;
|
||||
subregion.And(region, textureRect);
|
||||
if (subregion.IsEmpty()) // Region is empty, nothing to draw
|
||||
return;
|
||||
|
||||
nsIntRegion screenRects;
|
||||
nsIntRegion regionRects;
|
||||
|
||||
// Collect texture/screen coordinates for drawing
|
||||
nsIntRegionRectIterator iter(subregion);
|
||||
while (const nsIntRect* iterRect = iter.Next()) {
|
||||
nsIntRect regionRect = *iterRect;
|
||||
nsIntRect screenRect = regionRect;
|
||||
screenRect.MoveBy(origin);
|
||||
|
||||
screenRects.Or(screenRects, screenRect);
|
||||
regionRects.Or(regionRects, regionRect);
|
||||
}
|
||||
|
||||
mTexImage->BeginTileIteration();
|
||||
if (mTexImageOnWhite) {
|
||||
NS_ASSERTION(mTexImage->GetTileCount() == mTexImageOnWhite->GetTileCount(),
|
||||
"Tile count mismatch on component alpha texture");
|
||||
mTexImageOnWhite->BeginTileIteration();
|
||||
}
|
||||
|
||||
bool usingTiles = (mTexImage->GetTileCount() > 1);
|
||||
do {
|
||||
nsIntRect textureRect = mTexImage->GetTileRect();
|
||||
textureRect.MoveBy(region.GetBounds().x, region.GetBounds().y);
|
||||
nsIntRegion subregion(region);
|
||||
subregion.And(region, textureRect); // region this texture is visible in
|
||||
if (subregion.IsEmpty()) {
|
||||
continue;
|
||||
if (mTexImageOnWhite) {
|
||||
NS_ASSERTION(mTexImageOnWhite->GetTileRect() == mTexImage->GetTileRect(), "component alpha textures should be the same size.");
|
||||
}
|
||||
|
||||
nsIntRect tileRect = mTexImage->GetTileRect();
|
||||
|
||||
// Bind textures.
|
||||
TextureImage::ScopedBindTexture texBind(mTexImage, LOCAL_GL_TEXTURE0);
|
||||
TextureImage::ScopedBindTexture texOnWhiteBind(mTexImageOnWhite, LOCAL_GL_TEXTURE1);
|
||||
|
||||
nsIntRegionRectIterator iter(subregion);
|
||||
while (const nsIntRect *iterRect = iter.Next()) {
|
||||
nsIntRect regionRect = *iterRect; // one rectangle of this texture's region
|
||||
// translate into the correct place for this texture sub-region
|
||||
nsIntRect screenRect = regionRect;
|
||||
screenRect.MoveBy(origin);
|
||||
program->SetLayerQuadRect(screenRect);
|
||||
// Draw texture. If we're using tiles, we do repeating manually, as texture
|
||||
// repeat would cause each individual tile to repeat instead of the
|
||||
// compound texture as a whole. This involves drawing at most 4 sections,
|
||||
// 2 for each axis that has texture repeat.
|
||||
for (int y = 0; y < (usingTiles ? 2 : 1); y++) {
|
||||
for (int x = 0; x < (usingTiles ? 2 : 1); x++) {
|
||||
nsIntRect currentTileRect(tileRect);
|
||||
currentTileRect.MoveBy(x * texSize.width, y * texSize.height);
|
||||
|
||||
regionRect.MoveBy(-mTexImage->GetTileRect().TopLeft()); // get region of tile
|
||||
aManager->BindAndDrawQuadWithTextureRect(program, regionRect,
|
||||
textureRect.Size(),
|
||||
mTexImage->GetWrapMode());
|
||||
nsIntRegionRectIterator screenIter(screenRects);
|
||||
nsIntRegionRectIterator regionIter(regionRects);
|
||||
|
||||
const nsIntRect* screenRect;
|
||||
const nsIntRect* regionRect;
|
||||
while ((screenRect = screenIter.Next()) &&
|
||||
(regionRect = regionIter.Next())) {
|
||||
nsIntRect tileScreenRect(*screenRect);
|
||||
nsIntRect tileRegionRect(*regionRect);
|
||||
|
||||
// When we're using tiles, find the intersection between the tile
|
||||
// rect and this region rect. Tiling is then handled by the
|
||||
// outer for-loops and modifying the tile rect.
|
||||
if (usingTiles) {
|
||||
tileScreenRect.MoveBy(-origin);
|
||||
tileScreenRect = tileScreenRect.Intersect(currentTileRect);
|
||||
tileScreenRect.MoveBy(origin);
|
||||
|
||||
if (tileScreenRect.IsEmpty())
|
||||
continue;
|
||||
|
||||
tileRegionRect = regionRect->Intersect(currentTileRect);
|
||||
tileRegionRect.MoveBy(-currentTileRect.TopLeft());
|
||||
}
|
||||
|
||||
program->SetLayerQuadRect(tileScreenRect);
|
||||
aManager->BindAndDrawQuadWithTextureRect(program, tileRegionRect,
|
||||
tileRect.Size(),
|
||||
mTexImage->GetWrapMode());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mTexImageOnWhite)
|
||||
mTexImageOnWhite->NextTile();
|
||||
} while (mTexImage->NextTile());
|
||||
}
|
||||
|
||||
|
@ -901,6 +901,11 @@ void TiledTextureImage::Resize(const nsIntSize& aSize)
|
||||
mTextureState = Allocated;
|
||||
}
|
||||
|
||||
PRUint32 TiledTextureImage::GetTileCount()
|
||||
{
|
||||
return mImages.Length();
|
||||
}
|
||||
|
||||
PRBool
|
||||
GLContext::ResizeOffscreenFBO(const gfxIntSize& aSize)
|
||||
{
|
||||
|
@ -218,6 +218,11 @@ public:
|
||||
};
|
||||
|
||||
virtual GLuint GetTextureID() = 0;
|
||||
|
||||
virtual PRUint32 GetTileCount() {
|
||||
return 1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set this TextureImage's size, and ensure a texture has been
|
||||
* allocated. Must not be called between BeginUpdate and EndUpdate.
|
||||
@ -394,6 +399,7 @@ public:
|
||||
virtual gfxASurface* BeginUpdate(nsIntRegion& aRegion);
|
||||
virtual void EndUpdate();
|
||||
virtual void Resize(const nsIntSize& aSize);
|
||||
virtual PRUint32 GetTileCount();
|
||||
virtual void BeginTileIteration();
|
||||
virtual PRBool NextTile();
|
||||
virtual nsIntRect GetTileRect();
|
||||
|
Loading…
Reference in New Issue
Block a user