@ -101,6 +101,7 @@ struct window {
int num_buffers ;
int num_buffers ;
int next ;
int next ;
int refresh_nsec ;
int refresh_nsec ;
int commit_delay_msecs ;
struct wl_callback * callback ;
struct wl_callback * callback ;
struct wl_list feedback_list ;
struct wl_list feedback_list ;
@ -201,19 +202,21 @@ static const struct wl_shell_surface_listener shell_surface_listener = {
static struct window *
static struct window *
create_window ( struct display * display , int width , int height ,
create_window ( struct display * display , int width , int height ,
enum run_mode mode )
enum run_mode mode , int commit_delay_msecs )
{
{
struct window * window ;
struct window * window ;
char title [ 128 ] ;
char title [ 128 ] ;
int ret ;
int ret ;
snprintf ( title , sizeof ( title ) ,
snprintf ( title , sizeof ( title ) ,
" presentation-shm: %s " , run_mode_name [ mode ] ) ;
" presentation-shm: %s [Delay %i msecs] " , run_mode_name [ mode ] ,
commit_delay_msecs ) ;
window = calloc ( 1 , sizeof * window ) ;
window = calloc ( 1 , sizeof * window ) ;
if ( ! window )
if ( ! window )
return NULL ;
return NULL ;
window - > commit_delay_msecs = commit_delay_msecs ;
window - > mode = mode ;
window - > mode = mode ;
window - > callback = NULL ;
window - > callback = NULL ;
wl_list_init ( & window - > feedback_list ) ;
wl_list_init ( & window - > feedback_list ) ;
@ -468,6 +471,23 @@ static const struct presentation_feedback_listener feedback_listener = {
feedback_discarded
feedback_discarded
} ;
} ;
static void
window_emulate_rendering ( struct window * window )
{
struct timespec delay ;
int ret ;
if ( window - > commit_delay_msecs < = 0 )
return ;
delay . tv_sec = window - > commit_delay_msecs / 1000 ;
delay . tv_nsec = ( window - > commit_delay_msecs % 1000 ) * 1000000 ;
ret = nanosleep ( & delay , NULL ) ;
if ( ret )
printf ( " nanosleep failed: %m \n " ) ;
}
static void
static void
window_create_feedback ( struct window * window , uint32_t frame_stamp )
window_create_feedback ( struct window * window , uint32_t frame_stamp )
{
{
@ -490,6 +510,7 @@ window_create_feedback(struct window *window, uint32_t frame_stamp)
& feedback_listener , feedback ) ;
& feedback_listener , feedback ) ;
feedback - > frame_no = seq ;
feedback - > frame_no = seq ;
clock_gettime ( window - > display - > clk_id , & feedback - > commit ) ;
clock_gettime ( window - > display - > clk_id , & feedback - > commit ) ;
feedback - > frame_stamp = frame_stamp ;
feedback - > frame_stamp = frame_stamp ;
feedback - > target = feedback - > commit ;
feedback - > target = feedback - > commit ;
@ -524,6 +545,8 @@ redraw_mode_feedback(void *data, struct wl_callback *callback, uint32_t time)
if ( callback )
if ( callback )
wl_callback_destroy ( callback ) ;
wl_callback_destroy ( callback ) ;
window_emulate_rendering ( window ) ;
window - > callback = wl_surface_frame ( window - > surface ) ;
window - > callback = wl_surface_frame ( window - > surface ) ;
wl_callback_add_listener ( window - > callback ,
wl_callback_add_listener ( window - > callback ,
& frame_listener_mode_feedback , window ) ;
& frame_listener_mode_feedback , window ) ;
@ -566,6 +589,7 @@ feedkick_presented(void *data,
switch ( window - > mode ) {
switch ( window - > mode ) {
case RUN_MODE_PRESENT :
case RUN_MODE_PRESENT :
window_emulate_rendering ( window ) ;
window_create_feedback ( window , 0 ) ;
window_create_feedback ( window , 0 ) ;
window_feedkick ( window ) ;
window_feedkick ( window ) ;
window_commit_next ( window ) ;
window_commit_next ( window ) ;
@ -586,6 +610,7 @@ feedkick_discarded(void *data,
switch ( window - > mode ) {
switch ( window - > mode ) {
case RUN_MODE_PRESENT :
case RUN_MODE_PRESENT :
window_emulate_rendering ( window ) ;
window_create_feedback ( window , 0 ) ;
window_create_feedback ( window , 0 ) ;
window_feedkick ( window ) ;
window_feedkick ( window ) ;
window_commit_next ( window ) ;
window_commit_next ( window ) ;
@ -605,6 +630,8 @@ static const struct presentation_feedback_listener feedkick_listener = {
static void
static void
firstdraw_mode_burst ( struct window * window )
firstdraw_mode_burst ( struct window * window )
{
{
window_emulate_rendering ( window ) ;
switch ( window - > mode ) {
switch ( window - > mode ) {
case RUN_MODE_PRESENT :
case RUN_MODE_PRESENT :
window_create_feedback ( window , 0 ) ;
window_create_feedback ( window , 0 ) ;
@ -807,10 +834,12 @@ usage(const char *prog, int exit_code)
{
{
fprintf ( stderr , " Usage: %s [mode] [options] \n "
fprintf ( stderr , " Usage: %s [mode] [options] \n "
" where 'mode' is one of \n "
" where 'mode' is one of \n "
" -f \t run in feedback mode (default) \n "
" -f \t \t run in feedback mode (default) \n "
" -i \t run in feedback-idle mode; sleep 1s between frames \n "
" -i \t \t run in feedback-idle mode; sleep 1s between frames \n "
" -p \t run in low-latency presentation mode \n "
" -p \t \t run in low-latency presentation mode \n "
" and 'options' may include \n " ,
" and 'options' may include \n "
" -d msecs \t emulate the time used for rendering by a delay \n "
" \t \t of the given milliseconds before commit \n \n " ,
prog ) ;
prog ) ;
fprintf ( stderr , " Printed timing statistics, depending on mode: \n "
fprintf ( stderr , " Printed timing statistics, depending on mode: \n "
@ -835,6 +864,7 @@ main(int argc, char **argv)
int ret = 0 ;
int ret = 0 ;
enum run_mode mode = RUN_MODE_FEEDBACK ;
enum run_mode mode = RUN_MODE_FEEDBACK ;
int i ;
int i ;
int commit_delay_msecs = 0 ;
for ( i = 1 ; i < argc ; i + + ) {
for ( i = 1 ; i < argc ; i + + ) {
if ( strcmp ( " -f " , argv [ i ] ) = = 0 )
if ( strcmp ( " -f " , argv [ i ] ) = = 0 )
@ -843,12 +873,16 @@ main(int argc, char **argv)
mode = RUN_MODE_FEEDBACK_IDLE ;
mode = RUN_MODE_FEEDBACK_IDLE ;
else if ( strcmp ( " -p " , argv [ i ] ) = = 0 )
else if ( strcmp ( " -p " , argv [ i ] ) = = 0 )
mode = RUN_MODE_PRESENT ;
mode = RUN_MODE_PRESENT ;
else if ( ( strcmp ( " -d " , argv [ i ] ) = = 0 ) & & ( i + 1 < argc ) ) {
i + + ;
commit_delay_msecs = atoi ( argv [ i ] ) ;
}
else
else
usage ( argv [ 0 ] , EXIT_FAILURE ) ;
usage ( argv [ 0 ] , EXIT_FAILURE ) ;
}
}
display = create_display ( ) ;
display = create_display ( ) ;
window = create_window ( display , 250 , 250 , mode ) ;
window = create_window ( display , 250 , 250 , mode , commit_delay_msecs ) ;
if ( ! window )
if ( ! window )
return 1 ;
return 1 ;