Bug 1741956 - Avoid OP_OVER on Cairo Xlib window surface. r=jrmuizel a=pascalc
authorLee Salzman <lsalzman@mozilla.com>
Mon, 29 Nov 2021 16:34:23 +0000
changeset 671276 ca72cedba6d462d975ed20eb8a4e32f810d75edc
parent 671275 e1e02ca86a8e08d28a750053f51cc30ed144fbb8
child 671277 16f146ce02075f41fba700b8887083cf6c44551b
push id2713
push userpchevrel@mozilla.com
push dateWed, 15 Dec 2021 17:30:39 +0000
treeherdermozilla-release@126673f222be [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, pascalc
bugs1741956
milestone95.0.1
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
widget/gtk/WindowSurfaceX11Image.cpp
--- 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