@ -16,6 +16,52 @@ static struct wlr_gbm_buffer *get_gbm_buffer_from_buffer(
return ( struct wlr_gbm_buffer * ) buffer ;
}
static bool export_gbm_bo ( struct gbm_bo * bo ,
struct wlr_dmabuf_attributes * out ) {
struct wlr_dmabuf_attributes attribs = { 0 } ;
attribs . n_planes = gbm_bo_get_plane_count ( bo ) ;
if ( attribs . n_planes > WLR_DMABUF_MAX_PLANES ) {
wlr_log ( WLR_ERROR , " GBM BO contains too many planes (%d) " ,
attribs . n_planes ) ;
return false ;
}
attribs . width = gbm_bo_get_width ( bo ) ;
attribs . height = gbm_bo_get_height ( bo ) ;
attribs . format = gbm_bo_get_format ( bo ) ;
attribs . modifier = gbm_bo_get_modifier ( bo ) ;
int i ;
for ( i = 0 ; i < attribs . n_planes ; + + i ) {
union gbm_bo_handle handle = gbm_bo_get_handle_for_plane ( bo , i ) ;
if ( handle . s32 < 0 ) {
wlr_log ( WLR_ERROR , " gbm_bo_get_handle_for_plane failed " ) ;
goto error_fd ;
}
int drm_fd = gbm_device_get_fd ( gbm_bo_get_device ( bo ) ) ;
int ret = drmPrimeHandleToFD ( drm_fd , handle . s32 ,
DRM_CLOEXEC , & attribs . fd [ i ] ) ;
if ( ret < 0 | | attribs . fd [ i ] < 0 ) {
wlr_log_errno ( WLR_ERROR , " drmPrimeHandleToFD failed " ) ;
goto error_fd ;
}
attribs . offset [ i ] = gbm_bo_get_offset ( bo , i ) ;
attribs . stride [ i ] = gbm_bo_get_stride_for_plane ( bo , i ) ;
}
memcpy ( out , & attribs , sizeof ( attribs ) ) ;
return true ;
error_fd :
for ( int j = 0 ; j < i ; + + j ) {
close ( attribs . fd [ j ] ) ;
}
return false ;
}
static struct wlr_gbm_buffer * create_buffer ( struct wlr_gbm_allocator * alloc ,
int width , int height , const struct wlr_drm_format * format ) {
struct gbm_device * gbm_device = alloc - > gbm_device ;
@ -47,6 +93,12 @@ static struct wlr_gbm_buffer *create_buffer(struct wlr_gbm_allocator *alloc,
buffer - > gbm_bo = bo ;
wl_list_insert ( & alloc - > buffers , & buffer - > link ) ;
if ( ! export_gbm_bo ( bo , & buffer - > dmabuf ) ) {
free ( buffer ) ;
gbm_bo_destroy ( bo ) ;
return NULL ;
}
wlr_log ( WLR_DEBUG , " Allocated %dx%d GBM buffer (format 0x% " PRIX32 " , "
" modifier 0x% " PRIX64 " ) " , buffer - > base . width , buffer - > base . height ,
gbm_bo_get_format ( bo ) , gbm_bo_get_modifier ( bo ) ) ;
@ -65,72 +117,10 @@ static void buffer_destroy(struct wlr_buffer *wlr_buffer) {
free ( buffer ) ;
}
static bool buffer_create_dmabuf ( struct wlr_gbm_buffer * buffer ) {
assert ( buffer - > dmabuf . n_planes = = 0 ) ;
struct gbm_bo * bo = buffer - > gbm_bo ;
if ( bo = = NULL ) {
return false ;
}
struct wlr_dmabuf_attributes attribs = { 0 } ;
attribs . n_planes = gbm_bo_get_plane_count ( bo ) ;
if ( attribs . n_planes > WLR_DMABUF_MAX_PLANES ) {
wlr_log ( WLR_ERROR , " GBM BO contains too many planes (%d) " ,
attribs . n_planes ) ;
return false ;
}
attribs . width = gbm_bo_get_width ( bo ) ;
attribs . height = gbm_bo_get_height ( bo ) ;
attribs . format = gbm_bo_get_format ( bo ) ;
attribs . modifier = gbm_bo_get_modifier ( bo ) ;
int i ;
for ( i = 0 ; i < attribs . n_planes ; + + i ) {
union gbm_bo_handle handle = gbm_bo_get_handle_for_plane ( bo , i ) ;
if ( handle . s32 < 0 ) {
wlr_log ( WLR_ERROR , " gbm_bo_get_handle_for_plane failed " ) ;
goto error_fd ;
}
int drm_fd = gbm_device_get_fd ( gbm_bo_get_device ( bo ) ) ;
int ret = drmPrimeHandleToFD ( drm_fd , handle . s32 ,
DRM_CLOEXEC , & attribs . fd [ i ] ) ;
if ( ret < 0 | | attribs . fd [ i ] < 0 ) {
wlr_log_errno ( WLR_ERROR , " drmPrimeHandleToFD failed " ) ;
goto error_fd ;
}
attribs . offset [ i ] = gbm_bo_get_offset ( bo , i ) ;
attribs . stride [ i ] = gbm_bo_get_stride_for_plane ( bo , i ) ;
}
memcpy ( & buffer - > dmabuf , & attribs , sizeof ( attribs ) ) ;
return true ;
error_fd :
for ( int j = 0 ; j < i ; + + j ) {
close ( attribs . fd [ j ] ) ;
}
return false ;
}
static bool buffer_get_dmabuf ( struct wlr_buffer * wlr_buffer ,
struct wlr_dmabuf_attributes * attribs ) {
struct wlr_gbm_buffer * buffer =
get_gbm_buffer_from_buffer ( wlr_buffer ) ;
memset ( attribs , 0 , sizeof ( * attribs ) ) ;
// Only export the buffer once
if ( buffer - > dmabuf . n_planes = = 0 ) {
if ( ! buffer_create_dmabuf ( buffer ) ) {
return false ;
}
}
memcpy ( attribs , & buffer - > dmabuf , sizeof ( buffer - > dmabuf ) ) ;
return true ;
}