@ -10,29 +10,48 @@ void wlr_buffer_init(struct wlr_buffer *buffer,
const struct wlr_buffer_impl * impl ) {
assert ( impl - > destroy ) ;
buffer - > impl = impl ;
buffer - > n_refs = 1 ;
wl_signal_init ( & buffer - > events . destroy ) ;
wl_signal_init ( & buffer - > events . release ) ;
}
struct wlr_buffer * wlr_buffer_ref ( struct wlr_buffer * buffer ) {
buffer - > n_refs + + ;
return buffer ;
static void buffer_consider_destroy ( struct wlr_buffer * buffer ) {
if ( ! buffer - > dropped | | buffer - > n_locks > 0 ) {
return ;
}
wlr_signal_emit_safe ( & buffer - > events . destroy , NULL ) ;
buffer - > impl - > destroy ( buffer ) ;
}
void wlr_buffer_unref ( struct wlr_buffer * buffer ) {
void wlr_buffer_ drop ( struct wlr_buffer * buffer ) {
if ( buffer = = NULL ) {
return ;
}
assert ( buffer - > n_refs > 0 ) ;
buffer - > n_refs - - ;
if ( buffer - > n_refs > 0 ) {
assert ( ! buffer - > dropped ) ;
buffer - > dropped = true ;
buffer_consider_destroy ( buffer ) ;
}
struct wlr_buffer * wlr_buffer_lock ( struct wlr_buffer * buffer ) {
buffer - > n_locks + + ;
return buffer ;
}
void wlr_buffer_unlock ( struct wlr_buffer * buffer ) {
if ( buffer = = NULL ) {
return ;
}
wlr_signal_emit_safe ( & buffer - > events . destroy , NULL ) ;
assert ( buffer - > n_locks > 0 ) ;
buffer - > n_locks - - ;
buffer - > impl - > destroy ( buffer ) ;
if ( buffer - > n_locks = = 0 ) {
wl_signal_emit ( & buffer - > events . release , NULL ) ;
}
buffer_consider_destroy ( buffer ) ;
}
bool wlr_buffer_get_dmabuf ( struct wlr_buffer * buffer ,
@ -134,7 +153,17 @@ static void client_buffer_resource_handle_destroy(struct wl_listener *listener,
// which case we'll read garbage. We decide to accept this risk.
}
struct wlr_client_buffer * wlr_client_buffer_create (
static void client_buffer_handle_release ( struct wl_listener * listener ,
void * data ) {
struct wlr_client_buffer * buffer =
wl_container_of ( listener , buffer , release ) ;
if ( ! buffer - > resource_released & & buffer - > resource ! = NULL ) {
wl_buffer_send_release ( buffer - > resource ) ;
buffer - > resource_released = true ;
}
}
struct wlr_client_buffer * wlr_client_buffer_import (
struct wlr_renderer * renderer , struct wl_resource * resource ) {
assert ( wlr_resource_is_buffer ( resource ) ) ;
@ -198,6 +227,13 @@ struct wlr_client_buffer *wlr_client_buffer_create(
wl_resource_add_destroy_listener ( resource , & buffer - > resource_destroy ) ;
buffer - > resource_destroy . notify = client_buffer_resource_handle_destroy ;
buffer - > release . notify = client_buffer_handle_release ;
wl_signal_add ( & buffer - > base . events . release , & buffer - > release ) ;
// Ensure the buffer will be released before being destroyed
wlr_buffer_lock ( & buffer - > base ) ;
wlr_buffer_drop ( & buffer - > base ) ;
return buffer ;
}
@ -206,7 +242,7 @@ struct wlr_client_buffer *wlr_client_buffer_apply_damage(
pixman_region32_t * damage ) {
assert ( wlr_resource_is_buffer ( resource ) ) ;
if ( buffer - > base . n_ ref s > 1 ) {
if ( buffer - > base . n_ lock s > 1 ) {
// Someone else still has a reference to the buffer
return NULL ;
}