Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
7
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Open sidebar
Plasma
KWin
Commits
9ab68806
Commit
9ab68806
authored
Nov 28, 2020
by
Xaver Hugl
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create egl backend for multiple backends and enable multi-gpu usage for the gbm backend
parent
2a8395c7
Changes
16
Hide whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
698 additions
and
166 deletions
+698
-166
platformsupport/scenes/opengl/abstract_egl_backend.cpp
platformsupport/scenes/opengl/abstract_egl_backend.cpp
+14
-3
platformsupport/scenes/opengl/abstract_egl_backend.h
platformsupport/scenes/opengl/abstract_egl_backend.h
+15
-2
plugins/platforms/drm/CMakeLists.txt
plugins/platforms/drm/CMakeLists.txt
+2
-0
plugins/platforms/drm/abstract_egl_drm_backend.cpp
plugins/platforms/drm/abstract_egl_drm_backend.cpp
+43
-0
plugins/platforms/drm/abstract_egl_drm_backend.h
plugins/platforms/drm/abstract_egl_drm_backend.h
+68
-0
plugins/platforms/drm/drm_backend.cpp
plugins/platforms/drm/drm_backend.cpp
+25
-7
plugins/platforms/drm/drm_buffer_gbm.cpp
plugins/platforms/drm/drm_buffer_gbm.cpp
+16
-1
plugins/platforms/drm/drm_buffer_gbm.h
plugins/platforms/drm/drm_buffer_gbm.h
+1
-0
plugins/platforms/drm/drm_gpu.cpp
plugins/platforms/drm/drm_gpu.cpp
+1
-1
plugins/platforms/drm/drm_gpu.h
plugins/platforms/drm/drm_gpu.h
+9
-0
plugins/platforms/drm/egl_gbm_backend.cpp
plugins/platforms/drm/egl_gbm_backend.cpp
+269
-106
plugins/platforms/drm/egl_gbm_backend.h
plugins/platforms/drm/egl_gbm_backend.h
+24
-11
plugins/platforms/drm/egl_multi_backend.cpp
plugins/platforms/drm/egl_multi_backend.cpp
+148
-0
plugins/platforms/drm/egl_multi_backend.h
plugins/platforms/drm/egl_multi_backend.h
+54
-0
plugins/platforms/drm/egl_stream_backend.cpp
plugins/platforms/drm/egl_stream_backend.cpp
+3
-25
plugins/platforms/drm/egl_stream_backend.h
plugins/platforms/drm/egl_stream_backend.h
+6
-10
No files found.
platformsupport/scenes/opengl/abstract_egl_backend.cpp
View file @
9ab68806
...
...
@@ -89,10 +89,15 @@ static void destroyGlobalShareContext()
kwinApp
()
->
platform
()
->
setSceneEglGlobalShareContext
(
EGL_NO_CONTEXT
);
}
AbstractEglBackend
*
AbstractEglBackend
::
s_primaryBackend
=
nullptr
;
AbstractEglBackend
::
AbstractEglBackend
()
:
QObject
(
nullptr
)
,
OpenGLBackend
()
{
if
(
s_primaryBackend
==
nullptr
)
{
setPrimaryBackend
(
this
);
}
connect
(
Compositor
::
self
(),
&
Compositor
::
aboutToDestroy
,
this
,
&
AbstractEglBackend
::
teardown
);
}
...
...
@@ -346,19 +351,25 @@ bool AbstractEglBackend::createContext()
return
false
;
}
m_context
=
ctx
;
kwinApp
()
->
platform
()
->
setSceneEglContext
(
m_context
);
if
(
isPrimary
())
{
kwinApp
()
->
platform
()
->
setSceneEglContext
(
m_context
);
}
return
true
;
}
void
AbstractEglBackend
::
setEglDisplay
(
const
EGLDisplay
&
display
)
{
m_display
=
display
;
kwinApp
()
->
platform
()
->
setSceneEglDisplay
(
display
);
if
(
isPrimary
())
{
kwinApp
()
->
platform
()
->
setSceneEglDisplay
(
display
);
}
}
void
AbstractEglBackend
::
setConfig
(
const
EGLConfig
&
config
)
{
m_config
=
config
;
kwinApp
()
->
platform
()
->
setSceneEglConfig
(
config
);
if
(
isPrimary
())
{
kwinApp
()
->
platform
()
->
setSceneEglConfig
(
config
);
}
}
void
AbstractEglBackend
::
setSurface
(
const
EGLSurface
&
surface
)
...
...
platformsupport/scenes/opengl/abstract_egl_backend.h
View file @
9ab68806
...
...
@@ -51,6 +51,17 @@ public:
QSharedPointer
<
GLTexture
>
textureForOutput
(
AbstractOutput
*
output
)
const
override
;
static
void
setPrimaryBackend
(
AbstractEglBackend
*
primaryBackend
)
{
s_primaryBackend
=
primaryBackend
;
}
static
AbstractEglBackend
*
primaryBackend
()
{
return
s_primaryBackend
;
}
bool
isPrimary
()
const
{
return
this
==
s_primaryBackend
;
}
protected:
AbstractEglBackend
();
void
setEglDisplay
(
const
EGLDisplay
&
display
);
...
...
@@ -65,7 +76,6 @@ protected:
void
initWayland
();
bool
hasClientExtension
(
const
QByteArray
&
ext
)
const
;
bool
isOpenGLES
()
const
;
bool
createContext
();
private:
...
...
@@ -75,8 +85,11 @@ private:
EGLSurface
m_surface
=
EGL_NO_SURFACE
;
EGLContext
m_context
=
EGL_NO_CONTEXT
;
EGLConfig
m_config
=
nullptr
;
QList
<
QByteArray
>
m_clientExtensions
;
// note: m_dmaBuf is nullptr if this is not the primary backend
EglDmabuf
*
m_dmaBuf
=
nullptr
;
QList
<
QByteArray
>
m_clientExtensions
;
static
AbstractEglBackend
*
s_primaryBackend
;
};
class
KWIN_EXPORT
AbstractEglTexture
:
public
SceneOpenGLTexturePrivate
...
...
plugins/platforms/drm/CMakeLists.txt
View file @
9ab68806
...
...
@@ -12,6 +12,8 @@ set(DRM_SOURCES
scene_qpainter_drm_backend.cpp
screens_drm.cpp
drm_gpu.cpp
egl_multi_backend.cpp
abstract_egl_drm_backend.cpp
)
if
(
HAVE_GBM
)
...
...
plugins/platforms/drm/abstract_egl_drm_backend.cpp
0 → 100644
View file @
9ab68806
/*
* KWin - the KDE window manager
* This file is part of the KDE project.
*
* SPDX-FileCopyrightText: 2020 Xaver Hugl <xaver.hugl@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "abstract_egl_drm_backend.h"
#include "drm_backend.h"
#include "drm_gpu.h"
using
namespace
KWin
;
AbstractEglDrmBackend
::
AbstractEglDrmBackend
(
DrmBackend
*
drmBackend
,
DrmGpu
*
gpu
)
:
m_backend
(
drmBackend
),
m_gpu
(
gpu
)
{
m_gpu
->
setEglBackend
(
this
);
// Egl is always direct rendering.
setIsDirectRendering
(
true
);
setSyncsToVBlank
(
true
);
}
AbstractEglDrmBackend
::~
AbstractEglDrmBackend
()
{
cleanup
();
}
void
AbstractEglDrmBackend
::
screenGeometryChanged
(
const
QSize
&
size
)
{
Q_UNUSED
(
size
)
}
bool
AbstractEglDrmBackend
::
usesOverlayWindow
()
const
{
return
false
;
}
bool
AbstractEglDrmBackend
::
perScreenRendering
()
const
{
return
true
;
}
plugins/platforms/drm/abstract_egl_drm_backend.h
0 → 100644
View file @
9ab68806
/*
* KWin - the KDE window manager
* This file is part of the KDE project.
*
* SPDX-FileCopyrightText: 2020 Xaver Hugl <xaver.hugl@gmail.com>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#ifndef KWIN_ABSTRACTEGLDRMBACKEND_H
#define KWIN_ABSTRACTEGLDRMBACKEND_H
#include "abstract_egl_backend.h"
namespace
KWin
{
class
DrmBackend
;
class
DrmGpu
;
class
AbstractEglDrmBackend
:
public
AbstractEglBackend
{
public:
~
AbstractEglDrmBackend
();
bool
usesOverlayWindow
()
const
override
;
bool
perScreenRendering
()
const
override
;
void
screenGeometryChanged
(
const
QSize
&
size
)
override
;
virtual
int
screenCount
()
const
=
0
;
virtual
void
addSecondaryGpuOutput
(
AbstractOutput
*
output
)
{
Q_UNUSED
(
output
)
}
virtual
int
getDmabufForSecondaryGpuOutput
(
AbstractOutput
*
output
,
uint32_t
*
format
,
uint32_t
*
stride
)
{
Q_UNUSED
(
output
)
Q_UNUSED
(
format
)
Q_UNUSED
(
stride
)
return
0
;
}
virtual
void
cleanupDmabufForSecondaryGpuOutput
(
AbstractOutput
*
output
)
{
Q_UNUSED
(
output
)
}
virtual
void
removeSecondaryGpuOutput
(
AbstractOutput
*
output
)
{
Q_UNUSED
(
output
)
}
virtual
QRegion
beginFrameForSecondaryGpu
(
AbstractOutput
*
output
)
{
Q_UNUSED
(
output
)
return
QRegion
();
}
virtual
void
renderFramebufferToSurface
(
AbstractOutput
*
output
)
{
Q_UNUSED
(
output
)
}
static
AbstractEglDrmBackend
*
renderingBackend
()
{
return
static_cast
<
AbstractEglDrmBackend
*>
(
primaryBackend
());
}
protected:
AbstractEglDrmBackend
(
DrmBackend
*
drmBackend
,
DrmGpu
*
gpu
);
DrmBackend
*
m_backend
;
DrmGpu
*
m_gpu
;
};
}
#endif // KWIN_ABSTRACTEGLDRMBACKEND_H
plugins/platforms/drm/drm_backend.cpp
View file @
9ab68806
...
...
@@ -47,6 +47,7 @@
#include <libdrm/drm_mode.h>
#include "drm_gpu.h"
#include "egl_multi_backend.h"
#ifndef DRM_CAP_CURSOR_WIDTH
#define DRM_CAP_CURSOR_WIDTH 0x8
...
...
@@ -274,8 +275,15 @@ void DrmBackend::openDrm()
DrmGpu
*
gpu
=
new
DrmGpu
(
this
,
devNode
,
fd
,
device
->
sysNum
());
connect
(
gpu
,
&
DrmGpu
::
outputAdded
,
this
,
&
DrmBackend
::
addOutput
);
connect
(
gpu
,
&
DrmGpu
::
outputRemoved
,
this
,
&
DrmBackend
::
removeOutput
);
m_gpus
.
append
(
gpu
);
break
;
if
(
gpu
->
useEglStreams
())
{
// TODO this needs to be removed once EglStreamBackend supports multi-gpu operation
if
(
gpu_index
==
0
)
{
m_gpus
.
append
(
gpu
);
break
;
}
}
else
{
m_gpus
.
append
(
gpu
);
}
}
// trying to activate Atomic Mode Setting (this means also Universal Planes)
...
...
@@ -349,8 +357,9 @@ bool DrmBackend::updateOutputs()
return
false
;
}
const
auto
oldOutputs
=
m_outputs
;
for
(
auto
gpu
:
m_gpus
)
for
(
auto
gpu
:
m_gpus
)
{
gpu
->
updateOutputs
();
}
std
::
sort
(
m_outputs
.
begin
(),
m_outputs
.
end
(),
[]
(
DrmOutput
*
a
,
DrmOutput
*
b
)
{
return
a
->
m_conn
->
id
()
<
b
->
m_conn
->
id
();
});
if
(
oldOutputs
!=
m_outputs
)
{
...
...
@@ -623,12 +632,21 @@ OpenGLBackend *DrmBackend::createOpenGLBackend()
{
#if HAVE_EGL_STREAMS
if
(
m_gpus
.
at
(
0
)
->
useEglStreams
())
{
return
new
EglStreamBackend
(
this
,
m_gpus
.
at
(
0
));
auto
backend
=
new
EglStreamBackend
(
this
,
m_gpus
.
at
(
0
));
AbstractEglBackend
::
setPrimaryBackend
(
backend
);
return
backend
;
}
#endif
#if HAVE_GBM
return
new
EglGbmBackend
(
this
,
m_gpus
.
at
(
0
));
auto
backend0
=
new
EglGbmBackend
(
this
,
m_gpus
.
at
(
0
));
AbstractEglBackend
::
setPrimaryBackend
(
backend0
);
EglMultiBackend
*
backend
=
new
EglMultiBackend
(
backend0
);
for
(
int
i
=
1
;
i
<
m_gpus
.
count
();
i
++
)
{
auto
backendi
=
new
EglGbmBackend
(
this
,
m_gpus
.
at
(
i
));
backend
->
addBackend
(
backendi
);
}
return
backend
;
#else
return
Platform
::
createOpenGLBackend
();
#endif
...
...
@@ -678,9 +696,9 @@ QString DrmBackend::supportInformation() const
DmaBufTexture
*
DrmBackend
::
createDmaBufTexture
(
const
QSize
&
size
)
{
#if HAVE_GBM
// gpu_index is a fixed 0 here
// as the first GPU is assumed to always be the one used for scene rendering
// and this function is only used for Pipewire
// make sure we're on the right context:
m_gpus
.
at
(
0
)
->
eglBackend
()
->
makeCurrent
();
return
GbmDmaBuf
::
createBuffer
(
size
,
m_gpus
.
at
(
0
)
->
gbmDevice
());
#else
return
nullptr
;
...
...
plugins/platforms/drm/drm_buffer_gbm.cpp
View file @
9ab68806
...
...
@@ -41,6 +41,17 @@ DrmSurfaceBuffer::DrmSurfaceBuffer(int fd, const std::shared_ptr<GbmSurface> &su
gbm_bo_set_user_data
(
m_bo
,
this
,
nullptr
);
}
DrmSurfaceBuffer
::
DrmSurfaceBuffer
(
int
fd
,
gbm_bo
*
buffer
)
:
DrmBuffer
(
fd
)
,
m_bo
(
buffer
)
{
m_size
=
QSize
(
gbm_bo_get_width
(
m_bo
),
gbm_bo_get_height
(
m_bo
));
if
(
drmModeAddFB
(
fd
,
m_size
.
width
(),
m_size
.
height
(),
24
,
32
,
gbm_bo_get_stride
(
m_bo
),
gbm_bo_get_handle
(
m_bo
).
u32
,
&
m_bufferId
)
!=
0
)
{
qCWarning
(
KWIN_DRM
)
<<
"drmModeAddFB failed"
;
}
gbm_bo_set_user_data
(
m_bo
,
this
,
nullptr
);
}
DrmSurfaceBuffer
::~
DrmSurfaceBuffer
()
{
if
(
m_bufferId
)
{
...
...
@@ -51,7 +62,11 @@ DrmSurfaceBuffer::~DrmSurfaceBuffer()
void
DrmSurfaceBuffer
::
releaseGbm
()
{
m_surface
->
releaseBuffer
(
m_bo
);
if
(
m_surface
)
{
m_surface
->
releaseBuffer
(
m_bo
);
}
else
if
(
m_bo
)
{
gbm_bo_destroy
(
m_bo
);
}
m_bo
=
nullptr
;
}
...
...
plugins/platforms/drm/drm_buffer_gbm.h
View file @
9ab68806
...
...
@@ -25,6 +25,7 @@ class DrmSurfaceBuffer : public DrmBuffer
{
public:
DrmSurfaceBuffer
(
int
fd
,
const
std
::
shared_ptr
<
GbmSurface
>
&
surface
);
DrmSurfaceBuffer
(
int
fd
,
gbm_bo
*
buffer
);
~
DrmSurfaceBuffer
()
override
;
bool
needsModeChange
(
DrmBuffer
*
b
)
const
override
{
...
...
plugins/platforms/drm/drm_gpu.cpp
View file @
9ab68806
...
...
@@ -256,7 +256,7 @@ bool DrmGpu::updateOutputs()
if
(
!
output
->
initCursor
(
m_cursorSize
))
{
m_backend
->
setSoftwareCursorForced
(
true
);
}
qCDebug
(
KWIN_DRM
)
<<
"Found new output with uuid"
<<
output
->
uuid
();
qCDebug
(
KWIN_DRM
)
<<
"Found new output with uuid"
<<
output
->
uuid
()
<<
"on gpu"
<<
m_devNode
;
connectedOutputs
<<
output
;
emit
outputAdded
(
output
);
...
...
plugins/platforms/drm/drm_gpu.h
View file @
9ab68806
...
...
@@ -78,6 +78,10 @@ public:
return
m_planes
;
}
AbstractEglBackend
*
eglBackend
()
{
return
m_eglBackend
;
}
void
setGbmDevice
(
gbm_device
*
d
)
{
m_gbmDevice
=
d
;
}
...
...
@@ -94,6 +98,10 @@ public:
return
new
DrmDumbBuffer
(
m_fd
,
size
);
}
void
setEglBackend
(
AbstractEglBackend
*
eglBackend
)
{
m_eglBackend
=
eglBackend
;
}
Q_SIGNALS:
void
outputAdded
(
DrmOutput
*
output
);
void
outputRemoved
(
DrmOutput
*
output
);
...
...
@@ -110,6 +118,7 @@ private:
DrmOutput
*
findOutput
(
quint32
connector
);
DrmBackend
*
const
m_backend
;
AbstractEglBackend
*
m_eglBackend
;
const
QByteArray
m_devNode
;
QSize
m_cursorSize
;
...
...
plugins/platforms/drm/egl_gbm_backend.cpp
View file @
9ab68806
...
...
@@ -21,27 +21,18 @@
#include <kwineglimagetexture.h>
// system
#include <gbm.h>
#include <unistd.h>
namespace
KWin
{
EglGbmBackend
::
EglGbmBackend
(
DrmBackend
*
drmBackend
,
DrmGpu
*
gpu
)
:
AbstractEglBackend
()
,
m_backend
(
drmBackend
)
,
m_gpu
(
gpu
)
:
AbstractEglDrmBackend
(
drmBackend
,
gpu
)
{
// Egl is always direct rendering.
setIsDirectRendering
(
true
);
setSyncsToVBlank
(
true
);
connect
(
m_gpu
,
&
DrmGpu
::
outputEnabled
,
this
,
&
EglGbmBackend
::
createOutput
);
connect
(
m_gpu
,
&
DrmGpu
::
outputDisabled
,
this
,
&
EglGbmBackend
::
removeOutput
);
}
EglGbmBackend
::~
EglGbmBackend
()
{
cleanup
();
}
void
EglGbmBackend
::
cleanupSurfaces
()
{
for
(
auto
it
=
m_outputs
.
begin
();
it
!=
m_outputs
.
end
();
++
it
)
{
...
...
@@ -55,6 +46,7 @@ void EglGbmBackend::cleanupFramebuffer(Output &output)
if
(
!
output
.
render
.
framebuffer
)
{
return
;
}
makeContextCurrent
(
output
);
glDeleteTextures
(
1
,
&
output
.
render
.
texture
);
output
.
render
.
texture
=
0
;
glDeleteFramebuffers
(
1
,
&
output
.
render
.
framebuffer
);
...
...
@@ -69,6 +61,15 @@ void EglGbmBackend::cleanupOutput(Output &output)
if
(
output
.
eglSurface
!=
EGL_NO_SURFACE
)
{
eglDestroySurface
(
eglDisplay
(),
output
.
eglSurface
);
}
if
(
output
.
secondaryGbmBo
)
{
output
.
gbmSurface
.
get
()
->
releaseBuffer
(
output
.
secondaryGbmBo
);
}
if
(
output
.
importedGbmBo
)
{
gbm_bo_destroy
(
output
.
importedGbmBo
);
}
if
(
output
.
dmabufFd
)
{
close
(
output
.
dmabufFd
);
}
}
bool
EglGbmBackend
::
initializeEgl
()
...
...
@@ -118,42 +119,52 @@ void EglGbmBackend::init()
setFailed
(
"Could not initialize rendering context"
);
return
;
}
initKWinGL
();
initBufferAge
();
initWayland
();
// at the moment: no secondary GPU -> no OpenGL context!
if
(
isPrimary
())
{
initKWinGL
();
initWayland
();
}
}
bool
EglGbmBackend
::
initRenderingContext
()
{
initBufferConfigs
();
if
(
!
createContext
())
{
// no secondary GPU -> no OpenGL context!
if
(
isPrimary
()
&&
!
createContext
())
{
return
false
;
}
const
auto
outputs
=
m_
backend
->
drmO
utputs
();
const
auto
outputs
=
m_
gpu
->
o
utputs
();
for
(
DrmOutput
*
drmOutput
:
outputs
)
{
createOutput
(
drmOutput
);
}
if
(
m_outputs
.
isEmpty
())
{
if
(
m_outputs
.
isEmpty
()
&&
!
outputs
.
isEmpty
()
)
{
qCCritical
(
KWIN_DRM
)
<<
"Create Window Surfaces failed"
;
return
false
;
}
// Set our first surface as the one for the abstract backend, just to make it happy.
setSurface
(
m_outputs
.
first
().
eglSurface
);
return
makeContextCurrent
(
m_outputs
.
first
());
if
(
!
m_outputs
.
isEmpty
())
{
// Set our first surface as the one for the abstract backend, just to make it happy.
setSurface
(
m_outputs
.
first
().
eglSurface
);
if
(
isPrimary
())
{
return
makeContextCurrent
(
m_outputs
.
first
());
}
}
return
true
;
}
std
::
shared_ptr
<
GbmSurface
>
EglGbmBackend
::
createGbmSurface
(
const
QSize
&
size
)
const
std
::
shared_ptr
<
GbmSurface
>
EglGbmBackend
::
createGbmSurface
(
const
QSize
&
size
,
const
bool
linear
)
const
{
auto
flags
=
GBM_BO_USE_SCANOUT
|
GBM_BO_USE_RENDERING
;
if
(
linear
)
{
flags
|=
GBM_BO_USE_LINEAR
;
}
auto
gbmSurface
=
std
::
make_shared
<
GbmSurface
>
(
m_gpu
->
gbmDevice
(),
size
.
width
(),
size
.
height
(),
GBM_FORMAT_XRGB8888
,
GBM_BO_USE_SCANOUT
|
GBM_BO_USE_RENDERING
);
flags
);
if
(
!
gbmSurface
)
{
qCCritical
(
KWIN_DRM
)
<<
"Creating GBM surface failed"
;
return
nullptr
;
...
...
@@ -178,7 +189,7 @@ bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput)
const
QSize
size
=
drmOutput
->
hardwareTransforms
()
?
drmOutput
->
pixelSize
()
:
drmOutput
->
modeSize
();
auto
gbmSurface
=
createGbmSurface
(
size
);
auto
gbmSurface
=
createGbmSurface
(
size
,
output
.
onSecondaryGPU
);
if
(
!
gbmSurface
)
{
return
false
;
}
...
...
@@ -187,11 +198,11 @@ bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput)
return
false
;
}
if
(
surface
()
==
output
.
eglSurface
||
surface
()
==
EGL_NO_SURFACE
)
{
setSurface
(
eglSurface
);
}
// destroy previous surface
if
(
output
.
eglSurface
!=
EGL_NO_SURFACE
)
{
if
(
surface
()
==
output
.
eglSurface
)
{
setSurface
(
eglSurface
);
}
eglDestroySurface
(
eglDisplay
(),
output
.
eglSurface
);
}
output
.
eglSurface
=
eglSurface
;
...
...
@@ -203,38 +214,163 @@ bool EglGbmBackend::resetOutput(Output &output, DrmOutput *drmOutput)
void
EglGbmBackend
::
createOutput
(
DrmOutput
*
drmOutput
)
{
if
(
isPrimary
())
{
Output
newOutput
;
if
(
resetOutput
(
newOutput
,
drmOutput
))
{
connect
(
drmOutput
,
&
DrmOutput
::
modeChanged
,
this
,
[
drmOutput
,
this
]
{
auto
it
=
std
::
find_if
(
m_outputs
.
begin
(),
m_outputs
.
end
(),
[
drmOutput
]
(
const
auto
&
output
)
{
return
output
.
output
==
drmOutput
;
}
);
if
(
it
==
m_outputs
.
end
())
{
return
;
}
resetOutput
(
*
it
,
drmOutput
);
}
);
m_outputs
<<
newOutput
;
}
}
else
{
Output
newOutput
;
newOutput
.
output
=
drmOutput
;
renderingBackend
()
->
addSecondaryGpuOutput
(
drmOutput
);
m_outputs
<<
newOutput
;
}
}
void
EglGbmBackend
::
removeOutput
(
DrmOutput
*
drmOutput
)
{
auto
it
=
std
::
find_if
(
m_outputs
.
begin
(),
m_outputs
.
end
(),
[
drmOutput
]
(
const
Output
&
output
)
{
return
output
.
output
==
drmOutput
;
}
);
if
(
it
==
m_outputs
.
end
())
{
return
;
}
if
(
this
!=
primaryBackend
())
{
renderingBackend
()
->
removeSecondaryGpuOutput
((
*
it
).
output
);
}
else
{
cleanupOutput
(
*
it
);
}
m_outputs
.
erase
(
it
);
}
void
EglGbmBackend
::
addSecondaryGpuOutput
(
AbstractOutput
*
output
)
{
DrmOutput
*
drmOutput
=
static_cast
<
DrmOutput
*>
(
output
);
Output
newOutput
;
newOutput
.
onSecondaryGPU
=
true
;
if
(
resetOutput
(
newOutput
,
drmOutput
))
{
connect
(
drmOutput
,
&
DrmOutput
::
modeChanged
,
this
,
[
drmOutput
,
this
]
{
auto
it
=
std
::
find_if
(
m_
o
utputs
.
begin
(),
m_
o
utputs
.
end
(),
auto
it
=
std
::
find_if
(
m_
secondaryGpuO
utputs
.
begin
(),
m_
secondaryGpuO
utputs
.
end
(),
[
drmOutput
]
(
const
auto
&
output
)
{
return
output
.
output
==
drmOutput
;
}
);
if
(
it
==
m_
o
utputs
.
end
())
{
if
(
it
==
m_
secondaryGpuO
utputs
.
end
())
{
return
;
}
resetOutput
(
*
it
,
drmOutput
);
}
);
m_
o
utputs
<<
newOutput
;
m_
secondaryGpuO
utputs
<<
newOutput
;
}
}
void
EglGbmBackend
::
removeOutput
(
DrmOutput
*
drmOutput
)
int
EglGbmBackend
::
getDmabufForSecondaryGpuOutput
(
AbstractOutput
*
output
,
uint32_t
*
format
,
uint32_t
*
stride
)
{
auto
it
=
std
::
find_if
(
m_outputs
.
begin
(),
m_outputs
.
end
(),
DrmOutput
*
drmOutput
=
static_cast
<
DrmOutput
*>
(
output
);
auto
it
=
std
::
find_if
(
m_secondaryGpuOutputs
.
begin
(),
m_secondaryGpuOutputs
.
end
(),
[
drmOutput
]
(
const
Output
&
output
)
{
return
output
.
output
==
drmOutput
;
}
);
if
(
it
==
m_outputs
.
end
())
{
if
(
it
==
m_secondaryGpuOutputs
.
end
())
{
return
-
1
;
}
auto
error
=
eglSwapBuffers
(
eglDisplay
(),
it
->
eglSurface
);
if
(
error
!=
EGL_TRUE
)
{
qCDebug
(
KWIN_DRM
)
<<
"an error occurred while swapping buffers"
<<
error
;
return
-
1
;
}
it
->
secondaryGbmBo
=
it
->
gbmSurface
->
lockFrontBuffer
();
int
fd
=
gbm_bo_get_fd
(
it
->
secondaryGbmBo
);
if
(
fd
==
-
1
)
{
qCDebug
(
KWIN_DRM
)
<<
"failed to export gbm_bo as dma-buf!"
;
return
-
1
;
}
it
->
dmabufFd
=
fd
;
*
format
=
gbm_bo_get_format
(
it
->
secondaryGbmBo
);
*
stride
=
gbm_bo_get_stride
(
it
->
secondaryGbmBo
);
return
it
->
dmabufFd
;
}