Bug 1640048 - [X11] Initial EGL runtime support, r=jgilbert,rmader
authorMartin Stransky <stransky@redhat.com>
Thu, 02 Jul 2020 13:50:41 +0000
changeset 538434 26aa0ccc6c5e29342acf553b44c9c43564224e03
parent 538433 624547a0b29caa05bcd10bdfd938d95a74aa15f8
child 538435 93f6f1edf8a097e36230431142aba37345c0b3fe
push id37563
push usercbrindusan@mozilla.com
push dateThu, 02 Jul 2020 21:49:48 +0000
treeherdermozilla-central@f0ac79e1ed53 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjgilbert, rmader
bugs1640048
milestone80.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 1640048 - [X11] Initial EGL runtime support, r=jgilbert,rmader Patch by Robert Mader [:rmader] This enables support for EGL on X11, toggled by setting the MOZ_X11_EGL env variable. It allows running the Webrender and OpenGL compositors basically like we do with GLX by default. Note that that there are several things missing: - no pixmap sharing support (not clear if we want/need it) - it still uses GLX for several things like finding the X11 visual, VSync and glxtest. It includes some cleanups, mostly in order to decouple the X11 and Wayland implementations a bit more. Differential Revision: https://phabricator.services.mozilla.com/D76417
gfx/gl/GLContextProvider.h
gfx/gl/GLContextProviderEGL.cpp
gfx/gl/GLContextProviderWayland.cpp
gfx/gl/GLContextProviderX11.cpp
gfx/gl/moz.build
widget/gtk/GtkCompositorWidget.cpp
widget/gtk/GtkCompositorWidget.h
--- a/gfx/gl/GLContextProvider.h
+++ b/gfx/gl/GLContextProvider.h
@@ -38,38 +38,42 @@ namespace gl {
 
 #ifdef XP_MACOSX
 #  define GL_CONTEXT_PROVIDER_NAME GLContextProviderCGL
 #  include "GLContextProviderImpl.h"
 #  undef GL_CONTEXT_PROVIDER_NAME
 #  define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderCGL
 #endif
 
+#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
+#include "GLContextProviderImpl.h"
+#undef GL_CONTEXT_PROVIDER_NAME
+
 #if defined(MOZ_X11)
 #  define GL_CONTEXT_PROVIDER_NAME GLContextProviderGLX
 #  include "GLContextProviderImpl.h"
 #  undef GL_CONTEXT_PROVIDER_NAME
-#  define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderGLX
+#  define GL_CONTEXT_PROVIDER_NAME GLContextProviderX11
+#  include "GLContextProviderImpl.h"
+#  undef GL_CONTEXT_PROVIDER_NAME
+#  if defined(MOZ_WAYLAND)
+#    define GL_CONTEXT_PROVIDER_NAME GLContextProviderWayland
+#    include "GLContextProviderImpl.h"
+#    undef GL_CONTEXT_PROVIDER_NAME
+#    define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWayland
+#  endif
+#  ifndef GL_CONTEXT_PROVIDER_DEFAULT
+#    define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderX11
+#  endif
 #endif
 
-#define GL_CONTEXT_PROVIDER_NAME GLContextProviderEGL
-#include "GLContextProviderImpl.h"
-#undef GL_CONTEXT_PROVIDER_NAME
 #ifndef GL_CONTEXT_PROVIDER_DEFAULT
 #  define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEGL
 #endif
 
-#if defined(MOZ_WAYLAND)
-#  define GL_CONTEXT_PROVIDER_NAME GLContextProviderWayland
-#  include "GLContextProviderImpl.h"
-#  undef GL_CONTEXT_PROVIDER_NAME
-#  undef GL_CONTEXT_PROVIDER_DEFAULT
-#  define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderWayland
-#endif
-
 #if defined(MOZ_WIDGET_UIKIT)
 #  define GL_CONTEXT_PROVIDER_NAME GLContextProviderEAGL
 #  include "GLContextProviderImpl.h"
 #  undef GL_CONTEXT_PROVIDER_NAME
 #  ifndef GL_CONTEXT_PROVIDER_DEFAULT
 #    define GL_CONTEXT_PROVIDER_DEFAULT GLContextProviderEAGL
 #  endif
 #endif
--- a/gfx/gl/GLContextProviderEGL.cpp
+++ b/gfx/gl/GLContextProviderEGL.cpp
@@ -70,30 +70,24 @@
 #include "nsDebug.h"
 #include "nsIWidget.h"
 #include "nsThreadUtils.h"
 #include "ScopedGLHelpers.h"
 #include "TextureImageEGL.h"
 
 #if defined(MOZ_WIDGET_GTK)
 #  include "mozilla/widget/GtkCompositorWidget.h"
-#endif
-
-#if defined(MOZ_WAYLAND)
-#  include "nsDataHashtable.h"
-
-#  include <gtk/gtk.h>
-#  include <gdk/gdkx.h>
-#  include <gdk/gdkwayland.h>
-#  include <wayland-egl.h>
-#  include <dlfcn.h>
-
-#  define IS_WAYLAND_DISPLAY()    \
-    (gdk_display_get_default() && \
-     !GDK_IS_X11_DISPLAY(gdk_display_get_default()))
+#  if defined(MOZ_WAYLAND)
+#    include <dlfcn.h>
+#    include <gdk/gdkwayland.h>
+#    include <wayland-egl.h>
+#    define IS_WAYLAND_DISPLAY()    \
+      (gdk_display_get_default() && \
+       GDK_IS_WAYLAND_DISPLAY(gdk_display_get_default()))
+#  endif
 #endif
 
 using namespace mozilla::gfx;
 
 namespace mozilla {
 namespace gl {
 
 using namespace mozilla::widget;
@@ -237,27 +231,29 @@ static EGLSurface CreateSurfaceFromNativ
 /* GLContextEGLFactory class was added as a friend of GLContextEGL
  * so that it could access  GLContextEGL::CreateGLContext. This was
  * done so that a new function would not need to be added to the shared
  * GLContextProvider interface.
  */
 class GLContextEGLFactory {
  public:
   static already_AddRefed<GLContext> Create(EGLNativeWindowType aWindow,
-                                            bool aWebRender);
+                                            bool aWebRender, int32_t aDepth);
   static already_AddRefed<GLContext> CreateImpl(EGLNativeWindowType aWindow,
-                                                bool aWebRender, bool aUseGles);
+                                                bool aWebRender, bool aUseGles,
+                                                int32_t aDepth);
 
  private:
   GLContextEGLFactory() = default;
   ~GLContextEGLFactory() = default;
 };
 
 already_AddRefed<GLContext> GLContextEGLFactory::CreateImpl(
-    EGLNativeWindowType aWindow, bool aWebRender, bool aUseGles) {
+    EGLNativeWindowType aWindow, bool aWebRender, bool aUseGles,
+    int32_t aDepth) {
   nsCString discardFailureId;
   if (!GLLibraryEGL::EnsureInitialized(false, &discardFailureId)) {
     gfxCriticalNote << "Failed to load EGL library 3!";
     return nullptr;
   }
 
   auto* egl = gl::GLLibraryEGL::Get();
   bool doubleBuffered = true;
@@ -268,20 +264,28 @@ already_AddRefed<GLContext> GLContextEGL
     // formart
     const int bpp = 32;
     const bool withDepth = true;
     if (!CreateConfig(egl, &config, bpp, withDepth, aUseGles)) {
       gfxCriticalNote << "Failed to create EGLConfig for WebRender ANGLE!";
       return nullptr;
     }
   } else {
-    if (!CreateConfigScreen(egl, &config, /* aEnableDepthBuffer */ aWebRender,
-                            aUseGles)) {
-      gfxCriticalNote << "Failed to create EGLConfig!";
-      return nullptr;
+    if (aDepth) {
+      if (!CreateConfig(egl, &config, aDepth, aWebRender, aUseGles)) {
+        gfxCriticalNote
+            << "Failed to create EGLConfig for WebRender with depth!";
+        return nullptr;
+      }
+    } else {
+      if (!CreateConfigScreen(egl, &config, /* aEnableDepthBuffer */ aWebRender,
+                              aUseGles)) {
+        gfxCriticalNote << "Failed to create EGLConfig!";
+        return nullptr;
+      }
     }
   }
 
   EGLSurface surface = EGL_NO_SURFACE;
   if (aWindow) {
     surface = mozilla::gl::CreateSurfaceFromNativeWindow(egl, aWindow, config);
   }
 
@@ -315,24 +319,24 @@ already_AddRefed<GLContext> GLContextEGL
   if (aWebRender && egl->IsANGLE()) {
     MOZ_ASSERT(doubleBuffered);
     egl->fSwapInterval(egl->Display(), 0);
   }
   return gl.forget();
 }
 
 already_AddRefed<GLContext> GLContextEGLFactory::Create(
-    EGLNativeWindowType aWindow, bool aWebRender) {
+    EGLNativeWindowType aWindow, bool aWebRender, int32_t aDepth) {
   RefPtr<GLContext> glContext;
 #if !defined(MOZ_WIDGET_ANDROID)
-  glContext = CreateImpl(aWindow, aWebRender, /* aUseGles */ false);
+  glContext = CreateImpl(aWindow, aWebRender, /* aUseGles */ false, aDepth);
 #endif  // !defined(MOZ_WIDGET_ANDROID)
 
   if (!glContext) {
-    glContext = CreateImpl(aWindow, aWebRender, /* aUseGles */ true);
+    glContext = CreateImpl(aWindow, aWebRender, /* aUseGles */ true, aDepth);
   }
   return glContext.forget();
 }
 
 #if defined(MOZ_WAYLAND) || defined(MOZ_WIDGET_ANDROID)
 /* static */
 EGLSurface GLContextEGL::CreateEGLSurfaceForCompositorWidget(
     widget::CompositorWidget* aCompositorWidget, const EGLConfig aConfig) {
@@ -948,20 +952,24 @@ already_AddRefed<GLContext> GLContextPro
 
   return gl.forget();
 }
 
 already_AddRefed<GLContext> GLContextProviderEGL::CreateForCompositorWidget(
     CompositorWidget* aCompositorWidget, bool aWebRender,
     bool aForceAccelerated) {
   EGLNativeWindowType window = nullptr;
+  int32_t depth = 0;
   if (aCompositorWidget) {
     window = GET_NATIVE_WINDOW_FROM_COMPOSITOR_WIDGET(aCompositorWidget);
+#if defined(MOZ_WIDGET_GTK)
+    depth = aCompositorWidget->AsX11()->GetDepth();
+#endif
   }
-  return GLContextEGLFactory::Create(window, aWebRender);
+  return GLContextEGLFactory::Create(window, aWebRender, depth);
 }
 
 #if defined(MOZ_WIDGET_ANDROID)
 EGLSurface GLContextEGL::CreateCompatibleSurface(void* aWindow) {
   if (mConfig == EGL_NO_CONFIG) {
     MOZ_CRASH("GFX: Failed with invalid EGLConfig 2!");
   }
 
--- a/gfx/gl/GLContextProviderWayland.cpp
+++ b/gfx/gl/GLContextProviderWayland.cpp
@@ -10,61 +10,61 @@
 
 #include "GLContextProvider.h"
 
 namespace mozilla::gl {
 
 using namespace mozilla::gfx;
 using namespace mozilla::widget;
 
-static class GLContextProviderGLX sGLContextProviderGLX;
+static class GLContextProviderX11 sGLContextProviderX11;
 static class GLContextProviderEGL sGLContextProviderEGL;
 
 already_AddRefed<GLContext> GLContextProviderWayland::CreateWrappingExisting(
     void* aContext, void* aSurface) {
   if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
-    return sGLContextProviderGLX.CreateWrappingExisting(aContext, aSurface);
+    return sGLContextProviderX11.CreateWrappingExisting(aContext, aSurface);
   } else {
     return sGLContextProviderEGL.CreateWrappingExisting(aContext, aSurface);
   }
 }
 
 already_AddRefed<GLContext> GLContextProviderWayland::CreateForCompositorWidget(
     CompositorWidget* aCompositorWidget, bool aWebRender,
     bool aForceAccelerated) {
   if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
-    return sGLContextProviderGLX.CreateForCompositorWidget(
+    return sGLContextProviderX11.CreateForCompositorWidget(
         aCompositorWidget, aWebRender, aForceAccelerated);
   } else {
     return sGLContextProviderEGL.CreateForCompositorWidget(
         aCompositorWidget, aWebRender, aForceAccelerated);
   }
 }
 
 /*static*/
 already_AddRefed<GLContext> GLContextProviderWayland::CreateHeadless(
     const GLContextCreateDesc& desc, nsACString* const out_failureId) {
   if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
-    return sGLContextProviderGLX.CreateHeadless(desc, out_failureId);
+    return sGLContextProviderX11.CreateHeadless(desc, out_failureId);
   } else {
     return sGLContextProviderEGL.CreateHeadless(desc, out_failureId);
   }
 }
 
 /*static*/
 GLContext* GLContextProviderWayland::GetGlobalContext() {
   if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
-    return sGLContextProviderGLX.GetGlobalContext();
+    return sGLContextProviderX11.GetGlobalContext();
   } else {
     return sGLContextProviderEGL.GetGlobalContext();
   }
 }
 
 /*static*/
 void GLContextProviderWayland::Shutdown() {
   if (GDK_IS_X11_DISPLAY(gdk_display_get_default())) {
-    sGLContextProviderGLX.Shutdown();
+    sGLContextProviderX11.Shutdown();
   } else {
     sGLContextProviderEGL.Shutdown();
   }
 }
 
 }  // namespace mozilla::gl
new file mode 100644
--- /dev/null
+++ b/gfx/gl/GLContextProviderX11.cpp
@@ -0,0 +1,72 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "prenv.h"
+
+#include "GLContextProvider.h"
+
+namespace mozilla::gl {
+
+using namespace mozilla::gfx;
+using namespace mozilla::widget;
+
+static class GLContextProviderGLX sGLContextProviderGLX;
+static class GLContextProviderEGL sGLContextProviderEGL;
+
+static bool UseGLX() {
+  static bool useGLX = !PR_GetEnv("MOZ_X11_EGL");
+  return useGLX;
+}
+
+already_AddRefed<GLContext> GLContextProviderX11::CreateWrappingExisting(
+    void* aContext, void* aSurface) {
+  if (UseGLX()) {
+    return sGLContextProviderGLX.CreateWrappingExisting(aContext, aSurface);
+  } else {
+    return sGLContextProviderEGL.CreateWrappingExisting(aContext, aSurface);
+  }
+}
+
+already_AddRefed<GLContext> GLContextProviderX11::CreateForCompositorWidget(
+    CompositorWidget* aCompositorWidget, bool aWebRender,
+    bool aForceAccelerated) {
+  if (UseGLX()) {
+    return sGLContextProviderGLX.CreateForCompositorWidget(
+        aCompositorWidget, aWebRender, aForceAccelerated);
+  } else {
+    return sGLContextProviderEGL.CreateForCompositorWidget(
+        aCompositorWidget, aWebRender, aForceAccelerated);
+  }
+}
+
+/*static*/
+already_AddRefed<GLContext> GLContextProviderX11::CreateHeadless(
+    const GLContextCreateDesc& desc, nsACString* const out_failureId) {
+  if (UseGLX()) {
+    return sGLContextProviderGLX.CreateHeadless(desc, out_failureId);
+  } else {
+    return sGLContextProviderEGL.CreateHeadless(desc, out_failureId);
+  }
+}
+
+/*static*/
+GLContext* GLContextProviderX11::GetGlobalContext() {
+  if (UseGLX()) {
+    return sGLContextProviderGLX.GetGlobalContext();
+  } else {
+    return sGLContextProviderEGL.GetGlobalContext();
+  }
+}
+
+/*static*/
+void GLContextProviderX11::Shutdown() {
+  if (UseGLX()) {
+    sGLContextProviderGLX.Shutdown();
+  } else {
+    sGLContextProviderEGL.Shutdown();
+  }
+}
+
+}  // namespace mozilla::gl
--- a/gfx/gl/moz.build
+++ b/gfx/gl/moz.build
@@ -47,22 +47,16 @@ EXPORTS += [
     'MozFramebuffer.h',
     'ScopedGLHelpers.h',
     'SharedSurface.h',
     'SharedSurfaceEGL.h',
     'SharedSurfaceGL.h',
     'SurfaceTypes.h',
 ]
 
-if CONFIG['MOZ_X11']:
-    EXPORTS += [
-        'GLContextGLX.h',
-        'GLXLibrary.h',
-    ]
-
 # Win32 is a special snowflake, for ANGLE
 if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'windows':
     EXPORTS += [
         'GLContextWGL.h',
         'SharedSurfaceANGLE.h', # Needs <windows.h> for `HANDLE`.
         'SharedSurfaceD3D11Interop.h',
         'WGLLibrary.h',
     ]
@@ -111,19 +105,22 @@ elif gl_provider == 'EAGL':
         'GLContextEAGL.h',
     ]
 
 elif gl_provider == 'GLX':
     # GLContextProviderGLX.cpp needs to be kept out of UNIFIED_SOURCES
     # as it includes X11 headers which cause conflicts.
     SOURCES += [
         'GLContextProviderGLX.cpp',
+        'GLContextProviderX11.cpp',
         'SharedSurfaceGLX.cpp'
     ]
     EXPORTS += [
+        'GLContextGLX.h',
+        'GLXLibrary.h',
         'SharedSurfaceGLX.h'
     ]
 
 if CONFIG['MOZ_WAYLAND']:
     SOURCES += [
         'GLContextProviderWayland.cpp',
         'SharedSurfaceDMABUF.cpp'
     ]
--- a/widget/gtk/GtkCompositorWidget.cpp
+++ b/widget/gtk/GtkCompositorWidget.cpp
@@ -13,59 +13,62 @@
 
 namespace mozilla {
 namespace widget {
 
 GtkCompositorWidget::GtkCompositorWidget(
     const GtkCompositorWidgetInitData& aInitData,
     const layers::CompositorOptions& aOptions, nsWindow* aWindow)
     : CompositorWidget(aOptions), mWidget(aWindow) {
-  // If we have a nsWindow, then grab the already existing display connection
-  // If we don't, then use the init data to connect to the display
-  if (aWindow) {
-    mXDisplay = aWindow->XDisplay();
-  } else {
-    mXDisplay = XOpenDisplay(aInitData.XDisplayString().get());
-  }
-
-#ifdef MOZ_WAYLAND
+#if defined(MOZ_WAYLAND)
   if (!aInitData.IsX11Display()) {
     if (!aWindow) {
       NS_WARNING("GtkCompositorWidget: We're missing nsWindow!");
     }
     mProvider.Initialize(aWindow);
-  } else
+  }
 #endif
-  {
+#if defined(MOZ_X11)
+  if (aInitData.IsX11Display()) {
+    // If we have a nsWindow, then grab the already existing display connection
+    // If we don't, then use the init data to connect to the display
+    if (aWindow) {
+      mXDisplay = aWindow->XDisplay();
+    } else {
+      mXDisplay = XOpenDisplay(aInitData.XDisplayString().get());
+    }
     mXWindow = (Window)aInitData.XWindow();
 
     // Grab the window's visual and depth
     XWindowAttributes windowAttrs;
     if (!XGetWindowAttributes(mXDisplay, mXWindow, &windowAttrs)) {
       NS_WARNING("GtkCompositorWidget(): XGetWindowAttributes() failed!");
     }
 
     Visual* visual = windowAttrs.visual;
-    int depth = windowAttrs.depth;
+    mDepth = windowAttrs.depth;
 
     // Initialize the window surface provider
-    mProvider.Initialize(mXDisplay, mXWindow, visual, depth,
+    mProvider.Initialize(mXDisplay, mXWindow, visual, mDepth,
                          aInitData.Shaped());
   }
+#endif
   mClientSize = aInitData.InitialClientSize();
 }
 
 GtkCompositorWidget::~GtkCompositorWidget() {
   mProvider.CleanupResources();
 
+#if defined(MOZ_X11)
   // If we created our own display connection, we need to destroy it
   if (!mWidget && mXDisplay) {
     XCloseDisplay(mXDisplay);
     mXDisplay = nullptr;
   }
+#endif
 }
 
 already_AddRefed<gfx::DrawTarget> GtkCompositorWidget::StartRemoteDrawing() {
   return nullptr;
 }
 void GtkCompositorWidget::EndRemoteDrawing() {}
 
 already_AddRefed<gfx::DrawTarget>
@@ -88,22 +91,30 @@ void GtkCompositorWidget::NotifyClientSi
 
 LayoutDeviceIntSize GtkCompositorWidget::GetClientSize() { return mClientSize; }
 
 uintptr_t GtkCompositorWidget::GetWidgetKey() {
   return reinterpret_cast<uintptr_t>(mWidget);
 }
 
 EGLNativeWindowType GtkCompositorWidget::GetEGLNativeWindow() {
-  return mWidget
-             ? (EGLNativeWindowType)mWidget->GetNativeData(NS_NATIVE_EGL_WINDOW)
-             : nullptr;
+  if (mWidget) {
+    return (EGLNativeWindowType)mWidget->GetNativeData(NS_NATIVE_EGL_WINDOW);
+  }
+#if defined(MOZ_X11)
+  if (mXWindow) {
+    return (EGLNativeWindowType)mXWindow;
+  }
+#endif
+  return nullptr;
 }
 
-#ifdef MOZ_WAYLAND
+int32_t GtkCompositorWidget::GetDepth() { return mDepth; }
+
+#if defined(MOZ_WAYLAND)
 void GtkCompositorWidget::SetEGLNativeWindowSize(
     const LayoutDeviceIntSize& aEGLWindowSize) {
   if (mWidget) {
     mWidget->SetEGLNativeWindowSize(aEGLWindowSize);
   }
 }
 #endif
 
--- a/widget/gtk/GtkCompositorWidget.h
+++ b/widget/gtk/GtkCompositorWidget.h
@@ -52,35 +52,42 @@ class GtkCompositorWidget : public Compo
   uintptr_t GetWidgetKey() override;
 
   LayoutDeviceIntSize GetClientSize() override;
 
   nsIWidget* RealWidget() override;
   GtkCompositorWidget* AsX11() override { return this; }
   CompositorWidgetDelegate* AsDelegate() override { return this; }
 
+  EGLNativeWindowType GetEGLNativeWindow();
+  int32_t GetDepth();
+
+#if defined(MOZ_X11)
   Display* XDisplay() const { return mXDisplay; }
   Window XWindow() const { return mXWindow; }
-
-  EGLNativeWindowType GetEGLNativeWindow();
-#ifdef MOZ_WAYLAND
+#endif
+#if defined(MOZ_WAYLAND)
   void SetEGLNativeWindowSize(const LayoutDeviceIntSize& aEGLWindowSize);
 #endif
 
   // PlatformCompositorWidgetDelegate Overrides
 
   void NotifyClientSizeChanged(const LayoutDeviceIntSize& aClientSize) override;
 
  protected:
   nsWindow* mWidget;
 
  private:
   LayoutDeviceIntSize mClientSize;
 
-  Display* mXDisplay;
-  Window mXWindow;
   WindowSurfaceProvider mProvider;
+
+#if defined(MOZ_X11)
+  Display* mXDisplay = {};
+  Window mXWindow = {};
+#endif
+  int32_t mDepth = {};
 };
 
 }  // namespace widget
 }  // namespace mozilla
 
 #endif  // widget_gtk_GtkCompositorWidget_h