1 #include "e_output_intern.h"
2 #include "e_client_intern.h"
3 #include "e_utils_intern.h"
4 #include "e_comp_screen_intern.h"
5 #include "e_comp_wl_intern.h"
6 #include "e_comp_wl_subsurface_intern.h"
7 #include "e_comp_wl_tbm_intern.h"
8 #include "e_comp_intern.h"
9 #include "e_input_intern.h"
10 #include "e_error_intern.h"
11 #include "e_hwc_window_intern.h"
12 #include "e_hwc_windows_intern.h"
13 #include "e_hwc_planes_intern.h"
14 #include "e_hwc_intern.h"
15 #include "e_comp_wl_video_buffer_intern.h"
16 #include "e_zone_intern.h"
17 #include "e_video_debug_intern.h"
19 #include <device/board-internal.h>
21 #define EOERR(f, output, x...) \
25 ELOGFE("OUTPUT", "%8s|"f, \
26 NULL, "Unknown", ##x); \
28 ELOGFE("OUTPUT", "%8s|"f, \
29 NULL, (output->id), ##x); \
33 #define EOINF(f, output, x...) \
37 ELOGF("OUTPUT", "%8s|"f, \
38 NULL, "Unknown", ##x); \
40 ELOGF("OUTPUT", "%8s|"f, \
41 NULL, (output->id), ##x); \
46 #define OUTPUT_DELAY_CONNECT_CHECK_TIMEOUT 3.0
48 typedef struct _E_Output_Capture E_Output_Capture;
49 typedef struct _E_Output_Layer E_Output_Layer;
50 typedef struct _E_Output_Stream_Capture_Mask_Data E_Output_Stream_Capture_Mask_Data;
52 struct _E_Output_Capture
55 tdm_capture *tcapture;
56 tbm_surface_h surface;
57 E_Output_Capture_Cb func;
63 struct _E_Output_Layer
69 struct _E_Output_Stream_Capture_Mask_Data
72 Eina_Stringshare *file;
73 Eina_Rectangle geometry;
76 static int _e_output_hooks_delete = 0;
77 static int _e_output_hooks_walking = 0;
79 static Eina_Inlist *_e_output_hooks[] =
81 [E_OUTPUT_HOOK_DPMS_CHANGE] = NULL,
82 [E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE] = NULL,
83 [E_OUTPUT_HOOK_MODE_CHANGE] = NULL,
84 [E_OUTPUT_HOOK_ADD] = NULL,
85 [E_OUTPUT_HOOK_REMOVE] = NULL,
88 static int _e_output_intercept_hooks_delete = 0;
89 static int _e_output_intercept_hooks_walking = 0;
91 static Eina_Inlist *_e_output_intercept_hooks[] =
93 [E_OUTPUT_INTERCEPT_HOOK_DPMS_ON] = NULL,
94 [E_OUTPUT_INTERCEPT_HOOK_DPMS_STANDBY] = NULL,
95 [E_OUTPUT_INTERCEPT_HOOK_DPMS_SUSPEND] = NULL,
96 [E_OUTPUT_INTERCEPT_HOOK_DPMS_OFF] = NULL,
99 /* Use hash mechanism to avoid ABI break.
100 * It can be widely used like private data for E_Output, if there will be need
101 * for more use case.*/
102 static Eina_Hash *_mask_data_hash = NULL;
104 static Eina_Bool _e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate);
105 static void _e_output_vblank_handler(tdm_output *output, unsigned int sequence,
106 unsigned int tv_sec, unsigned int tv_usec, void *data);
108 static E_Output_Stream_Capture_Mask_Data *_e_output_stream_capture_mask_data_get(E_Output *output);
109 static void _e_output_stream_capture_mask_data_hash_cb_data_free(void *data);
110 static void _e_output_stream_capture_mask_image_activate(E_Output *output);
111 static void _e_output_stream_capture_mask_image_deactivate(E_Output *output);
114 _e_output_display_mode_set(E_Output *output, E_Output_Display_Mode display_mode)
116 if (output == NULL) return;
117 if (output->display_mode == display_mode) return;
119 output->display_mode = display_mode;
123 _e_output_hooks_clean(void)
128 for (x = 0; x < E_OUTPUT_HOOK_LAST; x++)
129 EINA_INLIST_FOREACH_SAFE(_e_output_hooks[x], l, ch)
131 if (!ch->delete_me) continue;
132 _e_output_hooks[x] = eina_inlist_remove(_e_output_hooks[x], EINA_INLIST_GET(ch));
136 _e_output_hooks_delete = 0;
140 _e_output_hook_call(E_Output_Hook_Point hookpoint, E_Output *output)
144 _e_output_hooks_walking++;
145 EINA_INLIST_FOREACH(_e_output_hooks[hookpoint], ch)
147 if (ch->delete_me) continue;
148 ch->func(ch->data, output);
150 _e_output_hooks_walking--;
151 if ((_e_output_hooks_walking == 0) && (_e_output_hooks_delete > 0))
152 _e_output_hooks_clean();
156 _e_output_intercept_hooks_clean(void)
159 E_Output_Intercept_Hook *ch;
161 for (x = 0; x < E_OUTPUT_INTERCEPT_HOOK_LAST; x++)
162 EINA_INLIST_FOREACH_SAFE(_e_output_intercept_hooks[x], l, ch)
164 if (!ch->delete_me) continue;
165 _e_output_intercept_hooks[x] = eina_inlist_remove(_e_output_intercept_hooks[x], EINA_INLIST_GET(ch));
169 _e_output_intercept_hooks_delete = 0;
173 _e_output_intercept_hook_call(E_Output_Intercept_Hook_Point hookpoint, E_Output *output)
175 E_Output_Intercept_Hook *ch;
176 Eina_Bool res = EINA_TRUE;
178 _e_output_intercept_hooks_walking++;
179 EINA_INLIST_FOREACH(_e_output_intercept_hooks[hookpoint], ch)
181 if (ch->delete_me) continue;
182 res = ch->func(ch->data, output);
183 if (res == EINA_FALSE) break;
185 _e_output_intercept_hooks_walking--;
186 if ((_e_output_intercept_hooks_walking == 0) && (_e_output_intercept_hooks_delete > 0))
187 _e_output_intercept_hooks_clean();
193 _e_output_zoom_top_visible_ec_get()
198 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
200 ec = evas_object_data_get(o, "E_Client");
202 /* check e_client and skip e_clients not intersects with zone */
204 if (e_object_is_del(E_OBJECT(ec))) continue;
205 if (e_client_util_ignored_get(ec)) continue;
206 if (ec->iconic) continue;
207 if (ec->visible == 0) continue;
208 if (!(ec->visibility.obscured == 0 || ec->visibility.obscured == 1)) continue;
209 if (!ec->frame) continue;
210 if (!evas_object_visible_get(ec->frame)) continue;
211 if (e_comp_wl_subsurface_check(ec)) continue;
220 _e_output_zoom_get_angle(E_Output *output)
225 ec = _e_output_zoom_top_visible_ec_get();
227 ec_angle = ec->e.state.rot.ang.curr;
233 _e_output_zoom_raw_xy_get(E_Output *output, int *x, int *y)
237 e_output_size_get(output, &w, &h);
239 if (w <= 0 || h <= 0)
242 if ((output->zoom_conf.init_screen_rotation == 0) || (output->zoom_conf.init_screen_rotation == 180))
244 if (output->zoom_conf.current_screen_rotation == 0)
246 *x = output->zoom_conf.init_cx;
247 *y = output->zoom_conf.init_cy;
249 else if (output->zoom_conf.current_screen_rotation == 90)
251 *x = (float)w / h * output->zoom_conf.init_cy;
252 *y = h - (float)h / w * output->zoom_conf.init_cx - 1;
254 else if (output->zoom_conf.current_screen_rotation == 180)
256 *x = w - output->zoom_conf.init_cx - 1;
257 *y = h - output->zoom_conf.init_cy - 1;
259 else /* output->zoom_conf.current_screen_rotation == 270 */
261 *x = w - (float)w / h * output->zoom_conf.init_cy - 1;
262 *y = (float)h / w * output->zoom_conf.init_cx;
265 else /* (output->zoom_conf.init_screen_rotation == 90) || (output->zoom_conf.init_screen_rotation == 270) */
267 if (output->zoom_conf.current_screen_rotation == 0)
269 *x = (float)w / h * output->zoom_conf.init_cx;
270 *y = (float)h / w * output->zoom_conf.init_cy;
272 else if (output->zoom_conf.current_screen_rotation == 90)
274 *x = output->zoom_conf.init_cy;
275 *y = h - output->zoom_conf.init_cx - 1;
277 else if (output->zoom_conf.current_screen_rotation == 180)
279 *x = w - (float)w / h * output->zoom_conf.init_cx - 1;
280 *y = h - (float)h / w * output->zoom_conf.init_cy - 1;
282 else /* output->zoom_conf.current_screen_rotation == 270 */
284 *x = w - output->zoom_conf.init_cy - 1;
285 *y = output->zoom_conf.init_cx;
291 _e_output_zoom_scaled_rect_get(int out_w, int out_h, double zoomx, double zoomy, int cx, int cy, Eina_Rectangle *rect)
296 rect->w = (int)((double)out_w / zoomx);
297 rect->h = (int)((double)out_h / zoomy);
302 x = (((double)x) * zoomx);
303 y = (((double)y) * zoomy);
318 rect->x = (int)(dx / zoomx);
319 rect->y = (int)(dy / zoomy);
323 _e_output_zoom_coordinate_cal(E_Output *output)
327 double zoomx = 0, zoomy = 0;
328 int rotation_diff = 0;
330 rotation_diff = (360 + output->zoom_conf.current_screen_rotation - output->zoom_conf.init_screen_rotation) % 360;
332 e_output_size_get(output, &w, &h);
334 _e_output_zoom_raw_xy_get(output, &x, &y);
336 output->zoom_conf.adjusted_cx = x;
337 output->zoom_conf.adjusted_cy = y;
339 if (rotation_diff == 90 || rotation_diff == 270)
341 zoomx = output->zoom_conf.zoomy;
342 zoomy = output->zoom_conf.zoomx;
346 zoomx = output->zoom_conf.zoomx;
347 zoomy = output->zoom_conf.zoomy;
350 /* get the scaled rect */
351 _e_output_zoom_scaled_rect_get(w, h, zoomx, zoomy, x, y,
352 &output->zoom_conf.rect);
356 _e_output_zoom_touch_transform(E_Output *output, Eina_Bool set)
358 E_Input_Device *dev = NULL;
359 Eina_Bool ret = EINA_FALSE;
361 E_Output *primary_output = NULL;
364 EINA_LIST_FOREACH(e_input_devices_get(), l, dev)
366 primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
367 if (primary_output != NULL)
373 EOERR("fail get primary_output", output);
378 ret = e_input_device_touch_transformation_set(dev,
379 output->zoom_conf.rect_touch.x, output->zoom_conf.rect_touch.y,
380 output->zoom_conf.rect_touch.w, output->zoom_conf.rect_touch.h);
383 e_output_size_get(output, &w, &h);
384 ret = e_input_device_touch_transformation_set(dev, 0, 0, w, h);
387 if (ret != EINA_TRUE)
388 EOERR("fail e_input_device_touch_transformation_set", output);
394 _e_output_cb_ecore_event_filter(void *data, void *loop_data EINA_UNUSED, int type, void *event EINA_UNUSED)
396 E_Output *output = NULL;
397 E_Input_Device *dev = NULL;
399 if (type != ECORE_EVENT_MOUSE_BUTTON_UP)
400 return ECORE_CALLBACK_PASS_ON;
403 return ECORE_CALLBACK_PASS_ON;
407 dev = eina_list_data_get(e_input_devices_get());
410 EOERR("fail get e_input_device", output);
411 return ECORE_CALLBACK_PASS_ON;
414 if (output->zoom_conf.need_touch_set)
416 if (e_input_device_touch_pressed_get(dev) == 0)
418 _e_output_zoom_touch_transform(output, EINA_TRUE);
419 output->zoom_conf.need_touch_set = EINA_FALSE;
421 E_FREE_FUNC(output->touch_up_handler, ecore_event_filter_del);
425 return ECORE_CALLBACK_PASS_ON;
429 _e_output_zoom_touch_set(E_Output *output)
431 Eina_Bool ret = EINA_FALSE;
432 E_Input_Device *dev = NULL;
434 if (output->zoom_conf.need_touch_set) return EINA_TRUE;
436 dev = eina_list_data_get(e_input_devices_get());
439 EOERR("fail get e_input_device", output);
443 if (e_input_device_touch_pressed_get(dev))
445 if (output->touch_up_handler == NULL)
446 output->touch_up_handler = ecore_event_filter_add(NULL,
447 _e_output_cb_ecore_event_filter,
450 output->zoom_conf.need_touch_set = EINA_TRUE;
453 output->zoom_conf.need_touch_set = EINA_FALSE;
455 ret = _e_output_zoom_touch_transform(output, EINA_TRUE);
461 _e_output_zoom_touch_unset(E_Output *output)
463 Eina_Bool ret = EINA_FALSE;
465 if (!output) return EINA_FALSE;
467 output->zoom_conf.need_touch_set = EINA_FALSE;
469 if (output->touch_up_handler)
470 E_FREE_FUNC(output->touch_up_handler, ecore_event_filter_del);
472 ret = _e_output_zoom_touch_transform(output, EINA_FALSE);
478 _e_output_animating_check()
484 if (ec->visible && !ec->input_only)
486 if (e_comp_object_is_animating(ec->frame))
495 _e_output_render_update(E_Output *output)
499 if (_e_output_animating_check())
504 if (ec->visible && !ec->input_only)
505 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
508 e_output_render(output);
512 _e_output_force_render_set(E_Output *output)
516 EINA_SAFETY_ON_NULL_RETURN(output);
518 if (output->force_render)
521 e_output_size_get(output, &w, &h);
522 e_comp_override_add();
523 evas_damage_rectangle_add(output->hwc->evas, 0, 0, w, h);
525 output->force_render = EINA_TRUE;
526 EOINF("force render set", output);
530 _e_output_force_render_unset(E_Output *output)
532 EINA_SAFETY_ON_NULL_RETURN(output);
534 if (!output->force_render)
537 e_comp_override_del();
538 output->force_render = EINA_FALSE;
539 EOINF("force render unset", output);
543 _e_output_top_visible_ec_get()
548 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
550 ec = evas_object_data_get(o, "E_Client");
552 /* check e_client and skip e_clients not intersects with zone */
554 if (e_object_is_del(E_OBJECT(ec))) continue;
555 if (e_client_util_ignored_get(ec)) continue;
556 if (ec->iconic) continue;
557 if (ec->visible == 0) continue;
558 if (!(ec->visibility.obscured == 0 || ec->visibility.obscured == 1)) continue;
559 if (!ec->frame) continue;
560 if (!evas_object_visible_get(ec->frame)) continue;
561 if (e_comp_wl_subsurface_check(ec)) continue;
570 _e_output_top_ec_angle_get(void)
574 ec = _e_output_top_visible_ec_get();
576 return ec->e.state.rot.ang.curr;
582 _e_output_zoom_touch_rect_get(E_Output *output)
586 int zoomx = 0, zoomy = 0;
587 int rotation_diff = 0;
589 rotation_diff = (360 + output->zoom_conf.current_screen_rotation - output->zoom_conf.init_screen_rotation) % 360;
591 if (output->zoom_conf.current_screen_rotation == 0 || output->zoom_conf.current_screen_rotation == 180)
592 e_output_size_get(output, &w, &h);
594 e_output_size_get(output, &h, &w);
596 if ((rotation_diff == 90) || (rotation_diff == 270))
598 x = (float)h / w * output->zoom_conf.init_cx;
599 y = (float)w / h * output->zoom_conf.init_cy;
600 zoomx = output->zoom_conf.zoomy;
601 zoomy = output->zoom_conf.zoomx;
605 x = output->zoom_conf.init_cx;
606 y = output->zoom_conf.init_cy;
607 zoomx = output->zoom_conf.zoomx;
608 zoomy = output->zoom_conf.zoomy;
611 _e_output_zoom_scaled_rect_get(w, h, zoomx, zoomy, x, y,
612 &output->zoom_conf.rect_touch);
616 _e_output_zoom_rotate(E_Output *output)
622 EINA_SAFETY_ON_NULL_RETURN(output);
624 e_output_size_get(output, &w, &h);
626 _e_output_zoom_coordinate_cal(output);
627 _e_output_zoom_touch_rect_get(output);
629 EOINF("zoom_rect rotate(x:%d,y:%d) (w:%d,h:%d)",
630 output, output->zoom_conf.rect.x, output->zoom_conf.rect.y,
631 output->zoom_conf.rect.w, output->zoom_conf.rect.h);
633 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
635 EINA_LIST_FOREACH(output->planes, l, ep)
637 if (!e_plane_is_fb_target(ep)) continue;
639 e_plane_zoom_set(ep, &output->zoom_conf.rect);
643 if (!_e_output_zoom_touch_set(output))
644 EOERR("fail _e_output_zoom_touch_set", output);
646 /* update the ecore_evas */
647 _e_output_render_update(output);
651 e_hwc_windows_zoom_set(output->hwc, &output->zoom_conf.rect);
653 if (!_e_output_zoom_touch_set(output))
654 EOERR("fail _e_output_zoom_touch_set", output);
656 /* update the ecore_evas */
657 if (e_hwc_windows_pp_commit_possible_check(output->hwc))
658 _e_output_render_update(output);
663 e_output_zoom_rotating_check(E_Output *output)
667 angle = _e_output_zoom_get_angle(output);
668 if ((output->zoom_conf.current_angle != angle) ||
669 (output->zoom_conf.current_screen_rotation != output->config.rotation))
671 output->zoom_conf.current_angle = angle;
672 output->zoom_conf.current_screen_rotation = output->config.rotation;
673 _e_output_zoom_rotate(output);
678 _e_output_visible_client_check(E_Output *output)
682 Eina_Bool found = EINA_FALSE;
685 E_Comp_Wl_Client_Data *cdata;
686 E_Output *zone_output = NULL;
689 EINA_LIST_FOREACH(e_comp->zones, l, zone)
691 zone_output = e_output_find(zone->output_id);
692 if (!zone_output) continue;
693 if (zone_output != output) continue;
695 EINA_RECTANGLE_SET(&r, zone->x, zone->y, zone->w, zone->h);
697 E_CLIENT_REVERSE_FOREACH(ec)
699 if (e_object_is_del(E_OBJECT(ec))) continue;
700 if (e_client_util_ignored_get(ec)) continue;
701 if (!ec->frame) continue;
702 if (ec->is_cursor) continue;
703 if (!ec->visible) continue;
704 if (!evas_object_visible_get(ec->frame)) continue;
705 if (e_comp_wl_subsurface_check(ec)) continue;
706 cdata = e_client_cdata_get(ec);
707 if (cdata && !cdata->mapped) continue;
708 if (ec->iconic) continue;
709 e_client_geometry_get(ec, &x, &y, &w, &h);
710 if (E_INTERSECTS(x, y, w, h, r.x, r.y, r.w, r.h))
722 _e_output_dpms_on_render(E_Output *output)
726 if (_e_output_visible_client_check(output))
727 ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
731 _e_output_client_resize(int w, int h)
737 if ((ec->visible && !ec->input_only) ||
738 (e_client_util_name_get(ec) != NULL && !ec->input_only))
740 e_client_shell_configure_send(ec, 0, w, h);
746 _e_output_primary_update(E_Output *output)
752 e_output_update(output);
754 if (e_output_connected(output))
756 E_Output_Mode *mode = NULL;
758 mode = e_output_best_mode_find(output);
761 EOERR("fail to get best mode.", output);
765 ret = e_output_mode_apply(output, mode);
766 if (ret == EINA_FALSE)
768 EOERR("fail to e_output_mode_apply.", output);
772 output->fake_config = EINA_FALSE;
774 retval = device_board_get_boot_mode(bootmode, sizeof(bootmode));
775 if (!retval && !e_util_strcmp(bootmode, "silent"))
777 output->dpms = E_OUTPUT_DPMS_OFF;
778 EOINF("silent boot. do not set dpms", output);
782 ret = e_output_dpms_set(output, E_OUTPUT_DPMS_ON);
783 if (ret == EINA_FALSE)
785 EOERR("fail to e_output_dpms.", output);
790 ecore_event_add(E_EVENT_SCREEN_CHANGE, NULL, NULL, NULL);
792 _e_output_client_resize(e_comp->w, e_comp->h);
796 output->fake_config = EINA_TRUE;
798 ret = e_output_dpms_set(output, E_OUTPUT_DPMS_OFF);
799 if (ret == EINA_FALSE)
801 EOERR("fail to e_output_dpms.", output);
808 _e_output_external_update(E_Output *output)
810 E_Comp_Screen *e_comp_screen = NULL;
811 E_Output_Mode *mode = NULL;
812 E_Output *output_pri = NULL;
815 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
817 e_comp_screen = e_comp->e_comp_screen;
818 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
820 output_pri = e_comp_screen_primary_output_get(e_comp_screen);
823 e_error_message_show(_("Fail to get the primary output!\n"));
827 if (output_pri == output)
831 ret = e_output_update(output);
832 if (ret == EINA_FALSE)
834 EOERR("fail e_output_update.", output);
838 if (e_output_connected(output))
840 mode = e_output_best_mode_find(output);
843 EOERR("fail to get best mode.", output);
847 ret = e_output_mode_apply(output, mode);
848 if (ret == EINA_FALSE)
850 EOERR("fail to e_output_mode_apply.", output);
853 ret = e_output_dpms_set(output, E_OUTPUT_DPMS_ON);
854 if (ret == EINA_FALSE)
856 EOERR("fail to e_output_dpms.", output);
860 ret = e_output_hwc_setup(output);
861 if (ret == EINA_FALSE)
863 EOERR("fail to e_output_hwc_setup.", output);
867 _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
869 EOINF("Connect the external output", output);
873 EOINF("Disconnect the external output", output);
875 _e_output_hook_call(E_OUTPUT_HOOK_CONNECT_STATUS_CHANGE, output);
879 e_hwc_del(output->hwc);
883 if (!e_output_dpms_set(output, E_OUTPUT_DPMS_OFF))
885 EOERR("fail to e_output_dpms.", output);
894 _e_output_cb_output_change(tdm_output *toutput,
895 tdm_output_change_type type,
899 E_Output *output = NULL;
900 E_Output *primary = NULL;
902 tdm_output_dpms tdpms;
903 tdm_output_conn_status status;
904 static Eina_Bool override = EINA_FALSE;
906 EINA_SAFETY_ON_NULL_RETURN(toutput);
907 EINA_SAFETY_ON_NULL_RETURN(user_data);
909 output = (E_Output *)user_data;
913 case TDM_OUTPUT_CHANGE_CONNECTION:
914 status = (tdm_output_conn_status)value.u32;
915 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED ||
916 status == TDM_OUTPUT_CONN_STATUS_CONNECTED)
918 primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
919 EINA_SAFETY_ON_NULL_RETURN(primary);
921 if (primary == output)
922 _e_output_primary_update(output);
924 _e_output_external_update(output);
927 case TDM_OUTPUT_CHANGE_DPMS:
928 tdpms = (tdm_output_dpms)value.u32;
929 primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
930 EINA_SAFETY_ON_NULL_RETURN(primary);
932 if (tdpms == TDM_OUTPUT_DPMS_OFF)
934 edpms = E_OUTPUT_DPMS_OFF;
935 if (!override && (output == primary))
937 e_comp_override_add();
938 override = EINA_TRUE;
941 else if (tdpms == TDM_OUTPUT_DPMS_ON)
943 edpms = E_OUTPUT_DPMS_ON;
944 if (override && (output == primary))
946 e_comp_override_del();
947 override = EINA_FALSE;
949 _e_output_dpms_on_render(output);
951 else if (tdpms == TDM_OUTPUT_DPMS_STANDBY) edpms = E_OUTPUT_DPMS_STANDBY;
952 else if (tdpms == TDM_OUTPUT_DPMS_SUSPEND) edpms = E_OUTPUT_DPMS_SUSPEND;
953 else edpms = output->dpms;
955 output->dpms = edpms;
956 output->set_dpms = edpms;
958 _e_output_hook_call(E_OUTPUT_HOOK_DPMS_CHANGE, output);
967 _e_output_fb_over_plane_check(E_Output *output)
971 Eina_Bool check = EINA_FALSE;
973 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
974 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
976 fb = e_output_default_fb_target_get(output);
978 EINA_LIST_REVERSE_FOREACH(output->planes, p_l, ep)
985 if (ep->display_info.tsurface)
993 _e_output_update_fps()
995 static double time = 0.0;
996 static double lapse = 0.0;
997 static int cframes = 0;
998 static int flapse = 0;
1000 if (e_comp->calc_fps)
1003 double tim = ecore_time_get();
1005 dt = tim - e_comp->frametimes[0];
1006 e_comp->frametimes[0] = tim;
1016 else if ((tim - lapse) >= 0.5)
1018 e_comp->fps = (cframes - flapse) / (tim - lapse);
1030 eina_hash_pointer_new(_e_output_stream_capture_mask_data_hash_cb_data_free);
1036 e_output_shutdown(void)
1038 E_FREE_FUNC(_mask_data_hash, eina_hash_free);
1042 _output_type_to_str(tdm_output_type output_type)
1044 if (output_type == TDM_OUTPUT_TYPE_Unknown) return "Unknown";
1045 else if (output_type == TDM_OUTPUT_TYPE_VGA) return "VGA";
1046 else if (output_type == TDM_OUTPUT_TYPE_DVII) return "DVII";
1047 else if (output_type == TDM_OUTPUT_TYPE_DVID) return "DVID";
1048 else if (output_type == TDM_OUTPUT_TYPE_DVIA) return "DVIA";
1049 else if (output_type == TDM_OUTPUT_TYPE_SVIDEO) return "SVIDEO";
1050 else if (output_type == TDM_OUTPUT_TYPE_LVDS) return "LVDS";
1051 else if (output_type == TDM_OUTPUT_TYPE_Component) return "Component";
1052 else if (output_type == TDM_OUTPUT_TYPE_9PinDIN) return "9PinDIN";
1053 else if (output_type == TDM_OUTPUT_TYPE_DisplayPort) return "DisplayPort";
1054 else if (output_type == TDM_OUTPUT_TYPE_HDMIA) return "HDMIA";
1055 else if (output_type == TDM_OUTPUT_TYPE_HDMIB) return "HDMIB";
1056 else if (output_type == TDM_OUTPUT_TYPE_TV) return "TV";
1057 else if (output_type == TDM_OUTPUT_TYPE_eDP) return "eDP";
1058 else if (output_type == TDM_OUTPUT_TYPE_DSI) return "DSI";
1059 else return "Unknown";
1063 _e_output_cb_planes_sort(const void *d1, const void *d2)
1065 E_Plane *plane1 = (E_Plane *)d1;
1066 E_Plane *plane2 = (E_Plane *)d2;
1068 if (!plane1) return(1);
1069 if (!plane2) return(-1);
1071 return (plane1->zpos - plane2->zpos);
1074 static tdm_capture *
1075 _e_output_tdm_capture_create(E_Output *output, tdm_capture_capability cap)
1077 tdm_error error = TDM_ERROR_NONE;
1078 tdm_capture *tcapture = NULL;
1079 tdm_capture_capability capabilities;
1080 E_Comp_Screen *e_comp_screen = NULL;
1082 e_comp_screen = e_comp->e_comp_screen;
1083 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1085 error = tdm_display_get_capture_capabilities(e_comp_screen->tdisplay, &capabilities);
1086 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, NULL);
1088 if (!(capabilities & cap))
1091 tcapture = tdm_output_create_capture(output->toutput, &error);
1092 if (error != TDM_ERROR_NONE)
1094 EOERR("create tdm_capture failed", output);
1102 _e_output_center_rect_get (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
1106 if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
1109 rw = (float)src_w / dst_w;
1110 rh = (float)src_h / dst_h;
1115 fit->h = src_h / rw;
1117 fit->y = (dst_h - fit->h) / 2;
1121 fit->w = src_w / rh;
1123 fit->x = (dst_w - fit->w) / 2;
1135 fit->x = fit->x - 1;
1139 _e_output_capture_position_get(E_Output *output, int dst_w, int dst_h, Eina_Rectangle *fit, Eina_Bool rotate)
1141 int output_w = 0, output_h = 0;
1143 e_output_size_get(output, &output_w, &output_h);
1145 if (output_w == 0 || output_h == 0)
1149 _e_output_center_rect_get(output_h, output_w, dst_w, dst_h, fit);
1151 _e_output_center_rect_get(output_w, output_h, dst_w, dst_h, fit);
1156 static E_Output_Capture *
1157 _e_output_tdm_stream_capture_find_data(E_Output *output, tbm_surface_h tsurface)
1159 E_Output_Capture *cdata = NULL;
1162 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
1164 if (!cdata) continue;
1166 if (cdata->surface == tsurface)
1174 _e_output_tdm_stream_capture_stop(void *data)
1176 E_Output *output = data;
1178 EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_CANCEL);
1180 if (output->stream_capture.tcapture)
1182 DBG("output stream capture stop.");
1183 tdm_capture_destroy(output->stream_capture.tcapture);
1184 output->stream_capture.tcapture = NULL;
1187 output->stream_capture.timer = NULL;
1189 return ECORE_CALLBACK_CANCEL;
1193 _e_output_tdm_stream_capture_done_handler(tdm_capture *tcapture,
1194 tbm_surface_h tsurface, void *user_data)
1196 E_Output *output = NULL;
1197 E_Output_Capture *cdata = NULL;
1199 output = (E_Output *)user_data;
1201 tbm_surface_internal_unref(tsurface);
1203 cdata = _e_output_tdm_stream_capture_find_data(output, tsurface);
1206 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1207 if (!cdata->dequeued)
1208 cdata->func(output, tsurface, cdata->data);
1212 if (!output->stream_capture.start)
1214 if (eina_list_count(output->stream_capture.data) == 0)
1215 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
1216 _e_output_tdm_stream_capture_stop, output);
1221 _e_output_capture_transform_check(E_Output *output, Eina_Bool auto_rotate, int *transform)
1223 int output_angle = 0;
1225 Eina_Bool rotated = EINA_FALSE;
1229 output_angle = output->config.rotation;
1230 cal_angle = (_e_output_top_ec_angle_get() + output_angle) % 360;
1232 if (auto_rotate && (cal_angle == 90 || cal_angle == 270))
1233 rotated = EINA_TRUE;
1236 *transform = cal_angle;
1237 else if (auto_rotate)
1238 *transform = output_angle;
1244 _e_output_tdm_capture_info_set(E_Output *output, tdm_capture *tcapture, tbm_surface_h tsurface,
1245 tdm_capture_type type, Eina_Bool auto_rotate)
1247 tdm_error error = TDM_ERROR_NONE;
1248 tdm_info_capture capture_info;
1249 tbm_error_e tbm_error = TBM_ERROR_NONE;
1250 tbm_surface_info_s surf_info;
1251 Eina_Rectangle dst_pos;
1255 Eina_Bool rotated = EINA_FALSE;
1257 tbm_error = tbm_surface_get_info(tsurface, &surf_info);
1258 EINA_SAFETY_ON_FALSE_RETURN_VAL(tbm_error == TBM_ERROR_NONE, EINA_FALSE);
1260 width = e_comp_wl_tbm_aligned_width_get(tsurface);
1261 EINA_SAFETY_ON_TRUE_RETURN_VAL(width == 0, EINA_FALSE);
1263 memset(&capture_info, 0, sizeof(tdm_info_capture));
1264 capture_info.dst_config.size.h = width;
1265 capture_info.dst_config.size.v = surf_info.height;
1266 capture_info.dst_config.format = surf_info.format;
1267 capture_info.transform = TDM_TRANSFORM_NORMAL;
1269 rotated = _e_output_capture_transform_check(output, auto_rotate, &transform);
1271 ret = _e_output_capture_position_get(output, surf_info.width, surf_info.height, &dst_pos, rotated);
1274 capture_info.dst_config.pos.x = dst_pos.x;
1275 capture_info.dst_config.pos.y = dst_pos.y;
1276 capture_info.dst_config.pos.w = dst_pos.w;
1277 capture_info.dst_config.pos.h = dst_pos.h;
1280 capture_info.transform = TDM_TRANSFORM_NORMAL;
1281 else if (transform == 90)
1282 capture_info.transform = TDM_TRANSFORM_90;
1283 else if (transform == 180)
1284 capture_info.transform = TDM_TRANSFORM_180;
1285 else if (transform == 270)
1286 capture_info.transform = TDM_TRANSFORM_270;
1290 capture_info.dst_config.pos.x = 0;
1291 capture_info.dst_config.pos.y = 0;
1292 capture_info.dst_config.pos.w = surf_info.width;
1293 capture_info.dst_config.pos.h = surf_info.height;
1296 capture_info.type = type;
1298 error = tdm_capture_set_info(tcapture, &capture_info);
1299 if (error != TDM_ERROR_NONE)
1301 EOERR("tdm_capture set_info failed", output);
1305 if (auto_rotate && type == TDM_CAPTURE_TYPE_STREAM)
1306 output->stream_capture.current_angle = transform;
1312 _e_output_tdm_capture_done_handler(tdm_capture *tcapture, tbm_surface_h tsurface, void *user_data)
1314 E_Output *output = NULL;
1315 E_Output_Capture *cdata = NULL;
1317 cdata = (E_Output_Capture *)user_data;
1318 output = cdata->output;
1320 tbm_surface_internal_unref(tsurface);
1322 cdata->func(output, tsurface, cdata->data);
1324 tdm_capture_destroy(cdata->tcapture);
1328 DBG("tdm_capture done.(%p)", tsurface);
1332 _e_output_tdm_capture(E_Output *output, tdm_capture *tcapture,
1333 tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
1335 tdm_error error = TDM_ERROR_NONE;
1336 E_Output_Capture *cdata = NULL;
1338 cdata = E_NEW(E_Output_Capture, 1);
1339 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
1341 cdata->output = output;
1342 cdata->tcapture = tcapture;
1346 tbm_surface_internal_ref(tsurface);
1348 error = tdm_capture_set_done_handler(tcapture, _e_output_tdm_capture_done_handler, cdata);
1349 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1351 error = tdm_capture_attach(tcapture, tsurface);
1352 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1354 error = tdm_capture_commit(tcapture);
1355 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1360 tbm_surface_internal_unref(tsurface);
1368 _e_output_stream_capture_cb_timeout(void *data)
1370 E_Output *output = data;
1371 E_Output_Capture *cdata = NULL;
1374 EINA_SAFETY_ON_NULL_GOTO(output, done);
1376 if (!output->stream_capture.start)
1378 EINA_LIST_FREE(output->stream_capture.data, cdata)
1380 tbm_surface_internal_unref(cdata->surface);
1385 if (output->stream_capture.tcapture)
1387 tdm_capture_destroy(output->stream_capture.tcapture);
1388 output->stream_capture.tcapture = NULL;
1391 DBG("output stream capture stop.");
1393 output->stream_capture.timer = NULL;
1395 return ECORE_CALLBACK_CANCEL;
1398 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
1400 if (!cdata->in_using) break;
1403 /* can be null when client doesn't queue a buffer previously */
1407 cdata->in_using = EINA_TRUE;
1409 tbm_surface_internal_unref(cdata->surface);
1411 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1413 cdata->func(output, cdata->surface, cdata->data);
1417 return ECORE_CALLBACK_RENEW;
1421 _e_output_tdm_stream_capture(E_Output *output, tdm_capture *tcapture,
1422 tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
1424 tdm_error error = TDM_ERROR_NONE;
1425 E_Output_Capture *cdata = NULL;
1426 E_Output_Capture *tmp_cdata = NULL;
1429 cdata = E_NEW(E_Output_Capture, 1);
1430 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
1432 cdata->output = output;
1433 cdata->tcapture = tcapture;
1434 cdata->surface = tsurface;
1438 tbm_surface_internal_ref(tsurface);
1440 output->stream_capture.data = eina_list_append(output->stream_capture.data, cdata);
1442 if (output->stream_capture.start)
1444 if (e_output_dpms_get(output))
1446 if (!output->stream_capture.timer)
1447 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
1448 _e_output_stream_capture_cb_timeout, output);
1449 EINA_SAFETY_ON_NULL_RETURN_VAL(output->stream_capture.timer, EINA_FALSE);
1453 else if (output->stream_capture.timer)
1455 ecore_timer_del(output->stream_capture.timer);
1456 output->stream_capture.timer = NULL;
1458 EINA_LIST_FOREACH_SAFE(output->stream_capture.data, l, ll, tmp_cdata)
1460 if (!tmp_cdata) continue;
1462 if (!tmp_cdata->in_using)
1464 tmp_cdata->in_using = EINA_TRUE;
1466 error = tdm_capture_attach(tcapture, tsurface);
1467 if (error != TDM_ERROR_NONE)
1469 EOERR("tdm_capture_attach fail", output);
1470 output->stream_capture.data = eina_list_remove_list(output->stream_capture.data, l);
1471 tmp_cdata->func(tmp_cdata->output, tmp_cdata->surface, tmp_cdata->data);
1478 error = tdm_capture_commit(tcapture);
1479 if (error != TDM_ERROR_NONE)
1481 EOERR("tdm_capture_commit fail", output);
1487 cdata->in_using = EINA_TRUE;
1489 error = tdm_capture_attach(tcapture, tsurface);
1490 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1492 error = tdm_capture_commit(tcapture);
1493 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1498 if (e_output_dpms_get(output))
1501 cdata->in_using = EINA_TRUE;
1503 error = tdm_capture_attach(tcapture, tsurface);
1504 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1510 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1512 tbm_surface_internal_unref(tsurface);
1520 _e_output_watch_vblank_timer(void *data)
1522 E_Output *output = data;
1524 EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_RENEW);
1526 _e_output_vblank_handler(NULL, 0, 0, 0, (void *)output);
1528 return ECORE_CALLBACK_RENEW;
1532 _e_output_watch_vblank(E_Output *output)
1537 /* If not DPMS_ON, we call vblank handler directly to dump screen */
1538 if (e_output_dpms_get(output))
1540 if (!output->stream_capture.timer)
1541 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
1542 _e_output_watch_vblank_timer, output);
1543 EINA_SAFETY_ON_NULL_RETURN_VAL(output->stream_capture.timer, EINA_FALSE);
1547 else if (output->stream_capture.timer)
1549 ecore_timer_del(output->stream_capture.timer);
1550 output->stream_capture.timer = NULL;
1553 if (output->stream_capture.wait_vblank)
1556 per_vblank = output->config.mode.refresh / DUMP_FPS;
1557 if (per_vblank == 0)
1560 ret = tdm_output_wait_vblank(output->toutput, per_vblank, 0,
1561 _e_output_vblank_handler, output);
1562 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
1564 output->stream_capture.wait_vblank = EINA_TRUE;
1570 _e_output_capture_oneshot_cb(E_Output *output, tbm_surface_h tsurface, void *user_data)
1572 E_Output_Capture *cdata = (E_Output_Capture *)user_data;
1574 EINA_SAFETY_ON_NULL_RETURN(cdata);
1576 tbm_surface_internal_unref(cdata->surface);
1578 cdata->func(output, cdata->surface, cdata->data);
1582 /* timer is a substitution for vblank during dpms off. so if timer is running,
1583 * we don't watch vblank events recursively.
1585 if (!output->stream_capture.timer)
1586 _e_output_watch_vblank(output);
1588 // DBG("_e_output_capture_oneshot_cb done");
1592 _e_output_vblank_handler(tdm_output *toutput, unsigned int sequence,
1593 unsigned int tv_sec, unsigned int tv_usec, void *data)
1595 E_Output *output = data;
1596 E_Output_Capture *cdata = NULL;
1598 Eina_Bool ret = EINA_FALSE;
1599 tdm_capture *tcapture = NULL;
1601 EINA_SAFETY_ON_NULL_RETURN(output);
1603 output->stream_capture.wait_vblank = EINA_FALSE;
1605 if (!output->stream_capture.start)
1607 EINA_LIST_FREE(output->stream_capture.data, cdata)
1609 tbm_surface_internal_unref(cdata->surface);
1614 if (output->stream_capture.timer)
1616 ecore_timer_del(output->stream_capture.timer);
1617 output->stream_capture.timer = NULL;
1619 DBG("output stream capture stop.");
1624 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
1626 if (!cdata->in_using) break;
1629 /* can be null when client doesn't queue a buffer previously */
1633 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1635 tcapture = _e_output_tdm_capture_create(output, TDM_CAPTURE_CAPABILITY_ONESHOT);
1638 ret = _e_output_tdm_capture_info_set(output, tcapture, cdata->surface, TDM_CAPTURE_TYPE_ONESHOT, output->stream_capture.auto_rotate);
1639 if (ret == EINA_FALSE)
1641 EOERR("capture set info fail", output);
1642 tdm_capture_destroy(tcapture);
1646 ret = _e_output_tdm_capture(output, tcapture, cdata->surface, _e_output_capture_oneshot_cb, cdata);
1647 if (ret == EINA_FALSE)
1649 EOERR("capture fail", output);
1650 tdm_capture_destroy(tcapture);
1655 ret = _e_output_capture(output, cdata->surface, output->stream_capture.auto_rotate);
1656 if (ret == EINA_FALSE)
1657 EOERR("capture fail", output);
1659 tbm_surface_internal_unref(cdata->surface);
1661 cdata->func(output, cdata->surface, cdata->data);
1665 /* timer is a substitution for vblank during dpms off. so if timer is running,
1666 * we don't watch vblank events recursively.
1668 if (!output->stream_capture.timer)
1669 _e_output_watch_vblank(output);
1674 _e_output_vblank_stream_capture(E_Output *output, tbm_surface_h tsurface,
1675 E_Output_Capture_Cb func, void *data)
1677 E_Output_Capture *cdata = NULL;
1678 Eina_Bool ret = EINA_FALSE;
1680 cdata = E_NEW(E_Output_Capture, 1);
1681 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
1683 cdata->output = output;
1684 cdata->surface = tsurface;
1688 tbm_surface_internal_ref(tsurface);
1690 output->stream_capture.data = eina_list_append(output->stream_capture.data, cdata);
1692 if (output->stream_capture.start)
1694 ret = _e_output_watch_vblank(output);
1695 if (ret == EINA_FALSE)
1697 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1698 tbm_surface_internal_unref(tsurface);
1709 _e_output_capture_showing_rect_get(Eina_Rectangle *out_rect, Eina_Rectangle *dst_rect, Eina_Rectangle *showing_rect)
1711 showing_rect->x = dst_rect->x;
1712 showing_rect->y = dst_rect->y;
1714 if (dst_rect->x >= out_rect->w)
1715 showing_rect->w = 0;
1716 else if (dst_rect->x + dst_rect->w > out_rect->w)
1717 showing_rect->w = out_rect->w - dst_rect->x;
1719 showing_rect->w = dst_rect->w;
1721 if (dst_rect->y >= out_rect->h)
1722 showing_rect->h = 0;
1723 else if (dst_rect->y + dst_rect->h > out_rect->h)
1724 showing_rect->h = out_rect->h - dst_rect->y;
1726 showing_rect->h = dst_rect->h;
1730 _e_output_capture_src_crop_get(E_Output *output, tdm_layer *layer, Eina_Rectangle *fit, Eina_Rectangle *showing_rect)
1732 tdm_info_layer info;
1733 tdm_error error = TDM_ERROR_NONE;
1734 const tdm_output_mode *mode = NULL;
1735 float ratio_x, ratio_y;
1736 Eina_Rectangle out_rect;
1737 Eina_Rectangle dst_rect;
1744 error = tdm_output_get_mode(output->toutput, &mode);
1745 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1749 out_rect.w = mode->hdisplay;
1750 out_rect.h = mode->vdisplay;
1752 error = tdm_layer_get_info(layer, &info);
1753 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1755 dst_rect.x = info.dst_pos.x;
1756 dst_rect.y = info.dst_pos.y;
1757 dst_rect.w = info.dst_pos.w;
1758 dst_rect.h = info.dst_pos.h;
1760 _e_output_capture_showing_rect_get(&out_rect, &dst_rect, showing_rect);
1762 fit->x = info.src_config.pos.x;
1763 fit->y = info.src_config.pos.y;
1765 if (info.transform % 2 == 0)
1767 ratio_x = (float)info.src_config.pos.w / dst_rect.w;
1768 ratio_y = (float)info.src_config.pos.h / dst_rect.h;
1770 fit->w = showing_rect->w * ratio_x;
1771 fit->h = showing_rect->h * ratio_y;
1775 ratio_x = (float)info.src_config.pos.w / dst_rect.h;
1776 ratio_y = (float)info.src_config.pos.h / dst_rect.w;
1778 fit->w = showing_rect->h * ratio_x;
1779 fit->h = showing_rect->w * ratio_y;
1786 _e_output_capture_dst_crop_get(E_Output *output, E_Comp_Wl_Video_Buf *tmp, E_Comp_Wl_Video_Buf *dst, tdm_layer *layer,
1787 int w, int h, Eina_Rectangle *pos, Eina_Rectangle *showing_pos,
1788 Eina_Rectangle *dst_crop, int rotate)
1790 tdm_info_layer info;
1791 tdm_error error = TDM_ERROR_NONE;
1798 error = tdm_layer_get_info(layer, &info);
1799 EINA_SAFETY_ON_FALSE_RETURN(error == TDM_ERROR_NONE);
1801 if (info.src_config.pos.w == w && info.src_config.pos.h == h &&
1802 pos->x == 0 && pos->y == 0 && pos->w == tmp->width && pos->h == tmp->height)
1804 dst_crop->x = pos->x;
1805 dst_crop->y = pos->y;
1806 dst_crop->w = pos->w;
1807 dst_crop->h = pos->h;
1809 else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
1811 dst_crop->x = info.dst_pos.x + pos->x;
1812 dst_crop->y = info.dst_pos.y + pos->y;
1813 dst_crop->w = info.dst_pos.w;
1814 dst_crop->h = info.dst_pos.h;
1816 else if (rotate == 0)
1818 dst_crop->x = showing_pos->x * pos->w / w + pos->x;
1819 dst_crop->y = showing_pos->y * pos->h / h + pos->y;
1820 dst_crop->w = showing_pos->w * pos->w / w;
1821 dst_crop->h = showing_pos->h * pos->h / h;
1823 else if (rotate == 90)
1825 dst_crop->x = (h - showing_pos->y - showing_pos->h) * pos->w / h + pos->x;
1826 dst_crop->y = showing_pos->x * pos->h / w + pos->y;
1827 dst_crop->w = showing_pos->h * pos->w / h;
1828 dst_crop->h = showing_pos->w * pos->h / w;
1830 else if (rotate == 180)
1832 dst_crop->x = (w - showing_pos->x - showing_pos->w) * pos->w / w + pos->x;
1833 dst_crop->y = (h - showing_pos->y - showing_pos->h) * pos->h / h + pos->y;
1834 dst_crop->w = showing_pos->w * pos->w / w;
1835 dst_crop->h = showing_pos->h * pos->h / h;
1837 else if (rotate == 270)
1839 dst_crop->x = showing_pos->y * pos->w / h + pos->x;
1840 dst_crop->y = (w - showing_pos->x - showing_pos->w) * pos->h / w + pos->y;
1841 dst_crop->w = showing_pos->h * pos->w / h;
1842 dst_crop->h = showing_pos->w * pos->h / w;
1846 dst_crop->x = pos->x;
1847 dst_crop->y = pos->y;
1848 dst_crop->w = pos->w;
1849 dst_crop->h = pos->h;
1850 EOERR("get_cropinfo: unknown case error", output);
1855 _e_output_capture_src_crop_get_hwc_window(E_Output *output, E_Hwc_Window *hwc_window, Eina_Rectangle *fit, Eina_Rectangle *showing_rect)
1857 tdm_error error = TDM_ERROR_NONE;
1858 const tdm_output_mode *mode = NULL;
1859 float ratio_x, ratio_y;
1860 Eina_Rectangle out_rect;
1861 Eina_Rectangle dst_rect;
1868 error = tdm_output_get_mode(output->toutput, &mode);
1869 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1873 out_rect.w = mode->hdisplay;
1874 out_rect.h = mode->vdisplay;
1876 dst_rect.x = hwc_window->current.info.dst_pos.x;
1877 dst_rect.y = hwc_window->current.info.dst_pos.y;
1878 dst_rect.w = hwc_window->current.info.dst_pos.w;
1879 dst_rect.h = hwc_window->current.info.dst_pos.h;
1881 _e_output_capture_showing_rect_get(&out_rect, &dst_rect, showing_rect);
1883 fit->x = hwc_window->current.info.src_config.pos.x;
1884 fit->y = hwc_window->current.info.src_config.pos.y;
1886 if (hwc_window->current.info.transform % 2 == 0)
1888 ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.w;
1889 ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.h;
1891 fit->w = showing_rect->w * ratio_x;
1892 fit->h = showing_rect->h * ratio_y;
1896 ratio_x = (float)hwc_window->current.info.src_config.pos.w / dst_rect.h;
1897 ratio_y = (float)hwc_window->current.info.src_config.pos.h / dst_rect.w;
1899 fit->w = showing_rect->h * ratio_x;
1900 fit->h = showing_rect->w * ratio_y;
1907 _e_output_capture_dst_crop_get_hwc_window(E_Output *output, E_Hwc_Window *hwc_window, E_Comp_Wl_Video_Buf *tmp, E_Comp_Wl_Video_Buf *dst,
1908 int w, int h, Eina_Rectangle *pos, Eina_Rectangle *showing_pos,
1909 Eina_Rectangle *dst_crop, int rotate)
1916 if (hwc_window->current.info.src_config.pos.w == w && hwc_window->current.info.src_config.pos.h == h &&
1917 pos->x == 0 && pos->y == 0 && pos->w == tmp->width && pos->h == tmp->height)
1919 dst_crop->x = pos->x;
1920 dst_crop->y = pos->y;
1921 dst_crop->w = pos->w;
1922 dst_crop->h = pos->h;
1924 else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
1926 dst_crop->x = hwc_window->current.info.dst_pos.x + pos->x;
1927 dst_crop->y = hwc_window->current.info.dst_pos.y + pos->y;
1928 dst_crop->w = hwc_window->current.info.dst_pos.w;
1929 dst_crop->h = hwc_window->current.info.dst_pos.h;
1931 else if (rotate == 0)
1933 dst_crop->x = showing_pos->x * pos->w / w + pos->x;
1934 dst_crop->y = showing_pos->y * pos->h / h + pos->y;
1935 dst_crop->w = showing_pos->w * pos->w / w;
1936 dst_crop->h = showing_pos->h * pos->h / h;
1938 else if (rotate == 90)
1940 dst_crop->x = (h - showing_pos->y - showing_pos->h) * pos->w / h + pos->x;
1941 dst_crop->y = showing_pos->x * pos->h / w + pos->y;
1942 dst_crop->w = showing_pos->h * pos->w / h;
1943 dst_crop->h = showing_pos->w * pos->h / w;
1945 else if (rotate == 180)
1947 dst_crop->x = (w - showing_pos->x - showing_pos->w) * pos->w / w + pos->x;
1948 dst_crop->y = (h - showing_pos->y - showing_pos->h) * pos->h / h + pos->y;
1949 dst_crop->w = showing_pos->w * pos->w / w;
1950 dst_crop->h = showing_pos->h * pos->h / h;
1952 else if (rotate == 270)
1954 dst_crop->x = showing_pos->y * pos->w / h + pos->x;
1955 dst_crop->y = (w - showing_pos->x - showing_pos->w) * pos->h / w + pos->y;
1956 dst_crop->w = showing_pos->h * pos->w / h;
1957 dst_crop->h = showing_pos->w * pos->h / w;
1961 dst_crop->x = pos->x;
1962 dst_crop->y = pos->y;
1963 dst_crop->w = pos->w;
1964 dst_crop->h = pos->h;
1965 EOERR("get_cropinfo: unknown case error", output);
1970 _e_output_layer_sort_cb(const void *d1, const void *d2)
1972 E_Output_Layer *e_layer_1 = (E_Output_Layer *)d1;
1973 E_Output_Layer *e_layer_2 = (E_Output_Layer *)d2;
1975 if (!e_layer_1) return(1);
1976 if (!e_layer_2) return(-1);
1978 return (e_layer_1->zpos - e_layer_2->zpos);
1982 _e_output_cb_hwc_window_sort(const void *d1, const void *d2)
1984 E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
1985 E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
1987 if (!hwc_window1) return(1);
1988 if (!hwc_window2) return(-1);
1990 return (e_hwc_window_zpos_get(hwc_window1) - e_hwc_window_zpos_get(hwc_window2));
1994 _e_output_vbuf_capture_hwc_windows(E_Output *output, E_Hwc_Window *hwc_window, E_Comp_Wl_Video_Buf *vbuf, int rotate, Eina_Bool rotate_check)
1997 E_Comp_Wl_Video_Buf *tmp = NULL;
1998 tbm_surface_h tsurface = NULL, capturable_tsurface = NULL;
1999 Eina_Rectangle showing_pos = {0, };
2000 Eina_Rectangle dst_pos = {0, };
2001 Eina_Rectangle src_crop = {0, };
2002 Eina_Rectangle dst_crop = {0, };
2003 Eina_Bool ret = EINA_FALSE;
2005 e_output_size_get(output, &w, &h);
2007 tsurface = e_hwc_window_displaying_surface_get(hwc_window);
2008 if (!tsurface) return EINA_FALSE;
2010 capturable_tsurface = e_comp_wl_tbm_capturable_buffer_get(tsurface);
2011 if (!capturable_tsurface) return EINA_FALSE;
2013 tmp = e_comp_wl_video_buffer_create_tbm(capturable_tsurface);
2017 ret = _e_output_capture_src_crop_get_hwc_window(output, hwc_window, &src_crop, &showing_pos);
2018 if (ret == EINA_FALSE)
2021 ret = _e_output_capture_position_get(output, vbuf->width, vbuf->height, &dst_pos, rotate_check);
2022 if (ret == EINA_FALSE)
2025 _e_output_capture_dst_crop_get_hwc_window(output, hwc_window, tmp, vbuf, w, h,
2026 &dst_pos, &showing_pos, &dst_crop, rotate);
2028 e_comp_wl_video_buffer_convert(tmp, vbuf,
2029 src_crop.x, src_crop.y, src_crop.w, src_crop.h,
2030 dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
2031 EINA_TRUE, rotate, 0, 0);
2036 tbm_surface_internal_unref(capturable_tsurface);
2037 e_comp_wl_video_buffer_unref(tmp);
2043 _e_output_vbuf_capture_hwc_window(E_Output *output, E_Comp_Wl_Video_Buf *vbuf, int rotate, Eina_Bool rotate_check)
2045 int width = 0, height = 0;
2047 E_Hwc_Window *hwc_window = NULL;
2049 Eina_List *visible_list = NULL;
2050 Eina_Bool target_window = EINA_FALSE;
2052 e_output_size_get(output, &width, &height);
2053 if (width == 0 || height == 0)
2057 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
2059 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2061 if (!hwc_window) continue;
2062 if (hwc_window->is_target) continue;
2063 if (e_hwc_window_is_video(hwc_window)) continue;
2064 if (e_hwc_window_zpos_get(hwc_window) == -999) continue;
2066 if (e_hwc_window_accepted_state_get(hwc_window) == E_HWC_WINDOW_STATE_CLIENT)
2068 target_window = EINA_TRUE;
2069 visible_list = eina_list_append(visible_list, hwc_window);
2073 if (e_hwc_window_accepted_state_get(hwc_window) == E_HWC_WINDOW_STATE_DEVICE)
2074 visible_list = eina_list_append(visible_list, hwc_window);
2077 if (eina_list_count(visible_list) == 0)
2079 EOINF("no visible hwc_window for capture", output);
2080 _e_output_vbuf_capture_hwc_windows(output, (E_Hwc_Window *)hwc->target_hwc_window, vbuf, rotate, rotate_check);
2084 visible_list = eina_list_sort(visible_list, eina_list_count(visible_list), _e_output_cb_hwc_window_sort);
2086 EINA_LIST_FOREACH(visible_list, l, hwc_window)
2088 if (e_hwc_window_accepted_state_get(hwc_window) == E_HWC_WINDOW_STATE_CLIENT)
2092 target_window = EINA_FALSE;
2093 _e_output_vbuf_capture_hwc_windows(output, (E_Hwc_Window *)hwc->target_hwc_window, vbuf, rotate, rotate_check);
2098 _e_output_vbuf_capture_hwc_windows(output, hwc_window, vbuf, rotate, rotate_check);
2105 _e_output_vbuf_capture(E_Output *output, E_Comp_Wl_Video_Buf *vbuf, int rotate, Eina_Bool rotate_check)
2107 tdm_error error = TDM_ERROR_NONE;
2108 int width = 0, height = 0;
2110 E_Output_Layer *e_layer = NULL;
2111 Eina_List *layers = NULL;
2113 Eina_Bool ret = EINA_FALSE;
2115 e_output_size_get(output, &width, &height);
2116 if (width == 0 || height == 0)
2119 error = tdm_output_get_layer_count(output->toutput, &count);
2120 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, ret);
2121 EINA_SAFETY_ON_FALSE_RETURN_VAL(count >= 0, ret);
2123 for (i = 0; i < count; i++)
2127 E_Output_Layer *e_layer = E_NEW(E_Output_Layer, 1);
2128 EINA_SAFETY_ON_NULL_GOTO(e_layer, release);
2130 layers = eina_list_append(layers, e_layer);
2132 layer = tdm_output_get_layer(output->toutput, i, &error);
2133 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, release);
2135 tdm_layer_get_zpos(layer, &zpos);
2136 e_layer->layer = layer;
2137 e_layer->zpos = zpos;
2139 layers = eina_list_sort(layers, eina_list_count(layers), _e_output_layer_sort_cb);
2141 EINA_LIST_FOREACH(layers, l, e_layer)
2143 E_Comp_Wl_Video_Buf *tmp = NULL;
2145 tdm_layer_capability capability;
2146 tbm_surface_h tsurface = NULL, capturable_tsurface = NULL;
2147 Eina_Rectangle showing_pos = {0, };
2148 Eina_Rectangle dst_pos = {0, };
2149 Eina_Rectangle src_crop = {0, };
2150 Eina_Rectangle dst_crop = {0, };
2153 if (!e_layer) continue;
2155 if (e_layer->zpos < 0) continue;
2156 layer = e_layer->layer;
2158 error = tdm_layer_get_capabilities(layer, &capability);
2159 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, release);
2161 if (capability & TDM_LAYER_CAPABILITY_VIDEO)
2164 tsurface = tdm_layer_get_displaying_buffer(layer, &error);
2165 if (tsurface == NULL)
2168 capturable_tsurface = e_comp_wl_tbm_capturable_buffer_get(tsurface);
2169 if (!capturable_tsurface) continue;
2171 tmp = e_comp_wl_video_buffer_create_tbm(tsurface);
2174 tbm_surface_internal_unref(capturable_tsurface);
2178 ret = _e_output_capture_src_crop_get(output, layer, &src_crop, &showing_pos);
2179 if (ret == EINA_FALSE)
2181 tbm_surface_internal_unref(capturable_tsurface);
2182 e_comp_wl_video_buffer_unref(tmp);
2186 ret = _e_output_capture_position_get(output, vbuf->width, vbuf->height, &dst_pos, rotate_check);
2187 if (ret == EINA_FALSE)
2189 tbm_surface_internal_unref(capturable_tsurface);
2190 e_comp_wl_video_buffer_unref(tmp);
2194 _e_output_capture_dst_crop_get(output, tmp, vbuf, layer, width, height,
2195 &dst_pos, &showing_pos, &dst_crop, rotate);
2197 e_comp_wl_video_buffer_convert(tmp, vbuf,
2198 src_crop.x, src_crop.y, src_crop.w, src_crop.h,
2199 dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
2200 EINA_TRUE, rotate, 0, 0);
2202 tbm_surface_internal_unref(capturable_tsurface);
2203 e_comp_wl_video_buffer_unref(tmp);
2211 E_Output_Layer *e_layer = NULL;
2214 EINA_LIST_FOREACH_SAFE(layers, l, ll, e_layer)
2218 eina_list_free(layers);
2225 _e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate)
2227 E_Comp_Wl_Video_Buf *vbuf = NULL;
2228 Eina_Bool ret = EINA_FALSE;
2230 Eina_Bool rotated = EINA_FALSE;
2232 vbuf = e_comp_wl_video_buffer_create_tbm(tsurface);
2233 EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, EINA_FALSE);
2235 e_comp_wl_video_buffer_clear(vbuf);
2237 rotated = _e_output_capture_transform_check(output, auto_rotate, &transform);
2239 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_WINDOWS)
2240 ret = _e_output_vbuf_capture_hwc_window(output, vbuf, transform, rotated);
2242 ret = _e_output_vbuf_capture(output, vbuf, transform, rotated);
2244 e_comp_wl_video_buffer_unref(vbuf);
2250 _e_output_tdm_stream_capture_support(E_Output *output)
2252 tdm_error error = TDM_ERROR_NONE;
2253 tdm_capture_capability capabilities;
2254 E_Comp_Screen *e_comp_screen = NULL;
2256 e_comp_screen = e_comp->e_comp_screen;
2257 EINA_SAFETY_ON_NULL_RETURN(e_comp_screen);
2259 error = tdm_display_get_capture_capabilities(e_comp_screen->tdisplay, &capabilities);
2260 if (error != TDM_ERROR_NONE)
2262 EOINF("TDM Display has no capture capability.", output);
2266 if (capabilities & TDM_CAPTURE_CAPABILITY_STREAM)
2267 output->stream_capture.possible_tdm_capture = EINA_TRUE;
2271 _e_output_external_rect_get(E_Output *output, int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *rect)
2274 int output_angle = 0;
2275 Eina_Bool rotate_check = EINA_FALSE;
2277 angle = _e_output_top_ec_angle_get();
2278 output_angle = output->config.rotation;
2280 if (((angle + output_angle) % 360 == 90) || ((angle + output_angle) % 360 == 270))
2281 rotate_check = EINA_TRUE;
2284 _e_output_center_rect_get(src_h, src_w, dst_w, dst_h, rect);
2286 _e_output_center_rect_get(src_w, src_h, dst_w, dst_h, rect);
2290 _e_output_planes_commit(E_Output *output)
2292 E_Plane *plane = NULL, *fb_target = NULL;
2294 Eina_Bool fb_commit = EINA_FALSE;
2296 fb_target = e_output_fb_target_get(output);
2298 /* fetch the fb_target at first */
2299 fb_commit = e_plane_fetch(fb_target);
2300 // TODO: to be fixed. check fps of fb_target currently.
2301 if (fb_commit) _e_output_update_fps();
2303 if (output->zoom_conf.unset_skip == EINA_TRUE)
2305 output->zoom_conf.unset_skip = EINA_FALSE;
2306 if (output->dpms != E_OUTPUT_DPMS_OFF)
2308 e_output_zoom_rotating_check(output);
2309 if (!e_plane_pp_commit(fb_target))
2310 EOERR("fail to e_plane_pp_commit", output);
2316 EINA_LIST_FOREACH(output->planes, l, plane)
2318 /* skip the fb_target fetch because we do this previously */
2319 if (e_plane_is_fb_target(plane)) continue;
2321 /* if the plane is the candidate to unset,
2322 set the plane to be unset_try */
2323 if (e_plane_is_unset_candidate(plane))
2324 e_plane_unset_try_set(plane, EINA_TRUE);
2326 /* if the plane is trying to unset,
2327 * 1. if fetching the fb is not available, continue.
2328 * 2. if fetching the fb is available, verify the unset commit check. */
2329 if (e_plane_is_unset_try(plane))
2331 if (!e_plane_unset_commit_check(plane, fb_commit))
2335 if (!e_plane_set_commit_check(plane, fb_commit)) continue;
2337 /* fetch the surface to the plane */
2338 if (!e_plane_fetch(plane)) continue;
2340 if (e_plane_is_unset_try(plane))
2341 e_plane_unset_try_set(plane, EINA_FALSE);
2344 EINA_LIST_FOREACH(output->planes, l, plane)
2346 if (e_plane_is_fetch_retry(plane))
2348 if (!e_plane_fetch(plane)) continue;
2349 if (e_plane_is_fb_target(plane))
2351 fb_commit = EINA_TRUE;
2352 _e_output_update_fps();
2357 EINA_LIST_FOREACH(output->planes, l, plane)
2359 if (e_plane_is_unset_try(plane)) continue;
2361 if ((output->dpms == E_OUTPUT_DPMS_OFF) || output->fake_config)
2363 if (!e_plane_offscreen_commit(plane))
2364 EOERR("fail to e_plane_offscreen_commit", output);
2368 if ((output->zoom_set) && e_plane_is_fb_target(plane))
2370 e_output_zoom_rotating_check(output);
2371 if (!e_plane_pp_commit(plane))
2372 EOERR("fail to e_plane_pp_commit", output);
2376 if (!e_plane_commit(plane))
2377 EOERR("fail to e_plane_commit", output);
2387 _e_output_planes_init(E_Output *output)
2389 E_Plane *plane = NULL;
2390 E_Plane *default_fb = NULL;
2391 tdm_output *toutput = output->toutput;
2394 tdm_output_get_layer_count(toutput, &num_layers);
2397 EOERR("fail to get tdm_output_get_layer_count\n", output);
2400 output->plane_count = num_layers;
2401 EOINF("num_planes %i", output, output->plane_count);
2403 if (!e_plane_init())
2405 EOERR("fail to e_plane_init.", output);
2409 for (i = 0; i < output->plane_count; i++)
2411 plane = e_plane_new(output, i);
2414 EOERR("fail to create the e_plane.", output);
2417 output->planes = eina_list_append(output->planes, plane);
2420 output->planes = eina_list_sort(output->planes, eina_list_count(output->planes), _e_output_cb_planes_sort);
2422 default_fb = e_output_default_fb_target_get(output);
2425 EOERR("fail to get default_fb_target plane", output);
2429 if (!e_plane_fb_target_set(default_fb, EINA_TRUE))
2431 EOERR("fail to set fb_target plane", output);
2442 e_output_new(E_Comp_Screen *e_comp_screen, int index)
2444 E_Output *output = NULL;
2445 tdm_output *toutput = NULL;
2450 tdm_output_type output_type;
2451 int min_w, min_h, max_w, max_h, preferred_align;
2452 tdm_output_capability output_caps = 0;
2454 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
2456 output = E_NEW(E_Output, 1);
2457 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2458 output->index = index;
2460 toutput = tdm_display_get_output(e_comp_screen->tdisplay, index, NULL);
2461 if (!toutput) goto fail;
2462 output->toutput = toutput;
2464 error = tdm_output_add_change_handler(toutput, _e_output_cb_output_change, output);
2465 if (error != TDM_ERROR_NONE)
2466 WRN("fail to tdm_output_add_change_handler");
2468 error = tdm_output_get_output_type(toutput, &output_type);
2469 if (error != TDM_ERROR_NONE) goto fail;
2470 output->toutput_type = output_type;
2472 error = tdm_output_get_cursor_available_size(toutput, &min_w, &min_h, &max_w, &max_h, &preferred_align);
2473 if (error == TDM_ERROR_NONE)
2475 output->cursor_available.min_w = min_w;
2476 output->cursor_available.min_h = min_h;
2477 output->cursor_available.max_w = min_w;
2478 output->cursor_available.max_h = min_h;
2479 output->cursor_available.preferred_align = preferred_align;
2483 output->cursor_available.min_w = -1;
2484 output->cursor_available.min_h = -1;
2485 output->cursor_available.max_w = -1;
2486 output->cursor_available.max_h = -1;
2487 output->cursor_available.preferred_align = -1;
2490 name = _output_type_to_str(output_type);
2491 size = strlen(name) + 4;
2493 id = calloc(1, size);
2495 snprintf(id, size, "%s-%d", name, index);
2498 EOINF("(%d) output_id = %s", output, index, output->id);
2500 output->e_comp_screen = e_comp_screen;
2502 _e_output_tdm_stream_capture_support(output);
2504 error = tdm_output_get_capabilities(toutput, &output_caps);
2505 if (error != TDM_ERROR_NONE)
2507 EOERR("fail to tdm_output_get_capabilities", output);
2511 /* The E20 works the hwc_windows policy when tdm_output supports hwc capability e20.
2512 * The E_Plane, E_Plane_Renderer resource is not used in E20.
2514 if (output_caps & TDM_OUTPUT_CAPABILITY_HWC)
2515 output->tdm_hwc = EINA_TRUE;
2517 if (!_e_output_planes_init(output))
2520 if (output_caps & TDM_OUTPUT_CAPABILITY_ASYNC_DPMS)
2521 output->dpms_async = EINA_TRUE;
2523 if (output_caps & TDM_OUTPUT_CAPABILITY_MIRROR)
2524 output->tdm_mirror = EINA_TRUE;
2526 /* call output add hook */
2527 _e_output_hook_call(E_OUTPUT_HOOK_ADD, output);
2532 e_output_del(output);
2538 e_output_del(E_Output *output)
2543 if (!output) return;
2545 /* call output remove hook */
2546 _e_output_hook_call(E_OUTPUT_HOOK_REMOVE, output);
2548 if (output->hwc) e_hwc_del(output->hwc);
2552 if (output->id) free(output->id);
2553 if (output->info.screen) free(output->info.screen);
2554 if (output->info.name) free(output->info.name);
2555 if (output->info.edid) free(output->info.edid);
2557 tdm_output_remove_change_handler(output->toutput, _e_output_cb_output_change, output);
2559 EINA_LIST_FREE(output->info.modes, m) free(m);
2561 EINA_LIST_FREE(output->planes, plane) e_plane_free(plane);
2563 eina_hash_del_by_key(_mask_data_hash, &output);
2569 e_output_rotate(E_Output *output, int rotate)
2571 unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
2574 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2576 /* FIXME: currently the screen size can't be changed in runtime. To make it
2577 * possible, the output mode should be changeable first.
2579 rot_dif = output->config.rotation - rotate;
2580 if (rot_dif < 0) rot_dif = -rot_dif;
2582 if ((rot_dif % 180) && (output->config.geom.w != output->config.geom.h))
2584 EOERR("output size(%dx%d) should be square.", output,
2585 output->config.geom.w, output->config.geom.h);
2592 transform = WL_OUTPUT_TRANSFORM_90;
2595 transform = WL_OUTPUT_TRANSFORM_180;
2598 transform = WL_OUTPUT_TRANSFORM_270;
2602 transform = WL_OUTPUT_TRANSFORM_NORMAL;
2606 output->config.rotation = rotate;
2608 e_comp_wl_output_init(output->id, output->info.name,
2609 output->info.screen,
2610 output->config.geom.x, output->config.geom.y,
2611 output->config.geom.w, output->config.geom.h,
2612 output->info.size.w, output->info.size.h,
2613 output->config.mode.refresh, 0, transform);
2615 ELOGF("TRANSFORM", "output(%s) transform(%d)", NULL, output->info.name, transform);
2621 e_output_update(E_Output *output)
2623 E_Output_Mode *m = NULL;
2624 Eina_List *modes = NULL;
2625 Eina_Bool connected = EINA_TRUE;
2627 tdm_output_conn_status status;
2630 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2632 error = tdm_output_get_conn_status(output->toutput, &status);
2633 if (error != TDM_ERROR_NONE)
2635 EOERR("failt to get conn status.", output);
2639 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) connected = EINA_FALSE;
2643 /* disconnect --> connect */
2644 if (connected != output->info.connected)
2649 unsigned int phy_w, phy_h;
2650 const tdm_output_mode *tmodes = NULL;
2652 unsigned int pipe = 0;
2655 error = tdm_output_get_model_info(output->toutput, &maker, &screen, NULL);
2656 if (error != TDM_ERROR_NONE)
2658 EOERR("fail to get model info.", output);
2662 /* we apply the screen rotation only for the primary output */
2663 error = tdm_output_get_pipe(output->toutput, &pipe);
2664 if (error == TDM_ERROR_NONE && pipe == 0)
2665 output->config.rotation = e_comp->e_comp_screen->rotation;
2669 size = strlen(output->id) + 1 + strlen(maker) + 1;
2670 name = calloc(1, size);
2671 if (!name) return EINA_FALSE;
2672 snprintf(name, size, "%s-%s", output->id, maker);
2676 size = strlen(output->id) + 1;
2677 name = calloc(1, size);
2678 if (!name) return EINA_FALSE;
2679 snprintf(name, size, "%s", output->id);
2681 EOINF("screen = %s, name = %s", output, screen, name);
2683 error = tdm_output_get_physical_size(output->toutput, &phy_w, &phy_h);
2684 if (error != TDM_ERROR_NONE)
2686 EOERR("fail to get physical_size.", output);
2691 error = tdm_output_get_available_modes(output->toutput, &tmodes, &num_tmodes);
2692 if (error != TDM_ERROR_NONE || num_tmodes == 0)
2694 EOERR("fail to get tmodes", output);
2699 for (i = 0; i < num_tmodes; i++)
2701 E_Output_Mode *rmode;
2703 rmode = E_NEW(E_Output_Mode, 1);
2704 if (!rmode) continue;
2706 if (tmodes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
2707 rmode->preferred = EINA_TRUE;
2709 if (e_config->fake_output_resolution.use)
2711 rmode->w = e_config->fake_output_resolution.w;
2712 rmode->h = e_config->fake_output_resolution.h;
2716 rmode->w = tmodes[i].hdisplay;
2717 rmode->h = tmodes[i].vdisplay;
2719 rmode->refresh = tmodes[i].vrefresh;
2720 rmode->tmode = &tmodes[i];
2722 modes = eina_list_append(modes, rmode);
2725 /* resetting the output->info */
2726 if (output->info.screen) free(output->info.screen);
2727 if (output->info.name) free(output->info.name);
2728 EINA_LIST_FREE(output->info.modes, m) free(m);
2730 output->info.screen = strdup(screen);
2731 output->info.name = name;
2732 output->info.modes = modes;
2733 output->info.size.w = phy_w;
2734 output->info.size.h = phy_h;
2736 output->info.connected = EINA_TRUE;
2738 EOINF("id(%s) connected..", output, output->id);
2742 /* check the crtc setting */
2743 if (status != TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
2745 const tdm_output_mode *mode = NULL;
2747 error = tdm_output_get_mode(output->toutput, &mode);
2748 if (error != TDM_ERROR_NONE || mode == NULL)
2750 EOERR("fail to get mode.", output);
2754 output->config.geom.x = 0;
2755 output->config.geom.y = 0;
2756 output->config.geom.w = mode->hdisplay;
2757 output->config.geom.h = mode->vdisplay;
2759 output->config.mode.w = mode->hdisplay;
2760 output->config.mode.h = mode->vdisplay;
2761 output->config.mode.refresh = mode->vrefresh;
2763 output->config.enabled = 1;
2765 EOINF("'%s' %i %i %ix%i", output, output->info.name,
2766 output->config.geom.x, output->config.geom.y,
2767 output->config.geom.w, output->config.geom.h);
2774 output->info.connected = EINA_FALSE;
2776 /* reset output info */
2777 if (output->info.screen)
2779 free(output->info.screen);
2780 output->info.screen = NULL;
2782 if (output->info.name)
2784 free(output->info.name);
2785 output->info.name = NULL;
2787 EINA_LIST_FREE(output->info.modes, m) free(m);
2788 output->info.modes = NULL;
2790 output->info.size.w = 0;
2791 output->info.size.h = 0;
2793 /* reset output config */
2794 output->config.geom.x = 0;
2795 output->config.geom.y = 0;
2796 output->config.geom.w = 0;
2797 output->config.geom.h = 0;
2799 output->config.mode.w = 0;
2800 output->config.mode.h = 0;
2801 output->config.mode.refresh = 0;
2803 output->config.rotation = 0;
2804 output->config.priority = 0;
2805 output->config.enabled = 0;
2807 EOINF("Disconnected", output);
2810 /* the index of the tdm_output is higher, the tdm_output is important.
2811 the priority of the output is higher, the output is more important. */
2812 output->config.priority = 100 - output->index;
2818 e_output_mode_apply(E_Output *output, E_Output_Mode *mode)
2821 E_Output_Mode *current_mode = NULL;
2823 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2824 EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EINA_FALSE);
2826 if (!output->info.connected)
2828 EOERR("output is not connected.", output);
2832 current_mode = e_output_current_mode_get(output);
2833 if (current_mode != NULL)
2835 if (current_mode == mode)
2839 error = tdm_output_set_mode(output->toutput, mode->tmode);
2840 if (error != TDM_ERROR_NONE)
2842 EOERR("fail to set tmode.", output);
2846 if (current_mode != NULL)
2847 current_mode->current = EINA_FALSE;
2848 mode->current = EINA_TRUE;
2850 output->config.geom.x = 0;
2851 output->config.geom.y = 0;
2852 output->config.geom.w = mode->w;
2853 output->config.geom.h = mode->h;
2855 output->config.mode.w = mode->w;
2856 output->config.mode.h = mode->h;
2857 output->config.mode.refresh = mode->refresh;
2859 output->config.enabled = 1;
2861 EOINF("'%s' %i %i %ix%i %i %i", output, output->info.name,
2862 output->config.geom.x, output->config.geom.y,
2863 output->config.geom.w, output->config.geom.h,
2864 output->config.rotation, output->config.priority);
2866 EOINF("rotation = %d", output, output->config.rotation);
2868 _e_output_hook_call(E_OUTPUT_HOOK_MODE_CHANGE, output);
2874 e_output_hwc_setup(E_Output *output)
2877 E_Output *primary_output = NULL;
2878 Eina_Bool is_primary_output = EINA_FALSE;
2880 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2884 EOINF("Already has the HWC.", output);
2888 primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
2889 if (output == primary_output) is_primary_output = EINA_TRUE;
2891 hwc = e_hwc_new(output, is_primary_output);
2892 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
2899 EINTERN E_Output_Mode *
2900 e_output_best_mode_find(E_Output *output)
2902 Eina_List *l = NULL;
2903 E_Output_Mode *mode = NULL;
2904 E_Output_Mode *best_mode = NULL;
2907 double best_refresh = 0.0;
2909 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2910 EINA_SAFETY_ON_NULL_RETURN_VAL(output->info.modes, NULL);
2912 if (!output->info.connected)
2914 EOERR("output is not connected.", output);
2918 EINA_LIST_FOREACH(output->info.modes, l, mode)
2920 size = mode->w + mode->h;
2922 if (mode->preferred)
2926 best_refresh = mode->refresh;
2930 if (size > best_size)
2934 best_refresh = mode->refresh;
2937 if (size == best_size && mode->refresh > best_refresh)
2940 best_refresh = mode->refresh;
2948 e_output_mode_list_get(E_Output *output)
2950 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2951 EINA_SAFETY_ON_NULL_RETURN_VAL(output->info.modes, NULL);
2953 return output->info.modes;
2956 EINTERN E_Output_Mode *
2957 e_output_current_mode_get(E_Output *output)
2960 E_Output_Mode *emode = NULL;
2962 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2964 EINA_LIST_FOREACH(output->info.modes, l, emode)
2974 e_output_connected(E_Output *output)
2976 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2978 return output->info.connected;
2982 e_output_dpms_set(E_Output *output, E_OUTPUT_DPMS val)
2984 E_Output_Intercept_Hook_Point hookpoint;
2985 tdm_output_dpms tval;
2989 E_Output *output_primary = NULL;
2991 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2993 output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
2994 if (output_primary == output)
2996 /* FIXME: The zone controlling should be moved to e_zone */
2997 EINA_LIST_FOREACH(e_comp->zones, l, zone)
2999 if (val == E_OUTPUT_DPMS_ON)
3000 e_zone_display_state_set(zone, E_ZONE_DISPLAY_STATE_ON);
3001 else if (val == E_OUTPUT_DPMS_OFF)
3002 e_zone_display_state_set(zone, E_ZONE_DISPLAY_STATE_OFF);
3006 if (val == E_OUTPUT_DPMS_OFF)
3009 EINA_LIST_FOREACH(output->planes, l, ep)
3011 e_plane_dpms_off(ep);
3015 if (val == E_OUTPUT_DPMS_ON) hookpoint = E_OUTPUT_INTERCEPT_HOOK_DPMS_ON;
3016 else if (val == E_OUTPUT_DPMS_STANDBY) hookpoint = E_OUTPUT_INTERCEPT_HOOK_DPMS_STANDBY;
3017 else if (val == E_OUTPUT_DPMS_SUSPEND) hookpoint = E_OUTPUT_INTERCEPT_HOOK_DPMS_SUSPEND;
3018 else hookpoint = E_OUTPUT_INTERCEPT_HOOK_DPMS_OFF;
3020 if (!_e_output_intercept_hook_call(hookpoint, output))
3023 if (output->fake_config)
3025 output->set_dpms = val;
3030 if (val == E_OUTPUT_DPMS_ON) tval = TDM_OUTPUT_DPMS_ON;
3031 else if (val == E_OUTPUT_DPMS_STANDBY) tval = TDM_OUTPUT_DPMS_STANDBY;
3032 else if (val == E_OUTPUT_DPMS_SUSPEND) tval = TDM_OUTPUT_DPMS_SUSPEND;
3033 else tval = TDM_OUTPUT_DPMS_OFF;
3035 if (output->dpms_async)
3036 error = tdm_output_set_dpms_async(output->toutput, tval);
3038 error = tdm_output_set_dpms(output->toutput, tval);
3039 if (error != TDM_ERROR_NONE)
3041 EOERR("fail to set the dpms(value:%d).", output, tval);
3045 output->set_dpms = val;
3050 EINTERN E_OUTPUT_DPMS
3051 e_output_dpms_get(E_Output *output)
3053 EINA_SAFETY_ON_NULL_RETURN_VAL(output, E_OUTPUT_DPMS_OFF);
3055 return output->dpms;
3059 e_output_dpms_async_check(E_Output *output)
3061 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3063 return output->dpms_async;
3067 e_output_size_get(E_Output *output, int *w, int *h)
3069 EINA_SAFETY_ON_NULL_RETURN(output);
3071 *w = output->config.mode.w;
3072 *h = output->config.mode.h;
3076 e_output_phys_size_get(E_Output *output, int *phys_w, int *phys_h)
3078 EINA_SAFETY_ON_NULL_RETURN(output);
3080 *phys_w = output->info.size.w;
3081 *phys_h = output->info.size.h;
3085 e_output_fake_config_set(E_Output *output, int w, int h)
3087 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3089 output->config.geom.x = 0;
3090 output->config.geom.y = 0;
3091 output->config.geom.w = w;
3092 output->config.geom.h = h;
3094 output->config.mode.w = w;
3095 output->config.mode.h = h;
3096 output->config.mode.refresh = 30;
3097 output->config.enabled = 1;
3099 output->fake_config = EINA_TRUE;
3106 e_output_render(E_Output *output)
3108 E_Plane *plane = NULL;
3111 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3113 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3115 EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
3117 if (!e_plane_render(plane))
3119 EOERR("fail to e_plane_render.", output);
3126 /* render the only primary output */
3127 if (output != e_comp_screen_primary_output_get(output->e_comp_screen))
3130 if (!e_hwc_windows_render(output->hwc))
3132 EOERR("fail to e_hwc_windows_render.", output);
3141 e_output_commit(E_Output *output)
3143 E_Output *output_primary = NULL;
3144 E_Output_Display_Mode display_mode;
3146 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3148 if (!output->config.enabled)
3150 WRN("E_Output disconnected");
3154 output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
3155 EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
3157 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3159 e_hwc_planes_apply(output->hwc);
3161 if (output == output_primary)
3163 if (!_e_output_planes_commit(output))
3165 EOERR("fail to _e_output_commit.", output);
3171 display_mode = e_output_display_mode_get(output);
3173 /* output donot care about the external_commit
3174 when tdm has the mirror capability */
3175 if (display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR &&
3179 if (!e_hwc_planes_external_commit(output->hwc))
3181 EOERR("fail e_hwc_planes_external_commit", output);
3188 if (output == output_primary)
3190 if (output->zoom_set)
3191 e_output_zoom_rotating_check(output);
3194 display_mode = e_output_display_mode_get(output);
3196 /* The output do not commit when tdm has the mirror capability */
3197 if (display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR && output->tdm_mirror)
3200 if (!e_hwc_windows_commit(output->hwc, display_mode))
3202 EOERR("fail e_hwc_windows_commit", output);
3207 _e_output_force_render_unset(output);
3212 EINTERN const char *
3213 e_output_output_id_get(E_Output *output)
3215 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
3221 e_output_find(const char *id)
3224 E_Comp_Screen *e_comp_screen;
3227 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
3228 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
3229 EINA_SAFETY_ON_NULL_RETURN_VAL(id, NULL);
3231 e_comp_screen = e_comp->e_comp_screen;
3233 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
3235 if (!strcmp(output->id, id)) return output;
3240 E_API const Eina_List *
3241 e_output_planes_get(E_Output *output)
3243 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
3244 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, NULL);
3246 return output->planes;
3250 e_output_util_planes_print(void)
3252 Eina_List *l, *ll, *p_l;
3253 E_Output * output = NULL;
3254 E_Comp_Screen *e_comp_screen = NULL;
3256 EINA_SAFETY_ON_NULL_RETURN(e_comp);
3257 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
3259 e_comp_screen = e_comp->e_comp_screen;
3261 EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
3266 if (!output || !output->planes) continue;
3268 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3270 fprintf(stderr, "HWC in %s .. \n", output->id);
3271 fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
3273 EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
3276 if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (%8p)",
3278 plane->is_primary ? "--" : " ",
3279 ec->icccm.title, ec->frame);
3281 ec = plane->prepare_ec;
3282 if (ec) fprintf(stderr, "\t\t\t %s (%8p)",
3283 ec->icccm.title, ec->frame);
3284 fputc('\n', stderr);
3286 fputc('\n', stderr);
3292 e_output_is_fb_composing(E_Output *output)
3297 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3298 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
3300 EINA_LIST_FOREACH(output->planes, p_l, ep)
3302 if (e_plane_is_fb_target(ep))
3304 if(ep->ec == NULL) return EINA_TRUE;
3312 e_output_is_fb_full_compositing(E_Output *output)
3317 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3318 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
3320 EINA_LIST_FOREACH(output->planes, p_l, ep)
3321 if(ep->ec) return EINA_FALSE;
3327 e_output_fb_target_get(E_Output *output)
3332 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3333 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
3335 EINA_LIST_FOREACH(output->planes, p_l, ep)
3337 if (e_plane_is_fb_target(ep))
3345 e_output_default_fb_target_get(E_Output *output)
3350 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3351 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
3353 if (e_comp->hwc_ignore_primary)
3355 /* find lowest zpos graphic type layer */
3356 EINA_LIST_FOREACH(output->planes, p_l, ep)
3358 Eina_Bool available_rgb = EINA_FALSE;
3359 const tbm_format *formats;
3362 if (e_plane_type_get(ep) != E_PLANE_TYPE_GRAPHIC) continue;
3364 if (!e_plane_available_formats_get(ep, &formats, &count))
3367 for (i = 0; i < count; i++)
3369 if (formats[i] == TBM_FORMAT_ARGB8888 ||
3370 formats[i] == TBM_FORMAT_XRGB8888)
3372 available_rgb = EINA_TRUE;
3377 if (!available_rgb) continue;
3384 /* find primary layer */
3385 EINA_LIST_FOREACH(output->planes, p_l, ep)
3396 e_output_find_by_index(int index)
3399 E_Comp_Screen *e_comp_screen;
3402 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
3403 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
3405 e_comp_screen = e_comp->e_comp_screen;
3407 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
3409 if (output->index == index)
3417 e_output_plane_get_by_zpos(E_Output *output, int zpos)
3422 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3423 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
3425 EINA_LIST_FOREACH(output->planes, p_l, ep)
3427 if (ep->zpos == zpos)
3435 e_output_zoom_set(E_Output *output, double zoomx, double zoomy, int cx, int cy)
3440 E_Output *output_primary = NULL;
3442 if (!e_comp_screen_pp_support())
3444 EOINF("Comp Screen does not support the Zoom.", output);
3448 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3450 if (cx < 0 || cy < 0) return EINA_FALSE;
3451 if (zoomx <= 0 || zoomy <= 0) return EINA_FALSE;
3453 output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
3454 EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
3456 if (output != output_primary)
3458 EOERR("Only Primary Output can support the Zoom.", output);
3462 e_output_size_get(output, &w, &h);
3463 if (output->config.rotation % 180 == 0)
3465 if (cx >= w || cy >= h)
3470 if (cx >= h || cy >= w)
3474 angle = _e_output_zoom_get_angle(output);
3476 output->zoom_conf.zoomx = zoomx;
3477 output->zoom_conf.zoomy = zoomy;
3478 output->zoom_conf.init_cx = cx;
3479 output->zoom_conf.init_cy = cy;
3480 output->zoom_conf.init_angle = angle;
3481 output->zoom_conf.current_angle = angle;
3482 output->zoom_conf.init_screen_rotation = output->config.rotation;
3483 output->zoom_conf.current_screen_rotation = output->config.rotation;
3485 _e_output_zoom_coordinate_cal(output);
3486 _e_output_zoom_touch_rect_get(output);
3488 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3490 ep = e_output_fb_target_get(output);
3491 EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
3493 if (!output->zoom_set)
3495 if (_e_output_fb_over_plane_check(output))
3496 output->zoom_conf.unset_skip = EINA_TRUE;
3499 e_hwc_planes_multi_plane_set(output->hwc, EINA_FALSE);
3501 if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
3503 EOERR("e_plane_zoom_set failed.", output);
3504 output->zoom_conf.unset_skip = EINA_FALSE;
3505 e_hwc_planes_multi_plane_set(output->hwc, EINA_TRUE);
3510 /* update the ecore_evas */
3511 if (e_plane_pp_commit_possible_check(ep))
3512 _e_output_render_update(output);
3516 if (!e_hwc_windows_zoom_set(output->hwc, &output->zoom_conf.rect))
3518 EOERR("e_hwc_windows_zoom_set failed.", output);
3522 /* update the ecore_evas */
3523 if (e_hwc_windows_pp_commit_possible_check(output->hwc))
3524 _e_output_render_update(output);
3527 if (!_e_output_zoom_touch_set(output))
3528 EOERR("fail _e_output_zoom_touch_set", output);
3530 if (!output->zoom_set) output->zoom_set = EINA_TRUE;
3532 EOINF("Zoom set output:%s, zoom(x:%f, y:%f, cx:%d, cy:%d) rect(x:%d, y:%d, w:%d, h:%d)",
3533 output, output->id, zoomx, zoomy, cx, cy,
3534 output->zoom_conf.rect.x, output->zoom_conf.rect.y, output->zoom_conf.rect.w, output->zoom_conf.rect.h);
3540 e_output_zoom_get(E_Output *output, double *zoomx, double *zoomy, int *cx, int *cy)
3542 E_Output *output_primary = NULL;
3544 if (!e_comp_screen_pp_support())
3546 EOINF("Comp Screen does not support the Zoom.", output);
3550 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3552 output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
3553 EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
3555 if (output != output_primary)
3557 EOERR("Only Primary Output can support the Zoom.", output);
3561 if (zoomx) *zoomx = output->zoom_conf.zoomx;
3562 if (zoomy) *zoomy = output->zoom_conf.zoomy;
3563 if (cx) *cx = output->zoom_conf.init_cx;
3564 if (cy) *cy = output->zoom_conf.init_cy;
3570 e_output_zoom_unset(E_Output *output)
3574 EINA_SAFETY_ON_NULL_RETURN(output);
3576 if (!output->zoom_set) return;
3578 output->zoom_set = EINA_FALSE;
3579 output->zoom_conf.unset_skip = EINA_FALSE;
3581 if (!_e_output_zoom_touch_unset(output))
3582 EOERR("fail _e_output_zoom_touch_unset", output);
3584 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3586 ep = e_output_fb_target_get(output);
3587 if (ep) e_plane_zoom_unset(ep);
3589 e_hwc_planes_multi_plane_set(output->hwc, EINA_TRUE);
3593 e_hwc_windows_zoom_unset(output->hwc);
3596 output->zoom_conf.zoomx = 0;
3597 output->zoom_conf.zoomy = 0;
3598 output->zoom_conf.init_cx = 0;
3599 output->zoom_conf.init_cy = 0;
3600 output->zoom_conf.init_angle = 0;
3601 output->zoom_conf.current_angle = 0;
3602 output->zoom_conf.adjusted_cx = 0;
3603 output->zoom_conf.adjusted_cy = 0;
3604 output->zoom_conf.rect.x = 0;
3605 output->zoom_conf.rect.y = 0;
3606 output->zoom_conf.rect.w = 0;
3607 output->zoom_conf.rect.h = 0;
3608 output->zoom_conf.rect_touch.x = 0;
3609 output->zoom_conf.rect_touch.y = 0;
3610 output->zoom_conf.rect_touch.w = 0;
3611 output->zoom_conf.rect_touch.h = 0;
3613 /* update the ecore_evas */
3614 _e_output_render_update(output);
3616 ELOGF("ZOOM", "e_output_zoom_unset: output:%s", NULL, output->id);
3619 EINTERN E_Output_Hook *
3620 e_output_hook_add(E_Output_Hook_Point hookpoint, E_Output_Hook_Cb func, const void *data)
3624 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_OUTPUT_HOOK_LAST, NULL);
3625 ch = E_NEW(E_Output_Hook, 1);
3626 if (!ch) return NULL;
3627 ch->hookpoint = hookpoint;
3629 ch->data = (void*)data;
3630 _e_output_hooks[hookpoint] = eina_inlist_append(_e_output_hooks[hookpoint], EINA_INLIST_GET(ch));
3635 e_output_hook_del(E_Output_Hook *ch)
3638 if (_e_output_hooks_walking == 0)
3640 _e_output_hooks[ch->hookpoint] = eina_inlist_remove(_e_output_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3644 _e_output_hooks_delete++;
3647 EINTERN E_Output_Intercept_Hook *
3648 e_output_intercept_hook_add(E_Output_Intercept_Hook_Point hookpoint, E_Output_Intercept_Hook_Cb func, const void *data)
3650 E_Output_Intercept_Hook *ch;
3652 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_OUTPUT_INTERCEPT_HOOK_LAST, NULL);
3653 ch = E_NEW(E_Output_Intercept_Hook, 1);
3654 if (!ch) return NULL;
3655 ch->hookpoint = hookpoint;
3657 ch->data = (void*)data;
3658 _e_output_intercept_hooks[hookpoint] = eina_inlist_append(_e_output_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
3663 e_output_intercept_hook_del(E_Output_Intercept_Hook *ch)
3666 if (_e_output_intercept_hooks_walking == 0)
3668 _e_output_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_output_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
3672 _e_output_intercept_hooks_delete++;
3676 e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate, Eina_Bool sync, E_Output_Capture_Cb func, void *data)
3678 Eina_Bool ret = EINA_FALSE;
3679 tdm_capture *tcapture = NULL;
3681 if (e_output_dpms_get(output))
3683 func(output, tsurface, data);
3689 ret = _e_output_capture(output, tsurface, auto_rotate);
3690 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3692 DBG("capture done(%p)", tsurface);
3693 func(output, tsurface, data);
3698 tcapture = _e_output_tdm_capture_create(output, TDM_CAPTURE_CAPABILITY_ONESHOT);
3701 ret = _e_output_tdm_capture_info_set(output, tcapture, tsurface, TDM_CAPTURE_TYPE_ONESHOT, auto_rotate);
3702 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3704 ret = _e_output_tdm_capture(output, tcapture, tsurface, func, data);
3705 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3709 ret = _e_output_capture(output, tsurface, auto_rotate);
3710 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3712 DBG("capture done(%p)", tsurface);
3713 func(output, tsurface, data);
3720 tdm_capture_destroy(tcapture);
3726 e_output_stream_capture_queue(E_Output *output, tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
3728 Eina_Bool ret = EINA_FALSE;
3729 tdm_capture *tcapture = NULL;
3730 tdm_error error = TDM_ERROR_NONE;
3733 if (output->stream_capture.possible_tdm_capture)
3735 if (!output->stream_capture.tcapture)
3737 tcapture = _e_output_tdm_capture_create(output, TDM_CAPTURE_CAPABILITY_STREAM);
3738 EINA_SAFETY_ON_NULL_RETURN_VAL(tcapture, EINA_FALSE);
3740 ret = _e_output_tdm_capture_info_set(output, tcapture, tsurface, TDM_CAPTURE_TYPE_STREAM, output->stream_capture.auto_rotate);
3741 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3743 error = tdm_capture_set_done_handler(tcapture,
3744 _e_output_tdm_stream_capture_done_handler, output);
3745 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
3747 output->stream_capture.tcapture = tcapture;
3749 DBG("create tcapture(%p)", tcapture);
3753 tcapture = output->stream_capture.tcapture;
3754 _e_output_capture_transform_check(output, EINA_FALSE, &transform);
3755 if (transform != output->stream_capture.current_angle)
3757 ret = _e_output_tdm_capture_info_set(output, tcapture, tsurface, TDM_CAPTURE_TYPE_STREAM, output->stream_capture.auto_rotate);
3758 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
3762 ret = _e_output_tdm_stream_capture(output, tcapture, tsurface, func, data);
3763 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == EINA_TRUE, EINA_FALSE);
3767 ret = _e_output_vblank_stream_capture(output, tsurface, func, data);
3768 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == EINA_TRUE, EINA_FALSE);
3774 tdm_capture_destroy(tcapture);
3780 e_output_stream_capture_dequeue(E_Output *output, tbm_surface_h tsurface)
3782 E_Output_Capture *cdata = NULL;
3784 cdata = _e_output_tdm_stream_capture_find_data(output, tsurface);
3786 if (!cdata) return EINA_FALSE;
3788 if (!cdata->in_using)
3790 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
3792 tbm_surface_internal_unref(tsurface);
3796 cdata->dequeued = EINA_TRUE;
3802 e_output_stream_capture_start(E_Output *output)
3804 tdm_error error = TDM_ERROR_NONE;
3807 if (output->stream_capture.start) return EINA_TRUE;
3809 count = eina_list_count(output->stream_capture.data);
3812 EOERR("no queued buffer", output);
3816 DBG("output stream capture start.");
3818 output->stream_capture.start = EINA_TRUE;
3820 _e_output_stream_capture_mask_image_activate(output);
3822 if (output->stream_capture.possible_tdm_capture)
3824 if (e_output_dpms_get(output))
3826 if (!output->stream_capture.timer)
3827 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
3828 _e_output_stream_capture_cb_timeout, output);
3829 EINA_SAFETY_ON_NULL_GOTO(output->stream_capture.timer, fail);
3834 error = tdm_capture_commit(output->stream_capture.tcapture);
3835 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
3839 e_video_debug_display_primary_plane_set(EINA_TRUE);
3840 _e_output_watch_vblank(output);
3846 output->stream_capture.start = EINA_FALSE;
3852 e_output_stream_capture_stop(E_Output *output)
3854 E_Output_Capture *cdata = NULL;
3855 Eina_Bool capturing = EINA_FALSE;
3858 if (!output->stream_capture.start) return;
3860 output->stream_capture.start = EINA_FALSE;
3861 output->stream_capture.auto_rotate = EINA_FALSE;
3863 _e_output_stream_capture_mask_image_deactivate(output);
3865 if (!output->stream_capture.possible_tdm_capture)
3866 e_video_debug_display_primary_plane_set(EINA_FALSE);
3868 if (eina_list_count(output->stream_capture.data) == 0)
3870 if (!output->stream_capture.timer)
3872 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
3873 _e_output_tdm_stream_capture_stop, output);
3878 if (!output->stream_capture.timer && !output->stream_capture.wait_vblank)
3880 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
3882 if (cdata->in_using)
3883 capturing = EINA_TRUE;
3886 if (capturing == EINA_FALSE)
3888 EINA_LIST_FREE(output->stream_capture.data, cdata)
3890 tbm_surface_internal_unref(cdata->surface);
3895 if (output->stream_capture.tcapture)
3897 tdm_capture_destroy(output->stream_capture.tcapture);
3898 output->stream_capture.tcapture = NULL;
3902 DBG("output stream capture stop.");
3907 e_output_stream_capture_autorotate(E_Output *output, Eina_Bool auto_rotate)
3909 output->stream_capture.auto_rotate = auto_rotate;
3913 e_output_external_mode_change(E_Output *output, E_Output_Mode *mode)
3915 E_Output_Mode *emode = NULL, *current_emode = NULL;
3917 Eina_Bool found = EINA_FALSE;
3918 E_Output *output_primary = NULL;
3922 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3923 EINA_SAFETY_ON_NULL_RETURN_VAL(mode, EINA_FALSE);
3925 if (e_output_connected(output) != EINA_TRUE)
3928 current_emode = e_output_current_mode_get( output);
3929 EINA_SAFETY_ON_NULL_RETURN_VAL(current_emode, EINA_FALSE);
3931 if (current_emode == mode)
3934 EINA_LIST_FOREACH(output->info.modes, l, emode)
3942 EINA_SAFETY_ON_FALSE_RETURN_VAL(found == EINA_TRUE, EINA_FALSE);
3944 output_primary = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
3945 EINA_SAFETY_ON_NULL_RETURN_VAL(output_primary, EINA_FALSE);
3946 EINA_SAFETY_ON_TRUE_RETURN_VAL(output_primary == output, EINA_FALSE);
3948 e_output_size_get(output, &w, &h);
3949 e_output_size_get(output_primary, &p_w, &p_h);
3951 if (e_output_mode_apply(output, mode) == EINA_FALSE)
3953 EOERR("fail to e_output_mode_apply.", output);
3957 _e_output_external_rect_get(output_primary, p_w, p_h, w, h, &output->zoom_conf.rect);
3959 EOINF("mode change output: (%dx%d)", output, w, h);
3961 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
3963 ep = e_output_fb_target_get(output);
3964 EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
3966 e_plane_external_reset(ep, &output->zoom_conf.rect);
3970 /* TODO: HWC Windows */;
3973 _e_output_render_update(output_primary);
3975 EOINF("e_output_external_reset done.(%dx%d)", output, mode->w, mode->h);
3981 e_output_mirror_set(E_Output *output, E_Output *src_output)
3986 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3987 EINA_SAFETY_ON_NULL_RETURN_VAL(src_output, EINA_FALSE);
3988 EINA_SAFETY_ON_NULL_RETURN_VAL(output->hwc, EINA_FALSE);
3990 if (output->display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR)
3992 EOINF("Already Set MIRROR_MODE", output);
3996 if (output->tdm_mirror)
3998 EOINF("TDM supports the output mirroring.", output);
4000 ret = tdm_output_set_mirror(output->toutput, src_output->toutput, TDM_TRANSFORM_NORMAL);
4001 if (ret != TDM_ERROR_NONE)
4003 EOINF("tdm_output_set_mirror fails.", output);
4009 e_output_size_get(output, &w, &h);
4010 e_output_size_get(src_output, &p_w, &p_h);
4012 _e_output_external_rect_get(src_output, p_w, p_h, w, h, &output->zoom_conf.rect);
4014 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
4016 if (!e_hwc_planes_mirror_set(output->hwc, src_output->hwc, &output->zoom_conf.rect))
4018 EOERR("e_hwc_planes_mirror_set failed.", output);
4024 if (!e_hwc_windows_mirror_set(output->hwc, src_output->hwc))
4026 EOERR("e_hwc_windows_mirror_set failed.", output);
4032 output->mirror_src_output = src_output;
4034 _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_MIRROR);
4035 output->external_set = EINA_TRUE;
4037 /* update the ecore_evas of the src_output */
4038 _e_output_force_render_set(src_output);
4040 EOINF("e_output_mirror_set done: E_OUTPUT_DISPLAY_MODE_MIRROR", output);
4046 e_output_mirror_unset(E_Output *output)
4048 E_Output *src_output;
4051 EINA_SAFETY_ON_NULL_RETURN(output);
4053 EOINF("e_output_mirror_unset: E_OUTPUT_DISPLAY_MODE_NONE", output);
4055 src_output = output->mirror_src_output;
4057 if (e_output_display_mode_get(output) == E_OUTPUT_DISPLAY_MODE_MIRROR)
4059 /* update the ecore_evas of the src_output */
4060 _e_output_render_update(src_output);
4061 output->external_set = EINA_FALSE;
4062 _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_NONE);
4065 output->mirror_src_output = NULL;
4067 if (output->tdm_mirror)
4069 ret = tdm_output_unset_mirror(output->toutput);
4070 if (ret != TDM_ERROR_NONE)
4071 EOERR("tdm_output_unset_mirror fails.", output);
4075 if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
4076 e_hwc_planes_mirror_unset(output->hwc);
4078 e_hwc_windows_mirror_unset(output->hwc);
4083 e_output_presentation_update(E_Output *output, E_Client *ec)
4087 EINA_SAFETY_ON_FALSE_RETURN_VAL(output, EINA_FALSE);
4088 EINA_SAFETY_ON_FALSE_RETURN_VAL(ec, EINA_FALSE);
4091 EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc, EINA_FALSE);
4093 if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
4095 if (!e_hwc_planes_presentation_update(hwc, ec))
4097 EOERR("e_hwc_planes_presentation_update fails.", output);
4100 EOINF("e_output_presentation_update done: E_OUTPUT_DISPLAY_MODE_PRESENTATION", output);
4103 _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_PRESENTATION);
4105 output->external_set = EINA_TRUE;
4112 e_output_presentation_unset(E_Output *output)
4114 E_Output *primary_output;
4116 E_Comp_Wl_Client_Data *cdata;
4121 EINA_SAFETY_ON_FALSE_RETURN(output);
4124 EINA_SAFETY_ON_FALSE_RETURN(hwc);
4126 output->external_set = EINA_FALSE;
4128 _e_output_display_mode_set(output, E_OUTPUT_DISPLAY_MODE_NONE);
4130 if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
4132 e_hwc_planes_presentation_update(hwc, NULL);
4136 if (output->presentation_ec)
4138 primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
4139 EINA_SAFETY_ON_NULL_GOTO(primary_output, done);
4141 zone = e_comp_zone_find(e_output_output_id_get(primary_output));
4142 EINA_SAFETY_ON_NULL_RETURN(zone);
4144 cdata = e_client_cdata_get(output->presentation_ec);
4145 EINA_SAFETY_ON_NULL_RETURN(cdata);
4147 e_zone_client_add(zone, output->presentation_ec);
4149 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
4150 e_zone_client_add(zone, subc);
4152 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
4153 e_zone_client_add(zone, subc);
4158 output->presentation_ec = NULL;
4162 e_output_presentation_ec_set(E_Output *output, E_Client *ec)
4167 E_Comp_Wl_Client_Data *cdata;
4170 EINA_SAFETY_ON_FALSE_RETURN_VAL(output, EINA_FALSE);
4171 EINA_SAFETY_ON_FALSE_RETURN_VAL(ec, EINA_FALSE);
4174 EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc, EINA_FALSE);
4176 output->presentation_ec = ec;
4178 zone = e_comp_zone_find(e_output_output_id_get(output));
4179 EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
4181 cdata = e_client_cdata_get(ec);
4182 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
4184 e_zone_client_add(zone, ec);
4186 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
4187 e_zone_client_add(zone, subc);
4189 EINA_LIST_FOREACH(cdata->sub.list, l, subc)
4190 e_zone_client_add(zone, subc);
4196 e_output_presentation_ec_get(E_Output *output)
4198 EINA_SAFETY_ON_FALSE_RETURN_VAL(output, NULL);
4200 return output->presentation_ec;
4203 EINTERN E_Output_Display_Mode
4204 e_output_display_mode_get(E_Output *output)
4206 EINA_SAFETY_ON_FALSE_RETURN_VAL(output, E_OUTPUT_DISPLAY_MODE_NONE);
4208 return output->display_mode;
4212 e_output_norender_push(E_Output *output)
4214 EINA_SAFETY_ON_FALSE_RETURN(output);
4216 e_hwc_norender_push(output->hwc);
4220 e_output_norender_pop(E_Output *output)
4222 EINA_SAFETY_ON_FALSE_RETURN(output);
4224 e_hwc_norender_pop(output->hwc);
4228 e_output_norender_get(E_Output *output)
4230 EINA_SAFETY_ON_FALSE_RETURN_VAL(output, 0);
4232 return e_hwc_norender_get(output->hwc);
4236 _e_output_prop_name_get_by_id(E_Output *output, unsigned int id)
4238 const output_prop *props;
4241 if (!e_output_available_properties_get(output, &props, &count))
4243 EOERR("e_output_available_properties_get failed.", output);
4247 for (i = 0; i < count; i++)
4249 if (props[i].id == id)
4250 return props[i].name;
4253 EOERR("No available property: id %d", output, id);
4259 e_output_available_properties_get(E_Output *output, const output_prop **props, int *count)
4261 const tdm_prop *tprops;
4265 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
4266 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
4268 ret = tdm_output_get_available_properties(output->toutput, &tprops, count);
4269 EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
4271 *props = (output_prop *)tprops;
4273 EOINF(">>>>>>>> Available OUTPUT props : count = %d", output, *count);
4274 for (i = 0; i < *count; i++)
4275 EOINF(" [%d] %s, %u", output, i, tprops[i].name, tprops[i].id);
4281 e_output_property_get(E_Output *output, unsigned int id, output_prop_value *value)
4286 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
4287 EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
4289 ret = tdm_output_get_property(output->toutput, id, &tvalue);
4290 EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, EINA_FALSE);
4292 memcpy(&value->ptr, &tvalue.ptr, sizeof(tdm_value));
4298 e_output_property_set(E_Output *output, unsigned int id, output_prop_value value)
4304 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
4306 name = _e_output_prop_name_get_by_id(output, id);
4307 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
4309 memcpy(&tvalue.ptr, &value.ptr, sizeof(output_prop_value));
4311 ret = tdm_output_set_property(output->toutput, id, tvalue);
4312 EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, EINA_FALSE);
4318 e_output_stream_capture_mask_image_file_set(E_Output *output, const char *file)
4320 E_Output_Stream_Capture_Mask_Data *md;
4322 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
4324 EOINF("set mask image file for stream capture : %s", output, file);
4326 md = _e_output_stream_capture_mask_data_get(output);
4329 EOERR("failed to get mask data", output);
4333 if (eina_streq(md->file, file))
4336 eina_stringshare_replace(&md->file, file);
4338 if (output->stream_capture.start)
4340 _e_output_stream_capture_mask_image_deactivate(output);
4343 _e_output_stream_capture_mask_image_activate(output);
4350 e_output_stream_capture_mask_image_geometry_set(E_Output *output, int x, int y, int w, int h)
4352 E_Output_Stream_Capture_Mask_Data *md;
4354 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
4355 EINA_SAFETY_ON_FALSE_RETURN_VAL(w > 0, EINA_FALSE);
4356 EINA_SAFETY_ON_FALSE_RETURN_VAL(h > 0, EINA_FALSE);
4358 EOINF("set geometry of mask image object: %d,%d (%dx%d)",
4359 output, x, y, w, h);
4361 md = _e_output_stream_capture_mask_data_get(output);
4364 EOERR("failed to get mask data", output);
4368 EINA_RECTANGLE_SET(&md->geometry, x, y, w, h);
4370 if (output->stream_capture.start)
4373 evas_object_geometry_set(md->eo, x, y, w, h);
4380 _e_output_stream_capture_mask_data_hash_cb_data_free(void *data)
4382 E_Output_Stream_Capture_Mask_Data *md;
4386 E_FREE_FUNC(md->eo, evas_object_del);
4387 E_FREE_FUNC(md->file, eina_stringshare_del);
4392 static E_Output_Stream_Capture_Mask_Data *
4393 _e_output_stream_capture_mask_data_get(E_Output *output)
4395 E_Output_Stream_Capture_Mask_Data *md;
4397 md = eina_hash_find(_mask_data_hash, &output);
4400 md = E_NEW(E_Output_Stream_Capture_Mask_Data, 1);
4403 EOERR("failed to alloc memory for mask data", output);
4410 eina_hash_add(_mask_data_hash, &output, md);
4417 _e_output_stream_capture_mask_image_activate(E_Output *output)
4419 E_Output_Stream_Capture_Mask_Data *md;
4421 Evas_Load_Error err;
4423 md = eina_hash_find(_mask_data_hash, &output);
4426 /* It can be null if any api for mask image is not called. */
4427 EOINF("not found mask data", output);
4433 EOINF("no file name for mask image", output);
4439 EOERR("mask image object is already exist.", output);
4443 eo = evas_object_image_filled_add(e_comp->evas);
4445 evas_object_image_file_set(eo, md->file, NULL);
4446 err = evas_object_image_load_error_get(eo);
4447 if (err != EVAS_LOAD_ERROR_NONE)
4449 EOERR("failed to load image %s : %s", output,
4450 md->file, evas_load_error_str(err));
4451 evas_object_del(eo);
4455 evas_object_geometry_set(eo,
4456 md->geometry.x, md->geometry.y,
4457 md->geometry.w, md->geometry.h);
4459 evas_object_pass_events_set(eo, EINA_TRUE);
4460 evas_object_layer_set(eo, EVAS_LAYER_MAX);
4461 evas_object_raise(eo);
4462 evas_object_show(eo);
4468 _e_output_stream_capture_mask_image_deactivate(E_Output *output)
4470 E_Output_Stream_Capture_Mask_Data *md;
4472 md = eina_hash_find(_mask_data_hash, &output);
4475 EOINF("not found mask data", output);
4479 E_FREE_FUNC(md->eo, evas_object_del);