tpl_object_t obj; /* for mutex lock */
tpl_list_t *committed_buffers;
tpl_list_t *in_use_buffers;
+ tpl_list_t *vblank_waiting_buffers; /* for FIFO/FIFO_RELAXED modes */
+ tbm_surface_h draw_done_buffer; /* for MAILBOX mode */
tdm_client_vblank *vblank;
tpl_bool_t vblank_done;
tpl_bool_t is_destroying;
buf_info->wl_buffer, tbm_surface,
tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
tbm_surface_internal_unref(tbm_surface);
- }
+ return;
+ }
} else {
TPL_ERR("Invalid parameter | tbm_surface(%p)", tbm_surface);
}
}
static void
+_twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source,
+ tbm_surface_h tbm_surface);
+static void
__cb_tdm_client_wait_vblank(tdm_client_vblank *vblank, tdm_error error,
unsigned int sequence, unsigned int tv_sec,
unsigned int tv_usec, void *user_data)
{
twe_wl_surf_source *surf_source = (twe_wl_surf_source *)user_data;
+ twe_wl_disp_source *disp_source = NULL;
if (!surf_source) {
TPL_ERR("Invalid parameter. user_data(%p)", user_data);
return;
}
+ disp_source = surf_source->disp_source;
+
surf_source->vblank_done = TPL_TRUE;
- _twe_thread_wl_surface_acquire_and_commit(surf_source);
+
+ if (!disp_source->is_vulkan_dpy)
+ _twe_thread_wl_surface_acquire_and_commit(surf_source);
+ else {
+ switch (surf_source->swapchain_properties.present_mode) {
+ case TPL_DISPLAY_PRESENT_MODE_MAILBOX:
+ if (surf_source->draw_done_buffer) {
+ _twe_thread_wl_vk_surface_commit(surf_source,
+ surf_source->draw_done_buffer);
+ surf_source->draw_done_buffer = NULL;
+ }
+ break;
+
+ case TPL_DISPLAY_PRESENT_MODE_FIFO:
+ case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED:
+ if (surf_source->vblank_waiting_buffers) {
+ tbm_surface_h tbm_surface = NULL;
+ tbm_surface = (tbm_surface_h)__tpl_list_pop_front(
+ surf_source->vblank_waiting_buffers,
+ NULL);
+ if (tbm_surface)
+ _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+ }
+ break;
+ }
+ }
}
static tdm_client_vblank*
_twe_surface_create_vblank(tdm_client *tdm_client);
+static tpl_result_t
+_twe_surface_wait_vblank(twe_wl_surf_source *surf_source)
+{
+ tdm_error tdm_err = TDM_ERROR_NONE;
+
+ if (!_twe_ctx->tdm_source) {
+ TPL_WARN("tdm_vblank feature is disabled.");
+ return TPL_ERROR_INVALID_OPERATION;
+ }
+
+ if (!surf_source->vblank) {
+ surf_source->vblank =
+ _twe_surface_create_vblank(_twe_ctx->tdm_source->tdm_client);
+ if (!surf_source->vblank) {
+ TPL_WARN("Failed to create vblank. surf_source(%p)",
+ surf_source);
+ return TPL_ERROR_OUT_OF_MEMORY;
+ }
+ }
+
+ tdm_err = tdm_client_vblank_wait(surf_source->vblank,
+ 1, /* TODO: interval */
+ __cb_tdm_client_wait_vblank,
+ (void *)surf_source);
+
+ if (tdm_err == TDM_ERROR_NONE)
+ surf_source->vblank_done = TPL_FALSE;
+ else {
+ TPL_ERR("Failed to tdm_client_vblank_wait. tdm_err(%d)", tdm_err);
+ return TPL_ERROR_INVALID_OPERATION;
+ }
+
+ return TPL_ERROR_NONE;
+}
+
+static void
+_twe_thread_wl_vk_surface_commit(twe_wl_surf_source *surf_source,
+ tbm_surface_h tbm_surface)
+{
+ twe_wl_buffer_info *buf_info = NULL;
+ struct wl_surface *wl_surface = surf_source->surf;
+
+ tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+ (void **)&buf_info);
+ if (!buf_info) {
+ TPL_ERR("Failed to get wl_buffer_info from tbm_surface(%p)",
+ tbm_surface);
+ return;
+ }
+
+ wl_surface_attach(wl_surface, (void *)buf_info->wl_buffer,
+ 0, 0);
+
+ wl_surface_damage(wl_surface, 0, 0,
+ surf_source->swapchain_properties.width,
+ surf_source->swapchain_properties.height);
+ wl_surface_commit(wl_surface);
+
+ if (surf_source->swapchain_properties.present_mode
+ == TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED) {
+ if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+ TPL_ERR("Failed to set wait vblank");
+ }
+}
+
static void
_twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
tbm_surface_h tbm_surface)
{
twe_wl_buffer_info *buf_info = NULL;
+ twe_wl_disp_source *disp_source = surf_source->disp_source;
struct wl_surface *wl_surface = surf_source->surf;
struct wl_egl_window *wl_egl_window = surf_source->wl_egl_window;
uint32_t version;
if (buf_info->w_rotated == TPL_TRUE) {
wayland_tbm_client_set_buffer_transform(
- surf_source->disp_source->wl_tbm_client,
+ disp_source->wl_tbm_client,
(void *)buf_info->wl_buffer,
buf_info->w_transform);
buf_info->w_rotated = TPL_FALSE;
buf_info->wl_buffer, tbm_surface,
tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
- if (_twe_ctx->tdm_source && !surf_source->vblank) {
- surf_source->vblank =
- _twe_surface_create_vblank(_twe_ctx->tdm_source->tdm_client);
- if (!surf_source->vblank) {
- TPL_WARN("Failed to create vblank. surf_source(%p)",
- surf_source);
- }
- }
+ if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+ TPL_ERR("Failed to set wait vblank.");
- if (_twe_ctx->tdm_source && surf_source->vblank) {
- tdm_error tdm_err = TDM_ERROR_NONE;
- tdm_err = tdm_client_vblank_wait(surf_source->vblank,
- 1, /* TODO: interval */
- __cb_tdm_client_wait_vblank,
- (void *)surf_source);
-
- if (tdm_err == TDM_ERROR_NONE)
- surf_source->vblank_done = TPL_FALSE;
- else
- TPL_ERR("Failed to tdm_client_vblank_wait. tdm_err(%d)", tdm_err);
- }
if (surf_source->committed_buffers) {
__tpl_list_push_back(surf_source->committed_buffers, tbm_surface);
static void
_twe_thread_wl_surface_acquire_and_commit(twe_wl_surf_source *surf_source)
{
+ twe_wl_disp_source *disp_source = surf_source->disp_source;
tbm_surface_h tbm_surface = NULL;
tbm_surface_queue_error_e tsq_err = TBM_SURFACE_QUEUE_ERROR_NONE;
twe_wl_buffer_info *buf_info = NULL;
return;
}
+ if (!disp_source->is_vulkan_dpy && !surf_source->vblank_done) {
+ TPL_LOG_T("WL_EGL", "[ACQ_skip] It will be acquired next vblank.");
+ TPL_OBJECT_UNLOCK(&surf_source->obj);
+ return;
+ }
+
if (tbm_surface_queue_can_acquire(surf_source->tbm_queue, 0)) {
- if (surf_source->vblank_done == TPL_TRUE) {
- tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface);
- if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
- TPL_ERR("Failed to acquire from tbm_queue(%p)",
- surf_source->tbm_queue);
- TPL_OBJECT_UNLOCK(&surf_source->obj);
- return;
- }
+ tsq_err = tbm_surface_queue_acquire(surf_source->tbm_queue, &tbm_surface);
+ if (!tbm_surface || tsq_err != TBM_SURFACE_QUEUE_ERROR_NONE) {
+ TPL_ERR("Failed to acquire from tbm_queue(%p)",
+ surf_source->tbm_queue);
+ TPL_OBJECT_UNLOCK(&surf_source->obj);
+ return;
+ }
- tbm_surface_internal_ref(tbm_surface);
+ tbm_surface_internal_ref(tbm_surface);
- tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
- (void **)&buf_info);
- if (buf_info && buf_info->fence_waiting_thread) {
- g_thread_join(buf_info->fence_waiting_thread);
- buf_info->fence_waiting_thread = NULL;
- }
+ tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
+ (void **)&buf_info);
+ if (buf_info && buf_info->fence_waiting_thread) {
+ g_thread_join(buf_info->fence_waiting_thread);
+ buf_info->fence_waiting_thread = NULL;
+ }
+ if (!disp_source->is_vulkan_dpy) { /* wayland_egl */
TPL_LOG_T("WL_EGL", "[ACQ] tbm_surface(%p) bo(%d)",
- tbm_surface,
- tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
+ tbm_surface,
+ tbm_bo_export(tbm_surface_internal_get_bo(tbm_surface, 0)));
_twe_thread_wl_surface_commit(surf_source, tbm_surface);
-
- } else {
- TPL_LOG_T("WL_EGL", "[ACQ_skip] It will be acquired next vblank.");
+ } else { /* wayland_vulkan */
+ switch (surf_source->swapchain_properties.present_mode) {
+ case TPL_DISPLAY_PRESENT_MODE_IMMEDIATE:
+ _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+ break;
+
+ case TPL_DISPLAY_PRESENT_MODE_MAILBOX:
+ if (surf_source->draw_done_buffer) {
+ tbm_surface_internal_unref(surf_source->draw_done_buffer);
+ tbm_surface_queue_release(surf_source->tbm_queue,
+ surf_source->draw_done_buffer);
+ }
+
+ surf_source->draw_done_buffer = tbm_surface;
+
+ if (surf_source->vblank_done) {
+ if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+ TPL_ERR("Failed to set wait vblank");
+ }
+ break;
+
+ case TPL_DISPLAY_PRESENT_MODE_FIFO:
+ if (surf_source->vblank_waiting_buffers) {
+ __tpl_list_push_back(surf_source->vblank_waiting_buffers,
+ (void *)tbm_surface);
+ if (_twe_surface_wait_vblank(surf_source) != TPL_ERROR_NONE)
+ TPL_ERR("Failed to set wait vblank");
+ } else {
+ TPL_ERR("Invalid list. vblank_waiting_buffers is NULL.");
+ }
+ break;
+
+ case TPL_DISPLAY_PRESENT_MODE_FIFO_RELAXED:
+ if (surf_source->vblank_done) {
+ _twe_thread_wl_vk_surface_commit(surf_source, tbm_surface);
+ } else {
+ if (surf_source->vblank_waiting_buffers) {
+ __tpl_list_push_back(surf_source->vblank_waiting_buffers,
+ (void *)tbm_surface);
+ } else {
+ TPL_ERR("Invalid list. vblank_waiting_buffers is NULL.");
+ }
+ }
+ break;
+ }
}
}
static gboolean
_twe_thread_wl_surface_dispatch(GSource *source, GSourceFunc cb, gpointer data)
{
- twe_wl_surf_source *wl_surf_source = (twe_wl_surf_source *)source;
+ twe_wl_surf_source *surf_source = (twe_wl_surf_source *)source;
+ twe_wl_disp_source *disp_source = surf_source->disp_source;
GIOCondition cond;
if (g_source_is_destroyed(source)) {
return G_SOURCE_REMOVE;
}
- cond = g_source_query_unix_fd(source, wl_surf_source->tag);
+ cond = g_source_query_unix_fd(source, surf_source->tag);
if (cond & G_IO_IN) {
ssize_t s;
uint64_t u;
- s = read(wl_surf_source->event_fd, &u, sizeof(uint64_t));
+ s = read(surf_source->event_fd, &u, sizeof(uint64_t));
if (s != sizeof(uint64_t))
TPL_ERR("Failed to read from event_fd(%d)",
- wl_surf_source->event_fd);
+ surf_source->event_fd);
- _twe_thread_wl_surface_acquire_and_commit(wl_surf_source);
+ if (!disp_source->is_vulkan_dpy)
+ _twe_thread_wl_surface_acquire_and_commit(surf_source);
}
return G_SOURCE_CONTINUE;
source->rotate_cb = NULL;
source->format = format;
+ /* for vulkan swapchain */
+ source->vblank_waiting_buffers = NULL;
+ source->draw_done_buffer = NULL;
+
__tpl_object_init(&source->obj, TPL_OBJECT_SURFACE, NULL);
if (!disp_source->is_vulkan_dpy) {