Bug 1741956 - Avoid OP_OVER on Cairo Xlib window surface. r=jrmuizel a=pascalc
When we use OP_OVER for the final blit in WindowSurfaceX11Image::Commit,
this causes Cairo to hit a compositing fallback that uses XGetImage on
the window to get the pixel data, blends to it, then XPutImage's the
result back. We want to avoid this both because XGetImage may cause
errors and it is slow to read back from the window server.
If we use CopySurface/OP_SOURCE instead we avoid the readback via
XGetImage and so bypass both problems.
Differential Revision:
https://phabricator.services.mozilla.com/D132319
--- a/widget/gtk/WindowSurfaceX11Image.cpp
+++ b/widget/gtk/WindowSurfaceX11Image.cpp
@@ -224,36 +224,37 @@ void WindowSurfaceX11Image::Commit(
gfx::Factory::CreateSourceSurfaceForCairoSurface(
mImageSurface->CairoSurface(), mImageSurface->GetSize(),
mImageSurface->Format());
if (!dt || !surf) {
return;
}
gfx::IntRect bounds = aInvalidRegion.GetBounds().ToUnknownRect();
- gfx::Rect rect(bounds);
- if (rect.IsEmpty()) {
+ if (bounds.IsEmpty()) {
return;
}
+ if (mIsShaped) {
+ ApplyTransparencyBitmap();
+ }
+
uint32_t numRects = aInvalidRegion.GetNumRects();
- if (numRects != 1) {
+ if (numRects == 1) {
+ dt->CopySurface(surf, bounds, bounds.TopLeft());
+ } else {
AutoTArray<IntRect, 32> rects;
rects.SetCapacity(numRects);
for (auto iter = aInvalidRegion.RectIter(); !iter.Done(); iter.Next()) {
rects.AppendElement(iter.Get().ToUnknownRect());
}
dt->PushDeviceSpaceClipRects(rects.Elements(), rects.Length());
- }
- if (mIsShaped) {
- ApplyTransparencyBitmap();
- }
+ dt->DrawSurface(surf, gfx::Rect(bounds), gfx::Rect(bounds),
+ DrawSurfaceOptions(),
+ DrawOptions(1.0f, CompositionOp::OP_SOURCE));
- dt->DrawSurface(surf, rect, rect);
-
- if (numRects != 1) {
dt->PopClip();
}
}
} // namespace widget
} // namespace mozilla