AC_SUBST(SHM_OPEN_LIBS)
if test "x${e_cv_want_wayland_only}" != "xno" || test "x${e_cv_want_wayland_clients}" != "xno";then
- PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server],
+ PKG_CHECK_MODULES([WAYLAND], [wayland-server >= 1.8.0 xkbcommon uuid xdg-shell-unstable-v5-server xdg-shell-unstable-v6-server tizen-remote-surface-server scaler-server screenshooter-server tizen-extension-server tizen-launch-server tizen-surface-server tizen-dpms-server eom-server presentation-time-server tizen-hwc-server linux-explicit-synchronization-unstable-v1-server],
[
have_wayland=yes
AC_DEFINE_UNQUOTED([HAVE_WAYLAND],[1],[enable wayland support])
BuildRequires: pkgconfig(libinput)
BuildRequires: pkgconfig(presentation-time-server)
BuildRequires: pkgconfig(egl)
+BuildRequires: pkgconfig(linux-explicit-synchronization-unstable-v1-server)
BuildRequires: pkgconfig(tizen-hwc-server)
Requires: libwayland-extension-server
src/bin/e_hwc_windows.h \
src/bin/e_hwc_window.h \
src/bin/e_hwc_window_queue.h \
+src/bin/e_explicit_sync.h \
src/bin/e_egl_sync.h \
src/bin/e_info_server_input.h
src/bin/e_hwc_windows.c \
src/bin/e_hwc_window.c \
src/bin/e_hwc_window_queue.c \
+src/bin/e_explicit_sync.c \
src/bin/e_egl_sync.c \
src/bin/e_info_server_input.c \
$(ENLIGHTENMENTHEADERS)
Eina_Bool skip_save_img: 1; // indicates that window doesn't want to save its image file
E_Hwc_Window *hwc_window; // hwc window for the tdm_hwc.
+ E_Explicit_Sync_Surface *explicit_sync_surface;
int comp_override;
struct
e_output_del(output);
}
+ e_explicit_sync_deinit();
e_egl_sync_deinit();
e_hwc_deinit();
e_hwc_windows_deinit();
ELOGF("E_EGL_SYNC", "Enabled the E_Egl_Sync", NULL);
e_main_ts_end("\tE_Egl_Sync Init Done");
+ e_main_ts_begin("\tE_Explicit_Sync Init");
+ if (e_explicit_sync_init())
+ ELOGF("EX-SYNC", "Enabled the E_Explicit_Sync", NULL);
+ e_main_ts_end("\tE_Explicit_Sync Init Done");
+
/* pointer */
e_input_device_pointer_xy_get(NULL, &ptr_x, &ptr_y);
e_comp_wl->ptr.x = wl_fixed_from_int(ptr_x);
e_pixmap_image_clear(ec->pixmap, 1);
}
+ if (ec->explicit_sync_surface)
+ e_explicit_sync_surface_commit(ec->explicit_sync_surface);
+
ignored = ec->ignored;
if (e_comp_wl_subsurface_order_commit(ec))
ref->buffer->busy--;
if (ref->buffer->busy == 0)
{
+ if (ref->buffer->buffer_release)
+ {
+ e_explicit_sync_buffer_release_destroy(ref->buffer->buffer_release);
+ ref->buffer->buffer_release = NULL;
+ }
+
if (ref->buffer->resource)
{
if (!wl_resource_get_client(ref->buffer->resource)) return;
int32_t w, h;
int transform; // the value of wl_tbm.set_buffer_transform
uint32_t busy;
+
+ E_Explicit_Sync_Buffer_Release *buffer_release;
};
struct _E_Comp_Wl_Buffer_Ref
--- /dev/null
+#include "e.h"
+#include <linux-explicit-synchronization-unstable-v1-server-protocol.h>
+#include <tizen-extension-server-protocol.h>
+
+#define EX_SYNC_TRACE(f, ec, x... ) \
+ do \
+ { \
+ if (ex_sync_trace) \
+ { \
+ if (ec) \
+ { \
+ INF("EWL|%20.20s|w:0x%08zx|ec:%8p|"f, \
+ "EX-SYNC", \
+ (e_client_util_win_get(ec)), \
+ (ec), \
+ ##x); \
+ } \
+ else \
+ { \
+ INF("EWL|%20.20s| | |"f,\
+ "EX-SYNC",##x); \
+ } \
+ } \
+ } \
+ while (0)
+
+static E_Explicit_Sync *_explicit_sync = NULL;
+static Eina_Bool _explicit_sync_enabled = EINA_FALSE;
+static Eina_Bool ex_sync_trace = EINA_FALSE;
+
+static E_Comp_Wl_Buffer *
+_e_explicit_sync_comp_wl_buffer_get(E_Client *ec)
+{
+ E_Comp_Client_Data *cdata;
+
+ if (!ec) return NULL;
+
+ cdata = ec->comp_data;
+ if (!cdata) return NULL;
+
+ return cdata->buffer_ref.buffer;
+}
+
+static Eina_Bool
+_e_explicit_sync_fd_is_valid(int fd)
+{
+ /* need sync file check */
+ return EINA_TRUE;
+}
+
+static void
+_e_explicit_sync_fd_set(int *fd, int new_fd)
+{
+ if (*fd == new_fd) return;
+
+ if (*fd >= 0) close(*fd);
+ *fd = new_fd;
+}
+
+static void
+_e_explicit_sync_fd_clear(int* fd)
+{
+ _e_explicit_sync_fd_set(fd, -1);
+}
+
+static void
+_e_explicit_sync_fd_move(int *dst, int *src)
+{
+ if (dst == src) return;
+
+ _e_explicit_sync_fd_set(dst, *src);
+ *src = -1;
+}
+
+static void
+_e_explicit_sync_surface_cb_destroy(struct wl_client *client,
+ struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static void
+_e_explicit_sync_surface_cb_set_acquire_fence(struct wl_client *client,
+ struct wl_resource *resource,
+ int32_t fd)
+{
+ E_Explicit_Sync_Surface *explicit_sync_surface;
+
+ explicit_sync_surface = wl_resource_get_user_data(resource);
+ if (!explicit_sync_surface)
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE,
+ "surface no longer exists");
+ goto fail;
+ }
+
+ if (!_e_explicit_sync_fd_is_valid(fd))
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_INVALID_FENCE,
+ "invalid acquire fence fd");
+ goto fail;
+ }
+
+ if (explicit_sync_surface->pending_acquire_fence_fd != -1)
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_DUPLICATE_FENCE,
+ "exist acquire fence fd");
+ goto fail;
+ }
+
+ _e_explicit_sync_fd_set(&explicit_sync_surface->pending_acquire_fence_fd, fd);
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Set Acquire fence fd:%d",
+ explicit_sync_surface->ec, explicit_sync_surface, fd);
+
+ return;
+
+fail:
+ close(fd);
+}
+
+static void
+_e_explicit_sync_buffer_release_cb_resource_destroy(struct wl_resource *resource)
+{
+ E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release;
+
+ explicit_sync_buffer_release = wl_resource_get_user_data(resource);
+ if (!explicit_sync_buffer_release) return;
+
+ EX_SYNC_TRACE("Explicit_Sync Buffer_Release:%p Destroy", NULL, explicit_sync_buffer_release);
+
+ if (explicit_sync_buffer_release->fence_fd != -1)
+ _e_explicit_sync_fd_clear(&explicit_sync_buffer_release->fence_fd);
+
+ E_FREE(explicit_sync_buffer_release);
+}
+
+EINTERN void
+e_explicit_sync_buffer_release_destroy(E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release)
+{
+ EINA_SAFETY_ON_NULL_RETURN(explicit_sync_buffer_release);
+ EINA_SAFETY_ON_NULL_RETURN(explicit_sync_buffer_release->resource);
+
+ if (explicit_sync_buffer_release->fence_fd != -1)
+ {
+ zwp_linux_buffer_release_v1_send_fenced_release(explicit_sync_buffer_release->resource,
+ explicit_sync_buffer_release->fence_fd);
+
+ EX_SYNC_TRACE("Explicit_Sync Buffer_Release:%p Release fence:%d",
+ NULL, explicit_sync_buffer_release, explicit_sync_buffer_release->fence_fd);
+ }
+ else
+ {
+ zwp_linux_buffer_release_v1_send_immediate_release(explicit_sync_buffer_release->resource);
+
+ EX_SYNC_TRACE("Explicit_Sync Buffer_Release:%p Immediate Release", NULL, explicit_sync_buffer_release);
+ }
+
+ wl_resource_destroy(explicit_sync_buffer_release->resource);
+}
+
+EINTERN Eina_Bool
+e_explicit_sync_buffer_release_fence_fd_set(E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release,
+ int fence_fd)
+{
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync_buffer_release, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync_buffer_release->resource, EINA_FALSE);
+
+ if (explicit_sync_buffer_release->fence_fd != -1)
+ _e_explicit_sync_fd_clear(&explicit_sync_buffer_release->fence_fd);
+
+ explicit_sync_buffer_release->fence_fd = fence_fd;
+
+ EX_SYNC_TRACE("Explicit_Sync Buffer_Release:%p Set fence:%d",
+ NULL, explicit_sync_buffer_release, explicit_sync_buffer_release->fence_fd);
+
+ return EINA_TRUE;
+}
+
+static void
+_e_explicit_sync_surface_cb_get_release(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id)
+{
+ E_Explicit_Sync_Surface *explicit_sync_surface = NULL;
+ E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release = NULL;
+
+ explicit_sync_surface = wl_resource_get_user_data(resource);
+ if ((!explicit_sync_surface) ||
+ (!explicit_sync_surface->ec) ||
+ (e_object_is_del(E_OBJECT(explicit_sync_surface->ec))))
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_SURFACE,
+ "explicit_sync_surface is already destroyed");
+ goto fail;
+ }
+
+ if (explicit_sync_surface->pending_buffer_release)
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_DUPLICATE_RELEASE,
+ "already has a buffer release");
+ goto fail;
+ }
+
+ explicit_sync_buffer_release = E_NEW(E_Explicit_Sync_Buffer_Release, 1);
+ if (!explicit_sync_buffer_release)
+ {
+ wl_client_post_no_memory(client);
+ goto fail;
+ }
+
+ explicit_sync_buffer_release->fence_fd = -1;
+ explicit_sync_buffer_release->resource = wl_resource_create(client,
+ &zwp_linux_buffer_release_v1_interface,
+ wl_resource_get_version(resource),
+ id);
+ if (!explicit_sync_buffer_release->resource)
+ {
+ wl_client_post_no_memory(client);
+ goto fail;
+ }
+
+ wl_resource_set_implementation(explicit_sync_buffer_release->resource,
+ NULL,
+ explicit_sync_buffer_release,
+ _e_explicit_sync_buffer_release_cb_resource_destroy);
+
+ explicit_sync_surface->pending_buffer_release = explicit_sync_buffer_release;
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Buffer_Release:%p Create",
+ explicit_sync_surface->ec, explicit_sync_surface, explicit_sync_buffer_release);
+
+ return;
+
+fail:
+ if (explicit_sync_buffer_release)
+ E_FREE(explicit_sync_buffer_release);
+}
+
+static const struct zwp_linux_surface_synchronization_v1_interface _e_explicit_sync_surface_implementation = {
+ _e_explicit_sync_surface_cb_destroy,
+ _e_explicit_sync_surface_cb_set_acquire_fence,
+ _e_explicit_sync_surface_cb_get_release
+};
+
+static void
+_e_explicit_sync_surface_cb_ec_free(void *data, void *obj)
+{
+ E_Client *ec = (E_Client *)obj;
+
+ EINA_SAFETY_ON_NULL_RETURN(ec);
+
+ if (!ec->explicit_sync_surface) return;
+
+ ec->explicit_sync_surface->ec_delfn = NULL;
+ ec->explicit_sync_surface->ec = NULL;
+}
+
+static void
+_e_explicit_sync_surface_cb_resource_destroy(struct wl_resource *resource)
+{
+ E_Explicit_Sync_Surface *explicit_sync_surface;
+
+ explicit_sync_surface = wl_resource_get_user_data(resource);
+ if (!explicit_sync_surface) return;
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Destroy", explicit_sync_surface->ec, explicit_sync_surface);
+
+ if (explicit_sync_surface->pending_acquire_fence_fd != -1)
+ _e_explicit_sync_fd_clear(&explicit_sync_surface->pending_acquire_fence_fd);
+
+ if (explicit_sync_surface->acquire_fence_fd != -1)
+ _e_explicit_sync_fd_clear(&explicit_sync_surface->acquire_fence_fd);
+
+ if (explicit_sync_surface->ec)
+ {
+ e_object_delfn_del(E_OBJECT(explicit_sync_surface->ec), explicit_sync_surface->ec_delfn);
+ explicit_sync_surface->ec_delfn = NULL;
+ explicit_sync_surface->ec = NULL;
+ }
+
+ E_FREE(explicit_sync_surface);
+}
+
+static void _e_explicit_sync_cb_get_synchronization(struct wl_client *client,
+ struct wl_resource *resource,
+ uint32_t id,
+ struct wl_resource *surface)
+{
+ E_Client *ec;
+ E_Explicit_Sync_Surface *explicit_sync_surface = NULL;
+
+ ec = wl_resource_get_user_data(surface);
+ if ((!ec) || (e_object_is_del(E_OBJECT(ec))))
+ {
+ wl_resource_post_error(resource, WL_DISPLAY_ERROR_INVALID_OBJECT,
+ "invalid wl_surface resource:%u",
+ (unsigned int)wl_resource_get_id(surface));
+ goto fail;
+ }
+
+ if (ec->explicit_sync_surface)
+ {
+ wl_resource_post_error(resource,
+ ZWP_LINUX_EXPLICIT_SYNCHRONIZATION_V1_ERROR_SYNCHRONIZATION_EXISTS,
+ "wl_surface resource:%u already has synchronization",
+ (unsigned int)wl_resource_get_id(surface));
+ goto fail;
+ }
+
+ explicit_sync_surface = E_NEW(E_Explicit_Sync_Surface, 1);
+ if (!explicit_sync_surface)
+ {
+ wl_client_post_no_memory(client);
+ goto fail;
+ }
+
+ explicit_sync_surface->acquire_fence_fd = -1;
+ explicit_sync_surface->pending_acquire_fence_fd = -1;
+
+ explicit_sync_surface->resource = wl_resource_create(client,
+ &zwp_linux_surface_synchronization_v1_interface,
+ wl_resource_get_version(resource),
+ id);
+ if (!explicit_sync_surface->resource)
+ {
+ wl_client_post_no_memory(client);
+ goto fail;
+ }
+
+ wl_resource_set_implementation(explicit_sync_surface->resource,
+ &_e_explicit_sync_surface_implementation,
+ explicit_sync_surface,
+ _e_explicit_sync_surface_cb_resource_destroy);
+
+ ec->explicit_sync_surface = explicit_sync_surface;
+ explicit_sync_surface->ec = ec;
+ explicit_sync_surface->ec_delfn = e_object_delfn_add(E_OBJECT(ec),
+ _e_explicit_sync_surface_cb_ec_free,
+ NULL);
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Create", explicit_sync_surface->ec, explicit_sync_surface);
+
+ return;
+
+fail:
+ if (explicit_sync_surface)
+ E_FREE(explicit_sync_surface);
+}
+
+static void
+_e_explicit_sync_cb_destroy(struct wl_client *client, struct wl_resource *resource)
+{
+ wl_resource_destroy(resource);
+}
+
+static const struct zwp_linux_explicit_synchronization_v1_interface e_explicit_sync_implementation = {
+ _e_explicit_sync_cb_destroy,
+ _e_explicit_sync_cb_get_synchronization
+};
+
+static void
+_explicit_sync_cb_bind(struct wl_client *client, void *data, uint32_t version, uint32_t id)
+{
+ struct wl_resource *resource;
+ E_Explicit_Sync *explicit_sync;
+
+ explicit_sync = _explicit_sync;
+
+ resource = wl_resource_create(client, &zwp_linux_explicit_synchronization_v1_interface, version, id);
+ if (!resource)
+ {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &e_explicit_sync_implementation,
+ explicit_sync, NULL);
+}
+
+EINTERN Eina_Bool
+e_explicit_sync_surface_commit(E_Explicit_Sync_Surface *explicit_sync_surface)
+{
+ E_Client *ec;
+ E_Comp_Wl_Buffer *buffer;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync_surface, EINA_FALSE);
+
+ ec = explicit_sync_surface->ec;
+ if ((!ec) || e_object_is_del(E_OBJECT(ec)))
+ {
+ ERR("invalid ec");
+ return EINA_FALSE;
+ }
+
+ if (explicit_sync_surface->pending_acquire_fence_fd != -1)
+ {
+ if (explicit_sync_surface->acquire_fence_fd != -1)
+ _e_explicit_sync_fd_clear(&explicit_sync_surface->acquire_fence_fd);
+
+ _e_explicit_sync_fd_move(&explicit_sync_surface->acquire_fence_fd,
+ &explicit_sync_surface->pending_acquire_fence_fd);
+ }
+
+ if (explicit_sync_surface->pending_buffer_release)
+ {
+ buffer = _e_explicit_sync_comp_wl_buffer_get(ec);
+ if (buffer)
+ {
+ buffer->buffer_release = explicit_sync_surface->pending_buffer_release;
+ explicit_sync_surface->pending_buffer_release = NULL;
+ }
+ else
+ {
+ /* send error? */
+ // wl_resource_post_error(explicit_sync_surface->resource,
+ // ZWP_LINUX_SURFACE_SYNCHRONIZATION_V1_ERROR_NO_BUFFER,
+ // "no buffer for synchronization");
+ }
+ }
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Commit", explicit_sync_surface->ec, explicit_sync_surface);
+
+ return EINA_TRUE;
+}
+
+EINTERN Eina_Bool
+e_explicit_sync_surface_sync(E_Explicit_Sync_Surface *explicit_sync_surface)
+{
+ E_Explicit_Sync *explicit_sync;
+ E_Egl_Sync *egl_sync;
+
+ explicit_sync = _explicit_sync;
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync, EINA_FALSE);
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync_surface, EINA_FALSE);
+
+ if (explicit_sync_surface->acquire_fence_fd == -1)
+ return EINA_TRUE;
+
+ egl_sync = e_egl_sync_fence_create_with_fd(explicit_sync_surface->acquire_fence_fd);
+ EINA_SAFETY_ON_NULL_GOTO(egl_sync, fail);
+
+ if (!e_egl_sync_wait(egl_sync))
+ {
+ ERR("Failed to wait on E_Egl_Sync");
+ goto fail;
+ }
+
+ e_egl_sync_destroy(egl_sync);
+
+ EX_SYNC_TRACE("Explicit_Sync Surface:%p Sync", explicit_sync_surface->ec, explicit_sync_surface);
+
+ return EINA_TRUE;
+
+fail:
+ if (egl_sync)
+ e_egl_sync_destroy(egl_sync);
+
+ return EINA_FALSE;
+}
+
+EINTERN Eina_Bool
+e_explicit_sync_init(void)
+{
+ E_Explicit_Sync *explicit_sync;
+ tdm_hwc *thwc;
+ E_Output *output;
+ Eina_List *l;
+
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_wl->wl.disp, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, EINA_FALSE);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, EINA_FALSE);
+
+ if (_explicit_sync) return EINA_TRUE;
+ if (!e_comp_gl_get()) return EINA_FALSE;
+ if (!e_egl_sync_enabled_get()) return EINA_FALSE;
+
+ EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
+ {
+ if (!output)
+ continue;
+ if (!output->hwc)
+ return EINA_FALSE;
+ if (output->hwc->hwc_policy != E_HWC_POLICY_WINDOWS)
+ return EINA_FALSE;
+ if (!hwc->tdm_hwc_fence)
+ return EINA_FALSE;
+ }
+
+ explicit_sync = E_NEW(E_Explicit_Sync, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(explicit_sync, EINA_FALSE);
+
+ explicit_sync->global = wl_global_create(e_comp_wl->wl.disp,
+ &zwp_linux_explicit_synchronization_v1_interface,
+ 2,
+ explicit_sync,
+ _explicit_sync_cb_bind);
+ EINA_SAFETY_ON_NULL_GOTO(explicit_sync->global, fail);
+
+ _explicit_sync = explicit_sync;
+ _explicit_sync_enabled = EINA_TRUE;
+
+ return EINA_TRUE;
+
+fail:
+ if (explicit_sync)
+ {
+ if (explicit_sync->global)
+ wl_global_destroy(explicit_sync->global);
+
+ E_FREE(explicit_sync);
+ }
+
+ return EINA_FALSE;
+}
+
+EINTERN void
+e_explicit_sync_deinit(void)
+{
+ E_Explicit_Sync *explicit_sync;
+
+ explicit_sync = _explicit_sync;
+ if (!explicit_sync) return;
+
+ wl_global_destroy(explicit_sync->global);
+ E_FREE(explicit_sync);
+
+ _explicit_sync = NULL;
+}
+
+EINTERN void
+e_explicit_sync_trace_debug(Eina_Bool onoff)
+{
+ if (onoff == ex_sync_trace) return;
+ ex_sync_trace = onoff;
+ INF("Explicit Sync Debug is %s", onoff?"ON":"OFF");
+}
+
+EINTERN Eina_Bool
+e_explicit_sync_enabled_get(void)
+{
+ return _explicit_sync_enabled;
+}
--- /dev/null
+#ifdef E_TYPEDEFS
+
+typedef struct _E_Explicit_Sync E_Explicit_Sync;
+typedef struct _E_Explicit_Sync_Surface E_Explicit_Sync_Surface;
+typedef struct _E_Explicit_Sync_Buffer_Release E_Explicit_Sync_Buffer_Release;
+
+#else
+#ifndef E_EXPLICIT_SYNC_H
+#define E_EXPLICIT_SYNC_H
+
+struct _E_Explicit_Sync
+{
+ struct wl_global *global;
+};
+
+struct _E_Explicit_Sync_Surface
+{
+ struct wl_resource *resource;
+
+ int pending_acquire_fence_fd;
+ int acquire_fence_fd;
+
+ E_Client *ec;
+ E_Object_Delfn *ec_delfn;
+
+ E_Explicit_Sync_Buffer_Release *pending_buffer_release;
+};
+
+struct _E_Explicit_Sync_Buffer_Release
+{
+ struct wl_resource *resource;
+ int fence_fd;
+};
+
+
+EINTERN Eina_Bool e_explicit_sync_init(void);
+EINTERN void e_explicit_sync_deinit(void);
+EINTERN void e_explicit_sync_trace_debug(Eina_Bool onoff);
+EINTERN Eina_Bool e_explicit_sync_enabled_get(void);
+
+EINTERN Eina_Bool e_explicit_sync_surface_commit(E_Explicit_Sync_Surface *explicit_sync_surface);
+EINTERN Eina_Bool e_explicit_sync_surface_sync(E_Explicit_Sync_Surface *explicit_sync_surface);
+
+EINTERN Eina_Bool e_explicit_sync_buffer_release_fence_fd_set(E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release, int fence_fd);
+EINTERN void e_explicit_sync_buffer_release_destroy(E_Explicit_Sync_Buffer_Release *explicit_sync_buffer_release);
+
+#endif // E_EXPLICIT_SYNC_H
+#endif
EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
hwc->output = output;
+ hwc->commit_fence_fd = -1;
+
/*
* E20 has two hwc policy options.
* 1. One is the E_HWC_POLICY_PLANES.
hwc->tdm_hwc_video_transform = EINA_TRUE;
if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCANOUT)
hwc->tdm_hwc_video_scanout = EINA_TRUE;
+ if (hwc_caps & TDM_HWC_CAPABILITY_FENCE)
+ hwc->tdm_hwc_fence = EINA_TRUE;
}
/* set the pirmary_output */
_e_hwc_ee_deinit(hwc);
+ if (hwc->commit_fence_fd >= 0)
+ close(hwc->commit_fence_fd);
+
E_FREE(hwc);
}
int flapse;
Eina_Bool present_sync;
+
+ Eina_Bool tdm_hwc_fence;
+ int commit_fence_fd;
};
E_API extern int E_EVENT_HWC_ACTIVE;
error = tdm_hwc_window_set_buffer(thwc_window, hwc_window->buffer.tsurface);
EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+ if (ec && ec->explicit_sync_surface)
+ {
+ error = tdm_hwc_window_set_acquire_fence(thwc_window, ec->explicit_sync_surface->acquire_fence_fd);
+ EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
+ }
+
return EINA_TRUE;
}
E_Hwc_Window_Queue *queue;
struct wl_listener queue_destroy_listener;
Eina_Bool from_queue;
+ int sync_fence_fd;
};
struct _E_Hwc_Window
Eina_Bool is_rendering;
int max_transition_failures;
- Eina_Bool skip_surface_set;
+ Eina_Bool skip_surface_set;
+
+ E_Egl_Sync *end_render_sync;
};
struct _E_Hwc_Window_Commit_Data {
{
E_Presentation_Time_Container presentation_container;
Eina_Bool skip;
+ E_Egl_Sync *release_fence;
};
static Eina_Bool ehws_trace = EINA_FALSE;
if (tdm_set)
tdm_hwc_set_client_target_buffer(thwc, hwc_window->buffer.tsurface, fb_damage);
+ if (target_hwc_window->end_render_sync)
+ {
+ int fence = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
+ tdm_hwc_set_client_target_acquire_fence(thwc, fence);
+ close(fence);
+ }
+
if (ehws_trace)
{
rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(hwc_window->buffer.tsurface);
CLEAR(fb_damage);
tdm_hwc_set_client_target_buffer(thwc, NULL, fb_damage);
+ tdm_hwc_set_client_target_acquire_fence(thwc, -1);
}
return EINA_TRUE;
EHWS_RENDERED_WINDOWS_KEY,
_e_hwc_windows_rendered_windows_free);
target_hwc_window->dequeued_tsurface = tsurface;
+ buffer_comp_info = _e_hwc_windows_buffer_comp_info_get(tsurface);
+ if (buffer_comp_info && buffer_comp_info->release_fence)
+ e_egl_sync_wait(buffer_comp_info->release_fence);
if (!eina_list_data_find(target_hwc_window->rendering_tsurfaces, tsurface))
{
return EINA_TRUE;
}
+static void
+_e_hwc_windows_target_window_render_flush_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
+ E_Hwc_Window *hwc_window;
+ E_Hwc *hwc;
+ Eina_List *l;
+
+ hwc = target_hwc_window->hwc;
+ if (!(e_egl_sync_enabled_get() && e_egl_sync_enabled_get())) return;
+
+ if (target_hwc_window->end_render_sync)
+ {
+ e_egl_sync_destroy(target_hwc_window->end_render_sync);
+ target_hwc_window->end_render_sync = NULL;
+ }
+
+ target_hwc_window->end_render_sync = e_egl_sync_fence_create();
+ if (!target_hwc_window->end_render_sync)
+ EHWSERR("Failed to create E_Egl_Sync", hwc);
+
+ EINA_LIST_FOREACH(hwc->visible_windows, l, hwc_window)
+ {
+ if (!hwc_window->is_deleted) continue;
+ if (!hwc_window->ec) continue;
+ if (!hwc_window->ec->explicit_sync_surface) continue;
+
+ e_explicit_sync_surface_sync(hwc_window->ec->explicit_sync_surface);
+ }
+}
+
static void
_e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
{
Eina_List *rendered_windows = NULL;
Eina_List *visible_windows = NULL;
Eina_List *l;
+ Eina_Bool fence_enabled;
EHWSTRACE("{%s} gets render_flush_post noti.", NULL, target_hwc_window->hwc, "@TARGET WINDOW@");
if (!buffer_comp_info)
EHWSERR("fail to get buffer_comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface);
+ fence_enabled = (e_egl_sync_enabled_get() && e_explicit_sync_enabled_get());
+
/* all ecs have been composited so we can attach a list of composited e_hwc_windows to the surface
* which contains their ecs composited */
rendered_windows = eina_list_clone(target_hwc_window->rendered_windows);
*/
if (!buffer->resource) continue;
+ if ((fence_enabled) && (buffer->buffer_release) && (target_hwc_window->end_render_sync))
+ {
+ int fence_fd = -1;
+
+ fence_fd = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
+ if (fence_fd != -1)
+ {
+ if (!e_explicit_sync_buffer_release_fence_fd_set(buffer->buffer_release, fence_fd))
+ close(fence_fd);
+
+ continue;
+ }
+ else
+ EHWSERR("failed to dup native fence fd", target_hwc_window->hwc);
+ }
+
buffer_ref = E_NEW(E_Comp_Wl_Buffer_Ref, 1);
if (!buffer_ref) continue;
EVAS_CALLBACK_RENDER_FLUSH_POST,
_e_hwc_windows_target_window_render_flush_post_cb);
+ evas_event_callback_del(target_hwc_window->evas,
+ EVAS_CALLBACK_RENDER_FLUSH_PRE,
+ _e_hwc_windows_target_window_render_flush_pre_cb);
+
ecore_main_fd_handler_del(target_hwc_window->event_hdlr);
close(target_hwc_window->event_fd);
_e_hwc_windows_target_window_render_flush_post_cb,
target_hwc_window);
+ evas_event_callback_add(evas,
+ EVAS_CALLBACK_RENDER_FLUSH_PRE,
+ _e_hwc_windows_target_window_render_flush_pre_cb,
+ target_hwc_window);
+
return target_hwc_window;
fail:
return EINA_TRUE;
}
+static void
+_e_hwc_windows_release_fence_fd_update(E_Hwc *hwc)
+{
+ E_Hwc_Window *hwc_window;
+ E_Hwc_Window_Target *target_hwc_window;
+ E_Hwc_Window_Queue_Buffer *queue_buffer;
+ E_Hwc_Windows_Buffer_Comp_Info *comp_info;
+ tdm_hwc_window **thwc_wins = NULL;
+ int *release_fences = NULL;
+ uint32_t num_thwc_wins = 0;
+ tdm_error ret = TDM_ERROR_NONE;
+ int i;
+
+ target_hwc_window = hwc->target_hwc_window;
+ EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
+
+ hwc_window = (E_Hwc_Window *)target_hwc_window;
+ if ((hwc_window->display.buffer.tsurface) && (hwc_window->display.buffer.queue))
+ {
+ comp_info = _e_hwc_windows_buffer_comp_info_get(hwc_window->display.buffer.tsurface);
+ EINA_SAFETY_ON_NULL_RETURN(comp_info);
+
+ if (comp_info->release_fence)
+ e_egl_sync_destroy(comp_info->release_fence);
+
+ comp_info->release_fence = e_egl_sync_fence_create_with_fd(hwc->commit_fence_fd);
+
+ queue_buffer = e_hwc_window_queue_buffer_find(hwc_window->display.buffer.queue,
+ hwc_window->display.buffer.tsurface);
+ if (queue_buffer)
+ e_hwc_window_queue_buffer_release(hwc_window->display.buffer.queue, queue_buffer);
+
+ /* prevent release buffer to queue in commit handler */
+ hwc_window->display.buffer.queue = NULL;
+ }
+
+ ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, NULL, NULL);
+ EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
+
+ if (!num_thwc_wins) return;
+
+ thwc_wins = E_NEW(tdm_hwc_window *, num_thwc_wins);
+ EINA_SAFETY_ON_NULL_GOTO(thwc_wins, clean);
+
+ release_fences = E_NEW(int, num_thwc_wins);
+ EINA_SAFETY_ON_NULL_GOTO(release_fences, clean);
+
+ ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, thwc_wins, release_fences);
+ EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
+
+ for (i = 0; i < num_thwc_wins; i++)
+ {
+ hwc_window = _e_hwc_windows_window_find_by_twin(hwc, thwc_wins[i]);
+
+ if ((!hwc_window) ||
+ (!hwc_window->display.buffer_ref.buffer) ||
+ (!hwc_window->display.buffer_ref.buffer->buffer_release))
+ {
+ close(release_fences[i]);
+ continue;
+ }
+
+ if (!e_explicit_sync_buffer_release_fence_fd_set(hwc_window->display.buffer_ref.buffer->buffer_release,
+ release_fences[i]))
+ {
+ close(release_fences[i]);
+ continue;
+ }
+
+ e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
+ }
+
+clean:
+ if (thwc_wins) free(thwc_wins);
+ if (release_fences) free(release_fences);
+}
+
EINTERN Eina_Bool
e_hwc_windows_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
{
E_Output *output = NULL;
tdm_error error = TDM_ERROR_NONE;
+ int commit_fence_fd = -1;
EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
goto fail;
}
- /* send tizen_hwc_commit feedback committed */
- e_comp_wl_tizen_hwc_committed();
+ error = tdm_hwc_get_commit_fence(hwc->thwc, &commit_fence_fd);
+ if (error != TDM_ERROR_NONE)
+ EHWSERR("tdm_hwc_get_commit_sync_fence_fd failed.", hwc);
+
+ if (hwc->commit_fence_fd >= 0)
+ close(hwc->commit_fence_fd);
+
+ hwc->commit_fence_fd = commit_fence_fd;
+
+ _e_hwc_windows_release_fence_fd_update(hwc);
+
+ /* send tizen_hwc_commit feedback committed */
+ e_comp_wl_tizen_hwc_committed();
}
return EINA_TRUE;
#include "e_hwc_window.h"
#include "e_hwc_window_queue.h"
#include "e_presentation_time.h"
+#include "e_explicit_sync.h"
#include "e_egl_sync.h"
#include "e_comp_wl.h"
#include "e_comp_wl_subsurface.h"
}
return;
}
+ else if (eina_streq(argv[2], "exsync"))
+ {
+ if (!_e_info_client_eldbus_message_with_args("trace_message_exsync", NULL, "i", onoff))
+ {
+ printf("_e_info_client_eldbus_message_with_args error");
+ }
+ return;
+ }
}
arg_err:
#endif
{
"trace",
- "[hwc | serial] [off: 0, on: 1]",
+ "[hwc | serial | exsync] [off: 0, on: 1]",
"Show the trace log in detail",
_e_info_client_proc_trace
},
return reply;
}
+static Eldbus_Message *
+e_info_server_cb_exsync_trace_message(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
+{
+ Eldbus_Message *reply = eldbus_message_method_return_new(msg);
+ uint32_t on;
+
+ if (!eldbus_message_arguments_get(msg, "i", &on))
+ {
+ ERR("Error getting arguments.");
+ return reply;
+ }
+
+ if (on == 0 || on == 1)
+ e_explicit_sync_trace_debug(on);
+
+ return reply;
+}
+
static Eldbus_Message *
e_info_server_cb_show_plane_state(const Eldbus_Service_Interface *iface EINA_UNUSED, const Eldbus_Message *msg)
{
{ "trace_message_hwc", ELDBUS_ARGS({"i", "trace_message_hwc"}), NULL, e_info_server_cb_hwc_trace_message, 0},
{ "trace_message_serial", ELDBUS_ARGS({"i", "trace_message_serial"}), NULL, e_info_server_cb_serial_trace_message, 0},
{ "trace_message_prstt", ELDBUS_ARGS({"i", "trace_message_presentation_time"}), NULL, e_info_server_cb_prstt_trace_message, 0},
+ { "trace_message_exsync", ELDBUS_ARGS({"i", "trace_message_ex_sync"}), NULL, e_info_server_cb_exsync_trace_message, 0},
{ "hwc", ELDBUS_ARGS({"i", "hwc"}), NULL, e_info_server_cb_hwc, 0},
{ "show_plane_state", NULL, NULL, e_info_server_cb_show_plane_state, 0},
{ "show_pending_commit", NULL, ELDBUS_ARGS({"a("VALUE_TYPE_FOR_PENDING_COMMIT")", "array of pending commit"}), e_info_server_cb_show_pending_commit, 0},
"\tenlightenment_info -trace serial 1\n" \
"\tenlightenment_info -trace serial 0\n" \
"\tenlightenment_info -trace prstt 1\n" \
- "\tenlightenment_info -trace prstt 0\n"
+ "\tenlightenment_info -trace prstt 0\n" \
+ "\tenlightenment_info -trace exsync 1\n" \
+ "\tenlightenment_info -trace exsync 0\n"
/* -------------------------------------------------------------------------- */
/* HWC WINS */