@ -42,22 +42,39 @@ struct display {
uint32_t formats ;
} ;
struct buffer {
struct wl_buffer * buffer ;
void * shm_data ;
int busy ;
} ;
struct window {
struct display * display ;
int width , height ;
struct wl_surface * surface ;
struct wl_shell_surface * shell_surface ;
struct wl_buffer * buffer ;
void * shm_data ;
struct buffer buffers [ 2 ] ;
struct buffer * prev_buffer ;
struct wl_callback * callback ;
} ;
static struct wl_buffer *
create_shm_buffer ( struct display * display ,
int width , int height , uint32_t format , void * * data_out )
static void
buffer_release ( void * data , struct wl_buffer * buffer )
{
struct buffer * mybuf = data ;
mybuf - > busy = 0 ;
}
static const struct wl_buffer_listener buffer_listener = {
buffer_release
} ;
static int
create_shm_buffer ( struct display * display , struct buffer * buffer ,
int width , int height , uint32_t format )
{
struct wl_shm_pool * pool ;
struct wl_buffer * buffer ;
int fd , size , stride ;
void * data ;
@ -68,25 +85,27 @@ create_shm_buffer(struct display *display,
if ( fd < 0 ) {
fprintf ( stderr , " creating a buffer file for %d B failed: %m \n " ,
size ) ;
return NULL ;
return - 1 ;
}
data = mmap ( NULL , size , PROT_READ | PROT_WRITE , MAP_SHARED , fd , 0 ) ;
if ( data = = MAP_FAILED ) {
fprintf ( stderr , " mmap failed: %m \n " ) ;
close ( fd ) ;
return NULL ;
return - 1 ;
}
pool = wl_shm_create_pool ( display - > shm , fd , size ) ;
buffer = wl_shm_pool_create_buffer ( pool , 0 ,
width , height , stride , format ) ;
buffer - > buffer = wl_shm_pool_create_buffer ( pool , 0 ,
width , height ,
stride , format ) ;
wl_buffer_add_listener ( buffer - > buffer , & buffer_listener , buffer ) ;
wl_shm_pool_destroy ( pool ) ;
close ( fd ) ;
* data_out = data ;
buffer - > shm_data = data ;
return buffer ;
return 0 ;
}
static void
@ -117,18 +136,10 @@ static struct window *
create_window ( struct display * display , int width , int height )
{
struct window * window ;
window = malloc ( sizeof * window ) ;
window - > buffer = create_shm_buffer ( display ,
width , height ,
WL_SHM_FORMAT_XRGB8888 ,
& window - > shm_data ) ;
if ( ! window - > buffer ) {
free ( window ) ;
window = calloc ( 1 , sizeof * window ) ;
if ( ! window )
return NULL ;
}
window - > callback = NULL ;
window - > display = display ;
@ -155,12 +166,45 @@ destroy_window(struct window *window)
if ( window - > callback )
wl_callback_destroy ( window - > callback ) ;
wl_buffer_destroy ( window - > buffer ) ;
if ( window - > buffers [ 0 ] . buffer )
wl_buffer_destroy ( window - > buffers [ 0 ] . buffer ) ;
if ( window - > buffers [ 1 ] . buffer )
wl_buffer_destroy ( window - > buffers [ 1 ] . buffer ) ;
wl_shell_surface_destroy ( window - > shell_surface ) ;
wl_surface_destroy ( window - > surface ) ;
free ( window ) ;
}
static struct buffer *
window_next_buffer ( struct window * window )
{
struct buffer * buffer ;
int ret = 0 ;
if ( ! window - > buffers [ 0 ] . busy )
buffer = & window - > buffers [ 0 ] ;
else if ( ! window - > buffers [ 1 ] . busy )
buffer = & window - > buffers [ 1 ] ;
else
return NULL ;
if ( ! buffer - > buffer ) {
ret = create_shm_buffer ( window - > display , buffer ,
window - > width , window - > height ,
WL_SHM_FORMAT_XRGB8888 ) ;
if ( ret < 0 )
return NULL ;
/* paint the padding */
memset ( buffer - > shm_data , 0xff ,
window - > width * window - > height * 4 ) ;
}
return buffer ;
}
static void
paint_pixels ( void * image , int padding , int width , int height , uint32_t time )
{
@ -213,8 +257,23 @@ static void
redraw ( void * data , struct wl_callback * callback , uint32_t time )
{
struct window * window = data ;
struct buffer * buffer ;
buffer = window_next_buffer ( window ) ;
if ( ! buffer ) {
fprintf ( stderr ,
! callback ? " Failed to create the first buffer. \n " :
" Both buffers busy at redraw(). Server bug? \n " ) ;
abort ( ) ;
}
paint_pixels ( buffer - > shm_data , 20 , window - > width , window - > height , time ) ;
if ( window - > prev_buffer ! = buffer ) {
wl_surface_attach ( window - > surface , buffer - > buffer , 0 , 0 ) ;
window - > prev_buffer = buffer ;
}
paint_pixels ( window - > shm_data , 20 , window - > width , window - > height , time ) ;
wl_surface_damage ( window - > surface ,
20 , 20 , window - > width - 40 , window - > height - 40 ) ;
@ -224,6 +283,7 @@ redraw(void *data, struct wl_callback *callback, uint32_t time)
window - > callback = wl_surface_frame ( window - > surface ) ;
wl_callback_add_listener ( window - > callback , & frame_listener , window ) ;
wl_surface_commit ( window - > surface ) ;
buffer - > busy = 1 ;
}
static const struct wl_callback_listener frame_listener = {
@ -340,8 +400,9 @@ main(int argc, char **argv)
sigint . sa_flags = SA_RESETHAND ;
sigaction ( SIGINT , & sigint , NULL ) ;
memset ( window - > shm_data , 0xff , window - > width * window - > height * 4 ) ;
wl_surface_attach ( window - > surface , window - > buffer , 0 , 0 ) ;
/* Initialise damage to full surface, so the padding gets painted */
wl_surface_damage ( window - > surface , 0 , 0 ,
window - > width , window - > height ) ;
redraw ( window , NULL , 0 ) ;