Bug 1562023 - [Wayland] Factorize out DMABUF setup, r=ashie
authorMartin Stransky <stransky@redhat.com>
Mon, 01 Jul 2019 08:55:03 +0000
changeset 543626 ef154e1221d66e844a1854ca00f984c771e9b36d
parent 543625 1e3513e5290b6927d3f34474c29c65d9718ad4c7
child 543627 921c89bebafeba5c44cb5bc0dc97d8ebc7541f6f
push id2131
push userffxbld-merge
push dateMon, 26 Aug 2019 18:30:20 +0000
treeherdermozilla-release@b19ffb3ca153 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersashie
bugs1562023
milestone69.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 1562023 - [Wayland] Factorize out DMABUF setup, r=ashie Differential Revision: https://phabricator.services.mozilla.com/D36420
widget/gtk/WaylandDMABufSurface.cpp
widget/gtk/WaylandDMABufSurface.h
widget/gtk/WindowSurfaceWayland.cpp
widget/gtk/nsWaylandDisplay.cpp
widget/gtk/nsWaylandDisplay.h
--- a/widget/gtk/WaylandDMABufSurface.cpp
+++ b/widget/gtk/WaylandDMABufSurface.cpp
@@ -25,36 +25,16 @@
 using namespace mozilla;
 using namespace mozilla::widget;
 
 #ifndef DRM_FORMAT_MOD_INVALID
 #  define DRM_FORMAT_MOD_INVALID ((1ULL << 56) - 1)
 #endif
 #define BUFFER_FLAGS 0
 
-bool WaylandDMABufSurface::mAvailable = false;
-bool WaylandDMABufSurface::mInitialized = false;
-
-bool WaylandDMABufSurface::IsAvailable() {
-  if (!mInitialized) {
-    mInitialized = true;
-    if (!nsGbmLib::IsAvailable()) {
-      return false;
-    }
-
-    // Test Alpha and non-alpha formats
-    nsWaylandDisplay* display = WaylandDisplayGet();
-    if (!display->GetGbmFormat(false) || !display->GetGbmFormat(true)) {
-      return false;
-    }
-    mAvailable = true;
-  }
-  return static_cast<bool>(mAvailable);
-}
-
 void WaylandDMABufSurface::SetWLBuffer(struct wl_buffer* aWLBuffer) {
   MOZ_ASSERT(mWLBuffer == nullptr, "WLBuffer already assigned!");
   mWLBuffer = aWLBuffer;
 }
 
 wl_buffer* WaylandDMABufSurface::GetWLBuffer() { return mWLBuffer; }
 
 static void buffer_release(void* data, wl_buffer* buffer) {
--- a/widget/gtk/WaylandDMABufSurface.h
+++ b/widget/gtk/WaylandDMABufSurface.h
@@ -9,18 +9,16 @@
 
 #include <stdint.h>
 #include "mozilla/widget/nsWaylandDisplay.h"
 
 #define DMABUF_BUFFER_PLANES 4
 
 class WaylandDMABufSurface {
  public:
-  static bool IsAvailable();
-
   bool Create(int aWidth, int aHeight, bool aHasAlpha = true);
   bool Resize(int aWidth, int aHeight);
   void Release();
   void Clear();
 
   bool CopyFrom(class WaylandDMABufSurface* aSourceSurface);
 
   int GetWidth() { return mWidth; };
@@ -57,14 +55,11 @@ class WaylandDMABufSurface {
   uint64_t mBufferModifier;
   int mBufferPlaneCount;
   int mDmabufFds[DMABUF_BUFFER_PLANES];
   uint32_t mStrides[DMABUF_BUFFER_PLANES];
   uint32_t mOffsets[DMABUF_BUFFER_PLANES];
 
   bool mWLBufferAttached;
   bool mFastWLBufferCreation;
-
-  static bool mAvailable;
-  static bool mInitialized;
 };
 
 #endif
--- a/widget/gtk/WindowSurfaceWayland.cpp
+++ b/widget/gtk/WindowSurfaceWayland.cpp
@@ -527,20 +527,18 @@ WindowSurfaceWayland::~WindowSurfaceWayl
     if (mBackupBuffer[i]) {
       delete mBackupBuffer[i];
     }
   }
 }
 
 bool WindowSurfaceWayland::UseDMABufBackend() {
   if (!mUseDMABufInitialized) {
-    if (WaylandDMABufSurface::IsAvailable()) {
-      mUseDMABuf = nsWaylandDisplay::IsDMABufEnabled();
-      LOGWAYLAND(("%s DMABuf state %d\n", __PRETTY_FUNCTION__, mUseDMABuf));
-    }
+    mUseDMABuf = nsWaylandDisplay::IsDMABufEnabled();
+    LOGWAYLAND(("%s DMABuf state %d\n", __PRETTY_FUNCTION__, mUseDMABuf));
     mUseDMABufInitialized = true;
   }
   return mUseDMABuf;
 }
 
 WindowBackBuffer* WindowSurfaceWayland::CreateWaylandBuffer(int aWidth,
                                                             int aHeight) {
   if (UseDMABufBackend()) {
--- a/widget/gtk/nsWaylandDisplay.cpp
+++ b/widget/gtk/nsWaylandDisplay.cpp
@@ -8,18 +8,20 @@
 #include "nsWaylandDisplay.h"
 
 namespace mozilla {
 namespace widget {
 
 #define GBMLIB_NAME "libgbm.so.1"
 #define DRMLIB_NAME "libdrm.so.2"
 
-bool nsWaylandDisplay::mIsDMABufEnabled;
-bool nsWaylandDisplay::mIsDMABufPrefLoaded;
+bool nsWaylandDisplay::mIsDMABufEnabled = false;
+// -1 mean the pref was not loaded yet
+int nsWaylandDisplay::mIsDMABufPrefState = -1;
+bool nsWaylandDisplay::mIsDMABufConfigured = false;
 
 wl_display* WaylandDisplayGetWLDisplay(GdkDisplay* aGdkDisplay) {
   if (!aGdkDisplay) {
     aGdkDisplay = gdk_display_get_default();
   }
 
   // Available as of GTK 3.8+
   static auto sGdkWaylandDisplayGetWlDisplay = (wl_display * (*)(GdkDisplay*))
@@ -296,19 +298,22 @@ nsWaylandDisplay::nsWaylandDisplay(wl_di
       mXRGBFormat({false, false, -1, nullptr, 0}),
       mARGBFormat({false, false, -1, nullptr, 0}),
       mGdmConfigured(false),
       mExplicitSync(false) {
   mRegistry = wl_display_get_registry(mDisplay);
   wl_registry_add_listener(mRegistry, &registry_listener, this);
 
   if (NS_IsMainThread()) {
-    if (!mIsDMABufPrefLoaded) {
-      mIsDMABufPrefLoaded = true;
-      mIsDMABufEnabled =
+    // We can't load the preference from compositor/render thread,
+    // only from main one. So we can't call it directly from
+    // nsWaylandDisplay::IsDMABufEnabled() as it can be called from various
+    // threads.
+    if (mIsDMABufPrefState == -1) {
+      mIsDMABufPrefState =
           Preferences::GetBool("widget.wayland_dmabuf_backend.enabled", false);
     }
     // Use default event queue in main thread operated by Gtk+.
     mEventQueue = nullptr;
     wl_display_roundtrip(mDisplay);
     wl_display_roundtrip(mDisplay);
   } else {
     mDispatcherThreadLoop = MessageLoop::current();
@@ -329,16 +334,51 @@ nsWaylandDisplay::~nsWaylandDisplay() {
   mRegistry = nullptr;
 
   if (mEventQueue) {
     wl_event_queue_destroy(mEventQueue);
     mEventQueue = nullptr;
   }
 }
 
+bool nsWaylandDisplay::IsDMABufEnabled() {
+  if (mIsDMABufConfigured) {
+    return mIsDMABufEnabled;
+  }
+
+  // WaylandDisplayGet() sets mIsDMABufPrefState
+  nsWaylandDisplay* display = WaylandDisplayGet();
+  if (nsWaylandDisplay::mIsDMABufPrefState == -1) {
+    MOZ_ASSERT(false,
+               "We're missing nsWaylandDisplay preference configuration!");
+    return false;
+  }
+
+  mIsDMABufConfigured = true;
+  if (!nsWaylandDisplay::mIsDMABufPrefState) {
+    // Disabled by user, just quit.
+    return false;
+  }
+
+  if (!display->ConfigureGbm()) {
+    NS_WARNING("Failed to create GbmDevice, DMABUF/DRM won't be available!");
+    return false;
+  }
+
+  if (!display->GetGbmFormat(/* aHasAlpha */ false) ||
+      !display->GetGbmFormat(/* aHasAlpha */ true)) {
+    NS_WARNING(
+        "Failed to create obtain pixel format, DMABUF/DRM won't be available!");
+    return false;
+  }
+
+  mIsDMABufEnabled = true;
+  return true;
+}
+
 void* nsGbmLib::sGbmLibHandle = nullptr;
 void* nsGbmLib::sXf86DrmLibHandle = nullptr;
 bool nsGbmLib::sLibLoaded = false;
 CreateDeviceFunc nsGbmLib::sCreateDevice;
 CreateFunc nsGbmLib::sCreate;
 CreateWithModifiersFunc nsGbmLib::sCreateWithModifiers;
 GetModifierFunc nsGbmLib::sGetModifier;
 GetStrideFunc nsGbmLib::sGetStride;
--- a/widget/gtk/nsWaylandDisplay.h
+++ b/widget/gtk/nsWaylandDisplay.h
@@ -28,16 +28,18 @@ struct GbmFormat {
   bool mHasAlpha;
   int mFormat;
   uint64_t* mModifiers;
   int mModifiersCount;
 };
 
 // Our general connection to Wayland display server,
 // holds our display connection and runs event loop.
+// We have a global nsWaylandDisplay object for each thread,
+// recently we have three for main, compositor and render one.
 class nsWaylandDisplay {
  public:
   explicit nsWaylandDisplay(wl_display* aDisplay);
   virtual ~nsWaylandDisplay();
 
   bool DispatchEventQueue();
   bool Matches(wl_display* aDisplay);
 
@@ -67,17 +69,17 @@ class nsWaylandDisplay {
   zwp_linux_dmabuf_v1* GetDmabuf() { return mDmabuf; };
   gbm_device* GetGbmDevice();
   // Returns -1 if we fails to gbm device file descriptor.
   int GetGbmDeviceFd();
   bool IsExplicitSyncEnabled() { return mExplicitSync; }
   GbmFormat* GetGbmFormat(bool aHasAlpha);
   void AddFormatModifier(bool aHasAlpha, int aFormat, uint32_t mModifierHi,
                          uint32_t mModifierLo);
-  static bool IsDMABufEnabled() { return mIsDMABufEnabled; };
+  static bool IsDMABufEnabled();
 
  private:
   bool ConfigureGbm();
 
   MessageLoop* mDispatcherThreadLoop;
   PRThread* mThreadId;
   wl_display* mDisplay;
   wl_event_queue* mEventQueue;
@@ -90,17 +92,18 @@ class nsWaylandDisplay {
   zwp_linux_dmabuf_v1* mDmabuf;
   gbm_device* mGbmDevice;
   int mGbmFd;
   GbmFormat mXRGBFormat;
   GbmFormat mARGBFormat;
   bool mGdmConfigured;
   bool mExplicitSync;
   static bool mIsDMABufEnabled;
-  static bool mIsDMABufPrefLoaded;
+  static int mIsDMABufPrefState;
+  static bool mIsDMABufConfigured;
 };
 
 void WaylandDispatchDisplays();
 void WaylandDisplayShutdown();
 nsWaylandDisplay* WaylandDisplayGet(GdkDisplay* aGdkDisplay = nullptr);
 wl_display* WaylandDisplayGetWLDisplay(GdkDisplay* aGdkDisplay = nullptr);
 
 typedef struct gbm_device* (*CreateDeviceFunc)(int);