#include <glib-unix.h>
#include <tizen-surface-client-protocol.h>
#include <wayland-egl-backend.h>
+#include <presentation-time-client-protocol.h>
#include "tpl_utils.h"
#include "tpl_internal.h"
struct wl_event_queue *ev_queue;
struct wayland_tbm_client *wl_tbm_client;
struct tizen_surface_shm *tss; /* used for surface buffer_flush */
+ struct wp_presentation *presentation;
struct {
int min_buffer;
int max_buffer;
int render_sync_timestamp;
unsigned int render_sync_fence_number;
+ tbm_fd presentation_sync_timeline;
+ int presentation_sync_timestamp;
+ int presentation_sync_ts_backup;
+ int presentation_sync_req_cnt;
+ GMutex pst_mutex;
+
GMutex surf_mutex;
GMutex free_queue_mutex;
&wayland_vulkan_interface,
version);
}
+
+ if (!strcmp(interface, wp_presentation_interface.name)) {
+ disp_source->presentation =
+ wl_registry_bind(wl_registry,
+ name, &wp_presentation_interface, 1);
+ TPL_DEBUG("bind wp_presentation_interface");
+ }
}
void
TPL_LOG_T(BACKEND, "wl_vk_client(%p) init.", disp_source->wl_vk_client);
}
+ if (disp_source->presentation) {
+ wl_proxy_set_queue((struct wl_proxy *)disp_source->presentation,
+ disp_source->ev_queue);
+ TPL_LOG_T(BACKEND, "wp_presentation(%p) init.", disp_source->presentation);
+ }
+
fini:
if (display_wrapper)
wl_proxy_wrapper_destroy(display_wrapper);
return -1;
}
+static int
+__cb_create_presentation_sync_fd(struct wl_egl_window *wl_egl_window, void *private)
+{
+ TPL_ASSERT(private);
+ TPL_ASSERT(wl_egl_window);
+
+ struct tizen_private *tizen_private = (struct tizen_private *)private;
+ twe_wl_surf_source *surf_source = NULL;
+
+ tbm_fd presentation_sync_fd = -1;
+
+ surf_source = (twe_wl_surf_source *)tizen_private->data;
+ if (!surf_source) {
+ TPL_ERR("Invalid parameter. twe_surface(%p)", surf_source);
+ return -1;
+ }
+
+ if (surf_source->presentation_sync_timeline != -1) {
+ g_mutex_lock(&surf_source->pst_mutex);
+
+ presentation_sync_fd = tbm_sync_fence_create(surf_source->presentation_sync_timeline,
+ NULL,
+ surf_source->presentation_sync_timestamp++);
+ TPL_DEBUG("[PRESENTATION_SYNC] surf_source(%p) timeline(%d) timestamp(%d) sync_fence(%d)",
+ surf_source, surf_source->presentation_sync_timeline, surf_source->presentation_sync_timestamp,
+ presentation_sync_fd);
+
+ TRACE_ASYNC_BEGIN(surf_source->presentation_sync_timestamp, "[PRESENTATION]");
+
+ surf_source->presentation_sync_req_cnt++;
+
+ g_mutex_unlock(&surf_source->pst_mutex);
+ return presentation_sync_fd;
+ }
+
+ return -1;
+}
+
static void __cb_tss_flusher_flush_callback(void *data,
struct tizen_surface_shm_flusher *tss_flusher)
}
static void
+__cb_presentation_feedback_sync_output(void *data,
+ struct wp_presentation_feedback *presentation_feedback,
+ struct wl_output *output)
+{
+ TPL_IGNORE(data);
+ TPL_IGNORE(presentation_feedback);
+ TPL_IGNORE(output);
+}
+
+static void
+__cb_presentation_feedback_presented(void *data,
+ struct wp_presentation_feedback *presentation_feedback,
+ uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec,
+ uint32_t refresh_nsec,
+ uint32_t seq_hi,
+ uint32_t seq_lo,
+ uint32_t flags)
+{
+ TPL_IGNORE(tv_sec_hi);
+ TPL_IGNORE(tv_sec_lo);
+ TPL_IGNORE(tv_nsec);
+ TPL_IGNORE(refresh_nsec);
+ TPL_IGNORE(seq_hi);
+ TPL_IGNORE(seq_lo);
+ TPL_IGNORE(flags);
+
+ twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data;
+
+ g_mutex_lock(&surf_source->pst_mutex);
+
+ TPL_DEBUG("[FEEDBACK][PRESENTED] surf_source(%p) wl_surface(%p)",
+ surf_source, surf_source->surf);
+
+ if (surf_source->presentation_sync_timeline != -1 &&
+ surf_source->presentation_sync_req_cnt > 0) {
+
+ surf_source->presentation_sync_ts_backup++;
+ surf_source->presentation_sync_req_cnt--;
+
+ TRACE_ASYNC_END(surf_source->presentation_sync_ts_backup, "[PRESENTATION]");
+
+ TPL_DEBUG("[PRESENTATION][INC] surf_source(%p) timeline(%d) timestamp(%d)",
+ surf_source, surf_source->presentation_sync_timeline,
+ surf_source->presentation_sync_ts_backup);
+ if (!tbm_sync_timeline_inc(surf_source->presentation_sync_timeline, 1)) {
+ TPL_ERR("Failed to increase timeline(%d)",
+ surf_source->presentation_sync_timeline);
+ }
+ }
+
+ if (presentation_feedback)
+ wp_presentation_feedback_destroy(presentation_feedback);
+
+ g_mutex_unlock(&surf_source->pst_mutex);
+}
+
+static void
+__cb_presentation_feedback_discarded(void *data,
+ struct wp_presentation_feedback *presentation_feedback)
+{
+ twe_wl_surf_source *surf_source = (twe_wl_surf_source *)data;
+
+ g_mutex_lock(&surf_source->pst_mutex);
+
+ TPL_DEBUG("[FEEDBACK][DISCARDED] surf_source(%p) wl_surface(%p)",
+ surf_source, surf_source->surf);
+
+ if (surf_source->presentation_sync_timeline != -1 &&
+ surf_source->presentation_sync_req_cnt > 0) {
+
+ surf_source->presentation_sync_ts_backup++;
+ surf_source->presentation_sync_req_cnt--;
+
+ TRACE_ASYNC_END(surf_source->presentation_sync_ts_backup, "[PRESENTATION]");
+
+ TPL_DEBUG("[PRESENTATION][INC] surf_source(%p) timeline(%d) timestamp(%d)",
+ surf_source, surf_source->presentation_sync_timeline,
+ surf_source->presentation_sync_ts_backup);
+ if (!tbm_sync_timeline_inc(surf_source->presentation_sync_timeline, 1)) {
+ TPL_ERR("Failed to increase timeline(%d)",
+ surf_source->presentation_sync_timeline);
+ }
+ }
+
+ if (presentation_feedback)
+ wp_presentation_feedback_destroy(presentation_feedback);
+
+ g_mutex_unlock(&surf_source->pst_mutex);
+}
+
+static const struct wp_presentation_feedback_listener feedback_listener = {
+ __cb_presentation_feedback_sync_output, /* sync_output feedback -*/
+ __cb_presentation_feedback_presented,
+ __cb_presentation_feedback_discarded
+};
+
+static void
_twe_thread_wl_surface_commit(twe_wl_surf_source *surf_source,
tbm_surface_h tbm_surface)
{
struct wl_surface *wl_surface = surf_source->surf;
struct wl_egl_window *wl_egl_window = surf_source->wl_egl_window;
uint32_t version;
+ struct wp_presentation_feedback *p_feedback;
tbm_surface_internal_get_user_data(tbm_surface, KEY_BUFFER_INFO,
(void **)&buf_info);
version = wl_proxy_get_version((struct wl_proxy *)wl_surface);
+ g_mutex_lock(&surf_source->pst_mutex);
+ if (disp_source->presentation &&
+ surf_source->presentation_sync_req_cnt > 0) {
+ p_feedback = wp_presentation_feedback(disp_source->presentation,
+ wl_surface);
+ wp_presentation_feedback_add_listener(p_feedback, &feedback_listener, surf_source);
+ }
+ g_mutex_unlock(&surf_source->pst_mutex);
+
if (buf_info->w_rotated == TPL_TRUE) {
wayland_tbm_client_set_buffer_transform(
disp_source->wl_tbm_client,
source->render_sync_timestamp = 0;
source->render_sync_fence_number = 0;
+ source->presentation_sync_timeline = tbm_sync_timeline_create();
+ source->presentation_sync_timestamp = 0;
+ source->presentation_sync_ts_backup = 0;
+ source->presentation_sync_req_cnt = 0;
+
if (!disp_source->is_vulkan_dpy) {
struct wl_egl_window *wl_egl_window =
(struct wl_egl_window *)native_handle;
private->set_window_serial_callback = (void *)
__cb_set_window_serial_callback;
private->create_render_sync_fd = (void *)__cb_create_render_sync_fd;
+ private->create_presentation_sync_fd = (void *)__cb_create_presentation_sync_fd;
source->latest_transform = private->transform;
g_source_attach(&source->gsource, g_main_loop_get_context(ctx->twe_loop));
g_mutex_init(&source->surf_mutex);
+ g_mutex_init(&source->pst_mutex);
g_mutex_init(&source->free_queue_mutex);
g_cond_init(&source->free_queue_cond);