webkitgtk/fix-multi-gpus.patch
2023-04-17 13:50:46 -05:00

872 lines
37 KiB
Diff

From b835f528fa750ecddf79de8a9aea3900a0d169c8 Mon Sep 17 00:00:00 2001
From: Carlos Garcia Campos <cgarcia@igalia.com>
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<const char*>(glGetString(GL_VERSION))));
addTableRow(hardwareAccelerationObject, "GL_SHADING_LANGUAGE_VERSION"_s, makeString(reinterpret_cast<const char*>(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<EGLAttrib*>(&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<const char*>(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 <cgarcia@igalia.com>
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 <wtf/NeverDestroyed.h>
#endif
+#if USE(EGL) && USE(GBM)
+#include <fcntl.h>
+#include <gbm.h>
+#include <unistd.h>
+#include <wtf/SafeStrerror.h>
+#include <wtf/StdLibExtras.h>
+#include <xf86drm.h>
+#ifndef EGL_DRM_RENDER_NODE_FILE_EXT
+#define EGL_DRM_RENDER_NODE_FILE_EXT 0x3377
+#endif
+#endif
+
#if USE(ATSPI)
#include <wtf/glib/GUniquePtr.h>
#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<PlatformDisplay*>(this)->initializeEGLDisplay();
+
+ EGLDeviceEXT eglDevice;
+ if (eglQueryDisplayAttribEXT(m_eglDisplay, EGL_DEVICE_EXT, reinterpret_cast<EGLAttrib*>(&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 <wtf/unix/UnixFileDescriptor.h>
+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<EGLAttrib>&) 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<GLContext> m_sharingGLContext;
+
+#if USE(GBM)
+ std::optional<String> m_drmDeviceFile;
+ std::optional<String> m_drmRenderNodeFile;
+ struct {
+ WTF::UnixFileDescriptor deviceFD;
+ std::optional<struct gbm_device*> 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> 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> GLContext::create(GLNativeWindowType window, Platform
}
EGLContext eglSharingContext = platformDisplay.sharingGLContext() ? static_cast<GLContext*>(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> 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> 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> PlatformDisplayHeadless::create()
+std::unique_ptr<PlatformDisplaySurfaceless> PlatformDisplaySurfaceless::create()
{
- return std::unique_ptr<PlatformDisplayHeadless>(new PlatformDisplayHeadless());
+ return std::unique_ptr<PlatformDisplaySurfaceless>(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<PlatformDisplayHeadless> create();
+ static std::unique_ptr<PlatformDisplaySurfaceless> 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 <epoxy/egl.h>
+#include <fcntl.h>
+#include <gbm.h>
+#include <unistd.h>
+#include <wtf/SafeStrerror.h>
+#include <wtf/StdLibExtras.h>
+#include <wtf/unix/UnixFileDescriptor.h>
+
+namespace WebCore {
+
+std::unique_ptr<PlatformDisplayGBM> 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<PlatformDisplayGBM>(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<PlatformDisplayGBM> 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<String> renderDeviceFile;
+ decoder >> renderDeviceFile;
+ if (!renderDeviceFile)
+ return false;
+ parameters.renderDeviceFile = WTFMove(*renderDeviceFile);
std::optional<bool> 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<const char*>(glGetString(GL_VERSION))));
addTableRow(hardwareAccelerationObject, "GL_SHADING_LANGUAGE_VERSION"_s, makeString(reinterpret_cast<const char*>(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<EGLAttrib*>(&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 <WebCore/DMABufFormat.h>
-#include <WebCore/GBMDevice.h>
#include <WebCore/GLContext.h>
#include <WebCore/IntRect.h>
#include <WebCore/PlatformDisplay.h>
@@ -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<uint32_t>(m_size.width()), static_cast<uint32_t>(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> 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 <WebCore/DMABufFormat.h>
-#include <WebCore/GBMDevice.h>
#include <WebCore/PlatformDisplay.h>
#include <array>
#include <epoxy/egl.h>
@@ -48,7 +47,7 @@ std::unique_ptr<AcceleratedSurfaceDMABuf> 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::RenderTarget> AcceleratedSurfaceDMABuf
auto& display = WebCore::PlatformDisplay::sharedDisplayForCompositing();
auto createImage = [&]() -> std::pair<UnixFileDescriptor, EGLImage> {
- 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 <wpe/wpe.h>
#endif
-#if PLATFORM(GTK) && USE(EGL)
-#include <WebCore/PlatformDisplayHeadless.h>
+#if PLATFORM(GTK) && USE(GBM)
+#include <WebCore/PlatformDisplayGBM.h>
+#include <WebCore/PlatformDisplaySurfaceless.h>
#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)