Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
Plasma
KWin
Commits
50f03ac6
Commit
50f03ac6
authored
Mar 29, 2021
by
Xaver Hugl
Browse files
platforms/drm: improve buffer handling with GbmBuffer
parent
dbdc30da
Changes
8
Hide whitespace changes
Inline
Side-by-side
src/plugins/platforms/drm/drm_buffer.h
View file @
50f03ac6
...
...
@@ -17,9 +17,8 @@ namespace KWin
class
DrmGpu
;
class
DrmBuffer
:
public
QObject
class
DrmBuffer
{
Q_OBJECT
public:
DrmBuffer
(
DrmGpu
*
gpu
);
virtual
~
DrmBuffer
()
=
default
;
...
...
@@ -34,8 +33,6 @@ public:
return
m_size
;
}
virtual
void
releaseGbm
()
{}
DrmGpu
*
gpu
()
const
{
return
m_gpu
;
}
...
...
src/plugins/platforms/drm/drm_buffer_gbm.cpp
View file @
50f03ac6
...
...
@@ -28,58 +28,65 @@
namespace
KWin
{
// DrmSurfaceBuffer
DrmSurfaceBuffer
::
DrmSurfaceBuffer
(
DrmGpu
*
gpu
,
const
QSharedPointer
<
GbmSurface
>
&
surface
)
:
DrmBuffer
(
gpu
)
,
m_surface
(
surface
)
GbmBuffer
::
GbmBuffer
(
const
QSharedPointer
<
GbmSurface
>
&
surface
)
:
m_surface
(
surface
)
{
m_bo
=
m_surface
->
lockFrontBuffer
();
if
(
!
m_bo
)
{
qCWarning
(
KWIN_DRM
)
<<
"Locking front buffer failed"
;
return
;
}
initialize
();
}
DrmSurfaceBuffer
::
DrmSurfaceBuffer
(
DrmGpu
*
gpu
,
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
)
:
DrmBuffer
(
gpu
)
,
m_bo
(
buffer
)
GbmBuffer
::
GbmBuffer
(
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
)
:
m_bo
(
buffer
)
,
m_bufferInterface
(
bufferInterface
)
{
if
(
m_bufferInterface
)
{
m_bufferInterface
->
ref
();
connect
(
m_bufferInterface
,
&
KWaylandServer
::
BufferInterface
::
aboutToBeDestroyed
,
this
,
&
DrmSurface
Buffer
::
clearBufferInterface
);
connect
(
m_bufferInterface
,
&
KWaylandServer
::
BufferInterface
::
aboutToBeDestroyed
,
this
,
&
Gbm
Buffer
::
clearBufferInterface
);
}
initialize
();
}
DrmSurfaceBuffer
::~
DrmSurface
Buffer
()
GbmBuffer
::~
Gbm
Buffer
()
{
if
(
m_bufferId
)
{
drmModeRmFB
(
m_gpu
->
fd
(),
m_bufferId
);
}
releaseGbm
();
if
(
m_bufferInterface
)
{
clearBufferInterface
();
}
}
void
DrmSurfaceBuffer
::
releaseGbm
()
{
if
(
m_surface
)
{
m_surface
->
releaseBuffer
(
m_bo
);
}
else
if
(
m_bo
)
{
gbm_bo_destroy
(
m_bo
);
}
m_bo
=
nullptr
;
}
void
DrmSurface
Buffer
::
clearBufferInterface
()
void
Gbm
Buffer
::
clearBufferInterface
()
{
disconnect
(
m_bufferInterface
,
&
KWaylandServer
::
BufferInterface
::
aboutToBeDestroyed
,
this
,
&
Drm
Surface
Buffer
::
clearBufferInterface
);
disconnect
(
m_bufferInterface
,
&
KWaylandServer
::
BufferInterface
::
aboutToBeDestroyed
,
this
,
&
Drm
Gbm
Buffer
::
clearBufferInterface
);
m_bufferInterface
->
unref
();
m_bufferInterface
=
nullptr
;
}
void
DrmSurfaceBuffer
::
initialize
()
DrmGbmBuffer
::
DrmGbmBuffer
(
DrmGpu
*
gpu
,
const
QSharedPointer
<
GbmSurface
>
&
surface
)
:
DrmBuffer
(
gpu
),
GbmBuffer
(
surface
)
{
if
(
!
m_bo
)
{
qCWarning
(
KWIN_DRM
)
<<
"Locking front buffer failed"
;
return
;
}
initialize
();
}
DrmGbmBuffer
::
DrmGbmBuffer
(
DrmGpu
*
gpu
,
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
)
:
DrmBuffer
(
gpu
),
GbmBuffer
(
buffer
,
bufferInterface
)
{
initialize
();
}
DrmGbmBuffer
::~
DrmGbmBuffer
()
{
if
(
m_bufferId
)
{
drmModeRmFB
(
m_gpu
->
fd
(),
m_bufferId
);
}
}
void
DrmGbmBuffer
::
initialize
()
{
m_size
=
QSize
(
gbm_bo_get_width
(
m_bo
),
gbm_bo_get_height
(
m_bo
));
uint32_t
handles
[
4
]
=
{
};
...
...
src/plugins/platforms/drm/drm_buffer_gbm.h
View file @
50f03ac6
...
...
@@ -26,15 +26,35 @@ namespace KWin
class
GbmSurface
;
class
DrmSurface
Buffer
:
public
DrmBuffer
class
Gbm
Buffer
:
public
QObject
{
Q_OBJECT
public:
DrmSurfaceBuffer
(
DrmGpu
*
gpu
,
const
QSharedPointer
<
GbmSurface
>
&
surface
);
DrmSurfaceBuffer
(
DrmGpu
*
gpu
,
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
);
~
DrmSurfaceBuffer
()
override
;
GbmBuffer
(
const
QSharedPointer
<
GbmSurface
>
&
surface
);
GbmBuffer
(
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
);
virtual
~
GbmBuffer
();
gbm_bo
*
getBo
()
const
{
return
m_bo
;
}
protected:
QSharedPointer
<
GbmSurface
>
m_surface
;
gbm_bo
*
m_bo
=
nullptr
;
KWaylandServer
::
BufferInterface
*
m_bufferInterface
=
nullptr
;
void
clearBufferInterface
();
};
class
DrmGbmBuffer
:
public
DrmBuffer
,
public
GbmBuffer
{
public:
DrmGbmBuffer
(
DrmGpu
*
gpu
,
const
QSharedPointer
<
GbmSurface
>
&
surface
);
DrmGbmBuffer
(
DrmGpu
*
gpu
,
gbm_bo
*
buffer
,
KWaylandServer
::
BufferInterface
*
bufferInterface
);
~
DrmGbmBuffer
()
override
;
bool
needsModeChange
(
DrmBuffer
*
b
)
const
override
{
if
(
Drm
Surface
Buffer
*
sb
=
dynamic_cast
<
Drm
Surface
Buffer
*>
(
b
))
{
if
(
Drm
Gbm
Buffer
*
sb
=
dynamic_cast
<
Drm
Gbm
Buffer
*>
(
b
))
{
return
hasBo
()
!=
sb
->
hasBo
();
}
else
{
return
true
;
...
...
@@ -45,18 +65,7 @@ public:
return
m_bo
!=
nullptr
;
}
gbm_bo
*
getBo
()
const
{
return
m_bo
;
}
void
releaseGbm
()
override
;
private:
QSharedPointer
<
GbmSurface
>
m_surface
;
gbm_bo
*
m_bo
=
nullptr
;
KWaylandServer
::
BufferInterface
*
m_bufferInterface
=
nullptr
;
void
clearBufferInterface
();
void
initialize
();
};
...
...
src/plugins/platforms/drm/drm_object_crtc.h
View file @
50f03ac6
...
...
@@ -45,6 +45,9 @@ public:
QSharedPointer
<
DrmBuffer
>
next
()
{
return
m_nextBuffer
;
}
void
setCurrent
(
const
QSharedPointer
<
DrmBuffer
>
&
buffer
)
{
m_currentBuffer
=
buffer
;
}
void
setNext
(
const
QSharedPointer
<
DrmBuffer
>
&
buffer
)
{
m_nextBuffer
=
buffer
;
}
...
...
src/plugins/platforms/drm/drm_output.cpp
View file @
50f03ac6
...
...
@@ -77,14 +77,12 @@ void DrmOutput::teardown()
//this is needed so that the pageflipcallback handle isn't deleted
}
void
DrmOutput
::
release
Gbm
()
void
DrmOutput
::
release
Buffers
()
{
if
(
const
auto
&
b
=
m_crtc
->
current
())
{
b
->
releaseGbm
();
}
if
(
m_primaryPlane
&&
m_primaryPlane
->
current
())
{
m_primaryPlane
->
current
()
->
releaseGbm
();
}
m_crtc
->
setCurrent
(
nullptr
);
m_crtc
->
setNext
(
nullptr
);
m_primaryPlane
->
setCurrent
(
nullptr
);
m_primaryPlane
->
setNext
(
nullptr
);
}
bool
DrmOutput
::
hideCursor
()
...
...
@@ -566,23 +564,11 @@ void DrmOutput::pageFlipped()
return
;
}
if
(
m_gpu
->
atomicModeSetting
())
{
if
(
!
m_primaryPlane
->
next
())
{
if
(
m_primaryPlane
->
current
())
{
m_primaryPlane
->
current
()
->
releaseGbm
();
}
return
;
}
for
(
DrmPlane
*
p
:
m_nextPlanesFlipList
)
{
p
->
flipBuffer
();
}
m_nextPlanesFlipList
.
clear
();
}
else
{
if
(
!
m_crtc
->
next
())
{
// on manual vt switch
if
(
const
auto
&
b
=
m_crtc
->
current
())
{
b
->
releaseGbm
();
}
}
m_crtc
->
flipBuffer
();
}
...
...
src/plugins/platforms/drm/drm_output.h
View file @
50f03ac6
...
...
@@ -44,7 +44,7 @@ public:
///queues deleting the output after a page flip has completed.
void
teardown
();
void
release
Gbm
();
void
release
Buffers
();
bool
showCursor
(
DrmDumbBuffer
*
buffer
);
bool
showCursor
();
bool
hideCursor
();
...
...
src/plugins/platforms/drm/egl_gbm_backend.cpp
View file @
50f03ac6
...
...
@@ -64,20 +64,13 @@ void EglGbmBackend::cleanupFramebuffer(Output &output)
void
EglGbmBackend
::
cleanupOutput
(
Output
&
output
)
{
cleanupFramebuffer
(
output
);
output
.
output
->
release
Gbm
();
output
.
output
->
release
Buffers
();
output
.
buffer
=
nullptr
;
output
.
secondaryBuffer
=
nullptr
;
if
(
output
.
eglSurface
!=
EGL_NO_SURFACE
)
{
eglDestroySurface
(
eglDisplay
(),
output
.
eglSurface
);
}
if
(
output
.
secondaryGbmBo
)
{
output
.
gbmSurface
.
get
()
->
releaseBuffer
(
output
.
secondaryGbmBo
);
}
if
(
output
.
directScanoutBuffer
)
{
gbm_bo_destroy
(
output
.
directScanoutBuffer
);
}
if
(
output
.
dmabufFd
)
{
close
(
output
.
dmabufFd
);
}
}
bool
EglGbmBackend
::
initializeEgl
()
...
...
@@ -271,30 +264,22 @@ int EglGbmBackend::getDmabufForSecondaryGpuOutput(AbstractOutput *output, uint32
if
(
it
==
m_secondaryGpuOutputs
.
end
())
{
return
-
1
;
}
if
(
it
->
dmabufFd
)
{
close
(
it
->
dmabufFd
);
it
->
dmabufFd
=
0
;
}
if
(
it
->
secondaryGbmBo
)
{
it
->
gbmSurface
.
get
()
->
releaseBuffer
(
it
->
secondaryGbmBo
);
it
->
secondaryGbmBo
=
nullptr
;
}
renderFramebufferToSurface
(
*
it
);
auto
error
=
eglSwapBuffers
(
eglDisplay
(),
it
->
eglSurface
);
if
(
error
!=
EGL_TRUE
)
{
qCDebug
(
KWIN_DRM
)
<<
"an error occurred while swapping buffers"
<<
error
;
it
->
secondaryBuffer
=
nullptr
;
return
-
1
;
}
it
->
secondary
GbmBo
=
it
->
gbmSurface
->
lockFrontBuffer
(
);
int
fd
=
gbm_bo_get_fd
(
it
->
secondaryGbmBo
);
it
->
secondary
Buffer
=
QSharedPointer
<
GbmBuffer
>::
create
(
it
->
gbmSurface
);
int
fd
=
gbm_bo_get_fd
(
it
->
buffer
->
getBo
()
);
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
;
*
format
=
gbm_bo_get_format
(
it
->
buffer
->
getBo
());
*
stride
=
gbm_bo_get_stride
(
it
->
buffer
->
getBo
());
return
fd
;
}
QRegion
EglGbmBackend
::
beginFrameForSecondaryGpu
(
AbstractOutput
*
output
)
...
...
@@ -450,15 +435,13 @@ void EglGbmBackend::renderFramebufferToSurface(Output &output)
data
.
height
=
(
uint32_t
)
size
.
height
();
data
.
stride
=
stride
;
data
.
format
=
format
;
gbm_bo
*
importedBuffer
=
gbm_bo_import
(
m_gpu
->
gbmDevice
(),
GBM_BO_IMPORT_FD
,
&
data
,
GBM_BO_USE_SCANOUT
|
GBM_BO_USE_LINEAR
);
if
(
!
importedBuffer
)
{
qCDebug
(
KWIN_DRM
)
<<
"failed to import dma-buf!"
<<
strerror
(
errno
);
if
(
gbm_bo
*
importedBuffer
=
gbm_bo_import
(
m_gpu
->
gbmDevice
(),
GBM_BO_IMPORT_FD
,
&
data
,
GBM_BO_USE_SCANOUT
|
GBM_BO_USE_LINEAR
))
{
output
.
buffer
=
QSharedPointer
<
DrmGbmBuffer
>::
create
(
m_gpu
,
importedBuffer
,
nullptr
);
}
else
{
if
(
output
.
directScanoutBuffer
)
{
gbm_bo_destroy
(
output
.
directScanoutBuffer
);
}
output
.
directScanoutBuffer
=
importedBuffer
;
qCDebug
(
KWIN_DRM
)
<<
"failed to import dma-buf!"
<<
strerror
(
errno
);
output
.
buffer
=
nullptr
;
}
close
(
fd
);
}
}
}
...
...
@@ -580,9 +563,7 @@ void EglGbmBackend::aboutToStartPainting(int screenId, const QRegion &damagedReg
bool
EglGbmBackend
::
presentOnOutput
(
Output
&
output
,
const
QRegion
&
damagedRegion
)
{
if
(
output
.
directScanoutBuffer
)
{
output
.
buffer
=
QSharedPointer
<
DrmSurfaceBuffer
>::
create
(
m_gpu
,
output
.
directScanoutBuffer
,
output
.
bufferInterface
);
}
else
if
(
isPrimary
())
{
if
(
isPrimary
()
&&
!
directScanoutActive
(
output
))
{
if
(
supportsSwapBuffersWithDamage
())
{
QVector
<
EGLint
>
rects
=
regionToRects
(
damagedRegion
,
output
.
output
);
if
(
!
eglSwapBuffersWithDamageEXT
(
eglDisplay
(),
output
.
eglSurface
,
...
...
@@ -596,8 +577,8 @@ bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion
return
false
;
}
}
output
.
buffer
=
QSharedPointer
<
Drm
Surface
Buffer
>::
create
(
m_gpu
,
output
.
gbmSurface
);
}
else
{
output
.
buffer
=
QSharedPointer
<
Drm
Gbm
Buffer
>::
create
(
m_gpu
,
output
.
gbmSurface
);
}
else
if
(
!
output
.
buffer
)
{
qCDebug
(
KWIN_DRM
)
<<
"imported gbm_bo does not exist!"
;
return
false
;
}
...
...
@@ -613,6 +594,11 @@ bool EglGbmBackend::presentOnOutput(Output &output, const QRegion &damagedRegion
return
true
;
}
bool
EglGbmBackend
::
directScanoutActive
(
const
Output
&
output
)
{
return
output
.
surfaceInterface
!=
nullptr
;
}
SceneOpenGLTexturePrivate
*
EglGbmBackend
::
createBackendTexture
(
SceneOpenGLTexture
*
texture
)
{
return
new
EglGbmTexture
(
texture
,
this
);
...
...
@@ -631,12 +617,7 @@ void EglGbmBackend::setViewport(const Output &output) const
QRegion
EglGbmBackend
::
beginFrame
(
int
screenId
)
{
Output
&
output
=
m_outputs
[
screenId
];
if
(
output
.
directScanoutBuffer
)
{
gbm_bo_destroy
(
output
.
directScanoutBuffer
);
output
.
directScanoutBuffer
=
nullptr
;
output
.
surfaceInterface
=
nullptr
;
output
.
bufferInterface
=
nullptr
;
}
output
.
surfaceInterface
=
nullptr
;
if
(
isPrimary
())
{
return
prepareRenderingForOutput
(
output
);
}
else
{
...
...
@@ -757,12 +738,8 @@ bool EglGbmBackend::scanout(int screenId, SurfaceItem *surfaceItem)
}
else
{
damage
=
output
.
output
->
geometry
();
}
if
(
output
.
directScanoutBuffer
)
{
gbm_bo_destroy
(
output
.
directScanoutBuffer
);
}
output
.
directScanoutBuffer
=
importedBuffer
;
output
.
buffer
=
QSharedPointer
<
DrmGbmBuffer
>::
create
(
m_gpu
,
importedBuffer
,
buffer
);
output
.
surfaceInterface
=
surface
;
output
.
bufferInterface
=
buffer
;
return
presentOnOutput
(
output
,
damage
);
}
...
...
@@ -784,8 +761,7 @@ QSharedPointer<GLTexture> EglGbmBackend::textureForOutput(AbstractOutput *abstra
return
glTexture
;
}
EGLImageKHR
image
=
eglCreateImageKHR
(
eglDisplay
(),
nullptr
,
EGL_NATIVE_PIXMAP_KHR
,
itOutput
->
directScanoutBuffer
?
itOutput
->
directScanoutBuffer
:
itOutput
->
buffer
->
getBo
(),
nullptr
);
EGLImageKHR
image
=
eglCreateImageKHR
(
eglDisplay
(),
nullptr
,
EGL_NATIVE_PIXMAP_KHR
,
itOutput
->
buffer
->
getBo
(),
nullptr
);
if
(
image
==
EGL_NO_IMAGE_KHR
)
{
qCWarning
(
KWIN_DRM
)
<<
"Failed to record frame: Error creating EGLImageKHR - "
<<
glGetError
();
return
{};
...
...
src/plugins/platforms/drm/egl_gbm_backend.h
View file @
50f03ac6
...
...
@@ -25,9 +25,10 @@ namespace KWin
{
class
AbstractOutput
;
class
DrmBuffer
;
class
Drm
Surface
Buffer
;
class
Drm
Gbm
Buffer
;
class
DrmOutput
;
class
GbmSurface
;
class
GbmBuffer
;
/**
* @brief OpenGL Backend using Egl on a GBM surface.
...
...
@@ -68,7 +69,8 @@ private:
struct
Output
{
DrmOutput
*
output
=
nullptr
;
QSharedPointer
<
DrmSurfaceBuffer
>
buffer
;
QSharedPointer
<
DrmGbmBuffer
>
buffer
;
QSharedPointer
<
GbmBuffer
>
secondaryBuffer
;
QSharedPointer
<
GbmSurface
>
gbmSurface
;
EGLSurface
eglSurface
=
EGL_NO_SURFACE
;
int
bufferAge
=
0
;
...
...
@@ -83,11 +85,7 @@ private:
QSharedPointer
<
GLVertexBuffer
>
vbo
;
}
render
;
int
dmabufFd
=
0
;
gbm_bo
*
secondaryGbmBo
=
nullptr
;
gbm_bo
*
directScanoutBuffer
=
nullptr
;
KWaylandServer
::
SurfaceInterface
*
surfaceInterface
=
nullptr
;
KWaylandServer
::
BufferInterface
*
bufferInterface
=
nullptr
;
};
bool
resetOutput
(
Output
&
output
,
DrmOutput
*
drmOutput
);
...
...
@@ -104,6 +102,7 @@ private:
QRegion
prepareRenderingForOutput
(
Output
&
output
)
const
;
bool
presentOnOutput
(
Output
&
output
,
const
QRegion
&
damagedRegion
);
bool
directScanoutActive
(
const
Output
&
output
);
void
cleanupOutput
(
Output
&
output
);
void
cleanupFramebuffer
(
Output
&
output
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment