PlatformDisplay.cpp [plain text]
#include "config.h"
#include "PlatformDisplay.h"
#include "GLContext.h"
#include <cstdlib>
#include <mutex>
#if PLATFORM(X11)
#include "PlatformDisplayX11.h"
#endif
#if PLATFORM(WAYLAND)
#include "PlatformDisplayWayland.h"
#endif
#if PLATFORM(WIN)
#include "PlatformDisplayWin.h"
#endif
#if USE(WPE_RENDERER)
#include "PlatformDisplayLibWPE.h"
#endif
#if PLATFORM(GTK)
#include "GtkVersioning.h"
#endif
#if PLATFORM(GTK) && PLATFORM(X11)
#if USE(GTK4)
#include <gdk/x11/gdkx.h>
#else
#include <gdk/gdkx.h>
#endif
#if defined(None)
#undef None
#endif
#endif
#if PLATFORM(GTK) && PLATFORM(WAYLAND)
#if USE(GTK4)
#include <gdk/wayland/gdkwayland.h>
#else
#include <gdk/gdkwayland.h>
#endif
#endif
#if USE(EGL)
#if USE(LIBEPOXY)
#include "EpoxyEGL.h"
#else
#include <EGL/egl.h>
#endif
#include "GLContextEGL.h"
#include <wtf/HashSet.h>
#include <wtf/NeverDestroyed.h>
#endif
namespace WebCore {
std::unique_ptr<PlatformDisplay> PlatformDisplay::createPlatformDisplay()
{
#if PLATFORM(GTK)
if (gtk_init_check(nullptr, nullptr)) {
GdkDisplay* display = gdk_display_manager_get_default_display(gdk_display_manager_get());
#if PLATFORM(X11)
if (GDK_IS_X11_DISPLAY(display))
return PlatformDisplayX11::create(GDK_DISPLAY_XDISPLAY(display));
#endif
#if PLATFORM(WAYLAND)
if (GDK_IS_WAYLAND_DISPLAY(display))
return PlatformDisplayWayland::create(gdk_wayland_display_get_wl_display(display));
#endif
}
#endif // PLATFORM(GTK)
#if PLATFORM(WAYLAND)
if (auto platformDisplay = PlatformDisplayWayland::create())
return platformDisplay;
#endif
#if PLATFORM(X11)
if (auto platformDisplay = PlatformDisplayX11::create())
return platformDisplay;
#endif
#if PLATFORM(WAYLAND)
return PlatformDisplayWayland::create(nullptr);
#elif PLATFORM(X11)
return PlatformDisplayX11::create(nullptr);
#endif
#if USE(WPE_RENDERER)
return PlatformDisplayLibWPE::create();
#elif PLATFORM(WIN)
return PlatformDisplayWin::create();
#endif
RELEASE_ASSERT_NOT_REACHED();
}
PlatformDisplay& PlatformDisplay::sharedDisplay()
{
#if PLATFORM(WIN)
ASSERT(isMainThread());
static PlatformDisplay* display = createPlatformDisplay().release();
return *display;
#else
static std::once_flag onceFlag;
IGNORE_CLANG_WARNINGS_BEGIN("exit-time-destructors")
static std::unique_ptr<PlatformDisplay> display;
IGNORE_CLANG_WARNINGS_END
std::call_once(onceFlag, []{
display = createPlatformDisplay();
});
return *display;
#endif
}
static PlatformDisplay* s_sharedDisplayForCompositing;
PlatformDisplay& PlatformDisplay::sharedDisplayForCompositing()
{
return s_sharedDisplayForCompositing ? *s_sharedDisplayForCompositing : sharedDisplay();
}
void PlatformDisplay::setSharedDisplayForCompositing(PlatformDisplay& display)
{
s_sharedDisplayForCompositing = &display;
}
PlatformDisplay::PlatformDisplay(NativeDisplayOwned displayOwned)
: m_nativeDisplayOwned(displayOwned)
#if USE(EGL)
, m_eglDisplay(EGL_NO_DISPLAY)
#endif
{
}
PlatformDisplay::~PlatformDisplay()
{
#if USE(EGL) && !PLATFORM(WIN)
ASSERT(m_eglDisplay == EGL_NO_DISPLAY);
#endif
if (s_sharedDisplayForCompositing == this)
s_sharedDisplayForCompositing = nullptr;
}
#if USE(EGL) || USE(GLX)
GLContext* PlatformDisplay::sharingGLContext()
{
if (!m_sharingGLContext)
m_sharingGLContext = GLContext::createSharingContext(*this);
return m_sharingGLContext.get();
}
#endif
#if USE(EGL)
static HashSet<PlatformDisplay*>& eglDisplays()
{
static NeverDestroyed<HashSet<PlatformDisplay*>> displays;
return displays;
}
EGLDisplay PlatformDisplay::eglDisplay() const
{
if (!m_eglDisplayInitialized)
const_cast<PlatformDisplay*>(this)->initializeEGLDisplay();
return m_eglDisplay;
}
bool PlatformDisplay::eglCheckVersion(int major, int minor) const
{
if (!m_eglDisplayInitialized)
const_cast<PlatformDisplay*>(this)->initializeEGLDisplay();
return (m_eglMajorVersion > major) || ((m_eglMajorVersion == major) && (m_eglMinorVersion >= minor));
}
void PlatformDisplay::initializeEGLDisplay()
{
m_eglDisplayInitialized = true;
if (m_eglDisplay == EGL_NO_DISPLAY) {
m_eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (m_eglDisplay == EGL_NO_DISPLAY) {
WTFLogAlways("Cannot get default EGL display: %s\n", GLContextEGL::lastErrorString());
return;
}
}
EGLint majorVersion, minorVersion;
if (eglInitialize(m_eglDisplay, &majorVersion, &minorVersion) == EGL_FALSE) {
WTFLogAlways("EGLDisplay Initialization failed: %s\n", GLContextEGL::lastErrorString());
terminateEGLDisplay();
return;
}
m_eglMajorVersion = majorVersion;
m_eglMinorVersion = minorVersion;
eglDisplays().add(this);
#if !PLATFORM(WIN)
static bool eglAtexitHandlerInitialized = false;
if (!eglAtexitHandlerInitialized) {
eglAtexitHandlerInitialized = true;
std::atexit([] {
while (!eglDisplays().isEmpty()) {
auto* display = eglDisplays().takeAny();
display->terminateEGLDisplay();
}
});
}
#endif
}
void PlatformDisplay::terminateEGLDisplay()
{
#if ENABLE(VIDEO) && USE(GSTREAMER_GL)
m_gstGLDisplay = nullptr;
m_gstGLContext = nullptr;
#endif
m_sharingGLContext = nullptr;
ASSERT(m_eglDisplayInitialized);
if (m_eglDisplay == EGL_NO_DISPLAY)
return;
eglTerminate(m_eglDisplay);
m_eglDisplay = EGL_NO_DISPLAY;
}
#endif // USE(EGL)
}