2020-08-02 22:22:19 +00:00
/*
KWin - the KDE window manager
This file is part of the KDE project .
2017-05-09 19:00:33 +00:00
2020-08-02 22:22:19 +00:00
SPDX - FileCopyrightText : 2017 Roman Gilg < subdiff @ gmail . com >
SPDX - FileCopyrightText : 2015 Martin Gräßlin < mgraesslin @ kde . org >
2017-05-09 19:00:33 +00:00
2020-08-02 22:22:19 +00:00
SPDX - License - Identifier : GPL - 2.0 - or - later
*/
2017-05-09 19:00:33 +00:00
# include "drm_buffer_gbm.h"
2017-10-05 16:58:57 +00:00
# include "gbm_surface.h"
2017-05-09 19:00:33 +00:00
# include "logging.h"
2021-03-22 10:43:24 +00:00
# include "drm_gpu.h"
2017-05-09 19:00:33 +00:00
// system
# include <sys/mman.h>
2019-07-09 19:19:26 +00:00
// c++
# include <cerrno>
2017-05-09 19:00:33 +00:00
// drm
# include <xf86drm.h>
2017-11-12 20:00:02 +00:00
# include <xf86drmMode.h>
2017-05-09 19:00:33 +00:00
# include <gbm.h>
2021-02-02 13:26:43 +00:00
// KWaylandServer
2021-07-20 19:37:03 +00:00
# include "KWaylandServer/clientbuffer.h"
2021-03-06 15:24:52 +00:00
# include <drm_fourcc.h>
2017-05-09 19:00:33 +00:00
namespace KWin
{
2021-05-25 17:25:55 +00:00
GbmBuffer : : GbmBuffer ( GbmSurface * surface , gbm_bo * bo )
2021-03-29 11:17:44 +00:00
: m_surface ( surface )
2021-05-25 17:25:55 +00:00
, m_bo ( bo )
2017-05-09 19:00:33 +00:00
{
2021-05-25 17:25:55 +00:00
m_stride = gbm_bo_get_stride ( m_bo ) ;
2017-05-09 19:00:33 +00:00
}
2021-07-20 19:37:03 +00:00
GbmBuffer : : GbmBuffer ( gbm_bo * buffer , KWaylandServer : : ClientBuffer * clientBuffer )
2021-03-29 11:17:44 +00:00
: m_bo ( buffer )
2021-07-20 19:37:03 +00:00
, m_clientBuffer ( clientBuffer )
2021-05-04 10:19:31 +00:00
, m_stride ( gbm_bo_get_stride ( m_bo ) )
2020-11-28 17:53:41 +00:00
{
2021-07-20 19:37:03 +00:00
if ( m_clientBuffer ) {
m_clientBuffer - > ref ( ) ;
2021-02-02 13:26:43 +00:00
}
2020-11-28 17:53:41 +00:00
}
2021-03-29 11:17:44 +00:00
GbmBuffer : : ~ GbmBuffer ( )
2021-05-02 20:38:36 +00:00
{
releaseBuffer ( ) ;
}
void GbmBuffer : : releaseBuffer ( )
2017-05-09 19:00:33 +00:00
{
2021-07-20 19:37:03 +00:00
if ( m_clientBuffer ) {
m_clientBuffer - > unref ( ) ;
m_clientBuffer = nullptr ;
2021-02-02 13:26:43 +00:00
}
2021-05-04 10:19:31 +00:00
if ( ! m_bo ) {
return ;
}
if ( m_mapping ) {
gbm_bo_unmap ( m_bo , m_mapping ) ;
}
if ( m_surface ) {
2021-05-25 17:25:55 +00:00
m_surface - > releaseBuffer ( this ) ;
m_surface = nullptr ;
2021-05-04 10:19:31 +00:00
} else {
2021-03-29 11:17:44 +00:00
gbm_bo_destroy ( m_bo ) ;
2020-11-28 17:53:41 +00:00
}
2021-05-02 20:38:36 +00:00
m_bo = nullptr ;
2017-05-09 19:00:33 +00:00
}
2021-05-04 10:19:31 +00:00
bool GbmBuffer : : map ( uint32_t flags )
{
if ( m_data ) {
return true ;
}
if ( ! m_bo ) {
return false ;
}
m_data = gbm_bo_map ( m_bo , 0 , 0 , gbm_bo_get_width ( m_bo ) , gbm_bo_get_height ( m_bo ) , flags , & m_stride , & m_mapping ) ;
return m_data ;
}
2021-02-02 13:26:43 +00:00
2021-05-25 17:25:55 +00:00
DrmGbmBuffer : : DrmGbmBuffer ( DrmGpu * gpu , GbmSurface * surface , gbm_bo * bo )
: DrmBuffer ( gpu ) , GbmBuffer ( surface , bo )
2021-03-29 11:17:44 +00:00
{
initialize ( ) ;
}
2021-07-20 19:37:03 +00:00
DrmGbmBuffer : : DrmGbmBuffer ( DrmGpu * gpu , gbm_bo * buffer , KWaylandServer : : ClientBuffer * clientBuffer )
: DrmBuffer ( gpu ) , GbmBuffer ( buffer , clientBuffer )
2021-03-29 11:17:44 +00:00
{
initialize ( ) ;
}
DrmGbmBuffer : : ~ DrmGbmBuffer ( )
{
if ( m_bufferId ) {
2021-06-20 15:36:15 +00:00
if ( drmModeRmFB ( m_gpu - > fd ( ) , m_bufferId ) ! = 0 ) {
qCCritical ( KWIN_DRM ) < < " drmModeRmFB on GPU " < < m_gpu - > devNode ( ) < < " failed! " < < strerror ( errno ) ;
}
2021-03-29 11:17:44 +00:00
}
}
void DrmGbmBuffer : : initialize ( )
2021-03-06 15:24:52 +00:00
{
m_size = QSize ( gbm_bo_get_width ( m_bo ) , gbm_bo_get_height ( m_bo ) ) ;
2021-06-20 15:36:15 +00:00
uint32_t format = gbm_bo_get_format ( m_bo ) ;
2021-03-06 15:24:52 +00:00
uint32_t handles [ 4 ] = { } ;
uint32_t strides [ 4 ] = { } ;
uint32_t offsets [ 4 ] = { } ;
uint64_t modifiers [ 4 ] = { } ;
if ( gbm_bo_get_handle_for_plane ( m_bo , 0 ) . s32 ! = - 1 ) {
for ( int i = 0 ; i < gbm_bo_get_plane_count ( m_bo ) ; i + + ) {
handles [ i ] = gbm_bo_get_handle_for_plane ( m_bo , i ) . u32 ;
strides [ i ] = gbm_bo_get_stride_for_plane ( m_bo , i ) ;
offsets [ i ] = gbm_bo_get_offset ( m_bo , i ) ;
modifiers [ i ] = gbm_bo_get_modifier ( m_bo ) ;
}
} else {
2021-06-20 16:47:10 +00:00
handles [ 0 ] = gbm_bo_get_handle ( m_bo ) . u32 ;
2021-03-06 15:24:52 +00:00
strides [ 0 ] = gbm_bo_get_stride ( m_bo ) ;
modifiers [ 0 ] = DRM_FORMAT_MOD_INVALID ;
}
2021-03-22 10:43:24 +00:00
if ( modifiers [ 0 ] ! = DRM_FORMAT_MOD_INVALID & & m_gpu - > addFB2ModifiersSupported ( ) ) {
2021-06-20 15:36:15 +00:00
if ( drmModeAddFB2WithModifiers ( m_gpu - > fd ( ) , m_size . width ( ) , m_size . height ( ) , format , handles , strides , offsets , modifiers , & m_bufferId , DRM_MODE_FB_MODIFIERS ) ) {
gbm_format_name_desc name ;
gbm_format_get_name ( format , & name ) ;
qCCritical ( KWIN_DRM ) < < " drmModeAddFB2WithModifiers on GPU " < < m_gpu - > devNode ( ) < < " failed for a buffer with format " < < name . name < < " and modifier " < < modifiers [ 0 ] < < strerror ( errno ) ;
2021-03-06 15:24:52 +00:00
}
} else {
2021-06-20 15:36:15 +00:00
if ( drmModeAddFB2 ( m_gpu - > fd ( ) , m_size . width ( ) , m_size . height ( ) , format , handles , strides , offsets , & m_bufferId , 0 ) ) {
2021-03-06 15:24:52 +00:00
// fallback
2021-03-22 10:43:24 +00:00
if ( drmModeAddFB ( m_gpu - > fd ( ) , m_size . width ( ) , m_size . height ( ) , 24 , 32 , strides [ 0 ] , handles [ 0 ] , & m_bufferId ) ! = 0 ) {
2021-06-20 15:36:15 +00:00
gbm_format_name_desc name ;
gbm_format_get_name ( format , & name ) ;
qCCritical ( KWIN_DRM ) < < " drmModeAddFB2 and drmModeAddFB both failed on GPU " < < m_gpu - > devNode ( ) < < " for a buffer with format " < < name . name < < " and modifier " < < modifiers [ 0 ] < < strerror ( errno ) ;
2021-03-06 15:24:52 +00:00
}
}
}
gbm_bo_set_user_data ( m_bo , this , nullptr ) ;
}
2017-05-09 19:00:33 +00:00
}