@ -22,35 +22,19 @@ static const struct wl_buffer_interface buffer_impl = {
. destroy = buffer_handle_destroy ,
. destroy = buffer_handle_destroy ,
} ;
} ;
bool wlr_dmabuf_v1_resource_is_buffer ( struct wl_resource * buffer_ resource) {
bool wlr_dmabuf_v1_resource_is_buffer ( struct wl_resource * resource) {
if ( ! wl_resource_instance_of ( buffer_ resource, & wl_buffer_interface ,
if ( ! wl_resource_instance_of ( resource, & wl_buffer_interface ,
& buffer_impl ) ) {
& buffer_impl ) ) {
return false ;
return false ;
}
}
return wl_resource_get_user_data ( resource ) ! = NULL ;
struct wlr_dmabuf_v1_buffer * buffer =
wl_resource_get_user_data ( buffer_resource ) ;
if ( buffer & & buffer - > buffer_resource & & ! buffer - > params_resource & &
buffer - > buffer_resource = = buffer_resource ) {
return true ;
}
return false ;
}
}
struct wlr_dmabuf_v1_buffer * wlr_dmabuf_v1_buffer_from_buffer_resource (
struct wlr_dmabuf_v1_buffer * wlr_dmabuf_v1_buffer_from_buffer_resource (
struct wl_resource * buffer_ resource) {
struct wl_resource * resource ) {
assert ( wl_resource_instance_of ( buffer_ resource, & wl_buffer_interface ,
assert ( wl_resource_instance_of ( resource , & wl_buffer_interface ,
& buffer_impl ) ) ;
& buffer_impl ) ) ;
return wl_resource_get_user_data ( resource ) ;
struct wlr_dmabuf_v1_buffer * buffer =
wl_resource_get_user_data ( buffer_resource ) ;
assert ( buffer ) ;
assert ( buffer - > buffer_resource ) ;
assert ( ! buffer - > params_resource ) ;
assert ( buffer - > buffer_resource = = buffer_resource ) ;
return buffer ;
}
}
static void linux_dmabuf_buffer_destroy ( struct wlr_dmabuf_v1_buffer * buffer ) {
static void linux_dmabuf_buffer_destroy ( struct wlr_dmabuf_v1_buffer * buffer ) {
@ -58,22 +42,13 @@ static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_v1_buffer *buffer) {
free ( buffer ) ;
free ( buffer ) ;
}
}
static const struct zwp_linux_buffer_params_v1_interface linux_buffer_params_impl ;
static const struct zwp_linux_buffer_params_v1_interface buffer_params_impl ;
static struct wlr_dmabuf_v1_buffer * buffer_from_params_resource (
struct wl_resource * params_resource ) {
assert ( wl_resource_instance_of ( params_resource ,
& zwp_linux_buffer_params_v1_interface ,
& linux_buffer_params_impl ) ) ;
struct wlr_dmabuf_v1_buffer * buffer =
wl_resource_get_user_data ( params_resource ) ;
assert ( buffer ) ;
assert ( buffer - > params_resource ) ;
assert ( ! buffer - > buffer_resource ) ;
assert ( buffer - > params_resource = = params_resource ) ;
return buffer ;
static struct wlr_linux_buffer_params_v1 * params_from_resource (
struct wl_resource * resource ) {
assert ( wl_resource_instance_of ( resource ,
& zwp_linux_buffer_params_v1_interface , & buffer_params_impl ) ) ;
return wl_resource_get_user_data ( resource ) ;
}
}
static void params_destroy ( struct wl_client * client ,
static void params_destroy ( struct wl_client * client ,
@ -85,10 +60,9 @@ static void params_add(struct wl_client *client,
struct wl_resource * params_resource , int32_t fd ,
struct wl_resource * params_resource , int32_t fd ,
uint32_t plane_idx , uint32_t offset , uint32_t stride ,
uint32_t plane_idx , uint32_t offset , uint32_t stride ,
uint32_t modifier_hi , uint32_t modifier_lo ) {
uint32_t modifier_hi , uint32_t modifier_lo ) {
struct wlr_dmabuf_v1_buffer * buffer =
struct wlr_linux_buffer_params_v1 * params =
buffer_from_params_resource ( params_resource ) ;
params_from_resource ( params_resource ) ;
if ( ! params ) {
if ( ! buffer ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED ,
" params was already used to create a wl_buffer " ) ;
" params was already used to create a wl_buffer " ) ;
@ -104,33 +78,33 @@ static void params_add(struct wl_client *client,
return ;
return ;
}
}
if ( buffer - > attributes . fd [ plane_idx ] ! = - 1 ) {
if ( params - > attributes . fd [ plane_idx ] ! = - 1 ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET ,
" a dmabuf with FD %d has already been added for plane %u " ,
" a dmabuf with FD %d has already been added for plane %u " ,
buffer - > attributes . fd [ plane_idx ] , plane_idx ) ;
params - > attributes . fd [ plane_idx ] , plane_idx ) ;
close ( fd ) ;
close ( fd ) ;
return ;
return ;
}
}
uint64_t modifier = ( ( uint64_t ) modifier_hi < < 32 ) | modifier_lo ;
uint64_t modifier = ( ( uint64_t ) modifier_hi < < 32 ) | modifier_lo ;
if ( buffer - > has_modifier & & modifier ! = buffer - > attributes . modifier ) {
if ( params - > has_modifier & & modifier ! = params - > attributes . modifier ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT ,
" sent modifier % " PRIu64 " for plane %u, expected "
" sent modifier % " PRIu64 " for plane %u, expected "
" modifier % " PRIu64 " like other planes " ,
" modifier % " PRIu64 " like other planes " ,
modifier , plane_idx , buffer - > attributes . modifier ) ;
modifier , plane_idx , params - > attributes . modifier ) ;
close ( fd ) ;
close ( fd ) ;
return ;
return ;
}
}
buffer - > attributes . modifier = modifier ;
params - > attributes . modifier = modifier ;
buffer - > has_modifier = true ;
params - > has_modifier = true ;
buffer - > attributes . fd [ plane_idx ] = fd ;
params - > attributes . fd [ plane_idx ] = fd ;
buffer - > attributes . offset [ plane_idx ] = offset ;
params - > attributes . offset [ plane_idx ] = offset ;
buffer - > attributes . stride [ plane_idx ] = stride ;
params - > attributes . stride [ plane_idx ] = stride ;
buffer - > attributes . n_planes + + ;
params - > attributes . n_planes + + ;
}
}
static void buffer_handle_resource_destroy ( struct wl_resource * buffer_resource ) {
static void buffer_handle_resource_destroy ( struct wl_resource * buffer_resource ) {
@ -139,9 +113,10 @@ static void buffer_handle_resource_destroy(struct wl_resource *buffer_resource)
linux_dmabuf_buffer_destroy ( buffer ) ;
linux_dmabuf_buffer_destroy ( buffer ) ;
}
}
static bool check_import_dmabuf ( struct wlr_dmabuf_v1_buffer * buffer ) {
static bool check_import_dmabuf ( struct wlr_linux_dmabuf_v1 * linux_dmabuf ,
struct wlr_dmabuf_attributes * attribs ) {
struct wlr_texture * texture =
struct wlr_texture * texture =
wlr_texture_from_dmabuf ( buffer - > renderer , & buffer - > attrib ute s) ;
wlr_texture_from_dmabuf ( linux_dma buf- > renderer , attrib s) ;
if ( texture = = NULL ) {
if ( texture = = NULL ) {
return false ;
return false ;
}
}
@ -152,49 +127,51 @@ static bool check_import_dmabuf(struct wlr_dmabuf_v1_buffer *buffer) {
return true ;
return true ;
}
}
static void params_create_common ( struct wl_client * client ,
static void params_create_common ( struct wl_resource * params_resource ,
struct wl_resource * params_resource , uint32_t buffer_id , int32_t width ,
uint32_t buffer_id , int32_t width , int32_t height , uint32_t format ,
int32_t height , uint32_t format , uint32_t flags ) {
uint32_t flags ) {
if ( ! wl_resource_get_user_data ( params_resource ) ) {
struct wlr_linux_buffer_params_v1 * params =
params_from_resource ( params_resource ) ;
if ( ! params ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED ,
" params was already used to create a wl_buffer " ) ;
" params was already used to create a wl_buffer " ) ;
return ;
return ;
}
}
struct wlr_dmabuf_v1_buffer * buffer =
buffer_from_params_resource ( params_resource ) ;
/* Switch the linux_dmabuf_buffer object from params resource to
struct wlr_dmabuf_attributes attribs = params - > attributes ;
* eventually wl_buffer resource . */
struct wlr_linux_dmabuf_v1 * linux_dmabuf = params - > linux_dmabuf ;
wl_resource_set_user_data ( buffer - > params_resource , NULL ) ;
buffer - > params_resource = NULL ;
// Make the params resource inert
wl_resource_set_user_data ( params_resource , NULL ) ;
free ( params ) ;
if ( ! buffer - > attributes . n_planes ) {
if ( ! attribs. n_planes ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
" no dmabuf has been added to the params " ) ;
" no dmabuf has been added to the params " ) ;
goto err_out ;
goto err_out ;
}
}
if ( buffer- > attribute s. fd [ 0 ] = = - 1 ) {
if ( attribs. fd [ 0 ] = = - 1 ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
" no dmabuf has been added for plane 0 " ) ;
" no dmabuf has been added for plane 0 " ) ;
goto err_out ;
goto err_out ;
}
}
if ( ( buffer- > attribute s. fd [ 3 ] > = 0 | | buffer- > attribute s. fd [ 2 ] > = 0 ) & &
if ( ( attribs. fd [ 3 ] > = 0 | | attribs. fd [ 2 ] > = 0 ) & &
( buffer- > attribute s. fd [ 2 ] = = - 1 | | buffer- > attribute s. fd [ 1 ] = = - 1 ) ) {
( attribs. fd [ 2 ] = = - 1 | | attribs. fd [ 1 ] = = - 1 ) ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE ,
" gap in dmabuf planes " ) ;
" gap in dmabuf planes " ) ;
goto err_out ;
goto err_out ;
}
}
buffer- > attribute s. width = width ;
attribs. width = width ;
buffer- > attribute s. height = height ;
attribs. height = height ;
buffer- > attribute s. format = format ;
attribs. format = format ;
buffer- > attribute s. flags = flags ;
attribs. flags = flags ;
if ( width < 1 | | height < 1 ) {
if ( width < 1 | | height < 1 ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
@ -203,48 +180,48 @@ static void params_create_common(struct wl_client *client,
goto err_out ;
goto err_out ;
}
}
for ( int i = 0 ; i < buffer- > attribute s. n_planes ; i + + ) {
for ( int i = 0 ; i < attribs. n_planes ; i + + ) {
if ( ( uint64_t ) buffer- > attribute s. offset [ i ]
if ( ( uint64_t ) attribs. offset [ i ]
+ buffer- > attribute s. stride [ i ] > UINT32_MAX ) {
+ attribs. stride [ i ] > UINT32_MAX ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
" size overflow for plane %d " , i ) ;
" size overflow for plane %d " , i ) ;
goto err_out ;
goto err_out ;
}
}
if ( ( uint64_t ) buffer- > attribute s. offset [ i ]
if ( ( uint64_t ) attribs. offset [ i ]
+ ( uint64_t ) buffer- > attribute s. stride [ i ] * height > UINT32_MAX ) {
+ ( uint64_t ) attribs. stride [ i ] * height > UINT32_MAX ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
" size overflow for plane %d " , i ) ;
" size overflow for plane %d " , i ) ;
goto err_out ;
goto err_out ;
}
}
off_t size = lseek ( buffer- > attribute s. fd [ i ] , 0 , SEEK_END ) ;
off_t size = lseek ( attribs. fd [ i ] , 0 , SEEK_END ) ;
if ( size = = - 1 ) {
if ( size = = - 1 ) {
// Skip checks if kernel does no support seek on buffer
// Skip checks if kernel does no support seek on buffer
continue ;
continue ;
}
}
if ( buffer- > attribute s. offset [ i ] > size ) {
if ( attribs. offset [ i ] > size ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
" invalid offset % " PRIu32 " for plane %d " ,
" invalid offset % " PRIu32 " for plane %d " ,
buffer- > attribute s. offset [ i ] , i ) ;
attribs. offset [ i ] , i ) ;
goto err_out ;
goto err_out ;
}
}
if ( buffer- > attribute s. offset [ i ] + buffer- > attribute s. stride [ i ] > size | |
if ( attribs. offset [ i ] + attribs. stride [ i ] > size | |
buffer- > attribute s. stride [ i ] = = 0 ) {
attribs. stride [ i ] = = 0 ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
" invalid stride % " PRIu32 " for plane %d " ,
" invalid stride % " PRIu32 " for plane %d " ,
buffer- > attribute s. stride [ i ] , i ) ;
attribs. stride [ i ] , i ) ;
goto err_out ;
goto err_out ;
}
}
// planes > 0 might be subsampled according to fourcc format
// planes > 0 might be subsampled according to fourcc format
if ( i = = 0 & & buffer- > attribute s. offset [ i ] +
if ( i = = 0 & & attribs. offset [ i ] +
buffer- > attribute s. stride [ i ] * height > size ) {
attribs. stride [ i ] * height > size ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS ,
" invalid buffer stride or height for plane %d " , i ) ;
" invalid buffer stride or height for plane %d " , i ) ;
@ -253,34 +230,43 @@ static void params_create_common(struct wl_client *client,
}
}
/* reject unknown flags */
/* reject unknown flags */
if ( buffer- > attribute s. flags & ~ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT ) {
if ( attribs. flags & ~ ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT ) {
wl_resource_post_error ( params_resource ,
wl_resource_post_error ( params_resource ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT ,
ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT ,
" Unknown dmabuf flags % " PRIu32 , buffer- > attribute s. flags ) ;
" Unknown dmabuf flags % " PRIu32 , attribs. flags ) ;
goto err_out ;
goto err_out ;
}
}
/* Check if dmabuf is usable */
/* Check if dmabuf is usable */
if ( ! check_import_dmabuf ( buffer ) ) {
if ( ! check_import_dmabuf ( linux_dmabuf, & attribs ) ) {
goto err_failed ;
goto err_failed ;
}
}
buffer - > buffer_resource = wl_resource_create ( client , & wl_buffer_interface ,
struct wlr_dmabuf_v1_buffer * buffer = calloc ( 1 , sizeof ( * buffer ) ) ;
1 , buffer_id ) ;
if ( ! buffer ) {
if ( ! buffer - > buffer_resource ) {
wl_resource_post_no_memory ( params_resource ) ;
wl_resource_post_no_memory ( params_resource ) ;
goto err_failed ;
goto err_failed ;
}
}
wl_resource_set_implementation ( buffer - > buffer_resource ,
struct wl_client * client = wl_resource_get_client ( params_resource ) ;
buffer - > resource = wl_resource_create ( client , & wl_buffer_interface ,
1 , buffer_id ) ;
if ( ! buffer - > resource ) {
wl_resource_post_no_memory ( params_resource ) ;
goto err_failed ;
}
wl_resource_set_implementation ( buffer - > resource ,
& buffer_impl , buffer , buffer_handle_resource_destroy ) ;
& buffer_impl , buffer , buffer_handle_resource_destroy ) ;
buffer - > attributes = attribs ;
/* send 'created' event when the request is not for an immediate
/* send 'created' event when the request is not for an immediate
* import , that is buffer_id is zero */
* import , that is buffer_id is zero */
if ( buffer_id = = 0 ) {
if ( buffer_id = = 0 ) {
zwp_linux_buffer_params_v1_send_created ( params_resource ,
zwp_linux_buffer_params_v1_send_created ( params_resource ,
buffer - > buffer_resource ) ;
buffer - > resource) ;
}
}
return ;
return ;
err_failed :
err_failed :
@ -298,40 +284,37 @@ err_failed:
" importing the supplied dmabufs failed " ) ;
" importing the supplied dmabufs failed " ) ;
}
}
err_out :
err_out :
linux_dmabuf_buffer_destroy( buffer ) ;
wlr_dmabuf_attributes_finish( & attribs ) ;
}
}
static void params_create ( struct wl_client * client ,
static void params_create ( struct wl_client * client ,
struct wl_resource * params_resource ,
struct wl_resource * params_resource ,
int32_t width , int32_t height , uint32_t format , uint32_t flags ) {
int32_t width , int32_t height , uint32_t format , uint32_t flags ) {
params_create_common ( client, params_resource, 0 , width , height , format ,
params_create_common ( params_resource, 0 , width , height , format ,
flags ) ;
flags ) ;
}
}
static void params_create_immed ( struct wl_client * client ,
static void params_create_immed ( struct wl_client * client ,
struct wl_resource * params_resource , uint32_t buffer_id ,
struct wl_resource * params_resource , uint32_t buffer_id ,
int32_t width , int32_t height , uint32_t format , uint32_t flags ) {
int32_t width , int32_t height , uint32_t format , uint32_t flags ) {
params_create_common ( client, params_resource, buffer_id , width , height ,
params_create_common ( params_resource, buffer_id , width , height ,
format , flags ) ;
format , flags ) ;
}
}
static const struct zwp_linux_buffer_params_v1_interface
static const struct zwp_linux_buffer_params_v1_interface buffer_params_impl = {
linux_buffer_params_impl = {
. destroy = params_destroy ,
. destroy = params_destroy ,
. add = params_add ,
. add = params_add ,
. create = params_create ,
. create = params_create ,
. create_immed = params_create_immed ,
. create_immed = params_create_immed ,
} ;
} ;
static void handle_params _destroy( struct wl_resource * params_ resource) {
static void params_handle_resource _destroy( struct wl_resource * resource) {
/* Check for NULL since buffer_from_params_resource will choke */
struct wlr_linux_buffer_params_v1 * params = params_from_resource ( resource ) ;
if ( ! wl_resource_get_user_data ( params _resource) ) {
if ( ! params ) {
return ;
return ;
}
}
wlr_dmabuf_attributes_finish ( & params - > attributes ) ;
struct wlr_dmabuf_v1_buffer * buffer =
free ( params ) ;
buffer_from_params_resource ( params_resource ) ;
linux_dmabuf_buffer_destroy ( buffer ) ;
}
}
static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_impl ;
static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_impl ;
@ -352,31 +335,28 @@ static void linux_dmabuf_create_params(struct wl_client *client,
struct wlr_linux_dmabuf_v1 * linux_dmabuf =
struct wlr_linux_dmabuf_v1 * linux_dmabuf =
linux_dmabuf_from_resource ( linux_dmabuf_resource ) ;
linux_dmabuf_from_resource ( linux_dmabuf_resource ) ;
uint32_t version = wl_resource_get_version ( linux_dmabuf_resource ) ;
struct wlr_linux_buffer_params_v1 * params = calloc ( 1 , sizeof ( * params ) ) ;
struct wlr_dmabuf_v1_buffer * buffer = calloc ( 1 , sizeof * buffer ) ;
if ( ! params ) {
if ( ! buffer ) {
wl_resource_post_no_memory ( linux_dmabuf_resource ) ;
goto err ;
return ;
}
}
for ( int i = 0 ; i < WLR_DMABUF_MAX_PLANES ; i + + ) {
for ( int i = 0 ; i < WLR_DMABUF_MAX_PLANES ; i + + ) {
buffer - > attributes . fd [ i ] = - 1 ;
params - > attributes . fd [ i ] = - 1 ;
}
}
buffer - > renderer = linux_dmabuf - > renderer ;
params - > linux_dmabuf = linux_dmabuf ;
buffer - > params_resource = wl_resource_create ( client ,
uint32_t version = wl_resource_get_version ( linux_dmabuf_resource ) ;
params - > resource = wl_resource_create ( client ,
& zwp_linux_buffer_params_v1_interface , version , params_id ) ;
& zwp_linux_buffer_params_v1_interface , version , params_id ) ;
if ( ! buffer - > params_resource ) {
if ( ! params - > resource ) {
goto err_free ;
free ( params ) ;
wl_resource_post_no_memory ( linux_dmabuf_resource ) ;
return ;
}
}
wl_resource_set_implementation ( params - > resource ,
wl_resource_set_implementation ( buffer - > params_resource ,
& buffer_params_impl , params , params_handle_resource_destroy ) ;
& linux_buffer_params_impl , buffer , handle_params_destroy ) ;
return ;
err_free :
free ( buffer ) ;
err :
wl_resource_post_no_memory ( linux_dmabuf_resource ) ;
}
}
static void linux_dmabuf_destroy ( struct wl_client * client ,
static void linux_dmabuf_destroy ( struct wl_client * client ,