diff --git a/gfx/drivers_context/vc_egl_ctx.c b/gfx/drivers_context/vc_egl_ctx.c index 0c1761b92a..c9b5647acd 100644 --- a/gfx/drivers_context/vc_egl_ctx.c +++ b/gfx/drivers_context/vc_egl_ctx.c @@ -24,6 +24,7 @@ #include #include +#include #ifdef HAVE_CONFIG_H #include "../../config.h" @@ -59,6 +60,12 @@ typedef struct egl_ctx_data_t egl; #endif EGL_DISPMANX_WINDOW_T native_window; + DISPMANX_DISPLAY_HANDLE_T dispman_display; + + /* For vsync wait after eglSwapBuffers when max_swapchain < 3 */ + scond_t *vsync_condition; + slock_t *vsync_condition_mutex; + bool vsync_callback_set; bool resize; unsigned fb_width, fb_height; @@ -134,6 +141,15 @@ static void gfx_ctx_vc_get_video_size(void *data, } } +static void dispmanx_vsync_callback(DISPMANX_UPDATE_HANDLE_T u, void *data) +{ + vc_ctx_data_t *vc = (vc_ctx_data_t*)data; + + slock_lock(vc->vsync_condition_mutex); + scond_signal(vc->vsync_condition); + slock_unlock(vc->vsync_condition_mutex); +} + static void gfx_ctx_vc_destroy(void *data); static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver) @@ -235,6 +251,7 @@ static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver) } dispman_display = vc_dispmanx_display_open(0 /* LCD */); + vc->dispman_display = dispman_display; vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo); dispman_update = vc_dispmanx_update_start(0); @@ -281,6 +298,16 @@ static void *gfx_ctx_vc_init(video_frame_info_t *video_info, void *video_driver) goto error; #endif + /* For vsync after eglSwapBuffers when max_swapchain < 3 */ + vc->vsync_condition = scond_new(); + vc->vsync_condition_mutex = slock_new(); + vc->vsync_callback_set = false; + if (video_info->max_swapchain_images <= 2) { + /* Start sending vsync callbacks so we can wait for vsync after eglSwapBuffers */ + vc_dispmanx_vsync_callback(vc->dispman_display, dispmanx_vsync_callback, (void*)vc); + vc->vsync_callback_set = true; + } + return vc; error: @@ -291,7 +318,6 @@ error: static void gfx_ctx_vc_set_swap_interval(void *data, unsigned swap_interval) { vc_ctx_data_t *vc = (vc_ctx_data_t*)data; - #ifdef HAVE_EGL egl_set_swap_interval(&vc->egl, swap_interval); #endif @@ -305,18 +331,18 @@ static bool gfx_ctx_vc_set_video_mode(void *data, vc_ctx_data_t *vc = (vc_ctx_data_t*)data; #ifdef HAVE_EGL + if (g_egl_inited) return false; frontend_driver_install_signal_handler(); - gfx_ctx_vc_set_swap_interval(&vc->egl, vc->egl.interval); /* If we set this env variable, Broadcom's EGL implementation will block * on vsync with a double buffer when we call eglSwapBuffers. Less input lag! */ - if (video_info->max_swapchain_images <= 2) + /*if (video_info->max_swapchain_images <= 2) setenv("V3D_DOUBLE_BUFFER", "1", 1); else - setenv("V3D_DOUBLE_BUFFER", "0", 1); + setenv("V3D_DOUBLE_BUFFER", "0", 1);*/ gfx_ctx_vc_set_swap_interval(&vc->egl, vc->egl.interval); @@ -436,6 +462,10 @@ static void gfx_ctx_vc_destroy(void *data) vc->eglBuffer[i] = NULL; vc->vgimage[i] = 0; } + + /* Destroy mutexes and conditions. */ + slock_free(vc->vsync_condition_mutex); + scond_free(vc->vsync_condition); } static void gfx_ctx_vc_input_driver(void *data, @@ -593,9 +623,26 @@ error: static void gfx_ctx_vc_swap_buffers(void *data, void *data2) { vc_ctx_data_t *vc = (vc_ctx_data_t*)data; + video_frame_info_t *video_info = (video_frame_info_t*)data2; #ifdef HAVE_EGL egl_swap_buffers(&vc->egl); + + /* Wait for vsync immediately if we don't wait egl_swap_buffers to triple-buffer */ + if (video_info->max_swapchain_images <= 2) { + /* We DON'T wait to wait without callback function ready! */ + if(!vc->vsync_callback_set) { + vc_dispmanx_vsync_callback(vc->dispman_display, dispmanx_vsync_callback, (void*)vc); + vc->vsync_callback_set = true; + } + slock_lock(vc->vsync_condition_mutex); + scond_wait(vc->vsync_condition, vc->vsync_condition_mutex); + slock_unlock(vc->vsync_condition_mutex); + } + else if (vc->vsync_callback_set) { + /* Stop generating vsync callbacks from now on */ + vc_dispmanx_vsync_callback(vc->dispman_display, NULL, NULL); + } #endif }