From 86da16f9a5a4f4bb77e48154426eee76d4655f29 Mon Sep 17 00:00:00 2001 From: Andrew Osmond Date: Tue, 16 Mar 2021 20:14:51 +0000 Subject: [PATCH] Bug 1696071 - Add support for DMABuf to the blocklist. r=rmader Differential Revision: https://phabricator.services.mozilla.com/D107019 --- gfx/config/gfxFeature.h | 1 + gfx/config/gfxVars.h | 3 +- gfx/thebes/gfxPlatformGtk.cpp | 56 +++++++++++++++++++++--- gfx/thebes/gfxPlatformGtk.h | 1 + modules/libpref/init/StaticPrefList.yaml | 6 +++ widget/GfxInfoBase.cpp | 6 +++ widget/gtk/DMABufLibWrapper.cpp | 27 +++++++++--- widget/gtk/DMABufLibWrapper.h | 3 +- widget/nsIGfxInfo.idl | 4 +- 9 files changed, 90 insertions(+), 17 deletions(-) diff --git a/gfx/config/gfxFeature.h b/gfx/config/gfxFeature.h index e10989ca3ff3..a8bfe2483013 100644 --- a/gfx/config/gfxFeature.h +++ b/gfx/config/gfxFeature.h @@ -36,6 +36,7 @@ namespace gfx { _(OMTP, Feature, "Off Main Thread Painting") \ _(WEBGPU, Feature, "WebGPU") \ _(X11_EGL, Feature, "X11 EGL") \ + _(DMABUF, Feature, "DMABUF") \ /* Add new entries above this comment */ enum class Feature : uint32_t { diff --git a/gfx/config/gfxVars.h b/gfx/config/gfxVars.h index 37352d050b3d..e02739f06e1a 100644 --- a/gfx/config/gfxVars.h +++ b/gfx/config/gfxVars.h @@ -75,7 +75,8 @@ class gfxVarReceiver; _(UseAHardwareBufferContent, bool, false) \ _(UseAHardwareBufferSharedSurface, bool, false) \ _(UseEGL, bool, false) \ - _(DrmRenderDevice, nsCString, nsCString()) + _(DrmRenderDevice, nsCString, nsCString()) \ + _(UseDMABuf, bool, false) /* Add new entries above this line. */ diff --git a/gfx/thebes/gfxPlatformGtk.cpp b/gfx/thebes/gfxPlatformGtk.cpp index 86d0e979d8a9..8767a23b2b83 100644 --- a/gfx/thebes/gfxPlatformGtk.cpp +++ b/gfx/thebes/gfxPlatformGtk.cpp @@ -60,7 +60,7 @@ # include # include "mozilla/widget/nsWaylandDisplay.h" # include "mozilla/widget/DMABufLibWrapper.h" -# include "mozilla/StaticPrefs_media.h" +# include "mozilla/StaticPrefs_widget.h" #endif #define GDK_PIXMAP_SIZE_MAX 32767 @@ -106,14 +106,13 @@ gfxPlatformGtk::gfxPlatformGtk() { #endif InitX11EGLConfig(); - if (IsWaylandDisplay() || gfxConfig::IsEnabled(Feature::X11_EGL)) { gfxVars::SetUseEGL(true); + } - nsCOMPtr gfxInfo = components::GfxInfo::Service(); - nsAutoCString drmRenderDevice; - gfxInfo->GetDrmRenderDevice(drmRenderDevice); - gfxVars::SetDrmRenderDevice(drmRenderDevice); + InitDmabufConfig(); + if (gfxConfig::IsEnabled(Feature::DMABUF)) { + gfxVars::SetUseDMABuf(true); } } @@ -121,7 +120,7 @@ gfxPlatformGtk::gfxPlatformGtk() { #ifdef MOZ_WAYLAND mUseWebGLDmabufBackend = - gfxVars::UseEGL() && GetDMABufDevice()->IsDMABufWebGLEnabled(); + gfxVars::UseDMABuf() && GetDMABufDevice()->IsDMABufWebGLEnabled(); #endif gPlatformFTLibrary = Factory::NewFTLibrary(); @@ -180,6 +179,49 @@ void gfxPlatformGtk::InitX11EGLConfig() { #endif } +void gfxPlatformGtk::InitDmabufConfig() { + FeatureState& feature = gfxConfig::GetFeature(Feature::DMABUF); +#ifdef MOZ_WAYLAND + feature.EnableByDefault(); + + if (StaticPrefs::widget_dmabuf_force_enabled_AtStartup()) { + feature.UserForceEnable("Force enabled by pref"); + } + + nsCString failureId; + int32_t status; + nsCOMPtr gfxInfo = components::GfxInfo::Service(); + if (NS_FAILED(gfxInfo->GetFeatureStatus(nsIGfxInfo::FEATURE_DMABUF, failureId, + &status))) { + feature.Disable(FeatureStatus::BlockedNoGfxInfo, "gfxInfo is broken", + "FEATURE_FAILURE_NO_GFX_INFO"_ns); + } else if (status != nsIGfxInfo::FEATURE_STATUS_OK) { + feature.Disable(FeatureStatus::Blocklisted, "Blocklisted by gfxInfo", + failureId); + } + + if (!gfxVars::UseEGL()) { + feature.ForceDisable(FeatureStatus::Unavailable, "Requires EGL", + "FEATURE_FAILURE_REQUIRES_EGL"_ns); + } + + if (feature.IsEnabled()) { + nsAutoCString drmRenderDevice; + gfxInfo->GetDrmRenderDevice(drmRenderDevice); + gfxVars::SetDrmRenderDevice(drmRenderDevice); + + if (!GetDMABufDevice()->Configure(failureId)) { + feature.ForceDisable(FeatureStatus::Failed, "Failed to configure", + failureId); + } + } +#else + feature.DisableByDefault(FeatureStatus::Unavailable, + "Wayland support missing", + "FEATURE_FAILURE_NO_WAYLAND"_ns); +#endif +} + void gfxPlatformGtk::FlushContentDrawing() { if (gfxVars::UseXRender()) { XFlush(DefaultXDisplay()); diff --git a/gfx/thebes/gfxPlatformGtk.h b/gfx/thebes/gfxPlatformGtk.h index 28595ef04f44..eebf9825348d 100644 --- a/gfx/thebes/gfxPlatformGtk.h +++ b/gfx/thebes/gfxPlatformGtk.h @@ -93,6 +93,7 @@ class gfxPlatformGtk final : public gfxPlatform { protected: void InitX11EGLConfig(); + void InitDmabufConfig(); void InitPlatformGPUProcessPrefs() override; bool CheckVariationFontSupport() override; diff --git a/modules/libpref/init/StaticPrefList.yaml b/modules/libpref/init/StaticPrefList.yaml index 40c41bda06f4..2c22b033f0c8 100644 --- a/modules/libpref/init/StaticPrefList.yaml +++ b/modules/libpref/init/StaticPrefList.yaml @@ -10823,6 +10823,12 @@ mirror: always #ifdef MOZ_WAYLAND +# Whether to override the DMABuf blocklist. +- name: widget.dmabuf.force-enabled + type: bool + value: false + mirror: once + #ifdef NIGHTLY_BUILD # Keep those pref hidden on non-nightly builds to avoid people accidentally # turning it on. diff --git a/widget/GfxInfoBase.cpp b/widget/GfxInfoBase.cpp index effba297d037..2d206e07e5e1 100644 --- a/widget/GfxInfoBase.cpp +++ b/widget/GfxInfoBase.cpp @@ -234,6 +234,9 @@ static const char* GetPrefNameForFeature(int32_t aFeature) { case nsIGfxInfo::FEATURE_X11_EGL: name = BLOCKLIST_PREF_BRANCH "x11.egl"; break; + case nsIGfxInfo::FEATURE_DMABUF: + name = BLOCKLIST_PREF_BRANCH "dmabuf"; + break; default: MOZ_ASSERT_UNREACHABLE("Unexpected nsIGfxInfo feature?!"); break; @@ -432,6 +435,8 @@ static int32_t BlocklistFeatureToGfxFeature(const nsAString& aFeature) { return nsIGfxInfo::FEATURE_WEBRENDER_SOFTWARE; else if (aFeature.EqualsLiteral("X11_EGL")) return nsIGfxInfo::FEATURE_X11_EGL; + else if (aFeature.EqualsLiteral("DMABUF")) + return nsIGfxInfo::FEATURE_DMABUF; // If we don't recognize the feature, it may be new, and something // this version doesn't understand. So, nothing to do. This is @@ -1294,6 +1299,7 @@ void GfxInfoBase::EvaluateDownloadedBlocklist( nsIGfxInfo::FEATURE_GL_SWIZZLE, nsIGfxInfo::FEATURE_ALLOW_WEBGL_OUT_OF_PROCESS, nsIGfxInfo::FEATURE_X11_EGL, + nsIGfxInfo::FEATURE_DMABUF, 0}; // For every feature we know about, we evaluate whether this blocklist has a diff --git a/widget/gtk/DMABufLibWrapper.cpp b/widget/gtk/DMABufLibWrapper.cpp index 95e8e52d0224..f9b662bfd6c2 100644 --- a/widget/gtk/DMABufLibWrapper.cpp +++ b/widget/gtk/DMABufLibWrapper.cpp @@ -168,7 +168,8 @@ nsDMABufDevice::nsDMABufDevice() : mXRGBFormat({true, false, GBM_FORMAT_XRGB8888, nullptr, 0}), mARGBFormat({true, true, GBM_FORMAT_ARGB8888, nullptr, 0}), mGbmDevice(nullptr), - mGbmFd(-1) { + mGbmFd(-1), + mInitialized(false) { if (GdkIsWaylandDisplay()) { wl_display* display = WaylandDisplayGetWLDisplay(); mRegistry = (void*)wl_display_get_registry(display); @@ -185,9 +186,12 @@ nsDMABufDevice::~nsDMABufDevice() { } } -bool nsDMABufDevice::Configure() { +bool nsDMABufDevice::Configure(nsACString& aFailureId) { LOGDMABUF(("nsDMABufDevice::Configure()")); + MOZ_ASSERT(!mInitialized); + mInitialized = true; + bool isDMABufUsed = ( #ifdef NIGHTLY_BUILD StaticPrefs::widget_dmabuf_textures_enabled() || @@ -199,11 +203,13 @@ bool nsDMABufDevice::Configure() { if (!isDMABufUsed) { // Disabled by user, just quit. LOGDMABUF(("IsDMABufEnabled(): Disabled by preferences.")); + aFailureId = "FEATURE_FAILURE_NO_PREFS_ENABLED"; return false; } if (!nsGbmLib::IsAvailable()) { LOGDMABUF(("nsGbmLib is not available!")); + aFailureId = "FEATURE_FAILURE_NO_LIBGBM"; return false; } @@ -212,6 +218,7 @@ bool nsDMABufDevice::Configure() { drm_render_node.Assign(gfx::gfxVars::DrmRenderDevice()); if (drm_render_node.IsEmpty()) { LOGDMABUF(("Failed: We're missing DRM render device!\n")); + aFailureId = "FEATURE_FAILURE_NO_DRM_RENDER_NODE"; return false; } } @@ -219,6 +226,7 @@ bool nsDMABufDevice::Configure() { mGbmFd = open(drm_render_node.get(), O_RDWR); if (mGbmFd < 0) { LOGDMABUF(("Failed to open drm render node %s\n", drm_render_node.get())); + aFailureId = "FEATURE_FAILURE_BAD_DRM_RENDER_NODE"; return false; } @@ -226,6 +234,7 @@ bool nsDMABufDevice::Configure() { if (!mGbmDevice) { LOGDMABUF( ("Failed to create drm render device %s\n", drm_render_node.get())); + aFailureId = "FEATURE_FAILURE_NO_DRM_RENDER_DEVICE"; close(mGbmFd); mGbmFd = -1; return false; @@ -236,13 +245,17 @@ bool nsDMABufDevice::Configure() { } bool nsDMABufDevice::IsDMABufEnabled() { - static bool isDMABufEnabled = Configure(); - return isDMABufEnabled; + if (!mInitialized) { + MOZ_ASSERT(!XRE_IsParentProcess()); + nsCString failureId; + return Configure(failureId); + } + return !!mGbmDevice; } #ifdef NIGHTLY_BUILD bool nsDMABufDevice::IsDMABufTexturesEnabled() { - return gfx::gfxVars::UseEGL() && IsDMABufEnabled() && + return gfx::gfxVars::UseDMABuf() && IsDMABufEnabled() && StaticPrefs::widget_dmabuf_textures_enabled(); } #else @@ -257,7 +270,7 @@ bool nsDMABufDevice::IsDMABufVAAPIEnabled() { StaticPrefs::media_ffmpeg_vaapi_enabled(), gfx::gfxVars::CanUseHardwareVideoDecoding(), !XRE_IsRDDProcess())); return StaticPrefs::media_ffmpeg_vaapi_enabled() && !XRE_IsRDDProcess() && - gfx::gfxVars::UseEGL() && IsDMABufEnabled() && + gfx::gfxVars::UseDMABuf() && IsDMABufEnabled() && gfx::gfxVars::CanUseHardwareVideoDecoding(); } bool nsDMABufDevice::IsDMABufWebGLEnabled() { @@ -266,7 +279,7 @@ bool nsDMABufDevice::IsDMABufWebGLEnabled() { "widget_dmabuf_webgl_enabled %d\n", gfx::gfxVars::UseEGL(), IsDMABufEnabled(), StaticPrefs::widget_dmabuf_webgl_enabled())); - return gfx::gfxVars::UseEGL() && IsDMABufEnabled() && + return gfx::gfxVars::UseDMABuf() && IsDMABufEnabled() && StaticPrefs::widget_dmabuf_webgl_enabled(); } diff --git a/widget/gtk/DMABufLibWrapper.h b/widget/gtk/DMABufLibWrapper.h index f6534e72a3e8..1ee051587a1b 100644 --- a/widget/gtk/DMABufLibWrapper.h +++ b/widget/gtk/DMABufLibWrapper.h @@ -150,10 +150,10 @@ class nsDMABufDevice { void ResetFormatsModifiers(); void AddFormatModifier(bool aHasAlpha, int aFormat, uint32_t mModifierHi, uint32_t mModifierLo); + bool Configure(nsACString& aFailureId); private: bool IsDMABufEnabled(); - bool Configure(); void* mRegistry; @@ -162,6 +162,7 @@ class nsDMABufDevice { gbm_device* mGbmDevice; int mGbmFd; + bool mInitialized; }; nsDMABufDevice* GetDMABufDevice(); diff --git a/widget/nsIGfxInfo.idl b/widget/nsIGfxInfo.idl index dbfa84876c5d..50832c077d05 100644 --- a/widget/nsIGfxInfo.idl +++ b/widget/nsIGfxInfo.idl @@ -175,8 +175,10 @@ interface nsIGfxInfo : nsISupports const long FEATURE_WEBRENDER_OPTIMIZED_SHADERS = 33; /* Whether we prefer EGL over GLX with X11, starting in 88. */ const long FEATURE_X11_EGL = 34; + /* Whether DMABUF is supported, starting in 88. */ + const long FEATURE_DMABUF = 35; /* the maximum feature value. */ - const long FEATURE_MAX_VALUE = FEATURE_X11_EGL; + const long FEATURE_MAX_VALUE = FEATURE_DMABUF; /* * A set of return values from GetFeatureStatus