backends/x11/standalone: port the egl backend away from AbstractEglBackend

This reduces the requirement on AbstractEglBackend to accomodate for X11
wilder/Plasma/6.2
Xaver Hugl 2 years ago
parent 866afcb94b
commit 686ea6374b
  1. 1
      src/backends/x11/standalone/x11_standalone_backend.cpp
  2. 75
      src/backends/x11/standalone/x11_standalone_egl_backend.cpp
  3. 27
      src/backends/x11/standalone/x11_standalone_egl_backend.h
  4. 6
      src/backends/x11/windowed/x11_windowed_egl_backend.cpp
  5. 3
      src/backends/x11/windowed/x11_windowed_egl_backend.h
  6. 2
      src/opengl/egldisplay.cpp
  7. 1
      src/opengl/egldisplay.h
  8. 25
      src/platformsupport/scenes/opengl/abstract_egl_backend.cpp
  9. 3
      src/platformsupport/scenes/opengl/abstract_egl_backend.h

@ -24,6 +24,7 @@
#endif
#include "core/renderloop.h"
#include "keyboard_input.h"
#include "opengl/egldisplay.h"
#include "options.h"
#include "utils/c_ptr.h"
#include "utils/edid.h"

@ -11,6 +11,8 @@
#include "core/outputlayer.h"
#include "core/overlaywindow.h"
#include "core/renderloop_p.h"
#include "opengl/eglcontext.h"
#include "opengl/egldisplay.h"
#include "opengl/glplatform.h"
#include "opengl/glrendertimequery.h"
#include "options.h"
@ -81,7 +83,10 @@ EglBackend::~EglBackend()
if (isFailed() && m_overlayWindow) {
m_overlayWindow->destroy();
}
cleanup();
if (m_surface != EGL_NO_SURFACE) {
eglDestroySurface(eglDisplayObject()->handle(), m_surface);
}
m_context.reset();
if (m_overlayWindow && m_overlayWindow->window()) {
m_overlayWindow->destroy();
@ -117,7 +122,7 @@ void EglBackend::init()
m_fbo = std::make_unique<GLFramebuffer>(0, workspace()->geometry().size());
m_backend->setEglDisplay(EglDisplay::create(shareDisplay, false));
kwinApp()->outputBackend()->setSceneEglGlobalShareContext(shareContext);
m_backend->setSceneEglGlobalShareContext(shareContext);
qputenv("EGL_PLATFORM", "x11");
if (!initRenderingContext()) {
@ -136,7 +141,7 @@ void EglBackend::init()
// check for EGL_NV_post_sub_buffer and whether it can be used on the surface
if (hasExtension(QByteArrayLiteral("EGL_NV_post_sub_buffer"))) {
if (eglQuerySurface(eglDisplayObject()->handle(), surface(), EGL_POST_SUB_BUFFER_SUPPORTED_NV, &m_havePostSubBuffer) == EGL_FALSE) {
if (eglQuerySurface(eglDisplayObject()->handle(), m_surface, EGL_POST_SUB_BUFFER_SUPPORTED_NV, &m_havePostSubBuffer) == EGL_FALSE) {
EGLint error = eglGetError();
if (error != EGL_SUCCESS && error != EGL_BAD_ATTRIBUTE) {
setFailed(QStringLiteral("query surface failed"));
@ -152,7 +157,7 @@ void EglBackend::init()
// check if swap interval 1 is supported
EGLint val;
eglGetConfigAttrib(eglDisplayObject()->handle(), config(), EGL_MAX_SWAP_INTERVAL, &val);
eglGetConfigAttrib(eglDisplayObject()->handle(), m_context->config(), EGL_MAX_SWAP_INTERVAL, &val);
if (val >= 1) {
if (eglSwapInterval(eglDisplayObject()->handle(), 1)) {
qCDebug(KWIN_CORE) << "Enabled v-sync";
@ -167,7 +172,7 @@ void EglBackend::init()
* eglSwapBuffers() for each frame. eglSwapBuffers() then does the copy (no page flip possible in this mode),
* which means it is slow and not synced to the v-blank. */
qCWarning(KWIN_CORE) << "eglPostSubBufferNV not supported, have to enable buffer preservation - which breaks v-sync and performance";
eglSurfaceAttrib(eglDisplayObject()->handle(), surface(), EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
eglSurfaceAttrib(eglDisplayObject()->handle(), m_surface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED);
}
m_swapStrategy = options->glPreferBufferSwap();
@ -183,6 +188,25 @@ void EglBackend::init()
}
}
void EglBackend::initClientExtensions()
{
// Get the list of client extensions
const char *clientExtensionsCString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
const QByteArray clientExtensionsString = QByteArray::fromRawData(clientExtensionsCString, qstrlen(clientExtensionsCString));
if (clientExtensionsString.isEmpty()) {
// If eglQueryString() returned NULL, the implementation doesn't support
// EGL_EXT_client_extensions. Expect an EGL_BAD_DISPLAY error.
(void)eglGetError();
}
m_clientExtensions = clientExtensionsString.split(' ');
}
bool EglBackend::hasClientExtension(const QByteArray &name)
{
return m_clientExtensions.contains(name);
}
bool EglBackend::initRenderingContext()
{
initClientExtensions();
@ -211,9 +235,11 @@ bool EglBackend::initRenderingContext()
}
}
setEglDisplay(display);
if (!createContext(chooseBufferConfig())) {
setSupportsBufferAge(display->supportsBufferAge());
setSupportsNativeFence(display->supportsNativeFence());
setExtensions(display->extensions());
m_context = EglContext::create(display, chooseBufferConfig(), m_backend->sceneEglGlobalShareContext());
if (!m_context) {
qCCritical(KWIN_CORE) << "Create OpenGL context failed";
return false;
}
@ -225,12 +251,11 @@ bool EglBackend::initRenderingContext()
m_overlayWindow->setup(XCB_WINDOW_NONE);
}
EGLSurface surface = createSurface(m_overlayWindow->window());
if (surface == EGL_NO_SURFACE) {
m_surface = createSurface(m_overlayWindow->window());
if (m_surface == EGL_NO_SURFACE) {
qCCritical(KWIN_CORE) << "Creating egl surface failed";
return false;
}
setSurface(surface);
if (!makeCurrent()) {
qCCritical(KWIN_CORE) << "Make Context Current failed";
@ -258,13 +283,13 @@ EGLSurface EglBackend::createSurface(xcb_window_t window)
EGLSurface surface = EGL_NO_SURFACE;
if (m_havePlatformBase) {
// eglCreatePlatformWindowSurfaceEXT() expects a pointer to the Window.
surface = eglCreatePlatformWindowSurfaceEXT(eglDisplayObject()->handle(), config(), (void *)&nativeWindow, nullptr);
surface = eglCreatePlatformWindowSurfaceEXT(eglDisplayObject()->handle(), m_context->config(), (void *)&nativeWindow, nullptr);
} else {
// eglCreateWindowSurface() expects a Window, not a pointer to the Window. Use
// a c style cast as there are (buggy) platforms where the size of the Window
// type is not the same as the size of EGLNativeWindowType, reinterpret_cast<>()
// may not compile.
surface = eglCreateWindowSurface(eglDisplayObject()->handle(), config(), (EGLNativeWindowType)(uintptr_t)nativeWindow, nullptr);
surface = eglCreateWindowSurface(eglDisplayObject()->handle(), m_context->config(), (EGLNativeWindowType)(uintptr_t)nativeWindow, nullptr);
}
return surface;
@ -284,7 +309,7 @@ EGLConfig EglBackend::chooseBufferConfig()
EGL_ALPHA_SIZE,
0,
EGL_RENDERABLE_TYPE,
isOpenGLES() ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
EglDisplay::shouldUseOpenGLES() ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
EGL_CONFIG_CAVEAT,
EGL_NONE,
EGL_NONE,
@ -374,7 +399,7 @@ void EglBackend::present(Output *output, const std::shared_ptr<OutputFrame> &fra
}
}
presentSurface(surface(), effectiveRenderedRegion, workspace()->geometry());
presentSurface(m_surface, effectiveRenderedRegion, workspace()->geometry());
if (overlayWindow() && overlayWindow()->window()) { // show the window only after the first pass,
overlayWindow()->show(); // since that pass may take long
@ -421,6 +446,26 @@ void EglBackend::vblank(std::chrono::nanoseconds timestamp)
m_frame.reset();
}
EglDisplay *EglBackend::eglDisplayObject() const
{
return m_backend->sceneEglDisplayObject();
}
OpenGlContext *EglBackend::openglContext() const
{
return m_context.get();
}
bool EglBackend::makeCurrent()
{
return m_context->makeCurrent(m_surface);
}
void EglBackend::doneCurrent()
{
m_context->doneCurrent();
}
EglSurfaceTextureX11::EglSurfaceTextureX11(EglBackend *backend, SurfacePixmapX11 *texture)
: OpenGLSurfaceTextureX11(backend, texture)
{

@ -8,13 +8,15 @@
#include "core/outputlayer.h"
#include "options.h"
#include "platformsupport/scenes/opengl/abstract_egl_backend.h"
#include "platformsupport/scenes/opengl/openglbackend.h"
#include "platformsupport/scenes/opengl/openglsurfacetexture_x11.h"
#include "utils/damagejournal.h"
#include "opengl/gltexture.h"
#include "opengl/gltexture_p.h"
#include <epoxy/egl.h>
typedef struct _XDisplay Display;
namespace KWin
@ -25,6 +27,8 @@ class SoftwareVsyncMonitor;
class X11StandaloneBackend;
class EglBackend;
class GLRenderTimeQuery;
class EglDisplay;
class EglContext;
class EglLayer : public OutputLayer
{
@ -39,10 +43,9 @@ private:
EglBackend *const m_backend;
};
class EglBackend : public AbstractEglBackend
class EglBackend : public OpenGLBackend
{
Q_OBJECT
public:
EglBackend(::Display *display, X11StandaloneBackend *platform);
~EglBackend() override;
@ -56,16 +59,20 @@ public:
OverlayWindow *overlayWindow() const override;
OutputLayer *primaryLayer(Output *output) override;
std::chrono::nanoseconds queryRenderTime();
EglDisplay *eglDisplayObject() const;
OpenGlContext *openglContext() const override;
bool makeCurrent() override;
void doneCurrent() override;
protected:
private:
EGLConfig chooseBufferConfig();
bool initRenderingContext();
private:
void initClientExtensions();
bool hasClientExtension(const QByteArray &name);
void screenGeometryChanged();
void presentSurface(EGLSurface surface, const QRegion &damage, const QRect &screenGeometry);
void presentSurface(::EGLSurface surface, const QRegion &damage, const QRect &screenGeometry);
void vblank(std::chrono::nanoseconds timestamp);
EGLSurface createSurface(xcb_window_t window);
::EGLSurface createSurface(xcb_window_t window);
X11StandaloneBackend *m_backend;
std::unique_ptr<SoftwareVsyncMonitor> m_vsyncMonitor;
@ -80,6 +87,10 @@ private:
bool m_havePlatformBase = false;
Options::GlSwapStrategy m_swapStrategy = Options::AutoSwapStrategy;
std::shared_ptr<OutputFrame> m_frame;
QList<QByteArray> m_clientExtensions;
std::unique_ptr<EglContext> m_context;
::EGLSurface m_surface = EGL_NO_SURFACE;
};
class EglPixmapTexture : public GLTexture

@ -185,6 +185,7 @@ X11WindowedEglBackend::X11WindowedEglBackend(X11WindowedBackend *backend)
X11WindowedEglBackend::~X11WindowedEglBackend()
{
m_outputs.clear();
cleanup();
}
@ -255,11 +256,6 @@ void X11WindowedEglBackend::init()
}
}
void X11WindowedEglBackend::cleanupSurfaces()
{
m_outputs.clear();
}
void X11WindowedEglBackend::present(Output *output, const std::shared_ptr<OutputFrame> &frame)
{
m_outputs[output].primaryLayer->present();

@ -85,9 +85,6 @@ public:
OutputLayer *primaryLayer(Output *output) override;
OutputLayer *cursorLayer(Output *output) override;
protected:
void cleanupSurfaces() override;
private:
bool initializeEgl();
bool initRenderingContext();

@ -23,7 +23,7 @@
namespace KWin
{
static bool shouldUseOpenGLES()
bool EglDisplay::shouldUseOpenGLES()
{
if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
return true;

@ -54,6 +54,7 @@ public:
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf) const;
EGLImageKHR importDmaBufAsImage(const DmaBufAttributes &dmabuf, int plane, int format, const QSize &size) const;
static bool shouldUseOpenGLES();
static std::unique_ptr<EglDisplay> create(::EGLDisplay display, bool owning = true);
private:

@ -33,14 +33,6 @@ namespace KWin
static std::unique_ptr<EglContext> s_globalShareContext;
static bool isOpenGLES_helper()
{
if (qstrcmp(qgetenv("KWIN_COMPOSE"), "O2ES") == 0) {
return true;
}
return QOpenGLContext::openGLModuleType() == QOpenGLContext::LibGLES;
}
AbstractEglBackend::AbstractEglBackend(dev_t deviceId)
: m_deviceId(deviceId)
{
@ -91,9 +83,6 @@ void AbstractEglBackend::cleanup()
void AbstractEglBackend::cleanupSurfaces()
{
if (m_surface != EGL_NO_SURFACE) {
eglDestroySurface(m_display->handle(), m_surface);
}
}
void AbstractEglBackend::setEglDisplay(EglDisplay *display)
@ -230,7 +219,7 @@ bool AbstractEglBackend::makeCurrent()
// Workaround to tell Qt that no QOpenGLContext is current
context->doneCurrent();
}
return m_context->makeCurrent(m_surface);
return m_context->makeCurrent();
}
void AbstractEglBackend::doneCurrent()
@ -240,7 +229,7 @@ void AbstractEglBackend::doneCurrent()
bool AbstractEglBackend::isOpenGLES() const
{
return isOpenGLES_helper();
return EglDisplay::shouldUseOpenGLES();
}
bool AbstractEglBackend::createContext(EGLConfig config)
@ -252,11 +241,6 @@ bool AbstractEglBackend::createContext(EGLConfig config)
return m_context != nullptr;
}
void AbstractEglBackend::setSurface(const EGLSurface &surface)
{
m_surface = surface;
}
QList<LinuxDmaBufV1Feedback::Tranche> AbstractEglBackend::tranches() const
{
return m_tranches;
@ -336,11 +320,6 @@ QHash<uint32_t, QList<uint64_t>> AbstractEglBackend::supportedFormats() const
return m_display->nonExternalOnlySupportedDrmFormats();
}
EGLSurface AbstractEglBackend::surface() const
{
return m_surface;
}
EGLConfig AbstractEglBackend::config() const
{
return m_context->config();

@ -32,7 +32,6 @@ public:
bool makeCurrent() override;
void doneCurrent() override;
EGLSurface surface() const;
EGLConfig config() const;
EglDisplay *eglDisplayObject() const;
EglContext *openglContext() const override;
@ -51,7 +50,6 @@ public:
protected:
AbstractEglBackend(dev_t deviceId = 0);
void setSurface(const EGLSurface &surface);
void cleanup();
virtual void cleanupSurfaces();
void setEglDisplay(EglDisplay *display);
@ -67,7 +65,6 @@ protected:
void teardown();
EglDisplay *m_display = nullptr;
EGLSurface m_surface = EGL_NO_SURFACE;
std::shared_ptr<EglContext> m_context;
QList<QByteArray> m_clientExtensions;
const dev_t m_deviceId;

Loading…
Cancel
Save