Bug 1478661 - Replace IsComposited() with explicit alpha visual state, r?jhorak draft
authorMartin Stransky <stransky@redhat.com>
Thu, 26 Jul 2018 13:23:34 +0200
changeset 823003 b48ea3677d66a4dd6347892af18538be60d1e9b6
parent 822828 7ba07ef0e4532b644b812942aa38af4510dbc74f
child 823405 5c3ea5c0690c2ae2c354d8c1b63902ab43992d17
push id117552
push userstransky@redhat.com
push dateThu, 26 Jul 2018 14:04:25 +0000
reviewersjhorak
bugs1478661
milestone63.0a1
Bug 1478661 - Replace IsComposited() with explicit alpha visual state, r?jhorak IsComposited() does not reflect Visual selected by GLContextGLX::FindVisual() which is used by WebRender which leads to shaped window rendering with WebRender. IsComposited() is replaced by mHasAlphaVisual variable which is explicitly set when we have an alpha visual and we don't need to use shape X11 extension. MozReview-Commit-ID: 1kDLwkUyHte
widget/gtk/nsWindow.cpp
widget/gtk/nsWindow.h
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -477,16 +477,18 @@ nsWindow::nsWindow()
     mTransparencyBitmapHeight = 0;
 
 #if GTK_CHECK_VERSION(3,4,0)
     mLastScrollEventTime = GDK_CURRENT_TIME;
 #endif
     mPendingConfigures = 0;
     mCSDSupportLevel = CSD_SUPPORT_NONE;
     mDrawInTitlebar = false;
+
+    mHasAlphaVisual = false;
 }
 
 nsWindow::~nsWindow()
 {
     LOG(("nsWindow::~nsWindow() [%p]\n", (void *)this));
 
     delete[] mTransparencyBitmap;
     mTransparencyBitmap = nullptr;
@@ -2129,17 +2131,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 
     // Our bounds may have changed after calling WillPaintWindow.  Clip
     // to the new bounds here.  The region is relative to this
     // window.
     region.And(region, LayoutDeviceIntRect(0, 0, mBounds.width, mBounds.height));
 
     bool shaped = false;
     if (eTransparencyTransparent == GetTransparencyMode()) {
-        if (IsComposited()) {
+        if (mHasAlphaVisual) {
             // Remove possible shape mask from when window manger was not
             // previously compositing.
             static_cast<nsWindow*>(GetTopLevelWidget())->
                 ClearTransparencyBitmap();
         } else {
             shaped = true;
         }
     }
@@ -2232,17 +2234,17 @@ nsWindow::OnExposeEvent(cairo_t *cr)
 
 #endif // MOZ_X11
 
     bool painted = false;
     {
       if (GetLayerManager()->GetBackendType() == LayersBackend::LAYERS_BASIC) {
         if (GetTransparencyMode() == eTransparencyTransparent &&
             layerBuffering == BufferMode::BUFFER_NONE &&
-            IsComposited()) {
+            mHasAlphaVisual) {
           // If our draw target is unbuffered and we use an alpha channel,
           // clear the image beforehand to ensure we don't get artifacts from a
           // reused SHM image. See bug 1258086.
           dt->ClearRect(Rect(boundsRect));
         }
         AutoLayerManagerSetup setupLayerManager(this, ctx, layerBuffering);
         painted = listener->PaintWindow(this, region);
 
@@ -3656,18 +3658,18 @@ nsWindow::Create(nsIWidget* aParent,
     // figure out our parent window
     GtkWidget      *parentMozContainer = nullptr;
     GtkContainer   *parentGtkContainer = nullptr;
     GdkWindow      *parentGdkWindow = nullptr;
     GtkWindow      *topLevelParent = nullptr;
     nsWindow       *parentnsWindow = nullptr;
     GtkWidget      *eventWidget = nullptr;
     bool            drawToContainer = false;
-    bool            useAlphaVisual = (mWindowType == eWindowType_popup &&
-                                     aInitData->mSupportTranslucency);
+    bool            needsAlphaVisual = (mWindowType == eWindowType_popup &&
+                                       aInitData->mSupportTranslucency);
 
     if (aParent) {
         parentnsWindow = static_cast<nsWindow*>(aParent);
         parentGdkWindow = parentnsWindow->mGdkWindow;
     } else if (aNativeParent && GDK_IS_WINDOW(aNativeParent)) {
         parentGdkWindow = GDK_WINDOW(aNativeParent);
         parentnsWindow = get_window_for_gdk_window(parentGdkWindow);
         if (!parentnsWindow)
@@ -3726,32 +3728,38 @@ nsWindow::Create(nsIWidget* aParent,
         // before the widget is realized.
         if (mIsX11Display && useWebRender) {
             auto display =
                 GDK_DISPLAY_XDISPLAY(gtk_widget_get_display(mShell));
             auto screen = gtk_widget_get_screen(mShell);
             int screenNumber = GDK_SCREEN_XNUMBER(screen);
             int visualId = 0;
             if (GLContextGLX::FindVisual(display, screenNumber,
-                                         useWebRender, useAlphaVisual,
+                                         useWebRender, needsAlphaVisual,
                                          &visualId)) {
                 // If we're using CSD, rendering will go through mContainer, but
                 // it will inherit this visual as it is a child of mShell.
                 gtk_widget_set_visual(mShell,
                                       gdk_x11_screen_lookup_visual(screen,
                                                                    visualId));
+                mHasAlphaVisual = true;
+            } else {
+                NS_WARNING("We're missing X11 Visual for WebRender!");
             }
         } else
 #endif // MOZ_X11
         {
-            if (useAlphaVisual) {
+            if (needsAlphaVisual) {
                 GdkScreen *screen = gtk_widget_get_screen(mShell);
                 if (gdk_screen_is_composited(screen)) {
                     GdkVisual *visual = gdk_screen_get_rgba_visual(screen);
-                    gtk_widget_set_visual(mShell, visual);
+                    if (visual) {
+                        gtk_widget_set_visual(mShell, visual);
+                        mHasAlphaVisual = true;
+                    }
                 }
             }
         }
 
         // We only move a general managed toplevel window if someone has
         // actually placed the window somewhere.  If no placement has taken
         // place, we just let the window manager Do The Right Thing.
         NativeResize();
@@ -4125,17 +4133,17 @@ nsWindow::Create(nsIWidget* aParent,
 #ifdef MOZ_X11
     if (mIsX11Display && mGdkWindow) {
       mXDisplay = GDK_WINDOW_XDISPLAY(mGdkWindow);
       mXWindow = gdk_x11_window_get_xid(mGdkWindow);
 
       GdkVisual* gdkVisual = gdk_window_get_visual(mGdkWindow);
       mXVisual = gdk_x11_visual_get_xvisual(gdkVisual);
       mXDepth = gdk_visual_get_depth(gdkVisual);
-      bool shaped = useAlphaVisual && !IsComposited();
+      bool shaped = needsAlphaVisual && !mHasAlphaVisual;
 
       mSurfaceProvider.Initialize(mXDisplay, mXWindow, mXVisual, mXDepth,
                                   shaped);
     }
 #ifdef MOZ_WAYLAND
     else if (!mIsX11Display) {
       mSurfaceProvider.Initialize(this);
     }
@@ -7185,34 +7193,20 @@ nsWindow::RoundsWidgetCoordinatesTo()
     return GdkScaleFactor();
 }
 
 void nsWindow::GetCompositorWidgetInitData(mozilla::widget::CompositorWidgetInitData* aInitData)
 {
   *aInitData = mozilla::widget::GtkCompositorWidgetInitData(
                                 (mXWindow != X11None) ? mXWindow : (uintptr_t)nullptr,
                                 mXDisplay ? nsCString(XDisplayString(mXDisplay)) : nsCString(),
-                                mIsTransparent && !IsComposited(),
+                                mIsTransparent && !mHasAlphaVisual,
                                 GetClientSize());
 }
 
-bool
-nsWindow::IsComposited() const
-{
-  if (!mGdkWindow) {
-    NS_WARNING("nsWindow::HasARGBVisual called before realization!");
-    return false;
-  }
-
-  GdkScreen* gdkScreen = gdk_window_get_screen(mGdkWindow);
-  return gdk_screen_is_composited(gdkScreen) &&
-         (gdk_window_get_visual(mGdkWindow)
-            == gdk_screen_get_rgba_visual(gdkScreen));
-}
-
 #ifdef MOZ_WAYLAND
 wl_display*
 nsWindow::GetWaylandDisplay()
 {
   // Available as of GTK 3.8+
   static auto sGdkWaylandDisplayGetWlDisplay =
       (wl_display *(*)(GdkDisplay *))
       dlsym(RTLD_DEFAULT, "gdk_wayland_display_get_wl_display");
--- a/widget/gtk/nsWindow.h
+++ b/widget/gtk/nsWindow.h
@@ -486,17 +486,16 @@ private:
       CheckForRollup(0, 0, false, true);
     }
 
     bool               GetDragInfo(mozilla::WidgetMouseEvent* aMouseEvent,
                                    GdkWindow** aWindow, gint* aButton,
                                    gint* aRootX, gint* aRootY);
     void               ClearCachedResources();
     nsIWidgetListener* GetListener();
-    bool               IsComposited() const;
 
     void               UpdateClientOffsetForCSDWindow();
 
     nsWindow*          GetTransientForWindowIfPopup();
     bool               IsHandlingTouchSequence(GdkEventSequence* aSequence);
 
 #ifdef MOZ_X11
     typedef enum { GTK_WIDGET_COMPOSIDED_DEFAULT = 0,
@@ -604,16 +603,19 @@ private:
     static GdkCursor   *gsGtkCursorCache[eCursorCount];
 
     // Transparency
     bool         mIsTransparent;
     // This bitmap tracks which pixels are transparent. We don't support
     // full translucency at this time; each pixel is either fully opaque
     // or fully transparent.
     gchar*       mTransparencyBitmap;
+    // True when we're on compositing window manager and this
+    // window is using visual with alpha channel.
+    bool         mHasAlphaVisual;
 
     // all of our DND stuff
     void   InitDragEvent(mozilla::WidgetDragEvent& aEvent);
 
     float              mLastMotionPressure;
 
     // Remember the last sizemode so that we can restore it when
     // leaving fullscreen