1 #include "e_zone_video_intern.h"
2 #include "e_client_video_intern.h"
3 #include "e_comp_wl_intern.h"
4 #include "e_zone_intern.h"
5 #include "e_comp_wl_subsurface_intern.h"
6 #include "e_video_debug_intern.h"
7 #include "iface/e_video_hwc_intern.h"
8 #include "iface/e_video_external_intern.h"
9 #include "iface/e_video_fallback_intern.h"
10 #include "e_comp_wl_rsm_intern.h"
11 #include "e_eom_intern.h"
13 #define EO_DATA_KEY "E_Client_Video"
15 #define INTERNAL_DATA_GET \
16 E_Client_Video *ecv; \
17 ecv = evas_object_data_get(ec->frame, EO_DATA_KEY)
19 #define IFACE_CHECK_RET(iname, ret) \
21 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, ret); \
24 if (!ecv->iface->iname) \
26 VER("No implementation for this interface(%s)", ec, #iname); \
31 struct _E_Client_Video
33 /* Composite interface ( hwc planes / hwc windows / fallback ) */
34 E_Video_Comp_Iface *iface;
39 Eina_List *event_handlers;
43 E_Comp_Wl_Hook *subsurf_create;
44 E_Client_Hook *ec_del;
47 Eina_Bool hw_composition;
48 Eina_Bool follow_topmost_visibility;
49 Eina_Bool allowed_property;
53 _e_client_video_comp_iface_deinit(E_Client_Video *ecv)
55 if (!ecv->iface) return;
57 ecv->iface->destroy(ecv->iface);
62 _e_client_video_cb_hwc_render_fail(E_Client_Video *ecv)
64 E_Video_Comp_Iface *new_iface;
65 E_Comp_Wl_Buffer *buffer;
67 VIN("Callback Called HWC Render Fail: Try to create fallback interface",
70 new_iface = e_video_fallback_iface_create(ecv);
73 VER("Failed to create fallback interface", ecv->ec);
74 /* It does maintain HWC interface since creating fallback interface has
79 ecv->iface->destroy(ecv->iface);
80 ecv->iface = new_iface;
83 * For redrawing compositor's canvas for video buffer. */
84 buffer = e_pixmap_resource_get(ecv->ec->pixmap);
87 buffer->type = E_COMP_WL_BUFFER_TYPE_TBM;
88 e_comp_wl_surface_commit(ecv->ec);
93 _e_client_video_comp_iface_init(E_Client_Video *ecv)
95 E_Video_Comp_Iface *iface = NULL;
98 hwc_pol = e_zone_video_hwc_policy_get(ecv->zone);
100 if ((e_config->eom_enable == EINA_TRUE) && (e_eom_is_ec_external(ecv->ec)) &&
101 (hwc_pol == E_HWC_POLICY_PLANES))
103 VIN("Try to intialize external interface", ecv->ec);
104 iface = e_video_external_iface_create(ecv);
108 if (e_video_debug_display_primary_plane_value_get())
110 VIN("Select SW Compositing mode according to configuration", ecv->ec);
114 if (hwc_pol != E_HWC_POLICY_NONE)
116 VIN("Initialize the interface of the client_video for HWC mode", ecv->ec);
117 iface = e_video_hwc_iface_create(ecv);
119 e_video_hwc_render_fail_callback_set(iface, _e_client_video_cb_hwc_render_fail);
125 iface = e_video_fallback_iface_create(ecv);
128 VER("Failed to create 'E_Video_Comp_Iface'", ecv->ec);
139 _e_client_video_deinit(E_Client_Video *ecv)
141 _e_client_video_comp_iface_deinit(ecv);
143 E_FREE_LIST(ecv->event_handlers, ecore_event_handler_del);
144 E_FREE_FUNC(ecv->hook.subsurf_create, e_comp_wl_hook_del);
145 E_FREE_FUNC(ecv->hook.ec_del, e_client_hook_del);
149 _e_client_video_del(E_Client_Video *ecv)
151 _e_client_video_deinit(ecv);
153 evas_object_data_del(ecv->ec->frame, EO_DATA_KEY);
154 e_object_unref(E_OBJECT(ecv->ec));
160 _e_client_video_cb_zone_del(void *data, int type EINA_UNUSED, void *event)
163 E_Event_Zone_Del *ev;
168 if (ecv->zone != ev->zone)
171 VIN("Zone(%p) deleted.", ecv->ec, ecv->zone);
173 _e_client_video_comp_iface_deinit(ecv);
177 return ECORE_CALLBACK_PASS_ON;
181 _e_client_video_cb_ec_zone_set(void *data, int type EINA_UNUSED, void *event)
184 E_Event_Client_Zone_Set *ev;
190 if (ecv->ec != ev->ec)
193 if (ecv->zone == ev->zone)
196 VIN("Zone changed: old(%p) new(%p)", ecv->ec, ecv->zone, ev->zone);
198 ecv->zone = ev->zone;
200 _e_client_video_comp_iface_deinit(ecv);
202 res = _e_client_video_comp_iface_init(ecv);
205 VER("Failed to initialize the composition interface for video", ev->ec);
206 return ECORE_CALLBACK_PASS_ON;
210 return ECORE_CALLBACK_PASS_ON;
214 _e_client_video_cb_hook_ec_del(void *data, E_Client *ec)
222 _e_client_video_del(ecv);
226 _e_client_video_ec_visibility_event_free(void *d EINA_UNUSED, E_Event_Client *ev)
228 e_object_unref(E_OBJECT(ev->ec));
233 _e_client_video_visibility_event_send(E_Client_Video *ecv)
240 obscured = ec->visibility.obscured;
241 VIN("Signal visibility change event of video, type %d",
244 ev = E_NEW(E_Event_Client , 1);
245 EINA_SAFETY_ON_NULL_RETURN(ev);
248 e_object_ref(E_OBJECT(ec));
249 ecore_event_add(E_EVENT_CLIENT_VISIBILITY_CHANGE, ev,
250 (Ecore_End_Cb)_e_client_video_ec_visibility_event_free, NULL);
254 _e_client_video_visibility_set(E_Client_Video *ecv, E_Visibility vis)
259 if (ec->visibility.obscured == vis)
262 ec->visibility.obscured = vis;
263 _e_client_video_visibility_event_send(ecv);
267 _e_client_video_cb_ec_visibility_change(void *data, int type EINA_UNUSED, void *event)
274 if (!ecv->follow_topmost_visibility)
277 topmost = e_comp_wl_topmost_parent_get(ecv->ec);
278 if ((!topmost) || (topmost == ecv->ec))
282 if (ev->ec != topmost)
285 _e_client_video_visibility_set(ecv, topmost->visibility.obscured);
288 return ECORE_CALLBACK_PASS_ON;
292 _e_client_video_offscreen_parent_get(E_Client_Video *ecv)
294 E_Client *ec, *parent = NULL;
297 if (!e_comp_wl_subsurface_check(ec))
300 parent = e_comp_wl_subsurface_parent_get(ec);
303 if (!parent->comp_data || !parent->comp_data->sub.data)
306 if (parent->comp_data->sub.data->remote_surface.offscreen_parent)
307 return parent->comp_data->sub.data->remote_surface.offscreen_parent;
309 parent = e_comp_wl_subsurface_parent_get(parent);
316 _e_client_video_cb_remote_surface_provider_visibility_change(void *data, int type EINA_UNUSED, void *event)
319 E_Event_Remote_Surface_Provider *ev;
320 E_Client *offscreen_parent;
323 offscreen_parent = _e_client_video_offscreen_parent_get(ecv);
324 if (!offscreen_parent)
328 if (ev->ec != offscreen_parent)
331 switch (ev->ec->visibility.obscured)
333 case E_VISIBILITY_FULLY_OBSCURED:
334 evas_object_hide(ecv->ec->frame);
336 case E_VISIBILITY_UNOBSCURED:
337 evas_object_show(ecv->ec->frame);
340 VER("Not implemented", ecv->ec);
345 return ECORE_CALLBACK_PASS_ON;
349 _e_client_video_cb_hook_subsurface_create(void *data, E_Client *ec)
352 E_Client *topmost1, *topmost2;
355 if (!ecv->follow_topmost_visibility)
358 /* This is to raise an 'VISIBILITY_CHANGE' event to video client when its
359 * topmost ancestor is changed. The reason why it uses hook handler of
360 * creation of subsurface is that there is no event for like parent change,
361 * and being created subsurface that has common topmost parent means
362 * it implies topmost parent has been possibly changed. */
363 topmost1 = e_comp_wl_topmost_parent_get(ec);
364 topmost2 = e_comp_wl_topmost_parent_get(ecv->ec);
365 if (topmost1 && topmost2)
367 if (topmost1 == topmost2)
368 _e_client_video_visibility_set(ecv, topmost1->visibility.obscured);
373 _e_client_video_init(E_Client_Video *ecv, E_Client *ec)
378 ecv->zone = e_comp_zone_find_by_ec(ec);
379 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv->zone, EINA_FALSE);
381 res = _e_client_video_comp_iface_init(ecv);
384 VER("Failed to initialize the composition interface for video", ec);
388 E_LIST_HANDLER_APPEND(ecv->event_handlers, E_EVENT_ZONE_DEL,
389 _e_client_video_cb_zone_del, ecv);
390 E_LIST_HANDLER_APPEND(ecv->event_handlers, E_EVENT_CLIENT_ZONE_SET,
391 _e_client_video_cb_ec_zone_set, ecv);
392 E_LIST_HANDLER_APPEND(ecv->event_handlers, E_EVENT_CLIENT_VISIBILITY_CHANGE,
393 _e_client_video_cb_ec_visibility_change, ecv);
394 E_LIST_HANDLER_APPEND(ecv->event_handlers, E_EVENT_REMOTE_SURFACE_PROVIDER_VISIBILITY_CHANGE,
395 _e_client_video_cb_remote_surface_provider_visibility_change, ecv);
397 ecv->hook.subsurf_create =
398 e_comp_wl_hook_add(E_COMP_WL_HOOK_SUBSURFACE_CREATE,
399 _e_client_video_cb_hook_subsurface_create, ecv);
401 ecv->hook.ec_del = e_client_hook_add(E_CLIENT_HOOK_DEL,
402 _e_client_video_cb_hook_ec_del,
409 e_client_video_set(E_Client *ec)
414 VIN("Set video client", ec);
416 EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
417 EINA_SAFETY_ON_NULL_RETURN_VAL(ec->frame, EINA_FALSE);
419 if (e_object_is_del(E_OBJECT(ec)))
421 VER("Can't handle deleted client", ec);
425 ecv = evas_object_data_get(ec->frame, EO_DATA_KEY);
428 VER("Given client was already set as Video client", ec);
432 ecv = E_NEW(E_Client_Video, 1);
435 VER("Failed to allocate memory", ec);
439 res = _e_client_video_init(ecv, ec);
442 VER("Failed to initialize video setting", ec);
447 evas_object_data_set(ec->frame, EO_DATA_KEY, ecv);
448 e_object_ref(E_OBJECT(ec));
454 e_client_video_unset(E_Client *ec)
460 VWR("It's not video client or already deleted(%d)",
461 ec, e_object_is_del(E_OBJECT(ec)));
465 VIN("Unset video client", ec);
467 _e_client_video_del(ecv);
471 e_client_video_topmost_visibility_follow(E_Client *ec)
475 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, EINA_FALSE);
477 ecv->follow_topmost_visibility = EINA_TRUE;
482 e_client_video_topmost_visibility_unfollow(E_Client *ec)
486 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, EINA_FALSE);
488 ecv->follow_topmost_visibility = EINA_FALSE;
490 /* reset ec's visibility to unknown */
491 _e_client_video_visibility_set(ecv, E_VISIBILITY_UNKNOWN);
496 e_client_video_property_allow(E_Client *ec)
500 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, EINA_FALSE);
502 ecv->allowed_property = EINA_TRUE;
507 e_client_video_property_disallow(E_Client *ec)
511 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, EINA_FALSE);
513 ecv->allowed_property = EINA_FALSE;
518 e_client_video_property_get(E_Client *ec, unsigned int id, tdm_value *value)
520 IFACE_CHECK_RET(property_get, EINA_FALSE);
522 return ecv->iface->property_get(ecv->iface, id, value);
526 e_client_video_property_set(E_Client *ec, unsigned int id, tdm_value value, Eina_Bool sync)
528 IFACE_CHECK_RET(property_set, EINA_FALSE);
530 return ecv->iface->property_set(ecv->iface, id, value, sync);
534 e_client_video_property_delay_set(E_Client *ec, unsigned int id, tdm_value value)
536 IFACE_CHECK_RET(property_delay_set, EINA_FALSE);
538 return ecv->iface->property_delay_set(ecv->iface, id, value);
542 e_client_video_available_properties_get(E_Client *ec, const tdm_prop **props, int *count)
544 IFACE_CHECK_RET(available_properties_get, EINA_FALSE);
546 return ecv->iface->available_properties_get(ecv->iface, props, count);
550 e_client_video_info_get(E_Client *ec, E_Client_Video_Info *info)
552 IFACE_CHECK_RET(info_get, EINA_FALSE);
554 return ecv->iface->info_get(ecv->iface, info);
558 e_client_video_commit_data_release(E_Client *ec, unsigned int sequence, unsigned int tv_sec, unsigned int tv_usec)
560 IFACE_CHECK_RET(commit_data_release, EINA_FALSE);
562 return ecv->iface->commit_data_release(ecv->iface, sequence, tv_sec, tv_usec);
565 EINTERN tbm_surface_h
566 e_client_video_tbm_surface_get(E_Client *ec)
568 IFACE_CHECK_RET(tbm_surface_get, EINA_FALSE);
570 return ecv->iface->tbm_surface_get(ecv->iface);
574 e_client_is_video(E_Client *ec)
582 e_client_video_hw_composition_check(E_Client *ec)
589 return ecv->hw_composition;
592 /* Video Internal Functions */
594 e_client_video_ec_get(E_Client_Video *ecv)
596 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, NULL);
601 e_client_video_hw_composition_set(E_Client_Video *ecv)
603 EINA_SAFETY_ON_NULL_RETURN(ecv);
604 ecv->hw_composition = EINA_TRUE;
608 e_client_video_hw_composition_unset(E_Client_Video *ecv)
610 EINA_SAFETY_ON_NULL_RETURN(ecv);
611 ecv->hw_composition = EINA_FALSE;
615 e_client_video_property_allow_get(E_Client_Video *ecv)
617 EINA_SAFETY_ON_NULL_RETURN_VAL(ecv, EINA_FALSE);
618 return ecv->allowed_property;