Skip to content
GitLab
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
c43eb6ec
Commit
c43eb6ec
authored
Apr 03, 2022
by
Xaver Hugl
Browse files
backends/drm: extract dmabuf feedback into its own class
This should reduce code duplication with overlay planes
parent
5df65e4b
Changes
5
Hide whitespace changes
Inline
Side-by-side
src/backends/drm/CMakeLists.txt
View file @
c43eb6ec
...
...
@@ -29,6 +29,7 @@ set(DRM_SOURCES
virtual_egl_gbm_layer.cpp
drm_lease_egl_gbm_layer.cpp
egl_gbm_layer_surface.cpp
dmabuf_feedback.cpp
)
add_library
(
KWinWaylandDrmBackend MODULE
${
DRM_SOURCES
}
)
...
...
src/backends/drm/dmabuf_feedback.cpp
0 → 100644
View file @
c43eb6ec
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include
"dmabuf_feedback.h"
#include
"drm_gpu.h"
#include
"egl_dmabuf.h"
#include
"egl_gbm_backend.h"
#include
<KWaylandServer/linuxdmabufv1clientbuffer.h>
#include
<KWaylandServer/surface_interface.h>
namespace
KWin
{
DmabufFeedback
::
DmabufFeedback
(
DrmGpu
*
gpu
,
EglGbmBackend
*
eglBackend
)
:
m_gpu
(
gpu
)
,
m_eglBackend
(
eglBackend
)
{
}
void
DmabufFeedback
::
renderingSurface
()
{
if
(
m_surface
&&
!
m_attemptedThisFrame
)
{
if
(
const
auto
&
feedback
=
m_surface
->
dmabufFeedbackV1
())
{
feedback
->
setTranches
({});
}
m_surface
=
nullptr
;
}
m_attemptedThisFrame
=
false
;
}
void
DmabufFeedback
::
scanoutSuccessful
(
KWaylandServer
::
SurfaceInterface
*
surface
)
{
if
(
surface
!=
m_surface
)
{
if
(
m_surface
&&
m_surface
->
dmabufFeedbackV1
())
{
m_surface
->
dmabufFeedbackV1
()
->
setTranches
({});
}
m_surface
=
surface
;
m_attemptedFormats
=
{};
}
}
void
DmabufFeedback
::
scanoutFailed
(
KWaylandServer
::
SurfaceInterface
*
surface
,
const
QMap
<
uint32_t
,
QVector
<
uint64_t
>>
&
formats
)
{
m_attemptedThisFrame
=
true
;
if
(
surface
!=
m_surface
)
{
m_attemptedFormats
=
{};
if
(
m_surface
&&
m_surface
->
dmabufFeedbackV1
())
{
m_surface
->
dmabufFeedbackV1
()
->
setTranches
({});
}
m_surface
=
surface
;
}
if
(
const
auto
&
feedback
=
m_surface
->
dmabufFeedbackV1
())
{
const
auto
buffer
=
qobject_cast
<
KWaylandServer
::
LinuxDmaBufV1ClientBuffer
*>
(
surface
->
buffer
());
Q_ASSERT
(
buffer
);
if
(
!
m_attemptedFormats
[
buffer
->
format
()].
contains
(
buffer
->
planes
().
first
().
modifier
))
{
m_attemptedFormats
[
buffer
->
format
()]
<<
buffer
->
planes
().
first
().
modifier
;
QVector
<
KWaylandServer
::
LinuxDmaBufV1Feedback
::
Tranche
>
scanoutTranches
;
const
auto
tranches
=
m_eglBackend
->
dmabuf
()
->
tranches
();
for
(
const
auto
&
tranche
:
tranches
)
{
KWaylandServer
::
LinuxDmaBufV1Feedback
::
Tranche
scanoutTranche
;
for
(
auto
it
=
tranche
.
formatTable
.
constBegin
();
it
!=
tranche
.
formatTable
.
constEnd
();
it
++
)
{
const
uint32_t
format
=
it
.
key
();
const
auto
trancheModifiers
=
it
.
value
();
const
auto
drmModifiers
=
formats
[
format
];
for
(
const
auto
&
mod
:
trancheModifiers
)
{
if
(
drmModifiers
.
contains
(
mod
)
&&
!
m_attemptedFormats
[
format
].
contains
(
mod
))
{
scanoutTranche
.
formatTable
[
format
]
<<
mod
;
}
}
}
if
(
!
scanoutTranche
.
formatTable
.
isEmpty
())
{
scanoutTranche
.
device
=
m_gpu
->
deviceId
();
scanoutTranche
.
flags
=
KWaylandServer
::
LinuxDmaBufV1Feedback
::
TrancheFlag
::
Scanout
;
scanoutTranches
<<
scanoutTranche
;
}
}
feedback
->
setTranches
(
scanoutTranches
);
}
}
}
}
src/backends/drm/dmabuf_feedback.h
0 → 100644
View file @
c43eb6ec
/*
KWin - the KDE window manager
This file is part of the KDE project.
SPDX-FileCopyrightText: 2022 Xaver Hugl <xaver.hugl@gmail.com>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include
<QMap>
#include
<QPointer>
#include
<QVector>
namespace
KWaylandServer
{
class
SurfaceInterface
;
class
LinuxDmaBufV1ClientBuffer
;
}
namespace
KWin
{
class
EglGbmBackend
;
class
DrmGpu
;
class
DmabufFeedback
{
public:
DmabufFeedback
(
DrmGpu
*
gpu
,
EglGbmBackend
*
eglBackend
);
void
renderingSurface
();
void
scanoutSuccessful
(
KWaylandServer
::
SurfaceInterface
*
surface
);
void
scanoutFailed
(
KWaylandServer
::
SurfaceInterface
*
surface
,
const
QMap
<
uint32_t
,
QVector
<
uint64_t
>>
&
formats
);
private:
QPointer
<
KWaylandServer
::
SurfaceInterface
>
m_surface
;
QMap
<
uint32_t
,
QVector
<
uint64_t
>>
m_attemptedFormats
;
bool
m_attemptedThisFrame
=
false
;
DrmGpu
*
const
m_gpu
;
EglGbmBackend
*
const
m_eglBackend
;
};
}
src/backends/drm/egl_gbm_layer.cpp
View file @
c43eb6ec
...
...
@@ -33,6 +33,7 @@ namespace KWin
EglGbmLayer
::
EglGbmLayer
(
EglGbmBackend
*
eglBackend
,
DrmPipeline
*
pipeline
)
:
DrmPipelineLayer
(
pipeline
)
,
m_surface
(
pipeline
->
gpu
(),
eglBackend
)
,
m_dmabufFeedback
(
pipeline
->
gpu
(),
eglBackend
)
{
connect
(
eglBackend
,
&
EglGbmBackend
::
aboutToBeDestroyed
,
this
,
&
EglGbmLayer
::
destroyResources
);
}
...
...
@@ -50,14 +51,7 @@ void EglGbmLayer::destroyResources()
OutputLayerBeginFrameInfo
EglGbmLayer
::
beginFrame
()
{
m_scanoutBuffer
.
reset
();
// dmabuf feedback
if
(
!
m_scanoutCandidate
.
attemptedThisFrame
&&
m_scanoutCandidate
.
surface
)
{
if
(
const
auto
feedback
=
m_scanoutCandidate
.
surface
->
dmabufFeedbackV1
())
{
feedback
->
setTranches
({});
}
m_scanoutCandidate
.
surface
=
nullptr
;
}
m_scanoutCandidate
.
attemptedThisFrame
=
false
;
m_dmabufFeedback
.
renderingSurface
();
return
m_surface
.
startRendering
(
m_pipeline
->
bufferSize
(),
m_pipeline
->
pending
.
sourceTransformation
,
m_pipeline
->
pending
.
bufferTransformation
,
m_pipeline
->
formats
());
}
...
...
@@ -119,70 +113,37 @@ bool EglGbmLayer::scanout(SurfaceItem *surfaceItem)
if
(
!
item
||
!
item
->
surface
())
{
return
false
;
}
const
auto
buffer
=
qobject_cast
<
KWaylandServer
::
LinuxDmaBufV1ClientBuffer
*>
(
item
->
surface
()
->
buffer
());
const
auto
surface
=
item
->
surface
();
const
auto
buffer
=
qobject_cast
<
KWaylandServer
::
LinuxDmaBufV1ClientBuffer
*>
(
surface
->
buffer
());
if
(
!
buffer
||
buffer
->
planes
().
isEmpty
()
||
buffer
->
size
()
!=
m_pipeline
->
sourceSize
())
{
return
false
;
}
if
(
m_scanoutCandidate
.
surface
&&
m_scanoutCandidate
.
surface
!=
item
->
surface
()
&&
m_scanoutCandidate
.
surface
->
dmabufFeedbackV1
())
{
m_scanoutCandidate
.
surface
->
dmabufFeedbackV1
()
->
setTranches
({});
}
m_scanoutCandidate
.
surface
=
item
->
surface
();
m_scanoutCandidate
.
attemptedThisFrame
=
true
;
if
(
!
m_pipeline
->
formats
().
contains
(
buffer
->
format
()))
{
sendDmabufFeedback
(
buffer
);
const
auto
formats
=
m_pipeline
->
formats
();
if
(
!
formats
.
contains
(
buffer
->
format
()))
{
m_dmabufFeedback
.
scanoutFailed
(
surface
,
formats
);
return
false
;
}
m_scanoutBuffer
=
QSharedPointer
<
DrmGbmBuffer
>::
create
(
m_pipeline
->
gpu
(),
buffer
);
if
(
!
m_scanoutBuffer
||
!
m_scanoutBuffer
->
bufferId
())
{
sendD
mabufFeedback
(
buffer
);
m_d
mabufFeedback
.
scanoutFailed
(
surface
,
formats
);
m_scanoutBuffer
.
reset
();
return
false
;
}
if
(
m_pipeline
->
testScanout
())
{
m_dmabufFeedback
.
scanoutSuccessful
(
surface
);
m_currentBuffer
=
m_scanoutBuffer
;
m_currentDamage
=
surfaceItem
->
damage
();
surfaceItem
->
resetDamage
();
return
true
;
}
else
{
m_dmabufFeedback
.
scanoutFailed
(
surface
,
formats
);
m_scanoutBuffer
.
reset
();
return
false
;
}
}
void
EglGbmLayer
::
sendDmabufFeedback
(
KWaylandServer
::
LinuxDmaBufV1ClientBuffer
*
failedBuffer
)
{
if
(
!
m_scanoutCandidate
.
attemptedFormats
[
failedBuffer
->
format
()].
contains
(
failedBuffer
->
planes
().
first
().
modifier
))
{
m_scanoutCandidate
.
attemptedFormats
[
failedBuffer
->
format
()]
<<
failedBuffer
->
planes
().
first
().
modifier
;
}
if
(
m_scanoutCandidate
.
surface
->
dmabufFeedbackV1
())
{
QVector
<
KWaylandServer
::
LinuxDmaBufV1Feedback
::
Tranche
>
scanoutTranches
;
const
auto
drmFormats
=
m_pipeline
->
formats
();
const
auto
tranches
=
m_surface
.
eglBackend
()
->
dmabuf
()
->
tranches
();
for
(
const
auto
&
tranche
:
tranches
)
{
KWaylandServer
::
LinuxDmaBufV1Feedback
::
Tranche
scanoutTranche
;
for
(
auto
it
=
tranche
.
formatTable
.
constBegin
();
it
!=
tranche
.
formatTable
.
constEnd
();
it
++
)
{
const
uint32_t
format
=
it
.
key
();
const
auto
trancheModifiers
=
it
.
value
();
const
auto
drmModifiers
=
drmFormats
[
format
];
for
(
const
auto
&
mod
:
trancheModifiers
)
{
if
(
drmModifiers
.
contains
(
mod
)
&&
!
m_scanoutCandidate
.
attemptedFormats
[
format
].
contains
(
mod
))
{
scanoutTranche
.
formatTable
[
format
]
<<
mod
;
}
}
}
if
(
!
scanoutTranche
.
formatTable
.
isEmpty
())
{
scanoutTranche
.
device
=
m_pipeline
->
gpu
()
->
deviceId
();
scanoutTranche
.
flags
=
KWaylandServer
::
LinuxDmaBufV1Feedback
::
TrancheFlag
::
Scanout
;
scanoutTranches
<<
scanoutTranche
;
}
}
m_scanoutCandidate
.
surface
->
dmabufFeedbackV1
()
->
setTranches
(
scanoutTranches
);
}
}
QSharedPointer
<
DrmBuffer
>
EglGbmLayer
::
currentBuffer
()
const
{
return
m_scanoutBuffer
?
m_scanoutBuffer
:
m_currentBuffer
;
...
...
src/backends/drm/egl_gbm_layer.h
View file @
c43eb6ec
...
...
@@ -9,6 +9,7 @@
#pragma once
#include
"drm_layer.h"
#include
"dmabuf_feedback.h"
#include
"egl_gbm_layer_surface.h"
#include
<QMap>
...
...
@@ -28,7 +29,6 @@ namespace KWin
{
class
EglGbmBackend
;
class
EglGbmLayerSurface
;
class
DrmGbmBuffer
;
class
EglGbmLayer
:
public
DrmPipelineLayer
...
...
@@ -48,22 +48,15 @@ public:
QSharedPointer
<
GLTexture
>
texture
()
const
override
;
private:
void
sendDmabufFeedback
(
KWaylandServer
::
LinuxDmaBufV1ClientBuffer
*
failedBuffer
);
bool
renderTestBuffer
();
void
destroyResources
();
struct
{
QPointer
<
KWaylandServer
::
SurfaceInterface
>
surface
;
QMap
<
uint32_t
,
QVector
<
uint64_t
>>
attemptedFormats
;
bool
attemptedThisFrame
=
false
;
}
m_scanoutCandidate
;
QSharedPointer
<
DrmGbmBuffer
>
m_scanoutBuffer
;
QSharedPointer
<
DrmBuffer
>
m_currentBuffer
;
QRegion
m_currentDamage
;
EglGbmLayerSurface
m_surface
;
DmabufFeedback
m_dmabufFeedback
;
};
}
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new 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