From b835f528fa750ecddf79de8a9aea3900a0d169c8 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Fri, 14 Apr 2023 06:08:42 -0700 Subject: [PATCH] [GTK][WPE] Show DRM device and render node files when available in webkit://gpu https://bugs.webkit.org/show_bug.cgi?id=255445 Reviewed by Adrian Perez de Castro. * Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp: (WebKit::WebKitProtocolHandler::handleGPU): Canonical link: https://commits.webkit.org/262958@main --- .../API/glib/WebKitProtocolHandler.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp b/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp index 167cb28bf97a..b629cc6536bf 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp @@ -58,6 +58,9 @@ #if USE(GBM) #include "AcceleratedBackingStoreDMABuf.h" +#ifndef EGL_DRM_RENDER_NODE_FILE_EXT +#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377 +#endif #endif #if PLATFORM(X11) @@ -278,6 +281,24 @@ void WebKitProtocolHandler::handleGPU(WebKitURISchemeRequest* request) addTableRow(hardwareAccelerationObject, "GL_VERSION"_s, makeString(reinterpret_cast(glGetString(GL_VERSION)))); addTableRow(hardwareAccelerationObject, "GL_SHADING_LANGUAGE_VERSION"_s, makeString(reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)))); + auto eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay(); +#if USE(GBM) + if (GLContext::isExtensionSupported(eglQueryString(nullptr, EGL_EXTENSIONS), "EGL_EXT_device_query")) { + EGLDeviceEXT eglDevice; + if (eglQueryDisplayAttribEXT(eglDisplay, EGL_DEVICE_EXT, reinterpret_cast(&eglDevice))) { + const char* deviceExtensions = eglQueryDeviceStringEXT(eglDevice, EGL_EXTENSIONS); + if (GLContext::isExtensionSupported(deviceExtensions, "EGL_EXT_device_drm")) { + if (const char* deviceFile = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT)) + addTableRow(hardwareAccelerationObject, "DRM Device"_s, makeString(deviceFile)); + } + if (GLContext::isExtensionSupported(deviceExtensions, "EGL_EXT_device_drm_render_node")) { + if (const char* renderNode = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_RENDER_NODE_FILE_EXT)) + addTableRow(hardwareAccelerationObject, "DRM Render Node"_s, makeString(renderNode)); + } + } + } +#endif + #if USE(OPENGL_ES) addTableRow(hardwareAccelerationObject, "GL_EXTENSIONS"_s, makeString(reinterpret_cast(glGetString(GL_EXTENSIONS)))); #else @@ -292,7 +313,6 @@ void WebKitProtocolHandler::handleGPU(WebKitURISchemeRequest* request) addTableRow(hardwareAccelerationObject, "GL_EXTENSIONS"_s, extensionsBuilder.toString()); #endif - auto eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay(); addTableRow(hardwareAccelerationObject, "EGL_VERSION"_s, makeString(eglQueryString(eglDisplay, EGL_VERSION))); addTableRow(hardwareAccelerationObject, "EGL_VENDOR"_s, makeString(eglQueryString(eglDisplay, EGL_VENDOR))); addTableRow(hardwareAccelerationObject, "EGL_EXTENSIONS"_s, makeString(eglQueryString(nullptr, EGL_EXTENSIONS), ' ', eglQueryString(eglDisplay, EGL_EXTENSIONS))); From d67f30551d7cbf5ec8bdd6d7fed92862db326110 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Mon, 17 Apr 2023 13:17:54 +0200 Subject: [PATCH] [GTK] Minibrowser does not render any content https://bugs.webkit.org/show_bug.cgi?id=254807 Reviewed by NOBODY (OOPS!). This happens in systems with multiple GPUs enabled. The problem is that we might end up using a different GPU than the one used by the application in the UI process. This is because both GBMDevice and mesa surfaceless platform use always the first device having a render node returned by drmGetDevices2(). To make sure we use the right GPU everywhere we need to get the GPU in used by the UI process and send it to the web process. Mesa surfaceless platform doesn't allow to chang the device, so we need to use GBM platform that receives the device as the native display when initializing the EGL display. Surfaceless platform is still used for swrast, because GBM requires a GPU device. * Source/WebCore/PlatformGTK.cmake: * Source/WebCore/SourcesGTK.txt: * Source/WebCore/platform/graphics/PlatformDisplay.cpp: (WebCore::PlatformDisplay::~PlatformDisplay): (WebCore::PlatformDisplay::eglDevice): (WebCore::PlatformDisplay::drmDeviceFile): (WebCore::drmRenderNodeFromPrimaryDeviceFile): (WebCore::PlatformDisplay::drmRenderNodeFile): (WebCore::PlatformDisplay::gbmDevice): * Source/WebCore/platform/graphics/PlatformDisplay.h: * Source/WebCore/platform/graphics/egl/GLContext.cpp: (WebCore::GLContext::getEGLConfig): (WebCore::GLContext::createWindowContext): (WebCore::GLContext::create): (WebCore::GLContext::createSharing): * Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.cpp: Renamed from Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.cpp. * Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.h: Renamed from Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.h. * Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.cpp: Added. (WebCore::PlatformDisplayGBM::create): (WebCore::PlatformDisplayGBM::PlatformDisplayGBM): (WebCore::PlatformDisplayGBM::~PlatformDisplayGBM): * Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.h: Added. * Source/WebKit/Shared/WebProcessCreationParameters.cpp: (WebKit::WebProcessCreationParameters::encode const): (WebKit::WebProcessCreationParameters::decode): * Source/WebKit/Shared/WebProcessCreationParameters.h: * Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp: (WebKit::WebKitProtocolHandler::handleGPU): * Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp: (WebKit::WebProcessPool::platformInitializeWebProcess): * Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp: (WebKit::AcceleratedBackingStoreDMABuf::Surface::Surface): * Source/WebKit/WebProcess/WebPage/AcceleratedSurface.cpp: (WebKit::AcceleratedSurface::create): * Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceDMABuf.cpp: (WebKit::AcceleratedSurfaceDMABuf::AcceleratedSurfaceDMABuf): (WebKit::AcceleratedSurfaceDMABuf::RenderTargetEGLImage::create): * Source/WebKit/WebProcess/glib/WebProcessGLib.cpp: (WebKit::WebProcess::platformInitializeWebProcess): --- Source/WebCore/PlatformGTK.cmake | 4 +- Source/WebCore/SourcesGTK.txt | 3 +- .../platform/graphics/PlatformDisplay.cpp | 117 ++++++++++++++++++ .../platform/graphics/PlatformDisplay.h | 30 ++++- .../platform/graphics/egl/GLContext.cpp | 19 ++- ...ess.cpp => PlatformDisplaySurfaceless.cpp} | 10 +- ...eadless.h => PlatformDisplaySurfaceless.h} | 10 +- .../graphics/gbm/PlatformDisplayGBM.cpp | 81 ++++++++++++ .../graphics/gbm/PlatformDisplayGBM.h | 46 +++++++ .../Shared/WebProcessCreationParameters.cpp | 6 + .../Shared/WebProcessCreationParameters.h | 1 + .../API/glib/WebKitProtocolHandler.cpp | 25 ++-- .../UIProcess/glib/WebProcessPoolGLib.cpp | 4 +- .../gtk/AcceleratedBackingStoreDMABuf.cpp | 8 +- .../WebProcess/WebPage/AcceleratedSurface.cpp | 3 +- .../WebPage/gtk/AcceleratedSurfaceDMABuf.cpp | 10 +- .../WebKit/WebProcess/glib/WebProcessGLib.cpp | 15 ++- 17 files changed, 341 insertions(+), 51 deletions(-) rename Source/WebCore/platform/graphics/egl/{PlatformDisplayHeadless.cpp => PlatformDisplaySurfaceless.cpp} (86%) rename Source/WebCore/platform/graphics/egl/{PlatformDisplayHeadless.h => PlatformDisplaySurfaceless.h} (83%) create mode 100644 Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.cpp create mode 100644 Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.h diff --git a/Source/WebCore/PlatformGTK.cmake b/Source/WebCore/PlatformGTK.cmake index 27b04aee02d4..76c08982c9b6 100644 --- a/Source/WebCore/PlatformGTK.cmake +++ b/Source/WebCore/PlatformGTK.cmake @@ -47,7 +47,9 @@ list(APPEND WebCore_PRIVATE_FRAMEWORK_HEADERS platform/glib/ApplicationGLib.h - platform/graphics/egl/PlatformDisplayHeadless.h + platform/graphics/egl/PlatformDisplaySurfaceless.h + + platform/graphics/gbm/PlatformDisplayGBM.h platform/graphics/gtk/GdkCairoUtilities.h diff --git a/Source/WebCore/SourcesGTK.txt b/Source/WebCore/SourcesGTK.txt index 2042f2d6a177..58a73bf31a5b 100644 --- a/Source/WebCore/SourcesGTK.txt +++ b/Source/WebCore/SourcesGTK.txt @@ -74,7 +74,7 @@ platform/graphics/egl/GLContext.cpp @no-unify platform/graphics/egl/GLContextLibWPE.cpp @no-unify platform/graphics/egl/GLContextWayland.cpp @no-unify platform/graphics/egl/GLContextX11.cpp @no-unify -platform/graphics/egl/PlatformDisplayHeadless.cpp +platform/graphics/egl/PlatformDisplaySurfaceless.cpp platform/graphics/gbm/GBMBufferSwapchain.cpp platform/graphics/gbm/GBMDevice.cpp @@ -82,6 +82,7 @@ platform/graphics/gbm/GraphicsContextGLANGLELinux.cpp platform/graphics/gbm/GraphicsContextGLFallback.cpp platform/graphics/gbm/GraphicsContextGLGBM.cpp platform/graphics/gbm/GraphicsContextGLGBMTextureMapper.cpp +platform/graphics/gbm/PlatformDisplayGBM.cpp platform/graphics/gtk/ColorGtk.cpp platform/graphics/gtk/DisplayRefreshMonitorGtk.cpp diff --git a/Source/WebCore/platform/graphics/PlatformDisplay.cpp b/Source/WebCore/platform/graphics/PlatformDisplay.cpp index e5a48c9c0b52..cdd10a7d1351 100644 --- a/Source/WebCore/platform/graphics/PlatformDisplay.cpp +++ b/Source/WebCore/platform/graphics/PlatformDisplay.cpp @@ -80,6 +80,18 @@ #include #endif +#if USE(EGL) && USE(GBM) +#include +#include +#include +#include +#include +#include +#ifndef EGL_DRM_RENDER_NODE_FILE_EXT +#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377 +#endif +#endif + #if USE(ATSPI) #include #endif @@ -221,6 +233,10 @@ PlatformDisplay::~PlatformDisplay() #if PLATFORM(GTK) if (m_sharedDisplay) g_signal_handlers_disconnect_by_data(m_sharedDisplay.get(), this); +#endif +#if USE(EGL) && USE(GBM) + if (m_gbm.device.has_value() && m_gbm.device.value()) + gbm_device_destroy(m_gbm.device.value()); #endif if (s_sharedDisplayForCompositing == this) s_sharedDisplayForCompositing = nullptr; @@ -402,6 +418,107 @@ bool PlatformDisplay::destroyEGLImage(EGLImage image) const #endif } +#if USE(GBM) +EGLDeviceEXT PlatformDisplay::eglDevice() +{ + if (!GLContext::isExtensionSupported(eglQueryString(nullptr, EGL_EXTENSIONS), "EGL_EXT_device_query")) + return nullptr; + + if (!m_eglDisplayInitialized) + const_cast(this)->initializeEGLDisplay(); + + EGLDeviceEXT eglDevice; + if (eglQueryDisplayAttribEXT(m_eglDisplay, EGL_DEVICE_EXT, reinterpret_cast(&eglDevice))) + return eglDevice; + + return nullptr; +} + +const String& PlatformDisplay::drmDeviceFile() +{ + if (!m_drmDeviceFile.has_value()) { + if (EGLDeviceEXT device = eglDevice()) { + if (GLContext::isExtensionSupported(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), "EGL_EXT_device_drm")) { + m_drmDeviceFile = String::fromUTF8(eglQueryDeviceStringEXT(device, EGL_DRM_DEVICE_FILE_EXT)); + return m_drmDeviceFile.value(); + } + } + m_drmDeviceFile = String(); + } + + return m_drmDeviceFile.value(); +} + +static String drmRenderNodeFromPrimaryDeviceFile(const String& primaryDeviceFile) +{ + if (primaryDeviceFile.isEmpty()) + return { }; + + drmDevicePtr devices[64]; + memset(devices, 0, sizeof(devices)); + + int numDevices = drmGetDevices2(0, devices, std::size(devices)); + if (numDevices <= 0) + return { }; + + String renderNodeDeviceFile; + for (int i = 0; i < numDevices; ++i) { + drmDevice* device = devices[i]; + if (!(device->available_nodes & (1 << DRM_NODE_PRIMARY | 1 << DRM_NODE_RENDER))) + continue; + + if (String::fromUTF8(device->nodes[DRM_NODE_PRIMARY]) == primaryDeviceFile) { + renderNodeDeviceFile = String::fromUTF8(device->nodes[DRM_NODE_RENDER]); + break; + } + } + drmFreeDevices(devices, numDevices); + + return renderNodeDeviceFile; +} + +const String& PlatformDisplay::drmRenderNodeFile() +{ + if (!m_drmRenderNodeFile.has_value()) { + if (EGLDeviceEXT device = eglDevice()) { + if (GLContext::isExtensionSupported(eglQueryDeviceStringEXT(device, EGL_EXTENSIONS), "EGL_EXT_device_drm_render_node")) { + m_drmRenderNodeFile = String::fromUTF8(eglQueryDeviceStringEXT(device, EGL_DRM_RENDER_NODE_FILE_EXT)); + return m_drmRenderNodeFile.value(); + } + + // If EGL_EXT_device_drm_render_node is not present, try to get the render node using DRM API. + m_drmRenderNodeFile = drmRenderNodeFromPrimaryDeviceFile(drmDeviceFile()); + } else + m_drmRenderNodeFile = String(); + } + + return m_drmRenderNodeFile.value(); +} + +struct gbm_device* PlatformDisplay::gbmDevice() +{ + if (!m_gbm.device.has_value()) { + const char* envDeviceFile = getenv("WEBKIT_WEB_RENDER_DEVICE_FILE"); + String deviceFile = envDeviceFile && *envDeviceFile ? String::fromUTF8(envDeviceFile) : drmRenderNodeFile(); + if (!deviceFile.isEmpty()) { + m_gbm.deviceFD = UnixFileDescriptor { open(deviceFile.utf8().data(), O_RDWR | O_CLOEXEC), UnixFileDescriptor::Adopt }; + if (m_gbm.deviceFD) { + m_gbm.device = gbm_create_device(m_gbm.deviceFD.value()); + if (m_gbm.device.value()) + return m_gbm.device.value(); + + WTFLogAlways("Failed to create GBM device for render device: %s: %s", deviceFile.utf8().data(), safeStrerror(errno).data()); + m_gbm.deviceFD = { }; + } else + WTFLogAlways("Failed to open DRM render device %s: %s", deviceFile.utf8().data(), safeStrerror(errno).data()); + } + m_gbm.device = nullptr; + } + + return m_gbm.device.value(); +} +#endif + #endif // USE(EGL) #if USE(LCMS) diff --git a/Source/WebCore/platform/graphics/PlatformDisplay.h b/Source/WebCore/platform/graphics/PlatformDisplay.h index 28b5e9dfbfda..db3a51de0512 100644 --- a/Source/WebCore/platform/graphics/PlatformDisplay.h +++ b/Source/WebCore/platform/graphics/PlatformDisplay.h @@ -36,6 +36,11 @@ typedef void *EGLContext; typedef void *EGLDisplay; typedef void *EGLImage; typedef unsigned EGLenum; +#if USE(GBM) +#include +typedef void *EGLDeviceEXT; +struct gbm_device; +#endif #endif #if PLATFORM(GTK) @@ -80,7 +85,10 @@ class PlatformDisplay { WPE, #endif #if USE(EGL) - Headless, + Surfaceless, +#if USE(GBM) + GBM, +#endif #endif }; @@ -105,6 +113,11 @@ class PlatformDisplay { EGLImage createEGLImage(EGLContext, EGLenum target, EGLClientBuffer, const Vector&) const; bool destroyEGLImage(EGLImage) const; +#if USE(GBM) + const String& drmDeviceFile(); + const String& drmRenderNodeFile(); + struct gbm_device* gbmDevice(); +#endif #endif #if ENABLE(VIDEO) && USE(GSTREAMER_GL) @@ -138,10 +151,16 @@ class PlatformDisplay { virtual void initializeEGLDisplay(); EGLDisplay m_eglDisplay; -#endif - -#if USE(EGL) std::unique_ptr m_sharingGLContext; + +#if USE(GBM) + std::optional m_drmDeviceFile; + std::optional m_drmRenderNodeFile; + struct { + WTF::UnixFileDescriptor deviceFD; + std::optional device; + } m_gbm; +#endif #endif #if USE(LCMS) @@ -159,6 +178,9 @@ class PlatformDisplay { #if USE(EGL) void terminateEGLDisplay(); +#if USE(GBM) + EGLDeviceEXT eglDevice(); +#endif bool m_eglDisplayInitialized { false }; int m_eglMajorVersion { 0 }; diff --git a/Source/WebCore/platform/graphics/egl/GLContext.cpp b/Source/WebCore/platform/graphics/egl/GLContext.cpp index 35b29618a291..9ce78bd920e7 100644 --- a/Source/WebCore/platform/graphics/egl/GLContext.cpp +++ b/Source/WebCore/platform/graphics/egl/GLContext.cpp @@ -146,7 +146,7 @@ bool GLContext::getEGLConfig(PlatformDisplay& platformDisplay, EGLConfig* config switch (surfaceType) { case GLContext::Surfaceless: - if (platformDisplay.type() == PlatformDisplay::Type::Headless) + if (platformDisplay.type() == PlatformDisplay::Type::Surfaceless) attributeList[13] = EGL_PBUFFER_BIT; else attributeList[13] = EGL_WINDOW_BIT; @@ -270,7 +270,10 @@ std::unique_ptr GLContext::createWindowContext(GLNativeWindowType win surface = createWindowSurfaceWPE(display, config, window); break; #endif // USE(WPE_RENDERER) - case PlatformDisplay::Type::Headless: +#if USE(GBM) + case PlatformDisplay::Type::GBM: +#endif + case PlatformDisplay::Type::Surfaceless: RELEASE_ASSERT_NOT_REACHED(); } @@ -359,7 +362,7 @@ std::unique_ptr GLContext::create(GLNativeWindowType window, Platform } EGLContext eglSharingContext = platformDisplay.sharingGLContext() ? static_cast(platformDisplay.sharingGLContext())->m_context : EGL_NO_CONTEXT; - if (platformDisplay.type() == PlatformDisplay::Type::Headless) { + if (platformDisplay.type() == PlatformDisplay::Type::Surfaceless) { auto context = createSurfacelessContext(platformDisplay, eglSharingContext); if (!context) WTFLogAlways("Could not create EGL surfaceless context: %s.", lastErrorString()); @@ -386,7 +389,10 @@ std::unique_ptr GLContext::create(GLNativeWindowType window, Platform context = createWPEContext(platformDisplay, eglSharingContext); break; #endif - case PlatformDisplay::Type::Headless: +#if USE(GBM) + case PlatformDisplay::Type::GBM: +#endif + case PlatformDisplay::Type::Surfaceless: RELEASE_ASSERT_NOT_REACHED(); } } @@ -443,7 +449,10 @@ std::unique_ptr GLContext::createSharing(PlatformDisplay& platformDis context = createWPEContext(platformDisplay); break; #endif - case PlatformDisplay::Type::Headless: +#if USE(GBM) + case PlatformDisplay::Type::GBM: +#endif + case PlatformDisplay::Type::Surfaceless: break; } } diff --git a/Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.cpp b/Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.cpp similarity index 86% rename from Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.cpp rename to Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.cpp index 62ca6526c82c..bc2af43534da 100644 --- a/Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.cpp +++ b/Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.cpp @@ -24,7 +24,7 @@ */ #include "config.h" -#include "PlatformDisplayHeadless.h" +#include "PlatformDisplaySurfaceless.h" #if USE(EGL) #include "GLContext.h" @@ -32,12 +32,12 @@ namespace WebCore { -std::unique_ptr PlatformDisplayHeadless::create() +std::unique_ptr PlatformDisplaySurfaceless::create() { - return std::unique_ptr(new PlatformDisplayHeadless()); + return std::unique_ptr(new PlatformDisplaySurfaceless()); } -PlatformDisplayHeadless::PlatformDisplayHeadless() +PlatformDisplaySurfaceless::PlatformDisplaySurfaceless() { #if PLATFORM(GTK) PlatformDisplay::setSharedDisplayForCompositing(*this); @@ -52,7 +52,7 @@ PlatformDisplayHeadless::PlatformDisplayHeadless() PlatformDisplay::initializeEGLDisplay(); } -PlatformDisplayHeadless::~PlatformDisplayHeadless() +PlatformDisplaySurfaceless::~PlatformDisplaySurfaceless() { } diff --git a/Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.h b/Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.h similarity index 83% rename from Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.h rename to Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.h index 189dd71fc92f..920fb252c026 100644 --- a/Source/WebCore/platform/graphics/egl/PlatformDisplayHeadless.h +++ b/Source/WebCore/platform/graphics/egl/PlatformDisplaySurfaceless.h @@ -30,15 +30,15 @@ namespace WebCore { -class PlatformDisplayHeadless final : public PlatformDisplay { +class PlatformDisplaySurfaceless final : public PlatformDisplay { public: - static std::unique_ptr create(); + static std::unique_ptr create(); - virtual ~PlatformDisplayHeadless(); + virtual ~PlatformDisplaySurfaceless(); private: - PlatformDisplayHeadless(); + PlatformDisplaySurfaceless(); - Type type() const override { return PlatformDisplay::Type::Headless; } + Type type() const override { return PlatformDisplay::Type::Surfaceless; } }; } // namespace WebCore diff --git a/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.cpp b/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.cpp new file mode 100644 index 000000000000..8bccfa61d057 --- /dev/null +++ b/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2023 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "PlatformDisplayGBM.h" + +#if USE(EGL) && USE(GBM) +#include "GLContext.h" +#include +#include +#include +#include +#include +#include +#include + +namespace WebCore { + +std::unique_ptr PlatformDisplayGBM::create(const String& deviceFile) +{ + auto fd = UnixFileDescriptor { open(deviceFile.utf8().data(), O_RDWR | O_CLOEXEC), UnixFileDescriptor::Adopt }; + if (!fd) { + WTFLogAlways("Failed to open DRM render device %s: %s", deviceFile.utf8().data(), safeStrerror(errno).data()); + return nullptr; + } + + auto* device = gbm_create_device(fd.value()); + if (!device) { + WTFLogAlways("Failed to create GBM device for render device: %s: %s", deviceFile.utf8().data(), safeStrerror(errno).data()); + return nullptr; + } + + return std::unique_ptr(new PlatformDisplayGBM(WTFMove(fd), device)); +} + +PlatformDisplayGBM::PlatformDisplayGBM(UnixFileDescriptor&& fd, struct gbm_device* device) +{ +#if PLATFORM(GTK) + PlatformDisplay::setSharedDisplayForCompositing(*this); +#endif + + m_gbm = { WTFMove(fd), device }; + + const char* extensions = eglQueryString(nullptr, EGL_EXTENSIONS); + if (GLContext::isExtensionSupported(extensions, "EGL_EXT_platform_base")) + m_eglDisplay = eglGetPlatformDisplayEXT(EGL_PLATFORM_GBM_KHR, m_gbm.device.value(), nullptr); + else if (GLContext::isExtensionSupported(extensions, "EGL_KHR_platform_base")) + m_eglDisplay = eglGetPlatformDisplay(EGL_PLATFORM_GBM_KHR, m_gbm.device.value(), nullptr); + + PlatformDisplay::initializeEGLDisplay(); +} + +PlatformDisplayGBM::~PlatformDisplayGBM() +{ +} + +} // namespace WebCore + +#endif // USE(EGL) && USE(GBM) diff --git a/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.h b/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.h new file mode 100644 index 000000000000..e0a0049f4c6b --- /dev/null +++ b/Source/WebCore/platform/graphics/gbm/PlatformDisplayGBM.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2023 Igalia S.L. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#if USE(EGL) && USE(GBM) +#include "PlatformDisplay.h" + +namespace WebCore { + +class PlatformDisplayGBM final : public PlatformDisplay { +public: + static std::unique_ptr create(const String&); + + virtual ~PlatformDisplayGBM(); +private: + PlatformDisplayGBM(UnixFileDescriptor&&, struct gbm_device*); + + Type type() const override { return PlatformDisplay::Type::GBM; } +}; + +} // namespace WebCore + +#endif // USE(EGL) && USE(GBM) diff --git a/Source/WebKit/Shared/WebProcessCreationParameters.cpp b/Source/WebKit/Shared/WebProcessCreationParameters.cpp index 36c4a3a77906..aea41beabf8e 100644 --- a/Source/WebKit/Shared/WebProcessCreationParameters.cpp +++ b/Source/WebKit/Shared/WebProcessCreationParameters.cpp @@ -188,6 +188,7 @@ void WebProcessCreationParameters::encode(IPC::Encoder& encoder) const #if PLATFORM(GTK) encoder << useDMABufSurfaceForCompositing; + encoder << renderDeviceFile; encoder << useSystemAppearanceForScrollbars; encoder << gtkSettings; #endif @@ -526,6 +527,11 @@ bool WebProcessCreationParameters::decode(IPC::Decoder& decoder, WebProcessCreat if (!useDMABufSurfaceForCompositing) return false; parameters.useDMABufSurfaceForCompositing = WTFMove(*useDMABufSurfaceForCompositing); + std::optional renderDeviceFile; + decoder >> renderDeviceFile; + if (!renderDeviceFile) + return false; + parameters.renderDeviceFile = WTFMove(*renderDeviceFile); std::optional useSystemAppearanceForScrollbars; decoder >> useSystemAppearanceForScrollbars; if (!useSystemAppearanceForScrollbars) diff --git a/Source/WebKit/Shared/WebProcessCreationParameters.h b/Source/WebKit/Shared/WebProcessCreationParameters.h index b3d9560fba26..a8d59c1bcb8f 100644 --- a/Source/WebKit/Shared/WebProcessCreationParameters.h +++ b/Source/WebKit/Shared/WebProcessCreationParameters.h @@ -229,6 +229,7 @@ struct WebProcessCreationParameters { #if PLATFORM(GTK) bool useDMABufSurfaceForCompositing { false }; + String renderDeviceFile; bool useSystemAppearanceForScrollbars { false }; GtkSettingsState gtkSettings; #endif diff --git a/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp b/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp index b629cc6536bf..0750e0b544c9 100644 --- a/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp +++ b/Source/WebKit/UIProcess/API/glib/WebKitProtocolHandler.cpp @@ -58,9 +58,6 @@ #if USE(GBM) #include "AcceleratedBackingStoreDMABuf.h" -#ifndef EGL_DRM_RENDER_NODE_FILE_EXT -#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377 -#endif #endif #if PLATFORM(X11) @@ -281,22 +278,13 @@ void WebKitProtocolHandler::handleGPU(WebKitURISchemeRequest* request) addTableRow(hardwareAccelerationObject, "GL_VERSION"_s, makeString(reinterpret_cast(glGetString(GL_VERSION)))); addTableRow(hardwareAccelerationObject, "GL_SHADING_LANGUAGE_VERSION"_s, makeString(reinterpret_cast(glGetString(GL_SHADING_LANGUAGE_VERSION)))); - auto eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay(); #if USE(GBM) - if (GLContext::isExtensionSupported(eglQueryString(nullptr, EGL_EXTENSIONS), "EGL_EXT_device_query")) { - EGLDeviceEXT eglDevice; - if (eglQueryDisplayAttribEXT(eglDisplay, EGL_DEVICE_EXT, reinterpret_cast(&eglDevice))) { - const char* deviceExtensions = eglQueryDeviceStringEXT(eglDevice, EGL_EXTENSIONS); - if (GLContext::isExtensionSupported(deviceExtensions, "EGL_EXT_device_drm")) { - if (const char* deviceFile = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_DEVICE_FILE_EXT)) - addTableRow(hardwareAccelerationObject, "DRM Device"_s, makeString(deviceFile)); - } - if (GLContext::isExtensionSupported(deviceExtensions, "EGL_EXT_device_drm_render_node")) { - if (const char* renderNode = eglQueryDeviceStringEXT(eglDevice, EGL_DRM_RENDER_NODE_FILE_EXT)) - addTableRow(hardwareAccelerationObject, "DRM Render Node"_s, makeString(renderNode)); - } - } - } + auto deviceFile = PlatformDisplay::sharedDisplay().drmDeviceFile(); + if (!deviceFile.isEmpty()) + addTableRow(hardwareAccelerationObject, "DRM Device"_s, deviceFile); + auto renderNode = PlatformDisplay::sharedDisplay().drmRenderNodeFile(); + if (!renderNode.isEmpty()) + addTableRow(hardwareAccelerationObject, "DRM Render Node"_s, renderNode); #endif #if USE(OPENGL_ES) @@ -313,6 +301,7 @@ void WebKitProtocolHandler::handleGPU(WebKitURISchemeRequest* request) addTableRow(hardwareAccelerationObject, "GL_EXTENSIONS"_s, extensionsBuilder.toString()); #endif + auto eglDisplay = PlatformDisplay::sharedDisplay().eglDisplay(); addTableRow(hardwareAccelerationObject, "EGL_VERSION"_s, makeString(eglQueryString(eglDisplay, EGL_VERSION))); addTableRow(hardwareAccelerationObject, "EGL_VENDOR"_s, makeString(eglQueryString(eglDisplay, EGL_VENDOR))); addTableRow(hardwareAccelerationObject, "EGL_EXTENSIONS"_s, makeString(eglQueryString(nullptr, EGL_EXTENSIONS), ' ', eglQueryString(eglDisplay, EGL_EXTENSIONS))); diff --git a/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp b/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp index 82feb4b26719..5abe94e29ad4 100644 --- a/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp +++ b/Source/WebKit/UIProcess/glib/WebProcessPoolGLib.cpp @@ -87,8 +87,10 @@ void WebProcessPool::platformInitializeWebProcess(const WebProcessProxy& process #endif #if PLATFORM(GTK) && USE(GBM) - if (AcceleratedBackingStoreDMABuf::checkRequirements()) + if (AcceleratedBackingStoreDMABuf::checkRequirements()) { parameters.useDMABufSurfaceForCompositing = true; + parameters.renderDeviceFile = WebCore::PlatformDisplay::sharedDisplay().drmRenderNodeFile(); + } #endif #if PLATFORM(WAYLAND) diff --git a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp index 3ed329cc9a86..bbdc911b0de2 100644 --- a/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp +++ b/Source/WebKit/UIProcess/gtk/AcceleratedBackingStoreDMABuf.cpp @@ -33,7 +33,6 @@ #include "WebPageProxy.h" #include "WebProcessProxy.h" #include -#include #include #include #include @@ -219,7 +218,12 @@ void AcceleratedBackingStoreDMABuf::Texture::paint(GtkWidget* widget, cairo_t* c AcceleratedBackingStoreDMABuf::Surface::Surface(const UnixFileDescriptor& backFD, const UnixFileDescriptor& frontFD, const WebCore::IntSize& size, uint32_t format, uint32_t offset, uint32_t stride, float deviceScaleFactor) : RenderSource(size, deviceScaleFactor) { - auto* device = WebCore::GBMDevice::singleton().device(); + auto* device = WebCore::PlatformDisplay::sharedDisplay().gbmDevice(); + if (!device) { + WTFLogAlways("Failed to get GBM device"); + return; + } + struct gbm_import_fd_data fdData = { backFD.value(), static_cast(m_size.width()), static_cast(m_size.height()), stride, format }; m_backBuffer = gbm_bo_import(device, GBM_BO_IMPORT_FD, &fdData, GBM_BO_USE_RENDERING); if (!m_backBuffer) { diff --git a/Source/WebKit/WebProcess/WebPage/AcceleratedSurface.cpp b/Source/WebKit/WebProcess/WebPage/AcceleratedSurface.cpp index 27f65723f70a..09cb12bb800f 100644 --- a/Source/WebKit/WebProcess/WebPage/AcceleratedSurface.cpp +++ b/Source/WebKit/WebProcess/WebPage/AcceleratedSurface.cpp @@ -47,7 +47,8 @@ using namespace WebCore; std::unique_ptr AcceleratedSurface::create(WebPage& webPage, Client& client) { #if USE(GBM) - if (PlatformDisplay::sharedDisplayForCompositing().type() == PlatformDisplay::Type::Headless) + if (PlatformDisplay::sharedDisplayForCompositing().type() == PlatformDisplay::Type::GBM + || PlatformDisplay::sharedDisplayForCompositing().type() == PlatformDisplay::Type::Surfaceless) return AcceleratedSurfaceDMABuf::create(webPage, client); #endif #if PLATFORM(WAYLAND) diff --git a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceDMABuf.cpp b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceDMABuf.cpp index 14a8631f3ed6..0300ea0b4436 100644 --- a/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceDMABuf.cpp +++ b/Source/WebKit/WebProcess/WebPage/gtk/AcceleratedSurfaceDMABuf.cpp @@ -32,7 +32,6 @@ #include "WebPage.h" #include "WebProcess.h" #include -#include #include #include #include @@ -48,7 +47,7 @@ std::unique_ptr AcceleratedSurfaceDMABuf::create(WebPa AcceleratedSurfaceDMABuf::AcceleratedSurfaceDMABuf(WebPage& webPage, Client& client) : AcceleratedSurface(webPage, client) - , m_isSoftwareRast(!WebCore::PlatformDisplay::sharedDisplayForCompositing().eglExtensions().EXT_image_dma_buf_import) + , m_isSoftwareRast(WebCore::PlatformDisplay::sharedDisplayForCompositing().type() == WebCore::PlatformDisplay::Type::Surfaceless) { } @@ -101,7 +100,12 @@ std::unique_ptr AcceleratedSurfaceDMABuf auto& display = WebCore::PlatformDisplay::sharedDisplayForCompositing(); auto createImage = [&]() -> std::pair { - auto* bo = gbm_bo_create(WebCore::GBMDevice::singleton().device(), size.width(), size.height(), uint32_t(WebCore::DMABufFormat::FourCC::ARGB8888), 0); + auto* device = display.gbmDevice(); + if (!device) { + WTFLogAlways("Failed to create GBM buffer of size %dx%d: no GBM device found", size.width(), size.height()); + return { }; + } + auto* bo = gbm_bo_create(device, size.width(), size.height(), uint32_t(WebCore::DMABufFormat::FourCC::ARGB8888), 0); if (!bo) { WTFLogAlways("Failed to create GBM buffer of size %dx%d: %s", size.width(), size.height(), safeStrerror(errno).data()); return { }; diff --git a/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp b/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp index 0b6108e29669..8a31082be1e5 100644 --- a/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp +++ b/Source/WebKit/WebProcess/glib/WebProcessGLib.cpp @@ -48,8 +48,9 @@ #include #endif -#if PLATFORM(GTK) && USE(EGL) -#include +#if PLATFORM(GTK) && USE(GBM) +#include +#include #endif #if PLATFORM(GTK) && !USE(GTK4) @@ -123,9 +124,13 @@ void WebProcess::platformInitializeWebProcess(WebProcessCreationParameters& para } #endif -#if PLATFORM(GTK) && USE(EGL) - if (parameters.useDMABufSurfaceForCompositing) - m_displayForCompositing = WebCore::PlatformDisplayHeadless::create(); +#if PLATFORM(GTK) && USE(GBM) + if (parameters.useDMABufSurfaceForCompositing) { + if (!parameters.renderDeviceFile.isEmpty()) + m_displayForCompositing = WebCore::PlatformDisplayGBM::create(parameters.renderDeviceFile); + else + m_displayForCompositing = WebCore::PlatformDisplaySurfaceless::create(); + } #endif #if PLATFORM(WAYLAND)