Make EGL_KHR_surfaceless_context mandatory

We use surfaceless contexts with internal windows. We also require
the EGL_KHR_surfaceless_context extension for making context current
without outputs.

Arguably, we could use pbuffers, but since mainstream drivers (Mesa and
NVIDIA) support surfaceless contexts, the extra complexity doesn't buy
us anything.
This commit is contained in:
Vlad Zahorodnii 2021-08-16 11:21:36 +03:00
parent 4af9674f17
commit 7f883fa724
15 changed files with 3 additions and 128 deletions

View file

@ -464,18 +464,6 @@ void Platform::warpPointer(const QPointF &globalPos)
Q_UNUSED(globalPos)
}
bool Platform::supportsSurfacelessContext() const
{
Compositor *compositor = Compositor::self();
if (Q_UNLIKELY(!compositor)) {
return false;
}
if (Scene *scene = compositor->scene()) {
return scene->supportsSurfacelessContext();
}
return false;
}
bool Platform::supportsNativeFence() const
{
if (Compositor *compositor = Compositor::self()) {

View file

@ -79,11 +79,6 @@ public:
*/
virtual void createPlatformCursor(QObject *parent = nullptr);
virtual void warpPointer(const QPointF &globalPos);
/**
* Whether our Compositing EGL display allows a surface less context
* so that a sharing context could be created.
*/
bool supportsSurfacelessContext() const;
/**
* Whether our Compositing EGL display supports creating native EGL fences.
*/

View file

@ -144,6 +144,7 @@ bool AbstractEglBackend::initEglAPI()
const QByteArray requiredExtensions[] = {
QByteArrayLiteral("EGL_KHR_no_config_context"),
QByteArrayLiteral("EGL_KHR_surfaceless_context"),
};
for (const QByteArray &extensionName : requiredExtensions) {
if (!hasExtension(extensionName)) {
@ -152,7 +153,6 @@ bool AbstractEglBackend::initEglAPI()
}
}
setSupportsSurfacelessContext(hasExtension(QByteArrayLiteral("EGL_KHR_surfaceless_context")));
setSupportsNativeFence(hasExtension(QByteArrayLiteral("EGL_ANDROID_native_fence_sync")));
return true;
}

View file

@ -117,10 +117,6 @@ public:
return m_haveSwapBuffersWithDamage;
}
bool supportsSurfacelessContext() const
{
return m_haveSurfacelessContext;
}
bool supportsNativeFence() const
{
return m_haveNativeFence;
@ -187,11 +183,6 @@ protected:
m_haveSwapBuffersWithDamage = value;
}
void setSupportsSurfacelessContext(bool value)
{
m_haveSurfacelessContext = value;
}
void setSupportsNativeFence(bool value)
{
m_haveNativeFence = value;
@ -220,10 +211,6 @@ private:
*/
bool m_havePartialUpdate = false;
bool m_haveSwapBuffersWithDamage = false;
/**
* @brief Whether the backend supports EGL_KHR_surfaceless_context.
*/
bool m_haveSurfacelessContext = false;
/**
* @brief Whether the backend supports EGL_ANDROID_native_fence_sync.
*/

View file

@ -113,11 +113,6 @@ void EglGbmBackend::init()
return;
}
if (!supportsSurfacelessContext()) {
setFailed("EGL_KHR_surfaceless_context extension is unavailable!");
return;
}
if (!initRenderingContext()) {
setFailed("Could not initialize rendering context");
return;

View file

@ -47,7 +47,6 @@ void EglMultiBackend::init()
b->init();
}
// we only care about the rendering GPU
setSupportsSurfacelessContext(m_backends[0]->supportsSurfacelessContext());
setSupportsBufferAge(m_backends[0]->supportsBufferAge());
setSupportsPartialUpdate(m_backends[0]->supportsPartialUpdate());
setSupportsSwapBuffersWithDamage(m_backends[0]->supportsSwapBuffersWithDamage());

View file

@ -261,10 +261,6 @@ void EglStreamBackend::init()
setFailed("Failed to initialize EGL api");
return;
}
if (!supportsSurfacelessContext()) {
setFailed("EGL_KHR_surfaceless_context extension is unavailable!");
return;
}
if (!initRenderingContext()) {
setFailed("Failed to initialize rendering context");
return;

View file

@ -107,11 +107,6 @@ bool EglGbmBackend::initRenderingContext()
{
initBufferConfigs();
if (!supportsSurfacelessContext()) {
qCWarning(KWIN_VIRTUAL) << "EGL_KHR_surfaceless_context extension is unavailable";
return false;
}
if (!createContext()) {
return false;
}

View file

@ -265,40 +265,13 @@ void EGLPlatformContext::create(const QSurfaceFormat &format, EGLContext shareCo
updateFormatFromContext();
}
static EGLSurface createDummyPbufferSurface(EGLDisplay display, const QSurfaceFormat &format)
{
const EGLConfig config = configFromFormat(display, format, EGL_PBUFFER_BIT);
if (config == EGL_NO_CONFIG_KHR) {
return EGL_NO_SURFACE;
}
const EGLint attribs[] = {
EGL_WIDTH, 16,
EGL_HEIGHT, 16,
EGL_NONE
};
return eglCreatePbufferSurface(display, config, attribs);
}
void EGLPlatformContext::updateFormatFromContext()
{
const EGLSurface oldDrawSurface = eglGetCurrentSurface(EGL_DRAW);
const EGLSurface oldReadSurface = eglGetCurrentSurface(EGL_READ);
const EGLContext oldContext = eglGetCurrentContext();
EGLSurface dummySurface;
if (!kwinApp()->platform()->supportsSurfacelessContext()) {
dummySurface = createDummyPbufferSurface(m_eglDisplay, m_format);
if (dummySurface == EGL_NO_SURFACE) {
qCWarning(KWIN_QPA, "Failed to create dummy surface: 0x%x", eglGetError());
return;
}
} else {
dummySurface = EGL_NO_SURFACE;
}
eglMakeCurrent(m_eglDisplay, dummySurface, dummySurface, m_context);
eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, m_context);
const char *version = reinterpret_cast<const char *>(glGetString(GL_VERSION));
int major, minor;
@ -337,10 +310,6 @@ void EGLPlatformContext::updateFormatFromContext()
}
eglMakeCurrent(m_eglDisplay, oldDrawSurface, oldReadSurface, oldContext);
if (dummySurface != EGL_NO_SURFACE) {
eglDestroySurface(m_eglDisplay, dummySurface);
}
}
} // namespace QPA

View file

@ -31,19 +31,10 @@ Window::Window(QWindow *window)
, m_windowId(++s_windowId)
, m_scale(std::max(qreal(1), screens()->maxScale()))
{
if (window->surfaceType() == QSurface::OpenGLSurface) {
// The window will use OpenGL for drawing.
if (!kwinApp()->platform()->supportsSurfacelessContext()) {
createPbuffer();
}
}
}
Window::~Window()
{
if (m_eglSurface != EGL_NO_SURFACE) {
eglDestroySurface(m_eglDisplay, m_eglSurface);
}
unmap();
}
@ -139,32 +130,6 @@ void Window::createFBO()
m_resized = false;
}
void Window::createPbuffer()
{
const QSurfaceFormat requestedFormat = window()->requestedFormat();
const EGLConfig config = configFromFormat(m_eglDisplay,
requestedFormat,
EGL_PBUFFER_BIT);
if (config == EGL_NO_CONFIG_KHR) {
qCWarning(KWIN_QPA) << "Could not find any EGL config for:" << requestedFormat;
return;
}
// The size doesn't matter as we render into a framebuffer object.
const EGLint attribs[] = {
EGL_WIDTH, 16,
EGL_HEIGHT, 16,
EGL_NONE
};
m_eglSurface = eglCreatePbufferSurface(m_eglDisplay, config, attribs);
if (m_eglSurface != EGL_NO_SURFACE) {
m_format = formatFromConfig(m_eglDisplay, config);
} else {
qCWarning(KWIN_QPA, "Failed to create a pbuffer for window: 0x%x", eglGetError());
}
}
void Window::map()
{
if (m_handle) {
@ -188,7 +153,7 @@ void Window::unmap()
EGLSurface Window::eglSurface() const
{
return m_eglSurface;
return EGL_NO_SURFACE; // EGL_KHR_surfaceless_context is required.
}
}

View file

@ -46,7 +46,6 @@ public:
private:
void createFBO();
void createPbuffer();
void map();
void unmap();
@ -54,7 +53,6 @@ private:
QPointer<InternalClient> m_handle;
QSharedPointer<QOpenGLFramebufferObject> m_contentFBO;
EGLDisplay m_eglDisplay = EGL_NO_DISPLAY;
EGLSurface m_eglSurface = EGL_NO_SURFACE;
quint32 m_windowId;
bool m_resized = false;
qreal m_scale = 1;

View file

@ -601,11 +601,6 @@ void SceneOpenGL::doneOpenGLContextCurrent()
m_backend->doneCurrent();
}
bool SceneOpenGL::supportsSurfacelessContext() const
{
return m_backend->supportsSurfacelessContext();
}
bool SceneOpenGL::supportsNativeFence() const
{
return m_backend->supportsNativeFence();

View file

@ -39,7 +39,6 @@ public:
OverlayWindow *overlayWindow() const override;
bool makeOpenGLContextCurrent() override;
void doneOpenGLContextCurrent() override;
bool supportsSurfacelessContext() const override;
bool supportsNativeFence() const override;
DecorationRenderer *createDecorationRenderer(Decoration::DecoratedClientImpl *impl) override;
virtual QMatrix4x4 projectionMatrix() const = 0;

View file

@ -539,11 +539,6 @@ void Scene::doneOpenGLContextCurrent()
{
}
bool Scene::supportsSurfacelessContext() const
{
return false;
}
bool Scene::supportsNativeFence() const
{
return false;

View file

@ -135,7 +135,6 @@ public:
virtual bool makeOpenGLContextCurrent();
virtual void doneOpenGLContextCurrent();
virtual bool supportsSurfacelessContext() const;
virtual bool supportsNativeFence() const;
virtual QMatrix4x4 screenProjectionMatrix() const;