-#include "e_client_video_intern.h"
#include "e_video_hwc_intern.h"
+#include "e_intern.h"
+#include "e_main_intern.h"
#include "e_comp_screen_intern.h"
#include "e_comp_wl_intern.h"
#include "e_comp_intern.h"
#include "e_client_intern.h"
#include "e_compositor_intern.h"
#include "e_view_client_intern.h"
+#include "e_hwc_windows_intern.h"
#include <wayland-tbm-server.h>
E_Video_Hwc *evh; \
evh = container_of(iface, E_Video_Hwc, iface)
+#define BUFFER_MAX_COUNT 5
+
+#ifndef CLEAR
+#define CLEAR(x) memset(&(x), 0, sizeof(x))
+#endif
+
+typedef struct _E_Video_Hwc E_Video_Hwc;
+typedef struct _E_Video_Hwc_Geometry E_Video_Hwc_Geometry;
+typedef struct _E_Video_Hwc_PP E_Video_Hwc_PP;
+
+struct _E_Video_Hwc_PP
+{
+ tdm_pp *tdm_handle;
+ tdm_info_pp info;
+
+ int minw, minh, maxw, maxh;
+ int align;
+ int align_vertical;
+
+ Eina_Bool scanout;
+};
+
+struct _E_Video_Hwc_Geometry
+{
+ Eina_Rectangle input_r; /* input buffer's content rect */
+ Eina_Rectangle output_r; /* video plane rect */
+ uint transform; /* rotate, flip */
+
+ struct {
+ Eina_Rectangle output_r; /* video plane rect in physical output coordinates */
+ uint transform; /* rotate, flip in physical output coordinates */
+ } tdm;
+};
+
+struct _E_Video_Hwc
+{
+ E_Video_Comp_Iface iface;
+
+ E_Client_Video *ecv;
+ E_Client *ec;
+ E_Output *e_output;
+ E_Hwc *hwc;
+ E_Hwc_Window *hwc_window;
+
+ Eina_List *ec_event_handler;
+
+ /* input info */
+ tbm_format tbmfmt;
+ Eina_List *input_buffer_list;
+
+ /* in screen coordinates */
+ E_Video_Hwc_Geometry geo, old_geo;
+
+ E_Comp_Wl_Buffer *old_comp_buffer;
+
+ /* converter info */
+ E_Video_Hwc_PP *pp;
+
+ tbm_format pp_tbmfmt;
+ Eina_List *pp_buffer_list;
+ Eina_List *next_buffer;
+
+ int output_align;
+
+ /* When a video buffer be attached, it will be appended to the end of waiting_list .
+ * And when it's committed, it will be moved to committed_list.
+ * Finally when the commit handler is called, it will become current_fb.
+ */
+ E_Comp_Wl_Video_Buf *committed_vbuf; /* A committed video buffer to backend */
+ E_Comp_Wl_Video_Buf *current_fb; /* buffer which is showing on screen currently */
+
+ struct wl_listener surface_viewport_listener;
+ E_Video_Hwc_Render_Fail_Cb render_fail_cb;
+
+ struct
+ {
+ E_Main_Hook *post_client_idler_before_hook;
+ Eina_Bool map;
+ Eina_Bool redraw;
+ Eina_Bool topmost_viewport;
+ } render;
+
+ struct
+ {
+ E_Video_Hwc_Render_Fail_Cb cb;
+ Eina_Bool walking;
+ } render_fail;
+
+ struct
+ {
+ E_Client_Video_Info info;
+ tbm_surface_h buffer;
+ Eina_Bool wait_release;
+ } commit_data;
+
+ Eina_Bool need_force_render;
+ Eina_Bool deleted;
+ struct wl_listener show_listener;
+ struct wl_listener resize_listener;
+ struct wl_listener move_listener;
+};
+
typedef struct
{
int x;
int y;
} E_Video_Point;
+static void _e_video_hwc_free(E_Video_Hwc *evh);
static Eina_Bool _e_video_hwc_render(E_Video_Hwc *evh, const char *func);
static void _e_video_hwc_buffer_show(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf, unsigned int transform);
-static void _e_video_hwc_buffer_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf);
static E_Client *
_e_video_hwc_client_offscreen_parent_get(E_Client *ec)
return EINA_FALSE;
}
+static Eina_Bool
+_e_video_hwc_commit_data_set(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
+{
+ if (!vbuf)
+ {
+ evh->commit_data.buffer = NULL;
+ goto end;
+ }
+
+ if ((evh->commit_data.info.src_config.size.h == vbuf->width_from_pitch) &&
+ (evh->commit_data.info.src_config.size.v == vbuf->height_from_size) &&
+ (evh->commit_data.info.src_config.pos.x == vbuf->content_r.x) &&
+ (evh->commit_data.info.src_config.pos.y == vbuf->content_r.y) &&
+ (evh->commit_data.info.src_config.pos.w == vbuf->content_r.w) &&
+ (evh->commit_data.info.src_config.pos.h == vbuf->content_r.h) &&
+ (evh->commit_data.info.src_config.format == vbuf->tbmfmt) &&
+ (evh->commit_data.info.dst_pos.x == evh->geo.tdm.output_r.x) &&
+ (evh->commit_data.info.dst_pos.y == evh->geo.tdm.output_r.y) &&
+ (evh->commit_data.info.dst_pos.w == evh->geo.tdm.output_r.w) &&
+ (evh->commit_data.info.dst_pos.h == evh->geo.tdm.output_r.h) &&
+ (evh->commit_data.info.transform == vbuf->content_t) &&
+ (evh->commit_data.buffer == vbuf->tbm_surface))
+ {
+ WRN("commit data ins't changed");
+ return EINA_FALSE;
+ }
+
+ CLEAR(evh->commit_data.info);
+
+ /* Set src_config */
+ evh->commit_data.info.src_config.size.h = vbuf->width_from_pitch;
+ evh->commit_data.info.src_config.size.v = vbuf->height_from_size;
+ evh->commit_data.info.src_config.pos.x = vbuf->content_r.x;
+ evh->commit_data.info.src_config.pos.y = vbuf->content_r.y;
+ evh->commit_data.info.src_config.pos.w = vbuf->content_r.w;
+ evh->commit_data.info.src_config.pos.h = vbuf->content_r.h;
+ evh->commit_data.info.src_config.format = vbuf->tbmfmt;
+
+ /* Set dst_pos */
+ evh->commit_data.info.dst_pos.x = evh->geo.tdm.output_r.x;
+ evh->commit_data.info.dst_pos.y = evh->geo.tdm.output_r.y;
+ evh->commit_data.info.dst_pos.w = evh->geo.tdm.output_r.w;
+ evh->commit_data.info.dst_pos.h = evh->geo.tdm.output_r.h;
+
+ /* Set transform */
+ evh->commit_data.info.transform = vbuf->content_t;
+
+ /* Set buffer */
+ evh->commit_data.buffer = vbuf->tbm_surface;
+
+end:
+ /* Set flag to wait until commit data is released. Otherwise, it maybe loses
+ * frame buffer. */
+ evh->commit_data.wait_release = EINA_TRUE;
+
+ e_hwc_window_changed_set(evh->hwc_window, E_HWC_WINS_CHANGED_WIN_GEOMETRY|E_HWC_WINS_CHANGED_WIN_BUFFER);
+
+ DBG("Client(%s):PID(%d), Buffer(%p, refcnt:%d) is shown."
+ "Geometry details are : buffer size(%dx%d) src(%d,%d, %dx%d)"
+ " dst(%d,%d, %dx%d), transform(%d)",
+ e_client_util_name_get(evh->ec) ?: "No Name" ,
+ evh->ec->netwm.pid,
+ vbuf, (vbuf ? vbuf->ref_cnt : 0),
+ evh->commit_data.info.src_config.size.h,
+ evh->commit_data.info.src_config.size.v,
+ evh->commit_data.info.src_config.pos.x,
+ evh->commit_data.info.src_config.pos.y,
+ evh->commit_data.info.src_config.pos.w,
+ evh->commit_data.info.src_config.pos.h,
+ evh->commit_data.info.dst_pos.x, evh->commit_data.info.dst_pos.y,
+ evh->commit_data.info.dst_pos.w, evh->commit_data.info.dst_pos.h,
+ evh->commit_data.info.transform);
+
+ return EINA_TRUE;
+}
+
+static void
+_e_video_hwc_client_mask_update(E_Video_Hwc *evh)
+{
+ E_Client *topmost;
+ Eina_Bool punch = EINA_FALSE;
+ int bw, bh;
+
+ if (e_video_debug_punch_value_get())
+ punch = EINA_TRUE;
+ else if ((topmost = e_comp_wl_topmost_parent_get(evh->ec)))
+ {
+ /* if it's laid above main surface */
+ if ((topmost->comp_data) &&
+ (eina_list_data_find(topmost->comp_data->sub.list, evh->ec)))
+ punch = EINA_TRUE;
+ /* if it's laid under main surface and main surface is transparent */
+ else if (topmost->argb)
+ {
+ /* FIXME: the mask obj can be drawn at the wrong position in the beginnig
+ * time. It happens caused by window manager policy.
+ */
+ if ((topmost->fullscreen || topmost->maximized) &&
+ (evh->geo.output_r.x == 0 || evh->geo.output_r.y == 0))
+ {
+ e_pixmap_size_get(topmost->pixmap, &bw, &bh);
+
+ if (bw > 100 && bh > 100 &&
+ evh->geo.output_r.w < 100 && evh->geo.output_r.h < 100)
+ {
+ VIN("don't punch. (%dx%d, %dx%d)", evh->ec,
+ bw, bh, evh->geo.output_r.w, evh->geo.output_r.h);
+ return;
+ }
+ }
+
+ punch = EINA_TRUE;
+ }
+ }
+
+ if (punch)
+ {
+ if (!e_view_client_mask_has(e_client_view_get(evh->ec)))
+ {
+ e_view_client_mask_set(e_client_view_get(evh->ec), true);
+ VIN("punched", evh->ec);
+ }
+ }
+ else
+ {
+ if (e_view_client_mask_has(e_client_view_get(evh->ec)))
+ {
+ e_view_client_mask_set(e_client_view_get(evh->ec), false);
+ VIN("Un-punched", evh->ec);
+ }
+ }
+}
+
+static Eina_Bool
+_e_video_hwc_buffer_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
+{
+ Eina_Bool ret;
+
+ /* show means that set the information of the buffer and the info of the hwc window */
+
+ ret = _e_video_hwc_commit_data_set(evh, vbuf);
+
+ // TODO:: this logic move to the hwc windows after hwc commit
+#if 1
+ _e_video_hwc_client_mask_update((E_Video_Hwc *)evh);
+#endif
+
+ return ret;
+}
+
static void
_e_video_hwc_input_buffer_cb_free(E_Comp_Wl_Video_Buf *vbuf, void *data)
{
}
if (need_hide)
- evh->backend.buffer_commit(evh, NULL);
+ _e_video_hwc_buffer_commit(evh, NULL);
}
static E_Comp_Wl_Video_Buf *
if ((evh->committed_vbuf) &&
(_e_video_hwc_can_commit(evh)))
{
- displaying_buffer = evh->backend.displaying_buffer_get(evh);
+ displaying_buffer = evh->commit_data.buffer;
if (evh->committed_vbuf->tbm_surface != displaying_buffer)
return EINA_FALSE;
}
static void
-_e_video_hwc_buffer_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
+_e_video_hwc_buffer_try_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
{
/* Send a message 'wl_surface.frame', right before commit a buffer to
* tdm driver. */
if (!_e_video_hwc_can_commit(evh))
goto no_commit;
- if (!evh->backend.buffer_commit(evh, vbuf))
+ if (!_e_video_hwc_buffer_commit(evh, vbuf))
goto no_commit;
return;
if (vbuf->comp_buffer)
e_comp_wl_buffer_reference(&vbuf->buffer_ref, vbuf->comp_buffer);
- _e_video_hwc_buffer_commit(evh, vbuf);
+ _e_video_hwc_buffer_try_commit(evh, vbuf);
}
static void
evh->committed_vbuf = NULL;
}
- evh->backend.buffer_commit(evh, NULL);
+ _e_video_hwc_buffer_commit(evh, NULL);
}
if (evh->old_comp_buffer)
if (evh->deleted)
{
VIN("Delete HWC interface", evh->ec);
- evh->backend.destroy(evh);
+ _e_video_hwc_free(evh);
}
}
}
return EINA_TRUE;
}
+static Eina_Bool
+_e_video_hwc_check_if_pp_needed(E_Video_Hwc *evh)
+{
+ E_Comp_Screen *e_comp_screen;
+ int i, count = 0;
+ const tbm_format *formats;
+ Eina_Bool found = EINA_FALSE;
+ E_Hwc *hwc;
+ tdm_error error = TDM_ERROR_NONE;
+
+ hwc = evh->hwc;
+ if (hwc->tdm_hwc_video_stream)
+ return EINA_FALSE;
+
+ error = tdm_hwc_get_video_supported_formats(hwc->thwc, &formats, &count);
+ if (error != TDM_ERROR_NONE)
+ return EINA_FALSE;
+
+ for (i = 0; i < count; i++)
+ if (formats[i] == evh->tbmfmt)
+ {
+ found = EINA_TRUE;
+ break;
+ }
+
+ if (!found)
+ {
+ if (formats && count > 0)
+ evh->pp_tbmfmt = formats[0];
+ else
+ {
+ WRN("No layer format information!!!");
+ evh->pp_tbmfmt = TBM_FORMAT_ARGB8888;
+ }
+ return EINA_TRUE;
+ }
+
+ if (hwc->tdm_hwc_video_scanout)
+ goto need_pp;
+
+ /* check size */
+ if (evh->geo.input_r.w != evh->geo.output_r.w || evh->geo.input_r.h != evh->geo.output_r.h)
+ if (!hwc->tdm_hwc_video_scale)
+ goto need_pp;
+
+ /* check rotate */
+ e_comp_screen = e_comp_screen_get();
+ if (evh->geo.transform || (e_comp_screen && e_comp_screen->rotation > 0))
+ if (!hwc->tdm_hwc_video_transform)
+ goto need_pp;
+
+ return EINA_FALSE;
+
+need_pp:
+ evh->pp_tbmfmt = evh->tbmfmt;
+
+ return EINA_TRUE;
+}
+
static Eina_Bool
_e_video_hwc_render(E_Video_Hwc *evh, const char *func)
{
evh->old_geo = evh->geo;
goto done;
}
- if (!evh->backend.check_if_pp_needed(evh))
+ if (!_e_video_hwc_check_if_pp_needed(evh))
{
/* 1. non converting case */
input_buffer = _e_video_hwc_input_buffer_get(evh, comp_buffer);
E_FREE_LIST(evh->ec_event_handler, ecore_event_handler_del);
}
+static void
+_e_video_hwc_free(E_Video_Hwc *evh)
+{
+ e_hwc_window_video_set(evh->hwc_window, EINA_FALSE);
+ e_hwc_window_unref(evh->hwc_window);
+ free(evh);
+}
+
static void
_e_video_hwc_iface_destroy(E_Video_Comp_Iface *iface)
{
return;
}
- evh->backend.destroy(evh);
+ _e_video_hwc_free(evh);
}
static Eina_Bool
_e_video_hwc_iface_property_get(E_Video_Comp_Iface *iface, unsigned int id, tdm_value *value)
{
+ tdm_error ret;
+
IFACE_ENTRY;
- return evh->backend.property_get(evh, id, value);
+ ret = tdm_hwc_window_get_property(evh->hwc_window->thwc_window, id, value);
+ if (ret != TDM_ERROR_NONE)
+ return EINA_FALSE;
+
+ return EINA_TRUE;
+}
+
+const char *
+_e_video_hwc_prop_name_get_by_id(E_Video_Hwc *evh, unsigned int id)
+{
+ const tdm_prop *props;
+ int i, count = 0;
+
+ e_hwc_windows_get_video_available_properties(evh->hwc, &props, &count);
+ for (i = 0; i < count; i++)
+ {
+ if (props[i].id == id)
+ {
+ VDB("check property(%s)", evh->ec, props[i].name);
+ return props[i].name;
+ }
+ }
+
+ VER("No available property: id %d", evh->ec, id);
+
+ return NULL;
}
static Eina_Bool
_e_video_hwc_iface_property_set(E_Video_Comp_Iface *iface, unsigned int id, tdm_value value, Eina_Bool sync)
{
+ const char *name;
+
IFACE_ENTRY;
- return evh->backend.property_set(evh, id, value, sync);
+ VIN("set_attribute", evh->ec);
+
+ name = _e_video_hwc_prop_name_get_by_id(evh, id);
+ if (!name)
+ {
+ VER("_e_video_hwc_prop_name_get_by_id failed", evh->ec);
+ return EINA_FALSE;
+ }
+
+ if ((e_client_video_property_allow_get(evh->ecv)) ||
+ (sync == EINA_TRUE))
+ {
+ VIN("set_attribute now : property(%s), value(%d)", evh->ec, name, value.u32);
+
+ /* set the property on the fly */
+ if (!e_hwc_window_set_property(evh->hwc_window, id, name, value, EINA_TRUE))
+ {
+ VER("set property failed", evh->ec);
+ return EINA_FALSE;
+ }
+ }
+ else
+ {
+ VIN("set_attribute at commit : property(%s), value(%d)", evh->ec, name, value.u32);
+
+ /* set the property before hwc commit */
+ if (!e_hwc_window_set_property(evh->hwc_window, id, name, value, EINA_FALSE))
+ {
+ VER("set property failed", evh->ec);
+ return EINA_FALSE;
+ }
+ }
+
+ return EINA_TRUE;
}
static Eina_Bool
{
IFACE_ENTRY;
- return evh->backend.available_properties_get(evh, props, count);
+ if (!e_hwc_windows_get_video_available_properties(evh->hwc, props, count))
+ return EINA_FALSE;
+
+ return EINA_TRUE;
}
static Eina_Bool
{
IFACE_ENTRY;
- return e_video_hwc_windows_info_get(evh, info);
+ memcpy(&info->src_config, &evh->commit_data.info.src_config, sizeof(tdm_info_config));
+ memcpy(&info->dst_pos, &evh->commit_data.info.dst_pos, sizeof(tdm_pos));
+ info->transform = evh->commit_data.info.transform;
+
+ return EINA_TRUE;
}
static Eina_Bool
{
IFACE_ENTRY;
- return e_video_hwc_windows_commit_data_release(evh, sequence, tv_sec, tv_usec);
+ evh->commit_data.wait_release = EINA_FALSE;
+ _e_video_hwc_current_fb_update(evh);
+
+ return EINA_TRUE;
}
static tbm_surface_h
{
IFACE_ENTRY;
- return e_video_hwc_windows_tbm_surface_get(evh);
+ return evh->commit_data.buffer;
}
static E_Video_Hwc *
return NULL;
}
- evh = e_video_hwc_windows_create(output, ec);
- if (!evh)
+ evh = E_NEW(E_Video_Hwc, 1);
+ EINA_SAFETY_ON_NULL_RETURN_VAL(evh, NULL);
+
+ evh->hwc = output->hwc;
+ if (!evh->hwc)
{
- VER("Failed to create 'E_Video_Hwc'", ec);
+ free(evh);
return NULL;
}
+ evh->hwc_window = e_hwc_window_get(evh->hwc, ec);
+ if (!evh->hwc_window)
+ {
+ free(evh);
+ return NULL;
+ }
+
+ e_hwc_window_ref(evh->hwc_window);
+ e_hwc_window_video_set(evh->hwc_window, EINA_TRUE);
+
/* Since video content will be displayed on the overlay plane,
* it's reasonable to keep the size of composite object to 1x1.
* Otherwise, it will cause memory usage to be increased unnecessarily. */
return &evh->iface;
}
-EINTERN Eina_Bool
-e_video_hwc_current_fb_update(E_Video_Hwc *evh)
-{
- return _e_video_hwc_current_fb_update(evh);
-}
-
-EINTERN void
-e_video_hwc_client_mask_update(E_Video_Hwc *evh)
-{
- E_Client *topmost;
- Eina_Bool punch = EINA_FALSE;
- int bw, bh;
-
- if (e_video_debug_punch_value_get())
- punch = EINA_TRUE;
- else if ((topmost = e_comp_wl_topmost_parent_get(evh->ec)))
- {
- /* if it's laid above main surface */
- if ((topmost->comp_data) &&
- (eina_list_data_find(topmost->comp_data->sub.list, evh->ec)))
- punch = EINA_TRUE;
- /* if it's laid under main surface and main surface is transparent */
- else if (topmost->argb)
- {
- /* FIXME: the mask obj can be drawn at the wrong position in the beginnig
- * time. It happens caused by window manager policy.
- */
- if ((topmost->fullscreen || topmost->maximized) &&
- (evh->geo.output_r.x == 0 || evh->geo.output_r.y == 0))
- {
- e_pixmap_size_get(topmost->pixmap, &bw, &bh);
-
- if (bw > 100 && bh > 100 &&
- evh->geo.output_r.w < 100 && evh->geo.output_r.h < 100)
- {
- VIN("don't punch. (%dx%d, %dx%d)", evh->ec,
- bw, bh, evh->geo.output_r.w, evh->geo.output_r.h);
- return;
- }
- }
-
- punch = EINA_TRUE;
- }
- }
-
- if (punch)
- {
- if (!e_view_client_mask_has(e_client_view_get(evh->ec)))
- {
- e_view_client_mask_set(e_client_view_get(evh->ec), true);
- VIN("punched", evh->ec);
- }
- }
- else
- {
- if (e_view_client_mask_has(e_client_view_get(evh->ec)))
- {
- e_view_client_mask_set(e_client_view_get(evh->ec), false);
- VIN("Un-punched", evh->ec);
- }
- }
-}
-
/* Sets render fail callback
*
* @in iface A instance of this composition mode
#ifndef E_VIDEO_HWC_INTERN_H
#define E_VIDEO_HWC_INTERN_H
-#include "e_intern.h"
+#include "e_client_video_intern.h"
#include "e_video_comp_iface.h"
-#include "e_comp_wl_video_buffer_intern.h"
-#include "e_main_intern.h"
-
-#define BUFFER_MAX_COUNT 5
-
-#ifndef CLEAR
-#define CLEAR(x) memset(&(x), 0, sizeof(x))
-#endif
-
-typedef struct _E_Video_Hwc E_Video_Hwc;
-typedef struct _E_Video_Hwc_Iface E_Video_Hwc_Iface;
-typedef struct _E_Video_Hwc_Geometry E_Video_Hwc_Geometry;
-typedef struct _E_Video_Hwc_PP E_Video_Hwc_PP;
/* A callback which is called when HWC backend fails to render buffer. */
typedef void (*E_Video_Hwc_Render_Fail_Cb)(E_Client_Video *ecv);
-struct _E_Video_Hwc_Iface
-{
- void (*destroy)(E_Video_Hwc *evh);
- Eina_Bool (*property_get)(E_Video_Hwc *evh, unsigned int id, tdm_value *value);
- Eina_Bool (*property_set)(E_Video_Hwc *evh, unsigned int id, tdm_value value, Eina_Bool sync);
- Eina_Bool (*available_properties_get)(E_Video_Hwc *evh, const tdm_prop **props, int *count);
- Eina_Bool (*buffer_commit)(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf);
- Eina_Bool (*check_if_pp_needed)(E_Video_Hwc *evh);
- tbm_surface_h (*displaying_buffer_get)(E_Video_Hwc *evh);
-};
-
-struct _E_Video_Hwc_PP
-{
- tdm_pp *tdm_handle;
- tdm_info_pp info;
-
- int minw, minh, maxw, maxh;
- int align;
- int align_vertical;
-
- Eina_Bool scanout;
-};
-
-struct _E_Video_Hwc_Geometry
-{
- Eina_Rectangle input_r; /* input buffer's content rect */
- Eina_Rectangle output_r; /* video plane rect */
- uint transform; /* rotate, flip */
-
- struct {
- Eina_Rectangle output_r; /* video plane rect in physical output coordinates */
- uint transform; /* rotate, flip in physical output coordinates */
- } tdm;
-};
-
-struct _E_Video_Hwc
-{
- E_Video_Comp_Iface iface;
- E_Video_Hwc_Iface backend;
-
- E_Client_Video *ecv;
- E_Client *ec;
- E_Output *e_output;
-
- Eina_List *ec_event_handler;
-
- /* input info */
- tbm_format tbmfmt;
- Eina_List *input_buffer_list;
-
- /* in screen coordinates */
- E_Video_Hwc_Geometry geo, old_geo;
-
- E_Comp_Wl_Buffer *old_comp_buffer;
-
- /* converter info */
- E_Video_Hwc_PP *pp;
-
- tbm_format pp_tbmfmt;
- Eina_List *pp_buffer_list;
- Eina_List *next_buffer;
-
- int output_align;
-
- /* When a video buffer be attached, it will be appended to the end of waiting_list .
- * And when it's committed, it will be moved to committed_list.
- * Finally when the commit handler is called, it will become current_fb.
- */
- E_Comp_Wl_Video_Buf *committed_vbuf; /* A committed video buffer to backend */
- E_Comp_Wl_Video_Buf *current_fb; /* buffer which is showing on screen currently */
-
- struct wl_listener surface_viewport_listener;
- E_Video_Hwc_Render_Fail_Cb render_fail_cb;
-
- struct
- {
- E_Main_Hook *post_client_idler_before_hook;
- Eina_Bool map;
- Eina_Bool redraw;
- Eina_Bool topmost_viewport;
- } render;
-
- struct
- {
- E_Video_Hwc_Render_Fail_Cb cb;
- Eina_Bool walking;
- } render_fail;
-
- Eina_Bool need_force_render;
- Eina_Bool deleted;
- struct wl_listener show_listener;
- struct wl_listener resize_listener;
- struct wl_listener move_listener;
-};
-
-/* For HWC interface */
-EINTERN E_Video_Comp_Iface *e_video_hwc_iface_create(E_Client_Video *ecv);
-EINTERN void e_video_hwc_render_fail_callback_set(E_Video_Comp_Iface *iface, E_Video_Hwc_Render_Fail_Cb func);
-
-/* Functions for HWC */
-EINTERN void e_video_hwc_client_mask_update(E_Video_Hwc *evh);
-EINTERN Eina_Bool e_video_hwc_current_fb_update(E_Video_Hwc *evh);
-
-/* Functions for HWC Windows */
-EINTERN E_Video_Hwc *e_video_hwc_windows_create(E_Output *output, E_Client *ec);
-EINTERN Eina_Bool e_video_hwc_windows_info_get(E_Video_Hwc *evh, E_Client_Video_Info *info);
-EINTERN Eina_Bool e_video_hwc_windows_commit_data_release(E_Video_Hwc *evh, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec);
-EINTERN tbm_surface_h e_video_hwc_windows_tbm_surface_get(E_Video_Hwc *evh);
+E_Video_Comp_Iface *e_video_hwc_iface_create(E_Client_Video *ecv);
+void e_video_hwc_render_fail_callback_set(E_Video_Comp_Iface *iface, E_Video_Hwc_Render_Fail_Cb func);
#endif
+++ /dev/null
-#include "e_video_hwc_intern.h"
-#include "e_comp_screen_intern.h"
-#include "e_hwc_windows_intern.h"
-#include "e_video_debug_intern.h"
-#include "e_client_intern.h"
-
-typedef struct _E_Video_Hwc_Windows E_Video_Hwc_Windows;
-
-struct _E_Video_Hwc_Windows
-{
- E_Video_Hwc base;
-
- E_Hwc *hwc;
- E_Hwc_Window *hwc_window;
-
- struct
- {
- E_Client_Video_Info info;
- tbm_surface_h buffer;
- Eina_Bool wait_release;
- } commit_data;
-};
-
-static Eina_Bool
-_e_video_hwc_windows_commit_data_set(E_Video_Hwc_Windows *evhw, E_Comp_Wl_Video_Buf *vbuf)
-{
- if (!vbuf)
- {
- evhw->commit_data.buffer = NULL;
- goto end;
- }
-
- if ((evhw->commit_data.info.src_config.size.h == vbuf->width_from_pitch) &&
- (evhw->commit_data.info.src_config.size.v == vbuf->height_from_size) &&
- (evhw->commit_data.info.src_config.pos.x == vbuf->content_r.x) &&
- (evhw->commit_data.info.src_config.pos.y == vbuf->content_r.y) &&
- (evhw->commit_data.info.src_config.pos.w == vbuf->content_r.w) &&
- (evhw->commit_data.info.src_config.pos.h == vbuf->content_r.h) &&
- (evhw->commit_data.info.src_config.format == vbuf->tbmfmt) &&
- (evhw->commit_data.info.dst_pos.x == evhw->base.geo.tdm.output_r.x) &&
- (evhw->commit_data.info.dst_pos.y == evhw->base.geo.tdm.output_r.y) &&
- (evhw->commit_data.info.dst_pos.w == evhw->base.geo.tdm.output_r.w) &&
- (evhw->commit_data.info.dst_pos.h == evhw->base.geo.tdm.output_r.h) &&
- (evhw->commit_data.info.transform == vbuf->content_t) &&
- (evhw->commit_data.buffer == vbuf->tbm_surface))
- {
- WRN("commit data ins't changed");
- return EINA_FALSE;
- }
-
- CLEAR(evhw->commit_data.info);
-
- /* Set src_config */
- evhw->commit_data.info.src_config.size.h = vbuf->width_from_pitch;
- evhw->commit_data.info.src_config.size.v = vbuf->height_from_size;
- evhw->commit_data.info.src_config.pos.x = vbuf->content_r.x;
- evhw->commit_data.info.src_config.pos.y = vbuf->content_r.y;
- evhw->commit_data.info.src_config.pos.w = vbuf->content_r.w;
- evhw->commit_data.info.src_config.pos.h = vbuf->content_r.h;
- evhw->commit_data.info.src_config.format = vbuf->tbmfmt;
-
- /* Set dst_pos */
- evhw->commit_data.info.dst_pos.x = evhw->base.geo.tdm.output_r.x;
- evhw->commit_data.info.dst_pos.y = evhw->base.geo.tdm.output_r.y;
- evhw->commit_data.info.dst_pos.w = evhw->base.geo.tdm.output_r.w;
- evhw->commit_data.info.dst_pos.h = evhw->base.geo.tdm.output_r.h;
-
- /* Set transform */
- evhw->commit_data.info.transform = vbuf->content_t;
-
- /* Set buffer */
- evhw->commit_data.buffer = vbuf->tbm_surface;
-
-end:
- /* Set flag to wait until commit data is released. Otherwise, it maybe loses
- * frame buffer. */
- evhw->commit_data.wait_release = EINA_TRUE;
-
- e_hwc_window_changed_set(evhw->hwc_window, E_HWC_WINS_CHANGED_WIN_GEOMETRY|E_HWC_WINS_CHANGED_WIN_BUFFER);
-
- DBG("Client(%s):PID(%d), Buffer(%p, refcnt:%d) is shown."
- "Geometry details are : buffer size(%dx%d) src(%d,%d, %dx%d)"
- " dst(%d,%d, %dx%d), transform(%d)",
- e_client_util_name_get(evhw->base.ec) ?: "No Name" ,
- evhw->base.ec->netwm.pid,
- vbuf, (vbuf ? vbuf->ref_cnt : 0),
- evhw->commit_data.info.src_config.size.h,
- evhw->commit_data.info.src_config.size.v,
- evhw->commit_data.info.src_config.pos.x,
- evhw->commit_data.info.src_config.pos.y,
- evhw->commit_data.info.src_config.pos.w,
- evhw->commit_data.info.src_config.pos.h,
- evhw->commit_data.info.dst_pos.x, evhw->commit_data.info.dst_pos.y,
- evhw->commit_data.info.dst_pos.w, evhw->commit_data.info.dst_pos.h,
- evhw->commit_data.info.transform);
-
- return EINA_TRUE;
-}
-
-static void
-_e_video_destroy(E_Video_Hwc_Windows *evhw)
-{
- e_hwc_window_video_set(evhw->hwc_window, EINA_FALSE);
- e_hwc_window_unref(evhw->hwc_window);
- free(evhw);
-}
-
-const char *
-_e_video_hwc_windows_prop_name_get_by_id(E_Video_Hwc_Windows *evhw, unsigned int id)
-{
- const tdm_prop *props;
- int i, count = 0;
-
- e_hwc_windows_get_video_available_properties(evhw->hwc, &props, &count);
- for (i = 0; i < count; i++)
- {
- if (props[i].id == id)
- {
- VDB("check property(%s)", evhw->base.ec, props[i].name);
- return props[i].name;
- }
- }
-
- VER("No available property: id %d", evhw->base.ec, id);
-
- return NULL;
-}
-
-static void
-_e_video_hwc_windows_iface_destroy(E_Video_Hwc *evh)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- _e_video_destroy(evhw);
-}
-
-static Eina_Bool
-_e_video_hwc_windows_iface_property_get(E_Video_Hwc *evh, unsigned int id, tdm_value *value)
-{
- E_Video_Hwc_Windows *evhw;
- tdm_error ret;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- ret = tdm_hwc_window_get_property(evhw->hwc_window->thwc_window, id, value);
- if (ret != TDM_ERROR_NONE)
- return EINA_FALSE;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_hwc_windows_iface_property_set(E_Video_Hwc *evh, unsigned int id, tdm_value value, Eina_Bool sync)
-{
- E_Video_Hwc_Windows *evhw;
- const char *name;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- VIN("set_attribute", evhw->base.ec);
-
- name = _e_video_hwc_windows_prop_name_get_by_id(evhw, id);
- if (!name)
- {
- VER("_e_video_hwc_windows_prop_name_get_by_id failed", evhw->base.ec);
- return EINA_FALSE;
- }
-
- if ((e_client_video_property_allow_get(evhw->base.ecv)) ||
- (sync == EINA_TRUE))
- {
- VIN("set_attribute now : property(%s), value(%d)", evhw->base.ec, name, value.u32);
-
- /* set the property on the fly */
- if (!e_hwc_window_set_property(evhw->hwc_window, id, name, value, EINA_TRUE))
- {
- VER("set property failed", evhw->base.ec);
- return EINA_FALSE;
- }
- }
- else
- {
- VIN("set_attribute at commit : property(%s), value(%d)", evhw->base.ec, name, value.u32);
-
- /* set the property before hwc commit */
- if (!e_hwc_window_set_property(evhw->hwc_window, id, name, value, EINA_FALSE))
- {
- VER("set property failed", evhw->base.ec);
- return EINA_FALSE;
- }
- }
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_hwc_windows_iface_available_properties_get(E_Video_Hwc *evh, const tdm_prop **props, int *count)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- if (!e_hwc_windows_get_video_available_properties(evhw->hwc, props, count))
- return EINA_FALSE;
-
- return EINA_TRUE;
-}
-
-static Eina_Bool
-_e_video_hwc_windows_iface_buffer_commit(E_Video_Hwc *evh, E_Comp_Wl_Video_Buf *vbuf)
-{
- E_Video_Hwc_Windows *evhw;
- Eina_Bool ret;
-
- evhw = (E_Video_Hwc_Windows *)evh;
-
- /* show means that set the information of the buffer and the info of the hwc window */
-
- ret = _e_video_hwc_windows_commit_data_set(evhw, vbuf);
-
- // TODO:: this logic move to the hwc windows after hwc commit
-#if 1
- e_video_hwc_client_mask_update((E_Video_Hwc *)evhw);
-#endif
-
- return ret;
-}
-
-static Eina_Bool
-_e_video_hwc_windows_iface_check_if_pp_needed(E_Video_Hwc *evh)
-{
- E_Video_Hwc_Windows *evhw;
- E_Comp_Screen *e_comp_screen;
- int i, count = 0;
- const tbm_format *formats;
- Eina_Bool found = EINA_FALSE;
- E_Hwc *hwc;
- tdm_error error = TDM_ERROR_NONE;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- hwc = evhw->hwc;
- if (hwc->tdm_hwc_video_stream)
- return EINA_FALSE;
-
- error = tdm_hwc_get_video_supported_formats(hwc->thwc, &formats, &count);
- if (error != TDM_ERROR_NONE)
- return EINA_FALSE;
-
- for (i = 0; i < count; i++)
- if (formats[i] == evhw->base.tbmfmt)
- {
- found = EINA_TRUE;
- break;
- }
-
- if (!found)
- {
- if (formats && count > 0)
- evhw->base.pp_tbmfmt = formats[0];
- else
- {
- WRN("No layer format information!!!");
- evhw->base.pp_tbmfmt = TBM_FORMAT_ARGB8888;
- }
- return EINA_TRUE;
- }
-
- if (hwc->tdm_hwc_video_scanout)
- goto need_pp;
-
- /* check size */
- if (evhw->base.geo.input_r.w != evhw->base.geo.output_r.w || evhw->base.geo.input_r.h != evhw->base.geo.output_r.h)
- if (!hwc->tdm_hwc_video_scale)
- goto need_pp;
-
- /* check rotate */
- e_comp_screen = e_comp_screen_get();
- if (evhw->base.geo.transform || (e_comp_screen && e_comp_screen->rotation > 0))
- if (!hwc->tdm_hwc_video_transform)
- goto need_pp;
-
- return EINA_FALSE;
-
-need_pp:
- evhw->base.pp_tbmfmt = evhw->base.tbmfmt;
-
- return EINA_TRUE;
-}
-
-static tbm_surface_h
-_e_video_hwc_windows_iface_displaying_buffer_get(E_Video_Hwc *evh)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- return evhw->commit_data.buffer;
-}
-
-static void
-_e_video_hwc_windows_iface_set(E_Video_Hwc_Iface *iface)
-{
- iface->destroy = _e_video_hwc_windows_iface_destroy;
- iface->property_get = _e_video_hwc_windows_iface_property_get;
- iface->property_set = _e_video_hwc_windows_iface_property_set;
- iface->available_properties_get = _e_video_hwc_windows_iface_available_properties_get;
- iface->buffer_commit = _e_video_hwc_windows_iface_buffer_commit;
- iface->check_if_pp_needed = _e_video_hwc_windows_iface_check_if_pp_needed;
- iface->displaying_buffer_get = _e_video_hwc_windows_iface_displaying_buffer_get;
-}
-
-EINTERN E_Video_Hwc *
-e_video_hwc_windows_create(E_Output *output, E_Client *ec)
-{
- E_Video_Hwc_Windows *evhw;
-
- EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
- EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
-
- VIN("Create HWC Windows backend", ec);
-
- evhw = E_NEW(E_Video_Hwc_Windows, 1);
- EINA_SAFETY_ON_NULL_RETURN_VAL(evhw, NULL);
-
- evhw->hwc = output->hwc;
- if (!evhw->hwc)
- {
- free(evhw);
- return NULL;
- }
-
- evhw->hwc_window = e_hwc_window_get(evhw->hwc, ec);
- if (!evhw->hwc_window)
- {
- free(evhw);
- return NULL;
- }
-
- e_hwc_window_ref(evhw->hwc_window);
- e_hwc_window_video_set(evhw->hwc_window, EINA_TRUE);
-
- _e_video_hwc_windows_iface_set(&evhw->base.backend);
-
- return (E_Video_Hwc *)evhw;
-}
-
-EINTERN Eina_Bool
-e_video_hwc_windows_info_get(E_Video_Hwc *evh, E_Client_Video_Info *info)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- memcpy(&info->src_config, &evhw->commit_data.info.src_config, sizeof(tdm_info_config));
- memcpy(&info->dst_pos, &evhw->commit_data.info.dst_pos, sizeof(tdm_pos));
- info->transform = evhw->commit_data.info.transform;
-
- return EINA_TRUE;
-}
-
-EINTERN Eina_Bool
-e_video_hwc_windows_commit_data_release(E_Video_Hwc *evh, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- evhw->commit_data.wait_release = EINA_FALSE;
-
- e_video_hwc_current_fb_update(evh);
-
- return EINA_TRUE;
-}
-
-EINTERN tbm_surface_h
-e_video_hwc_windows_tbm_surface_get(E_Video_Hwc *evh)
-{
- E_Video_Hwc_Windows *evhw;
-
- evhw = (E_Video_Hwc_Windows *)evh;
- return evhw->commit_data.buffer;
-}