25#include <QOpenGLContext>
26#include <drm_fourcc.h>
43 m_backend->
endFrame(renderedRegion, damagedRegion);
55 , m_layer(std::make_unique<
EglLayer>(this))
62 m_vsyncMonitor->setRefreshRate(backend->renderLoop()->refreshRate());
82 m_overlayWindow->destroy();
86 if (m_overlayWindow && m_overlayWindow->window()) {
87 m_overlayWindow->destroy();
93 return std::make_unique<EglSurfaceTextureX11>(
this, texture);
98 QOpenGLContext *qtShareContext = QOpenGLContext::globalShareContext();
99 ::EGLDisplay shareDisplay = EGL_NO_DISPLAY;
100 ::EGLContext shareContext = EGL_NO_CONTEXT;
101 if (qtShareContext) {
102 qDebug(KWIN_X11STANDALONE) <<
"Global share context format:" << qtShareContext->format();
103 const auto nativeHandle = qtShareContext->nativeInterface<QNativeInterface::QEGLContext>();
105 shareContext = nativeHandle->nativeContext();
106 shareDisplay = nativeHandle->display();
108 setFailed(QStringLiteral(
"Invalid QOpenGLContext::globalShareContext()"));
112 if (shareContext == EGL_NO_CONTEXT) {
113 setFailed(QStringLiteral(
"QOpenGLContext::globalShareContext() is required"));
117 m_fbo = std::make_unique<GLFramebuffer>(0,
workspace()->geometry().size());
120 kwinApp()->outputBackend()->setSceneEglGlobalShareContext(shareContext);
122 qputenv(
"EGL_PLATFORM",
"x11");
124 setFailed(QStringLiteral(
"Could not initialize rendering context"));
130 if (!
hasExtension(QByteArrayLiteral(
"EGL_KHR_image")) && (!
hasExtension(QByteArrayLiteral(
"EGL_KHR_image_base")) || !
hasExtension(QByteArrayLiteral(
"EGL_KHR_image_pixmap")))) {
131 setFailed(QStringLiteral(
"Required support for binding pixmaps to EGLImages not found, disabling compositing"));
135 setFailed(QStringLiteral(
"Required extension GL_OES_EGL_image not found, disabling compositing"));
140 if (
hasExtension(QByteArrayLiteral(
"EGL_NV_post_sub_buffer"))) {
141 if (eglQuerySurface(
eglDisplayObject()->handle(),
surface(), EGL_POST_SUB_BUFFER_SUPPORTED_NV, &m_havePostSubBuffer) == EGL_FALSE) {
142 EGLint error = eglGetError();
143 if (error != EGL_SUCCESS && error != EGL_BAD_ATTRIBUTE) {
144 setFailed(QStringLiteral(
"query surface failed"));
147 m_havePostSubBuffer = EGL_FALSE;
152 if (m_havePostSubBuffer) {
153 qCDebug(KWIN_CORE) <<
"EGL implementation and surface support eglPostSubBufferNV, let's use it";
160 qCDebug(KWIN_CORE) <<
"Enabled v-sync";
163 qCWarning(KWIN_CORE) <<
"Cannot enable v-sync as max. swap interval is" << val;
171 qCWarning(KWIN_CORE) <<
"eglPostSubBufferNV not supported, have to enable buffer preservation - which breaks v-sync and performance";
191 auto display = kwinApp()->outputBackend()->sceneEglDisplayObject();
197 if (m_havePlatformBase) {
200 qCWarning(KWIN_CORE) <<
"EGL_EXT_platform_base is supported, but neither EGL_EXT_platform_x11 nor EGL_KHR_platform_x11 is supported."
201 <<
"Cannot create EGLDisplay on X11";
211 qCWarning(KWIN_CORE) <<
"Failed to get the EGLDisplay";
219 qCCritical(KWIN_CORE) <<
"Create OpenGL context failed";
223 if (!m_overlayWindow->create()) {
224 qCCritical(KWIN_X11STANDALONE) <<
"Could not get overlay window";
227 m_overlayWindow->setup(XCB_WINDOW_NONE);
230 EGLSurface
surface = createSurface(m_overlayWindow->window());
231 if (
surface == EGL_NO_SURFACE) {
232 qCCritical(KWIN_CORE) <<
"Creating egl surface failed";
238 qCCritical(KWIN_CORE) <<
"Make Context Current failed";
242 EGLint error = eglGetError();
243 if (error != EGL_SUCCESS) {
244 qCWarning(KWIN_CORE) <<
"Error occurred while creating context " << error;
251EGLSurface EglBackend::createSurface(xcb_window_t window)
253 if (window == XCB_WINDOW_NONE) {
254 return EGL_NO_SURFACE;
260 EGLSurface
surface = EGL_NO_SURFACE;
261 if (m_havePlatformBase) {
277 const EGLint config_attribs[] = {
289 isOpenGLES() ? EGL_OPENGL_ES2_BIT : EGL_OPENGL_BIT,
296 EGLConfig configs[1024];
297 if (eglChooseConfig(
eglDisplayObject()->handle(), config_attribs, configs, 1024, &count) == EGL_FALSE) {
298 qCCritical(KWIN_CORE) <<
"choose config failed";
299 return EGL_NO_CONFIG_KHR;
306 qCCritical(KWIN_CORE) <<
"Failed to get window attributes of root window";
307 return EGL_NO_CONFIG_KHR;
310 for (
int i = 0; i < count; i++) {
312 if (eglGetConfigAttrib(
eglDisplayObject()->handle(), configs[i], EGL_NATIVE_VISUAL_ID, &val) == EGL_FALSE) {
313 qCCritical(KWIN_CORE) <<
"egl get config attrib failed";
315 if (uint32_t(val) == attribs->visual) {
322void EglBackend::screenGeometryChanged()
328 m_fbo = std::make_unique<GLFramebuffer>(0,
workspace()->geometry().size());
339 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
342 m_query = std::make_unique<GLRenderTimeQuery>();
356 m_damageJournal.
add(damagedRegion);
358 m_lastRenderedRegion = renderedRegion;
366 m_vsyncMonitor->arm();
368 QRegion effectiveRenderedRegion = m_lastRenderedRegion;
372 glReadBuffer(GL_FRONT);
373 copyPixels(QRegion(displayRect) - m_lastRenderedRegion, displayRect.size());
374 glReadBuffer(GL_BACK);
375 effectiveRenderedRegion = displayRect;
379 presentSurface(
surface(), effectiveRenderedRegion,
workspace()->geometry());
386void EglBackend::presentSurface(EGLSurface surface,
const QRegion &damage,
const QRect &screenGeometry)
390 if (fullRepaint || !m_havePostSubBuffer) {
398 for (
const QRect &r : damage) {
399 eglPostSubBufferNV(
eglDisplayObject()->handle(),
surface, r.left(), screenGeometry.height() - r.bottom() - 1, r.width(), r.height());
406 return m_overlayWindow.get();
411 return m_layer.get();
417 return m_query->result();
420void EglBackend::vblank(std::chrono::nanoseconds timestamp)
456 if (m_image != EGL_NO_IMAGE_KHR) {
463 const xcb_pixmap_t nativePixmap = pixmap->
pixmap();
464 if (nativePixmap == XCB_NONE) {
468 glGenTextures(1, &
d->m_texture);
472 const EGLint attribs[] = {
473 EGL_IMAGE_PRESERVED_KHR, EGL_TRUE,
477 EGL_NATIVE_PIXMAP_KHR,
478 reinterpret_cast<EGLClientBuffer>(
static_cast<uintptr_t
>(nativePixmap)),
481 if (EGL_NO_IMAGE_KHR == m_image) {
482 qCDebug(KWIN_X11STANDALONE) <<
"failed to create egl image";
486 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
static_cast<GLeglImageOES
>(m_image));
489 d->m_size = pixmap->
size();
494void EglPixmapTexture::onDamage()
499 eglWaitNative(EGL_CORE_NATIVE_ENGINE);
500 glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,
static_cast<GLeglImageOES
>(m_image));
506#include "moc_x11_standalone_egl_backend.cpp"
void initClientExtensions()
EGLSurface surface() const
bool makeCurrent() override
bool hasClientExtension(const QByteArray &ext) const
EglDisplay * eglDisplayObject() const
void setEglDisplay(EglDisplay *display)
void setSurface(const EGLSurface &surface)
bool createContext(EGLConfig config)
void add(const QRegion ®ion)
QRegion accumulate(int bufferAge, const QRegion &fallback=QRegion()) const
EglBackend(::Display *display, X11StandaloneBackend *platform)
bool initRenderingContext()
EGLConfig chooseBufferConfig()
std::chrono::nanoseconds queryRenderTime()
OverlayWindow * overlayWindow() const override
void present(Output *output, const std::shared_ptr< OutputFrame > &frame) override
void endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion)
std::unique_ptr< SurfaceTexture > createSurfaceTextureX11(SurfacePixmapX11 *texture) override
OutputLayerBeginFrameInfo beginFrame()
OutputLayer * primaryLayer(Output *output) override
static std::unique_ptr< EglDisplay > create(::EGLDisplay display, bool owning=true)
::EGLDisplay handle() const
EglLayer(EglBackend *backend)
std::chrono::nanoseconds queryRenderTime() const override
std::optional< OutputLayerBeginFrameInfo > beginFrame() override
bool endFrame(const QRegion &renderedRegion, const QRegion &damagedRegion) override
~EglPixmapTexture() override
EglPixmapTexture(EglBackend *backend)
EglSurfaceTextureX11(EglBackend *backend, SurfacePixmapX11 *texture)
void update(const QRegion ®ion) override
const std::unique_ptr< GLTexturePrivate > d
void setContentTransform(OutputTransform transform)
void setFilter(GLenum filter)
void setWrapMode(GLenum mode)
bool isFailed() const
Whether the creation of the Backend failed.
void setFailed(const QString &reason)
Sets the backend initialization to failed.
void copyPixels(const QRegion ®ion, const QSize &screenSize)
bool hasExtension(const QByteArray &extension) const
bool supportsBufferAge() const
OpenGLSurfaceContents m_texture
OpenGLBackend * m_backend
OpenGLSurfaceContents texture() const
SurfacePixmapX11 * m_pixmap
GlSwapStrategy glPreferBufferSwap
bool isGlStrictBinding() const
virtual void resize(const QSize &size)=0
void refreshRateChanged()
static RenderLoopPrivate * get(RenderLoop *loop)
static std::unique_ptr< SoftwareVsyncMonitor > create()
xcb_pixmap_t pixmap() const
void vblankOccurred(std::chrono::nanoseconds timestamp)
::Display * display() const
xcb_connection_t * connection() const
EglDisplay * sceneEglDisplayObject() const override
void setEglDisplay(std::unique_ptr< EglDisplay > &&display)
xcb_window_t rootWindow() const
RenderLoop * renderLoop() const
KWIN_EXPORT QRect infiniteRegion()
bool hasGLExtension(const QByteArray &extension)
std::unique_ptr< T, CDeleter > UniqueCPtr
RenderTarget renderTarget