Bug 1401455 - Use correct GLX visual when rendering with WebRender r=karlt
authorJames Willcox <snorp@snorp.net>
Tue, 13 Mar 2018 11:06:56 -0500
changeset 408591 8d73f18bc1a2097f1271d9d3af554cd23bcc9324
parent 408590 aa0394eb1c570b6d770af2ca55d82ca5b1809b13
child 408592 c0200f9fc1abf1e34a0bb1acb5a9f57d38ca677b
push id100986
push userjwillcox@mozilla.com
push dateFri, 16 Mar 2018 22:19:42 +0000
treeherdermozilla-inbound@8d73f18bc1a2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerskarlt
bugs1401455
milestone61.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1401455 - Use correct GLX visual when rendering with WebRender r=karlt MozReview-Commit-ID: AKT4bgdIkfV
gfx/gl/GLContextGLX.h
widget/gtk/mozgtk/mozgtk.c
widget/gtk/nsWindow.cpp
--- a/gfx/gl/GLContextGLX.h
+++ b/gfx/gl/GLContextGLX.h
@@ -6,16 +6,18 @@
 
 #ifndef GLCONTEXTGLX_H_
 #define GLCONTEXTGLX_H_
 
 #include "GLContext.h"
 #include "GLXLibrary.h"
 #include "mozilla/X11Util.h"
 
+class gfxXlibSurface;
+
 namespace mozilla {
 namespace gl {
 
 class GLContextGLX : public GLContext
 {
 public:
     MOZ_DECLARE_REFCOUNTED_VIRTUAL_TYPENAME(GLContextGLX, override)
     static already_AddRefed<GLContextGLX>
--- a/widget/gtk/mozgtk/mozgtk.c
+++ b/widget/gtk/mozgtk/mozgtk.c
@@ -130,16 +130,18 @@ STUB(gdk_x11_display_get_user_time)
 STUB(gdk_x11_display_get_xdisplay)
 STUB(gdk_x11_get_default_root_xwindow)
 STUB(gdk_x11_get_default_xdisplay)
 STUB(gdk_x11_get_server_time)
 STUB(gdk_x11_get_xatom_by_name)
 STUB(gdk_x11_get_xatom_by_name_for_display)
 STUB(gdk_x11_lookup_xdisplay)
 STUB(gdk_x11_screen_get_xscreen)
+STUB(gdk_x11_screen_get_screen_number)
+STUB(gdk_x11_screen_lookup_visual)
 STUB(gdk_x11_screen_supports_net_wm_hint)
 STUB(gdk_x11_visual_get_xvisual)
 STUB(gdk_x11_window_foreign_new_for_display)
 STUB(gdk_x11_window_lookup_for_display)
 STUB(gdk_x11_window_set_user_time)
 STUB(gdk_x11_xatom_to_atom)
 STUB(gdk_x11_set_sm_client_id)
 STUB(gtk_accel_label_new)
--- a/widget/gtk/nsWindow.cpp
+++ b/widget/gtk/nsWindow.cpp
@@ -111,16 +111,17 @@ using namespace mozilla::widget;
 #include "GLContextProvider.h"
 #include "mozilla/gfx/2D.h"
 #include "mozilla/gfx/HelpersCairo.h"
 #include "mozilla/gfx/GPUProcessManager.h"
 #include "mozilla/layers/CompositorBridgeParent.h"
 #include "mozilla/layers/CompositorThread.h"
 
 #ifdef MOZ_X11
+#include "GLContextGLX.h" // for GLContextGLX::FindVisual()
 #include "GtkCompositorWidget.h"
 #include "gfxXlibSurface.h"
 #include "WindowSurfaceX11Image.h"
 #include "WindowSurfaceX11SHM.h"
 #include "WindowSurfaceXRender.h"
 #endif // MOZ_X11
 #ifdef MOZ_WAYLAND
 #include "nsIClipboard.h"
@@ -134,16 +135,17 @@ using namespace mozilla::widget;
 
 #include <dlfcn.h>
 
 using namespace mozilla;
 using namespace mozilla::gfx;
 using namespace mozilla::widget;
 using namespace mozilla::layers;
 using mozilla::gl::GLContext;
+using mozilla::gl::GLContextGLX;
 
 // Don't put more than this many rects in the dirty region, just fluff
 // out to the bounding-box if there are more
 #define MAX_RECTS_IN_REGION 100
 
 const gint kEvents = GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK |
                      GDK_VISIBILITY_NOTIFY_MASK |
                      GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK |
@@ -3635,21 +3637,40 @@ nsWindow::Create(nsIWidget* aParent,
         bool useAlphaVisual = (mWindowType == eWindowType_popup &&
                                aInitData->mSupportTranslucency);
 
         // mozilla.widget.use-argb-visuals is a hidden pref defaulting to false
         // to allow experimentation
         if (Preferences::GetBool("mozilla.widget.use-argb-visuals", false))
             useAlphaVisual = true;
 
-        // We need to select an ARGB visual here instead of in
-        // SetTransparencyMode() because it has to be done before the
-        // widget is realized.  An ARGB visual is only useful if we
-        // are on a compositing window manager.
-        if (useAlphaVisual) {
+        bool useWebRender = gfxPlatform::Initialized() &&
+            gfx::gfxVars::UseWebRender() &&
+            AllowWebRenderForThisWindow();
+
+        // If using WebRender on X11, we need to select a visual with a depth buffer,
+        // as well as an alpha channel if transparency is requested. This must be done
+        // 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,
+                                         &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));
+            }
+        } else if (useAlphaVisual) {
             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);
             }
         }
 
         // We only move a general managed toplevel window if someone has
@@ -3754,17 +3775,17 @@ nsWindow::Create(nsIWidget* aParent,
         // Create a container to hold child windows and child GtkWidgets.
         GtkWidget *container = moz_container_new();
         mContainer = MOZ_CONTAINER(container);
 
         // "csd" style is set when widget is realized so we need to call
         // it explicitly now.
         gtk_widget_realize(mShell);
 
-        /* There are two cases here:
+        /* There are several cases here:
          *
          * 1) We're running on Gtk+ without client side decorations.
          *    Content is rendered to mShell window and we listen
          *    to the Gtk+ events on mShell
          * 2) We're running on Gtk+ and client side decorations
          *    are drawn by Gtk+ to mShell. Content is rendered to mContainer
          *    and we listen to the Gtk+ events on mContainer.
          * 3) We're running on Wayland. All gecko content is rendered