Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GTK] Minibrowser does not render any content #12791

Merged
merged 1 commit into from Apr 18, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 3 additions & 1 deletion Source/WebCore/PlatformGTK.cmake
Expand Up @@ -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

Expand Down
3 changes: 2 additions & 1 deletion Source/WebCore/SourcesGTK.txt
Expand Up @@ -74,14 +74,15 @@ 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
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
Expand Down
117 changes: 117 additions & 0 deletions Source/WebCore/platform/graphics/PlatformDisplay.cpp
Expand Up @@ -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
Expand Down Expand Up @@ -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());
carlosgcampos marked this conversation as resolved.
Show resolved Hide resolved
#endif
if (s_sharedDisplayForCompositing == this)
s_sharedDisplayForCompositing = nullptr;
Expand Down Expand Up @@ -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();
}
carlosgcampos marked this conversation as resolved.
Show resolved Hide resolved

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)
Expand Down
30 changes: 26 additions & 4 deletions Source/WebCore/platform/graphics/PlatformDisplay.h
Expand Up @@ -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)
Expand Down Expand Up @@ -80,7 +85,10 @@ class PlatformDisplay {
WPE,
#endif
#if USE(EGL)
Headless,
Surfaceless,
#if USE(GBM)
GBM,
#endif
#endif
};

Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand All @@ -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 };
Expand Down
19 changes: 14 additions & 5 deletions Source/WebCore/platform/graphics/egl/GLContext.cpp
Expand Up @@ -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;
Expand Down Expand Up @@ -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();
}

Expand Down Expand Up @@ -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());
Expand All @@ -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();
}
}
Expand Down Expand Up @@ -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;
}
}
Expand Down
Expand Up @@ -24,20 +24,20 @@
*/

#include "config.h"
#include "PlatformDisplayHeadless.h"
#include "PlatformDisplaySurfaceless.h"

#if USE(EGL)
#include "GLContext.h"
#include <epoxy/egl.h>

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);
Expand All @@ -52,7 +52,7 @@ PlatformDisplayHeadless::PlatformDisplayHeadless()
PlatformDisplay::initializeEGLDisplay();
}

PlatformDisplayHeadless::~PlatformDisplayHeadless()
PlatformDisplaySurfaceless::~PlatformDisplaySurfaceless()
{
}

Expand Down
Expand Up @@ -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
Expand Down