5 typedef struct _E_Output_Capture E_Output_Capture;
7 struct _E_Output_Capture
10 tdm_capture *tcapture;
11 tbm_surface_h surface;
12 E_Output_Capture_Cb func;
18 static int _e_output_hooks_delete = 0;
19 static int _e_output_hooks_walking = 0;
21 static Eina_Inlist *_e_output_hooks[] =
23 [E_OUTPUT_HOOK_DPMS_CHANGE] = NULL,
26 static Eina_Bool _e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate);
27 static void _e_output_vblank_handler(tdm_output *output, unsigned int sequence,
28 unsigned int tv_sec, unsigned int tv_usec, void *data);
32 _e_output_hooks_clean(void)
37 for (x = 0; x < E_OUTPUT_HOOK_LAST; x++)
38 EINA_INLIST_FOREACH_SAFE(_e_output_hooks[x], l, ch)
40 if (!ch->delete_me) continue;
41 _e_output_hooks[x] = eina_inlist_remove(_e_output_hooks[x], EINA_INLIST_GET(ch));
47 _e_output_hook_call(E_Output_Hook_Point hookpoint, E_Output *output)
51 _e_output_hooks_walking++;
52 EINA_INLIST_FOREACH(_e_output_hooks[hookpoint], ch)
54 if (ch->delete_me) continue;
55 ch->func(ch->data, output);
57 _e_output_hooks_walking--;
58 if ((_e_output_hooks_walking == 0) && (_e_output_hooks_delete > 0))
59 _e_output_hooks_clean();
63 _e_output_zoom_top_visible_ec_get()
67 E_Comp_Wl_Client_Data *cdata;
69 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
71 ec = evas_object_data_get(o, "E_Client");
73 /* check e_client and skip e_clients not intersects with zone */
75 if (e_object_is_del(E_OBJECT(ec))) continue;
76 if (e_client_util_ignored_get(ec)) continue;
77 if (ec->iconic) continue;
78 if (ec->visible == 0) continue;
79 if (!(ec->visibility.obscured == 0 || ec->visibility.obscured == 1)) continue;
80 if (!ec->frame) continue;
81 if (!evas_object_visible_get(ec->frame)) continue;
82 /* if ec is subsurface, skip this */
83 cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
84 if (cdata && cdata->sub.data) continue;
93 _e_output_zoom_get_angle(E_Output *output)
99 ec = _e_output_zoom_top_visible_ec_get();
101 ec_angle = ec->e.state.rot.ang.curr;
103 angle = (ec_angle + output->config.rotation) % 360;
109 _e_output_zoom_coordinate_cal_with_angle(E_Output *output, int angle)
114 if (angle == 0 || angle == 180)
116 w = output->config.geom.w;
117 h = output->config.geom.h;
121 w = output->config.geom.h;
122 h = output->config.geom.w;
125 if (angle == output->zoom_conf.init_angle)
129 output->zoom_conf.adjusted_cx = output->zoom_conf.init_cx;
130 output->zoom_conf.adjusted_cy = output->zoom_conf.init_cy;
132 else if (angle == 90)
134 output->zoom_conf.adjusted_cx = output->zoom_conf.init_cy;
135 output->zoom_conf.adjusted_cy = w - output->zoom_conf.init_cx - 1;
137 else if (angle == 180)
139 output->zoom_conf.adjusted_cx = w - output->zoom_conf.init_cx - 1;
140 output->zoom_conf.adjusted_cy = h - output->zoom_conf.init_cy - 1;
142 else /* angle == 270 */
144 output->zoom_conf.adjusted_cx = h - output->zoom_conf.init_cy - 1;
145 output->zoom_conf.adjusted_cy = output->zoom_conf.init_cx;
150 if ((angle % 180) == (output->zoom_conf.init_angle % 180)) /* 180 changed from init, don't have to cal ratio */
152 x = output->zoom_conf.init_cx;
153 y = output->zoom_conf.init_cy;
155 else /* 90 or 270 changed from init, need ratio cal*/
157 if (angle == 90 || angle == 270)
159 x = (float)output->config.geom.h / output->config.geom.w * output->zoom_conf.init_cx;
160 y = (float)output->config.geom.w / output->config.geom.h * output->zoom_conf.init_cy;
164 x = (float)output->config.geom.w / output->config.geom.h * output->zoom_conf.init_cx;
165 y = (float)output->config.geom.h / output->config.geom.w * output->zoom_conf.init_cy;
170 output->zoom_conf.adjusted_cx = x;
171 output->zoom_conf.adjusted_cy = y;
173 else if (angle == 90)
175 output->zoom_conf.adjusted_cx = y;
176 output->zoom_conf.adjusted_cy = w - x - 1;
178 else if (angle == 180)
180 output->zoom_conf.adjusted_cx = w - x - 1;
181 output->zoom_conf.adjusted_cy = h - y - 1;
183 else /* angle == 270 */
185 output->zoom_conf.adjusted_cx = h - y - 1;
186 output->zoom_conf.adjusted_cy = x;
192 _e_output_zoom_scaled_rect_get(int out_w, int out_h, double zoomx, double zoomy, int cx, int cy, Eina_Rectangle *rect)
197 rect->w = (int)((double)out_w / zoomx);
198 rect->h = (int)((double)out_h / zoomy);
203 x = (((double)x) * zoomx);
204 y = (((double)y) * zoomy);
219 rect->x = (int)(dx / zoomx);
220 rect->y = (int)(dy / zoomy);
224 _e_output_zoom_touch_transform(E_Output *output, Eina_Bool set)
226 E_Input_Device *dev = NULL;
227 Eina_Bool ret = EINA_FALSE;
229 E_Output *primary_output = NULL;
232 EINA_LIST_FOREACH(e_input_devices_get(), l, dev)
234 primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
235 if (primary_output != NULL)
241 ERR("fail get primary_output");
246 ret = e_input_device_touch_transformation_set(dev,
247 output->zoom_conf.rect.x, output->zoom_conf.rect.y,
248 output->zoom_conf.rect.w, output->zoom_conf.rect.h);
251 e_output_size_get(output, &w, &h);
252 ret = e_input_device_touch_transformation_set(dev, 0, 0, w, h);
255 if (ret != EINA_TRUE)
256 ERR("fail e_input_device_touch_transformation_set");
262 _e_output_cb_ecore_event_mouse_up(void *data, int type EINA_UNUSED, void *event EINA_UNUSED)
264 E_Output *output = NULL;
267 return ECORE_CALLBACK_PASS_ON;
271 if (output->zoom_conf.need_touch_set)
273 if (e_comp_wl->touch.pressed == 0)
275 _e_output_zoom_touch_transform(output, EINA_TRUE);
276 output->zoom_conf.need_touch_set = EINA_FALSE;
278 E_FREE_FUNC(output->touch_up_handler, ecore_event_handler_del);
282 return ECORE_CALLBACK_PASS_ON;
286 _e_output_zoom_touch_set(E_Output *output)
288 Eina_Bool ret = EINA_FALSE;
290 if (output->zoom_conf.need_touch_set) return EINA_TRUE;
292 if (e_comp_wl->touch.pressed)
294 if (output->touch_up_handler == NULL)
295 output->touch_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP,
296 _e_output_cb_ecore_event_mouse_up, output);
298 output->zoom_conf.need_touch_set = EINA_TRUE;
301 output->zoom_conf.need_touch_set = EINA_FALSE;
303 ret = _e_output_zoom_touch_transform(output, EINA_TRUE);
309 _e_output_zoom_touch_unset(E_Output *output)
311 Eina_Bool ret = EINA_FALSE;
313 if (!output) return EINA_FALSE;
315 output->zoom_conf.need_touch_set = EINA_FALSE;
317 if (output->touch_up_handler)
318 E_FREE_FUNC(output->touch_up_handler, ecore_event_handler_del);
320 ret = _e_output_zoom_touch_transform(output, EINA_FALSE);
326 _e_output_animating_check()
332 if (ec->visible && !ec->input_only)
334 if (e_comp_object_is_animating(ec->frame))
343 _e_output_render_update(E_Output *output)
347 if (_e_output_animating_check())
352 if (ec->visible && !ec->input_only)
353 e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
356 e_output_render(output);
360 _e_output_zoom_rotate(E_Output *output)
366 EINA_SAFETY_ON_NULL_RETURN(output);
368 e_output_size_get(output, &w, &h);
370 _e_output_zoom_coordinate_cal_with_angle(output, output->zoom_conf.current_angle);
372 /* get the scaled rect */
373 _e_output_zoom_scaled_rect_get(w, h, output->zoom_conf.zoomx, output->zoom_conf.zoomy,
374 output->zoom_conf.adjusted_cx, output->zoom_conf.adjusted_cy, &output->zoom_conf.rect);
375 DBG("zoom_rect rotate(x:%d,y:%d) (w:%d,h:%d)",
376 output->zoom_conf.rect.x, output->zoom_conf.rect.y, output->zoom_conf.rect.w, output->zoom_conf.rect.h);
378 EINA_LIST_FOREACH(output->planes, l, ep)
380 if (!e_plane_is_fb_target(ep)) continue;
382 e_plane_zoom_set(ep, &output->zoom_conf.rect);
386 /* update the ecore_evas */
387 _e_output_render_update(output);
391 _e_output_zoom_rotating_check(E_Output *output)
395 angle = _e_output_zoom_get_angle(output);
396 if (output->zoom_conf.current_angle != angle)
398 output->zoom_conf.current_angle = angle;
399 _e_output_zoom_rotate(output);
404 _e_output_visible_client_check(E_Output *output)
408 Eina_Bool found = EINA_FALSE;
411 E_Comp_Wl_Client_Data *cdata = NULL;
412 E_Output *zone_output = NULL;
415 EINA_LIST_FOREACH(e_comp->zones, l, zone)
417 zone_output = e_output_find(zone->output_id);
418 if (!zone_output) continue;
419 if (zone_output != output) continue;
421 EINA_RECTANGLE_SET(&r, zone->x, zone->y, zone->w, zone->h);
423 E_CLIENT_REVERSE_FOREACH(ec)
425 if (e_object_is_del(E_OBJECT(ec))) continue;
426 if (e_client_util_ignored_get(ec)) continue;
427 if (!ec->frame) continue;
428 if (ec->is_cursor) continue;
429 if (!ec->visible) continue;
430 if (!evas_object_visible_get(ec->frame)) continue;
431 cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
432 if (cdata && cdata->sub.data) continue; /* skip subsurface */
433 if (cdata && !cdata->mapped) continue;
434 if (!ec->iconic) continue;
435 e_client_geometry_get(ec, &x, &y, &w, &h);
436 if (E_INTERSECTS(x, y, w, h, r.x, r.y, r.w, r.h))
448 _e_output_dpms_on_render(E_Output *output)
452 if (_e_output_visible_client_check(output))
453 ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
457 _e_output_cb_output_change(tdm_output *toutput,
458 tdm_output_change_type type,
462 E_Output *e_output = NULL;
464 tdm_output_dpms tdpms = (tdm_output_dpms)value.u32;
465 static Eina_Bool override = EINA_FALSE;
467 EINA_SAFETY_ON_NULL_RETURN(toutput);
468 EINA_SAFETY_ON_NULL_RETURN(user_data);
470 e_output = (E_Output *)user_data;
474 case TDM_OUTPUT_CHANGE_DPMS:
475 if (tdpms == TDM_OUTPUT_DPMS_OFF)
477 edpms = E_OUTPUT_DPMS_OFF;
480 e_comp_override_add();
481 override = EINA_TRUE;
484 else if (tdpms == TDM_OUTPUT_DPMS_ON)
486 edpms = E_OUTPUT_DPMS_ON;
489 e_comp_override_del();
490 override = EINA_FALSE;
492 _e_output_dpms_on_render(e_output);
494 else if (tdpms == TDM_OUTPUT_DPMS_STANDBY) edpms = E_OUTPUT_DPMS_STANDBY;
495 else if (tdpms == TDM_OUTPUT_DPMS_SUSPEND) edpms = E_OUTPUT_DPMS_SUSPEND;
496 else edpms = e_output->dpms;
498 e_output->dpms = edpms;
500 _e_output_hook_call(E_OUTPUT_HOOK_DPMS_CHANGE, e_output);
509 _e_output_update_fps()
511 static double time = 0.0;
512 static double lapse = 0.0;
513 static int cframes = 0;
514 static int flapse = 0;
516 if (e_comp->calc_fps)
519 double tim = ecore_time_get();
521 dt = tim - e_comp->frametimes[0];
522 e_comp->frametimes[0] = tim;
532 else if ((tim - lapse) >= 0.5)
534 e_comp->fps = (cframes - flapse) / (tim - lapse);
550 e_output_shutdown(void)
556 _output_type_to_str(tdm_output_type output_type)
558 if (output_type == TDM_OUTPUT_TYPE_Unknown) return "Unknown";
559 else if (output_type == TDM_OUTPUT_TYPE_VGA) return "VGA";
560 else if (output_type == TDM_OUTPUT_TYPE_DVII) return "DVII";
561 else if (output_type == TDM_OUTPUT_TYPE_DVID) return "DVID";
562 else if (output_type == TDM_OUTPUT_TYPE_DVIA) return "DVIA";
563 else if (output_type == TDM_OUTPUT_TYPE_SVIDEO) return "SVIDEO";
564 else if (output_type == TDM_OUTPUT_TYPE_LVDS) return "LVDS";
565 else if (output_type == TDM_OUTPUT_TYPE_Component) return "Component";
566 else if (output_type == TDM_OUTPUT_TYPE_9PinDIN) return "9PinDIN";
567 else if (output_type == TDM_OUTPUT_TYPE_DisplayPort) return "DisplayPort";
568 else if (output_type == TDM_OUTPUT_TYPE_HDMIA) return "HDMIA";
569 else if (output_type == TDM_OUTPUT_TYPE_HDMIB) return "HDMIB";
570 else if (output_type == TDM_OUTPUT_TYPE_TV) return "TV";
571 else if (output_type == TDM_OUTPUT_TYPE_eDP) return "eDP";
572 else if (output_type == TDM_OUTPUT_TYPE_DSI) return "DSI";
573 else return "Unknown";
577 _e_output_cb_planes_sort(const void *d1, const void *d2)
579 E_Plane *plane1 = (E_Plane *)d1;
580 E_Plane *plane2 = (E_Plane *)d2;
582 if (!plane1) return(1);
583 if (!plane2) return(-1);
585 return (plane1->zpos - plane2->zpos);
589 _e_output_tdm_capture_create(E_Output *output, tdm_capture_capability cap)
591 tdm_error error = TDM_ERROR_NONE;
592 tdm_capture *tcapture = NULL;
593 tdm_capture_capability capabilities;
594 E_Comp_Screen *e_comp_screen = NULL;
596 e_comp_screen = e_comp->e_comp_screen;
597 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
599 error = tdm_display_get_capture_capabilities(e_comp_screen->tdisplay, &capabilities);
600 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
602 if (!(capabilities & cap))
605 tcapture = tdm_output_create_capture(output->toutput, &error);
606 if (error != TDM_ERROR_NONE)
608 ERR("create tdm_capture failed");
616 _e_output_center_rect_get (int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
620 if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
623 rw = (float)src_w / dst_w;
624 rh = (float)src_h / dst_h;
631 fit->y = (dst_h - fit->h) / 2;
637 fit->x = (dst_w - fit->w) / 2;
653 _e_output_capture_position_get(E_Output *output, int dst_w, int dst_h, Eina_Rectangle *fit, Eina_Bool rotate)
655 int output_w = 0, output_h = 0;
657 e_output_size_get(output, &output_w, &output_h);
659 if (output_w == 0 || output_h == 0)
663 _e_output_center_rect_get(output_h, output_w, dst_w, dst_h, fit);
665 _e_output_center_rect_get(output_w, output_h, dst_w, dst_h, fit);
671 _e_output_aligned_width_get(tbm_surface_h tsurface)
673 unsigned int aligned_width = 0;
674 tbm_surface_info_s surf_info;
676 tbm_surface_get_info(tsurface, &surf_info);
678 switch (surf_info.format)
680 case TBM_FORMAT_YUV420:
681 case TBM_FORMAT_YVU420:
682 case TBM_FORMAT_YUV422:
683 case TBM_FORMAT_YVU422:
684 case TBM_FORMAT_NV12:
685 case TBM_FORMAT_NV21:
686 aligned_width = surf_info.planes[0].stride;
688 case TBM_FORMAT_YUYV:
689 case TBM_FORMAT_UYVY:
690 aligned_width = surf_info.planes[0].stride >> 1;
692 case TBM_FORMAT_ARGB8888:
693 case TBM_FORMAT_XRGB8888:
694 aligned_width = surf_info.planes[0].stride >> 2;
697 ERR("not supported format: %x", surf_info.format);
700 return aligned_width;
704 _e_output_top_visible_ec_get()
708 E_Comp_Wl_Client_Data *cdata;
710 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
712 ec = evas_object_data_get(o, "E_Client");
714 /* check e_client and skip e_clients not intersects with zone */
716 if (e_object_is_del(E_OBJECT(ec))) continue;
717 if (e_client_util_ignored_get(ec)) continue;
718 if (ec->iconic) continue;
719 if (ec->visible == 0) continue;
720 if (!(ec->visibility.obscured == 0 || ec->visibility.obscured == 1)) continue;
721 if (!ec->frame) continue;
722 if (!evas_object_visible_get(ec->frame)) continue;
723 /* if ec is subsurface, skip this */
724 cdata = (E_Comp_Wl_Client_Data *)ec->comp_data;
725 if (cdata && cdata->sub.data) continue;
734 _e_output_top_ec_angle_get(void)
738 ec = _e_output_top_visible_ec_get();
740 return ec->e.state.rot.ang.curr;
745 static E_Output_Capture *
746 _e_output_tdm_stream_capture_find_data(E_Output *output, tbm_surface_h tsurface)
748 E_Output_Capture *cdata = NULL;
751 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
753 if (!cdata) continue;
755 if (cdata->surface == tsurface)
763 _e_output_tdm_stream_capture_stop(void *data)
765 E_Output *output = data;
767 EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_CANCEL);
769 if (output->stream_capture.tcapture)
771 DBG("e_output stream capture stop.");
772 tdm_capture_destroy(output->stream_capture.tcapture);
773 output->stream_capture.tcapture = NULL;
776 output->stream_capture.timer = NULL;
778 return ECORE_CALLBACK_CANCEL;
782 _e_output_tdm_stream_capture_done_handler(tdm_capture *tcapture,
783 tbm_surface_h tsurface, void *user_data)
785 E_Output *output = NULL;
786 E_Output_Capture *cdata = NULL;
788 output = (E_Output *)user_data;
790 tbm_surface_internal_unref(tsurface);
792 cdata = _e_output_tdm_stream_capture_find_data(output, tsurface);
795 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
796 if (!cdata->dequeued)
797 cdata->func(output, tsurface, cdata->data);
801 if (!output->stream_capture.start)
803 if (eina_list_count(output->stream_capture.data) == 0)
804 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
805 _e_output_tdm_stream_capture_stop, output);
810 _e_output_tdm_capture_info_set(E_Output *output, tdm_capture *tcapture, tbm_surface_h tsurface,
811 tdm_capture_type type, Eina_Bool auto_rotate)
813 tdm_error error = TDM_ERROR_NONE;
814 tdm_info_capture capture_info;
815 tbm_error_e tbm_error = TBM_ERROR_NONE;
816 tbm_surface_info_s surf_info;
817 Eina_Rectangle dst_pos;
820 int output_angle = 0;
822 Eina_Bool rotate_check = EINA_FALSE;
824 tbm_error = tbm_surface_get_info(tsurface, &surf_info);
825 EINA_SAFETY_ON_FALSE_RETURN_VAL(tbm_error == TBM_ERROR_NONE, EINA_FALSE);
827 width = _e_output_aligned_width_get(tsurface);
828 EINA_SAFETY_ON_TRUE_RETURN_VAL(width == 0, EINA_FALSE);
830 memset(&capture_info, 0, sizeof(tdm_info_capture));
831 capture_info.dst_config.size.h = width;
832 capture_info.dst_config.size.v = surf_info.height;
833 capture_info.dst_config.format = surf_info.format;
834 capture_info.transform = TDM_TRANSFORM_NORMAL;
836 angle = _e_output_top_ec_angle_get();
837 output_angle = output->config.rotation;
840 (((angle + output_angle) % 360 == 90) || ((angle + output_angle) % 360 == 270)))
841 rotate_check = EINA_TRUE;
843 ret = _e_output_capture_position_get(output, surf_info.width, surf_info.height, &dst_pos, rotate_check);
846 capture_info.dst_config.pos.x = dst_pos.x;
847 capture_info.dst_config.pos.y = dst_pos.y;
848 capture_info.dst_config.pos.w = dst_pos.w;
849 capture_info.dst_config.pos.h = dst_pos.h;
853 int tmp = (angle + output_angle) % 360;
855 capture_info.transform = TDM_TRANSFORM_90;
857 capture_info.transform = TDM_TRANSFORM_180;
859 capture_info.transform = TDM_TRANSFORM_270;
861 else if (auto_rotate && output_angle == 90)
862 capture_info.transform = TDM_TRANSFORM_90;
863 else if (auto_rotate && output_angle == 180)
864 capture_info.transform = TDM_TRANSFORM_180;
865 else if (auto_rotate && output_angle == 270)
866 capture_info.transform = TDM_TRANSFORM_270;
870 capture_info.dst_config.pos.x = 0;
871 capture_info.dst_config.pos.y = 0;
872 capture_info.dst_config.pos.w = surf_info.width;
873 capture_info.dst_config.pos.h = surf_info.height;
876 capture_info.type = type;
878 error = tdm_capture_set_info(tcapture, &capture_info);
879 if (error != TDM_ERROR_NONE)
881 ERR("tdm_capture set_info failed");
889 _e_output_tdm_capture_done_handler(tdm_capture *tcapture, tbm_surface_h tsurface, void *user_data)
891 E_Output *output = NULL;
892 E_Output_Capture *cdata = NULL;
894 cdata = (E_Output_Capture *)user_data;
895 output = cdata->output;
897 tbm_surface_internal_unref(tsurface);
899 cdata->func(output, tsurface, cdata->data);
901 tdm_capture_destroy(cdata->tcapture);
905 DBG("tdm_capture done.(%p)", tsurface);
909 _e_output_tdm_capture(E_Output *output, tdm_capture *tcapture,
910 tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
912 tdm_error error = TDM_ERROR_NONE;
913 E_Output_Capture *cdata = NULL;
915 cdata = E_NEW(E_Output_Capture, 1);
916 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
918 cdata->output = output;
919 cdata->tcapture = tcapture;
923 tbm_surface_internal_ref(tsurface);
925 error = tdm_capture_set_done_handler(tcapture, _e_output_tdm_capture_done_handler, cdata);
926 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
928 error = tdm_capture_attach(tcapture, tsurface);
929 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
931 error = tdm_capture_commit(tcapture);
932 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
937 tbm_surface_internal_unref(tsurface);
946 _e_output_stream_capture_cb_timeout(void *data)
948 E_Output *output = data;
949 E_Output_Capture *cdata = NULL;
952 EINA_SAFETY_ON_NULL_GOTO(output, done);
954 if (!output->stream_capture.start)
956 EINA_LIST_FREE(output->stream_capture.data, cdata)
958 tbm_surface_internal_unref(cdata->surface);
963 if (output->stream_capture.tcapture)
965 tdm_capture_destroy(output->stream_capture.tcapture);
966 output->stream_capture.tcapture = NULL;
969 DBG("e_output stream capture stop.");
971 output->stream_capture.timer = NULL;
973 return ECORE_CALLBACK_CANCEL;
976 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
978 if (!cdata->in_using) break;
981 /* can be null when client doesn't queue a buffer previously */
985 cdata->in_using = EINA_TRUE;
987 tbm_surface_internal_unref(cdata->surface);
989 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
991 cdata->func(output, cdata->surface, cdata->data);
995 return ECORE_CALLBACK_RENEW;
999 _e_output_tdm_stream_capture(E_Output *output, tdm_capture *tcapture,
1000 tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
1002 tdm_error error = TDM_ERROR_NONE;
1003 E_Output_Capture *cdata = NULL;
1004 E_Output_Capture *tmp_cdata = NULL;
1007 cdata = E_NEW(E_Output_Capture, 1);
1008 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
1010 cdata->output = output;
1011 cdata->tcapture = tcapture;
1012 cdata->surface = tsurface;
1016 tbm_surface_internal_ref(tsurface);
1018 output->stream_capture.data = eina_list_append(output->stream_capture.data, cdata);
1020 if (output->stream_capture.start)
1022 if (e_output_dpms_get(output))
1024 if (!output->stream_capture.timer)
1025 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
1026 _e_output_stream_capture_cb_timeout, output);
1027 EINA_SAFETY_ON_NULL_RETURN_VAL(output->stream_capture.timer, EINA_FALSE);
1031 else if (output->stream_capture.timer)
1033 ecore_timer_del(output->stream_capture.timer);
1034 output->stream_capture.timer = NULL;
1036 EINA_LIST_FOREACH_SAFE(output->stream_capture.data, l, ll, tmp_cdata)
1038 if (!tmp_cdata) continue;
1040 if (!tmp_cdata->in_using)
1042 tmp_cdata->in_using = EINA_TRUE;
1044 error = tdm_capture_attach(tcapture, tsurface);
1045 if (error != TDM_ERROR_NONE)
1047 ERR("tdm_capture_attach fail");
1048 output->stream_capture.data = eina_list_remove_list(output->stream_capture.data, l);
1049 tmp_cdata->func(tmp_cdata->output, tmp_cdata->surface, tmp_cdata->data);
1056 error = tdm_capture_commit(tcapture);
1057 if (error != TDM_ERROR_NONE)
1059 ERR("tdm_capture_commit fail");
1065 cdata->in_using = EINA_TRUE;
1067 error = tdm_capture_attach(tcapture, tsurface);
1068 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1070 error = tdm_capture_commit(tcapture);
1071 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1076 if (e_output_dpms_get(output))
1079 cdata->in_using = EINA_TRUE;
1081 error = tdm_capture_attach(tcapture, tsurface);
1082 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
1088 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1090 tbm_surface_internal_unref(tsurface);
1099 _e_output_watch_vblank_timer(void *data)
1101 E_Output *output = data;
1103 EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_RENEW);
1105 _e_output_vblank_handler(NULL, 0, 0, 0, (void *)output);
1107 return ECORE_CALLBACK_RENEW;
1111 _e_output_watch_vblank(E_Output *output)
1116 /* If not DPMS_ON, we call vblank handler directly to dump screen */
1117 if (e_output_dpms_get(output))
1119 if (!output->stream_capture.timer)
1120 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
1121 _e_output_watch_vblank_timer, output);
1122 EINA_SAFETY_ON_NULL_RETURN_VAL(output->stream_capture.timer, EINA_FALSE);
1126 else if (output->stream_capture.timer)
1128 ecore_timer_del(output->stream_capture.timer);
1129 output->stream_capture.timer = NULL;
1132 if (output->stream_capture.wait_vblank)
1135 per_vblank = output->config.mode.refresh / (DUMP_FPS * 1000);
1137 ret = tdm_output_wait_vblank(output->toutput, per_vblank, 0,
1138 _e_output_vblank_handler, output);
1139 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
1141 output->stream_capture.wait_vblank = EINA_TRUE;
1147 _e_output_vblank_handler(tdm_output *toutput, unsigned int sequence,
1148 unsigned int tv_sec, unsigned int tv_usec, void *data)
1150 E_Output *output = data;
1151 E_Output_Capture *cdata = NULL;
1153 Eina_Bool ret = EINA_FALSE;
1155 EINA_SAFETY_ON_NULL_RETURN(output);
1157 output->stream_capture.wait_vblank = EINA_FALSE;
1159 if (!output->stream_capture.start)
1161 EINA_LIST_FREE(output->stream_capture.data, cdata)
1163 tbm_surface_internal_unref(cdata->surface);
1168 if (output->stream_capture.timer)
1170 ecore_timer_del(output->stream_capture.timer);
1171 output->stream_capture.timer = NULL;
1173 DBG("e_output stream capture stop.");
1178 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
1180 if (!cdata->in_using) break;
1183 /* can be null when client doesn't queue a buffer previously */
1187 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1189 ret = _e_output_capture(output, cdata->surface, EINA_FALSE);
1190 if (ret == EINA_FALSE)
1191 ERR("capture fail");
1193 tbm_surface_internal_unref(cdata->surface);
1195 cdata->func(output, cdata->surface, cdata->data);
1199 /* timer is a substitution for vblank during dpms off. so if timer is running,
1200 * we don't watch vblank events recursively.
1202 if (!output->stream_capture.timer)
1203 _e_output_watch_vblank(output);
1207 _e_output_vblank_stream_capture(E_Output *output, tbm_surface_h tsurface,
1208 E_Output_Capture_Cb func, void *data)
1210 E_Output_Capture *cdata = NULL;
1211 Eina_Bool ret = EINA_FALSE;
1213 cdata = E_NEW(E_Output_Capture, 1);
1214 EINA_SAFETY_ON_NULL_RETURN_VAL(cdata, EINA_FALSE);
1216 cdata->output = output;
1217 cdata->surface = tsurface;
1221 tbm_surface_internal_ref(tsurface);
1223 output->stream_capture.data = eina_list_append(output->stream_capture.data, cdata);
1225 if (output->stream_capture.start)
1227 ret = _e_output_watch_vblank(output);
1228 if (ret == EINA_FALSE)
1230 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
1231 tbm_surface_internal_unref(tsurface);
1242 _e_output_capture_showing_rect_get(Eina_Rectangle *out_rect, Eina_Rectangle *dst_rect, Eina_Rectangle *showing_rect)
1244 showing_rect->x = dst_rect->x;
1245 showing_rect->y = dst_rect->y;
1247 if (dst_rect->x >= out_rect->w)
1248 showing_rect->w = 0;
1249 else if (dst_rect->x + dst_rect->w > out_rect->w)
1250 showing_rect->w = out_rect->w - dst_rect->x;
1252 showing_rect->w = dst_rect->w;
1254 if (dst_rect->y >= out_rect->h)
1255 showing_rect->h = 0;
1256 else if (dst_rect->y + dst_rect->h > out_rect->h)
1257 showing_rect->h = out_rect->h - dst_rect->y;
1259 showing_rect->h = dst_rect->h;
1263 _e_output_capture_src_crop_get(E_Output *output, tdm_layer *layer, Eina_Rectangle *fit, Eina_Rectangle *showing_rect)
1265 tdm_info_layer info;
1266 tdm_error error = TDM_ERROR_NONE;
1267 const tdm_output_mode *mode = NULL;
1268 float ratio_x, ratio_y;
1269 Eina_Rectangle out_rect;
1270 Eina_Rectangle dst_rect;
1277 tdm_output_get_mode(output->toutput, &mode);
1278 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1282 out_rect.w = mode->hdisplay;
1283 out_rect.h = mode->vdisplay;
1285 error = tdm_layer_get_info(layer, &info);
1286 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1288 dst_rect.x = info.dst_pos.x;
1289 dst_rect.y = info.dst_pos.y;
1290 dst_rect.w = info.dst_pos.w;
1291 dst_rect.h = info.dst_pos.h;
1293 _e_output_capture_showing_rect_get(&out_rect, &dst_rect, showing_rect);
1295 fit->x = info.src_config.pos.x;
1296 fit->y = info.src_config.pos.y;
1298 if (info.transform % 2 == 0)
1300 ratio_x = (float)info.src_config.pos.w / dst_rect.w;
1301 ratio_y = (float)info.src_config.pos.h / dst_rect.h;
1303 fit->w = showing_rect->w * ratio_x;
1304 fit->h = showing_rect->h * ratio_y;
1308 ratio_x = (float)info.src_config.pos.w / dst_rect.h;
1309 ratio_y = (float)info.src_config.pos.h / dst_rect.w;
1311 fit->w = showing_rect->h * ratio_x;
1312 fit->h = showing_rect->w * ratio_y;
1319 _e_output_capture_dst_crop_get(E_Comp_Wl_Video_Buf *tmp, E_Comp_Wl_Video_Buf *dst, tdm_layer *layer,
1320 int w, int h, Eina_Rectangle *pos, Eina_Rectangle *showing_pos,
1321 Eina_Rectangle *dst_crop, int rotate)
1323 tdm_info_layer info;
1324 tdm_error error = TDM_ERROR_NONE;
1331 error = tdm_layer_get_info(layer, &info);
1332 EINA_SAFETY_ON_FALSE_RETURN(error == TDM_ERROR_NONE);
1334 if (info.src_config.pos.w == w && info.src_config.pos.h == h &&
1335 pos->x == 0 && pos->y == 0 && pos->w == tmp->width && pos->h == tmp->height)
1337 dst_crop->x = pos->x;
1338 dst_crop->y = pos->y;
1339 dst_crop->w = pos->w;
1340 dst_crop->h = pos->h;
1342 else if ((w == pos->w) && (h == pos->h) && (showing_pos->w == pos->w) && (showing_pos->h == pos->h))
1344 dst_crop->x = info.dst_pos.x + pos->x;
1345 dst_crop->y = info.dst_pos.y + pos->y;
1346 dst_crop->w = info.dst_pos.w;
1347 dst_crop->h = info.dst_pos.h;
1349 else if (rotate == 0)
1351 dst_crop->x = showing_pos->x * pos->w / w + pos->x;
1352 dst_crop->y = showing_pos->y * pos->h / h + pos->y;
1353 dst_crop->w = showing_pos->w * pos->w / w;
1354 dst_crop->h = showing_pos->h * pos->h / h;
1356 else if (rotate == 90)
1358 dst_crop->x = (h - showing_pos->y - showing_pos->h) * pos->w / h + pos->x;
1359 dst_crop->y = showing_pos->x * pos->h / w + pos->y;
1360 dst_crop->w = showing_pos->h * pos->w / h;
1361 dst_crop->h = showing_pos->w * pos->h / w;
1363 else if (rotate == 180)
1365 dst_crop->x = (w - showing_pos->x - showing_pos->w) * pos->w / w + pos->x;
1366 dst_crop->y = (h - showing_pos->y - showing_pos->h) * pos->h / h + pos->y;
1367 dst_crop->w = showing_pos->w * pos->w / w;
1368 dst_crop->h = showing_pos->h * pos->h / h;
1370 else if (rotate == 270)
1372 dst_crop->x = showing_pos->y * pos->w / h + pos->x;
1373 dst_crop->y = (w - showing_pos->x - showing_pos->w) * pos->h / w + pos->y;
1374 dst_crop->w = showing_pos->h * pos->w / h;
1375 dst_crop->h = showing_pos->w * pos->h / w;
1379 dst_crop->x = pos->x;
1380 dst_crop->y = pos->y;
1381 dst_crop->w = pos->w;
1382 dst_crop->h = pos->h;
1383 ERR("get_cropinfo: unknown case error");
1388 _e_output_video_buffer_capture(E_Output *output, E_Comp_Wl_Video_Buf *vbuf, Eina_Bool auto_rotate)
1390 tdm_error error = TDM_ERROR_NONE;
1391 int width = 0, height = 0, rotate = 0;
1394 int output_angle = 0;
1395 Eina_Bool rotate_check = EINA_FALSE;
1397 e_output_size_get(output, &width, &height);
1398 if (width == 0 || height == 0)
1401 angle = _e_output_top_ec_angle_get();
1402 output_angle = output->config.rotation;
1405 ((angle + output_angle) % 360 == 90 || (angle + output_angle) % 360 == 270))
1406 rotate_check = EINA_TRUE;
1410 int tmp = (angle + output_angle) % 360;
1414 else if (tmp == 180)
1416 else if (tmp == 270)
1419 else if (auto_rotate && output_angle == 90)
1421 else if (auto_rotate && output_angle == 180)
1423 else if (auto_rotate && output_angle == 270)
1426 error = tdm_output_get_layer_count(output->toutput, &count);
1427 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1428 EINA_SAFETY_ON_FALSE_RETURN_VAL(count >= 0, EINA_FALSE);
1430 for (i = 0; i < count; i++)
1432 E_Comp_Wl_Video_Buf *tmp = NULL;
1434 tdm_layer_capability capability;
1435 tbm_surface_h surface = NULL;
1436 Eina_Rectangle showing_pos = {0, };
1437 Eina_Rectangle dst_pos = {0, };
1438 Eina_Rectangle src_crop = {0, };
1439 Eina_Rectangle dst_crop = {0, };
1442 layer = tdm_output_get_layer(output->toutput, i, &error);
1443 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1445 error = tdm_layer_get_capabilities(layer, &capability);
1446 EINA_SAFETY_ON_FALSE_RETURN_VAL(error == TDM_ERROR_NONE, EINA_FALSE);
1447 if (capability & TDM_LAYER_CAPABILITY_VIDEO)
1450 surface = tdm_layer_get_displaying_buffer(layer, &error);
1451 if (surface == NULL)
1454 tmp = e_comp_wl_video_buffer_create_tbm(surface);
1458 ret = _e_output_capture_src_crop_get(output, layer, &src_crop, &showing_pos);
1459 if (ret == EINA_FALSE)
1461 e_comp_wl_video_buffer_unref(tmp);
1465 ret = _e_output_capture_position_get(output, vbuf->width, vbuf->height, &dst_pos, rotate_check);
1466 if (ret == EINA_FALSE)
1468 e_comp_wl_video_buffer_unref(tmp);
1472 _e_output_capture_dst_crop_get(tmp, vbuf, layer, width, height,
1473 &dst_pos, &showing_pos, &dst_crop, rotate);
1475 e_comp_wl_video_buffer_convert(tmp, vbuf,
1476 src_crop.x, src_crop.y, src_crop.w, src_crop.h,
1477 dst_crop.x, dst_crop.y, dst_crop.w, dst_crop.h,
1478 EINA_TRUE, rotate, 0, 0);
1480 e_comp_wl_video_buffer_unref(tmp);
1487 _e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate)
1489 E_Comp_Wl_Video_Buf *vbuf = NULL;
1490 Eina_Bool ret = EINA_FALSE;
1492 vbuf = e_comp_wl_video_buffer_create_tbm(tsurface);
1493 EINA_SAFETY_ON_NULL_RETURN_VAL(vbuf, EINA_FALSE);
1495 e_comp_wl_video_buffer_clear(vbuf);
1497 ret = _e_output_video_buffer_capture(output, vbuf, auto_rotate);
1499 e_comp_wl_video_buffer_unref(vbuf);
1505 _e_output_tdm_strem_capture_support(E_Output *output)
1507 tdm_error error = TDM_ERROR_NONE;
1508 tdm_capture_capability capabilities;
1509 E_Comp_Screen *e_comp_screen = NULL;
1511 e_comp_screen = e_comp->e_comp_screen;
1512 EINA_SAFETY_ON_NULL_RETURN(e_comp_screen);
1514 error = tdm_display_get_capture_capabilities(e_comp_screen->tdisplay, &capabilities);
1515 EINA_SAFETY_ON_FALSE_RETURN(error == TDM_ERROR_NONE);
1517 if (capabilities & TDM_CAPTURE_CAPABILITY_STREAM)
1518 output->stream_capture.possible_tdm_capture = EINA_TRUE;
1522 e_output_new(E_Comp_Screen *e_comp_screen, int index)
1524 E_Output *output = NULL;
1525 E_Plane *plane = NULL;
1526 E_Plane *default_fb = NULL;
1527 tdm_output *toutput = NULL;
1534 tdm_output_type output_type;
1535 int min_w, min_h, max_w, max_h, preferred_align;
1537 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, NULL);
1539 output = E_NEW(E_Output, 1);
1540 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1541 output->index = index;
1543 toutput = tdm_display_get_output(e_comp_screen->tdisplay, index, NULL);
1544 if (!toutput) goto fail;
1545 output->toutput = toutput;
1547 error = tdm_output_add_change_handler(toutput, _e_output_cb_output_change, output);
1548 if (error != TDM_ERROR_NONE)
1549 WRN("fail to tdm_output_add_change_handler");
1551 error = tdm_output_get_output_type(toutput, &output_type);
1552 if (error != TDM_ERROR_NONE) goto fail;
1554 error = tdm_output_get_cursor_available_size(toutput, &min_w, &min_h, &max_w, &max_h, &preferred_align);
1555 if (error == TDM_ERROR_NONE)
1557 output->cursor_available.min_w = min_w;
1558 output->cursor_available.min_h = min_h;
1559 output->cursor_available.max_w = min_w;
1560 output->cursor_available.max_h = min_h;
1561 output->cursor_available.preferred_align = preferred_align;
1565 output->cursor_available.min_w = -1;
1566 output->cursor_available.min_h = -1;
1567 output->cursor_available.max_w = -1;
1568 output->cursor_available.max_h = -1;
1569 output->cursor_available.preferred_align = -1;
1572 name = _output_type_to_str(output_type);
1573 size = strlen(name) + 4;
1575 id = calloc(1, size);
1577 snprintf(id, size, "%s-%d", name, index);
1580 INF("E_OUTPUT: (%d) output_id = %s", index, output->id);
1582 tdm_output_get_layer_count(toutput, &num_layers);
1585 ERR("fail to get tdm_output_get_layer_count\n");
1588 output->plane_count = num_layers;
1589 INF("E_OUTPUT: num_planes %i", output->plane_count);
1591 if (!e_plane_init())
1593 ERR("fail to e_plane_init.");
1597 for (i = 0; i < output->plane_count; i++)
1599 plane = e_plane_new(output, i);
1602 ERR("fail to create the e_plane.");
1605 output->planes = eina_list_append(output->planes, plane);
1608 output->planes = eina_list_sort(output->planes, eina_list_count(output->planes), _e_output_cb_planes_sort);
1610 default_fb = e_output_default_fb_target_get(output);
1613 ERR("fail to get default_fb_target plane");
1617 if (!e_plane_fb_target_set(default_fb, EINA_TRUE))
1619 ERR("fail to set fb_target plane");
1623 output->e_comp_screen = e_comp_screen;
1625 _e_output_tdm_strem_capture_support(output);
1630 if (output) e_output_del(output);
1636 e_output_del(E_Output *output)
1641 if (!output) return;
1645 if (output->id) free(output->id);
1646 if (output->info.screen) free(output->info.screen);
1647 if (output->info.name) free(output->info.name);
1648 if (output->info.edid) free(output->info.edid);
1650 tdm_output_remove_change_handler(output->toutput, _e_output_cb_output_change, output);
1652 EINA_LIST_FREE(output->info.modes, m) free(m);
1654 EINA_LIST_FREE(output->planes, plane) e_plane_free(plane);
1659 e_output_rotate(E_Output *output, int rotate)
1661 unsigned int transform = WL_OUTPUT_TRANSFORM_NORMAL;
1664 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1666 /* FIXME: currently the screen size can't be changed in runtime. To make it
1667 * possible, the output mode should be changeable first.
1669 rot_dif = output->config.rotation - rotate;
1670 if (rot_dif < 0) rot_dif = -rot_dif;
1672 if ((rot_dif % 180) && (output->config.geom.w != output->config.geom.h))
1674 ERR("output size(%dx%d) should be squre.",
1675 output->config.geom.w, output->config.geom.h);
1682 transform = WL_OUTPUT_TRANSFORM_90;
1685 transform = WL_OUTPUT_TRANSFORM_180;
1688 transform = WL_OUTPUT_TRANSFORM_270;
1692 transform = WL_OUTPUT_TRANSFORM_NORMAL;
1696 output->config.rotation = rotate;
1698 e_comp_wl_output_init(output->id, output->info.name,
1699 output->info.screen,
1700 output->config.geom.x, output->config.geom.y,
1701 output->config.geom.w, output->config.geom.h,
1702 output->info.size.w, output->info.size.h,
1703 output->config.mode.refresh, 0, transform);
1705 ELOGF("TRANSFORM", "output(%s) transform(%d)", NULL, NULL, output->info.name, transform);
1711 e_output_update(E_Output *output)
1713 E_Output_Mode *m = NULL;
1714 Eina_List *modes = NULL;
1715 Eina_Bool connected = EINA_TRUE;
1717 tdm_output_conn_status status;
1720 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1722 error = tdm_output_get_conn_status(output->toutput, &status);
1723 if (error != TDM_ERROR_NONE)
1725 ERR("failt to get conn status.");
1729 if (status == TDM_OUTPUT_CONN_STATUS_DISCONNECTED) connected = EINA_FALSE;
1733 /* disconnect --> connect */
1734 if (connected != output->info.connected)
1739 unsigned int phy_w, phy_h;
1740 const tdm_output_mode *tmodes = NULL;
1742 unsigned int pipe = 0;
1745 error = tdm_output_get_model_info(output->toutput, &maker, &screen, NULL);
1746 if (error != TDM_ERROR_NONE)
1748 ERR("fail to get model info.");
1752 /* we apply the screen rotation only for the primary output */
1753 error = tdm_output_get_pipe(output->toutput, &pipe);
1754 if (error == TDM_ERROR_NONE && pipe == 0)
1755 output->config.rotation = e_comp->e_comp_screen->rotation;
1759 size = strlen(output->id) + 1 + strlen(maker) + 1;
1760 name = calloc(1, size);
1761 if (!name) return EINA_FALSE;
1762 snprintf(name, size, "%s-%s", output->id, maker);
1766 size = strlen(output->id) + 1;
1767 name = calloc(1, size);
1768 if (!name) return EINA_FALSE;
1769 snprintf(name, size, "%s", output->id);
1771 INF("E_OUTPUT: screen = %s, name = %s", screen, name);
1773 error = tdm_output_get_physical_size(output->toutput, &phy_w, &phy_h);
1774 if (error != TDM_ERROR_NONE)
1776 ERR("fail to get physical_size.");
1781 error = tdm_output_get_available_modes(output->toutput, &tmodes, &num_tmodes);
1782 if (error != TDM_ERROR_NONE || num_tmodes == 0)
1784 ERR("fail to get tmodes");
1789 for (i = 0; i < num_tmodes; i++)
1791 E_Output_Mode *rmode;
1793 rmode = E_NEW(E_Output_Mode, 1);
1794 if (!rmode) continue;
1796 if (tmodes[i].type & TDM_OUTPUT_MODE_TYPE_PREFERRED)
1797 rmode->preferred = EINA_TRUE;
1799 rmode->w = tmodes[i].hdisplay;
1800 rmode->h = tmodes[i].vdisplay;
1801 rmode->refresh = tmodes[i].vrefresh;
1802 rmode->tmode = &tmodes[i];
1804 modes = eina_list_append(modes, rmode);
1807 /* resetting the output->info */
1808 if (output->info.screen) free(output->info.screen);
1809 if (output->info.name) free(output->info.name);
1810 EINA_LIST_FREE(output->info.modes, m) free(m);
1812 output->info.screen = strdup(screen);
1813 output->info.name = name;
1814 output->info.modes = modes;
1815 output->info.size.w = phy_w;
1816 output->info.size.h = phy_h;
1818 output->info.connected = EINA_TRUE;
1820 INF("E_OUTPUT: id(%s) connected..", output->id);
1824 /* check the crtc setting */
1825 if (status != TDM_OUTPUT_CONN_STATUS_MODE_SETTED)
1827 const tdm_output_mode *mode = NULL;
1829 error = tdm_output_get_mode(output->toutput, &mode);
1830 if (error != TDM_ERROR_NONE || mode == NULL)
1832 ERR("fail to get mode.");
1836 output->config.geom.x = 0;
1837 output->config.geom.y = 0;
1838 output->config.geom.w = mode->hdisplay;
1839 output->config.geom.h = mode->vdisplay;
1841 output->config.mode.w = mode->hdisplay;
1842 output->config.mode.h = mode->vdisplay;
1843 output->config.mode.refresh = mode->vrefresh;
1845 output->config.enabled = 1;
1847 INF("E_OUTPUT: '%s' %i %i %ix%i", output->info.name,
1848 output->config.geom.x, output->config.geom.y,
1849 output->config.geom.w, output->config.geom.h);
1856 output->info.connected = EINA_FALSE;
1858 /* reset output info */
1859 if (output->info.screen)
1861 free(output->info.screen);
1862 output->info.screen = NULL;
1864 if (output->info.name)
1866 free(output->info.name);
1867 output->info.name = NULL;
1869 EINA_LIST_FREE(output->info.modes, m) free(m);
1870 output->info.modes = NULL;
1872 output->info.size.w = 0;
1873 output->info.size.h = 0;
1875 /* reset output config */
1876 output->config.geom.x = 0;
1877 output->config.geom.y = 0;
1878 output->config.geom.w = 0;
1879 output->config.geom.h = 0;
1881 output->config.mode.w = 0;
1882 output->config.mode.h = 0;
1883 output->config.mode.refresh = 0;
1885 output->config.rotation = 0;
1886 output->config.priority = 0;
1887 output->config.enabled = 0;
1889 INF("E_OUTPUT: disconnected.. id: %s", output->id);
1892 /* the index of the tdm_output is higher, the tdm_output is important.
1893 the priority of the e_output is higher, the e_output is more important. */
1894 output->config.priority = 100 - output->index;
1900 e_output_mode_apply(E_Output *output, E_Output_Mode *mode)
1904 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1906 if (!output->info.connected)
1908 ERR("output is not connected.");
1912 error = tdm_output_set_mode(output->toutput, mode->tmode);
1913 if (error != TDM_ERROR_NONE)
1915 ERR("fail to set tmode.");
1919 output->config.geom.x = 0;
1920 output->config.geom.y = 0;
1921 output->config.geom.w = mode->w;
1922 output->config.geom.h = mode->h;
1924 output->config.mode.w = mode->w;
1925 output->config.mode.h = mode->h;
1926 output->config.mode.refresh = mode->refresh;
1928 output->config.enabled = 1;
1930 INF("E_OUTPUT: '%s' %i %i %ix%i %i %i", output->info.name,
1931 output->config.geom.x, output->config.geom.y,
1932 output->config.geom.w, output->config.geom.h,
1933 output->config.rotation, output->config.priority);
1935 INF("E_OUTPUT: rotation = %d", output->config.rotation);
1941 e_output_setup(E_Output *output)
1944 E_Plane *plane = NULL;
1946 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1948 EINA_LIST_FOREACH_SAFE(output->planes, l, ll, plane)
1952 if (!e_plane_setup(plane)) return EINA_FALSE;
1953 else return EINA_TRUE;
1961 EINTERN E_Output_Mode *
1962 e_output_best_mode_find(E_Output *output)
1964 Eina_List *l = NULL;
1965 E_Output_Mode *mode = NULL;
1966 E_Output_Mode *best_mode = NULL;
1969 double best_refresh = 0.0;
1971 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
1972 EINA_SAFETY_ON_NULL_RETURN_VAL(output->info.modes, NULL);
1974 if (!output->info.connected)
1976 ERR("output is not connected.");
1980 EINA_LIST_FOREACH(output->info.modes, l, mode)
1982 size = mode->w + mode->h;
1984 if (mode->preferred)
1988 best_refresh = mode->refresh;
1992 if (size > best_size)
1996 best_refresh = mode->refresh;
1999 if (size == best_size && mode->refresh > best_refresh)
2002 best_refresh = mode->refresh;
2010 e_output_connected(E_Output *output)
2012 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2014 return output->info.connected;
2018 e_output_dpms_set(E_Output *output, E_OUTPUT_DPMS val)
2020 tdm_output_dpms tval;
2021 Eina_Bool ret = EINA_TRUE;
2024 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2026 if (val == E_OUTPUT_DPMS_OFF) tval = TDM_OUTPUT_DPMS_OFF;
2027 else if (val == E_OUTPUT_DPMS_ON) tval = TDM_OUTPUT_DPMS_ON;
2028 else if (val == E_OUTPUT_DPMS_STANDBY) tval = TDM_OUTPUT_DPMS_STANDBY;
2029 else if (val == E_OUTPUT_DPMS_SUSPEND) tval = TDM_OUTPUT_DPMS_SUSPEND;
2030 else ret = EINA_FALSE;
2032 if (!ret) return EINA_FALSE;
2034 error = tdm_output_set_dpms(output->toutput, tval);
2035 if (error != TDM_ERROR_NONE)
2037 ERR("fail to set the dpms(value:%d).", tval);
2045 e_output_dpms_get(E_Output *output)
2047 EINA_SAFETY_ON_NULL_RETURN_VAL(output, E_OUTPUT_DPMS_OFF);
2049 return output->dpms;
2053 e_output_size_get(E_Output *output, int *w, int *h)
2055 EINA_SAFETY_ON_NULL_RETURN(output);
2057 *w = output->config.mode.w;
2058 *h = output->config.mode.h;
2062 e_output_fake_config_set(E_Output *output, int w, int h)
2064 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2066 output->config.geom.x = 0;
2067 output->config.geom.y = 0;
2068 output->config.geom.w = w;
2069 output->config.geom.h = h;
2071 output->config.mode.w = w;
2072 output->config.mode.h = h;
2073 output->config.mode.refresh = 60;
2074 output->config.enabled = 1;
2081 e_output_render(E_Output *output)
2083 E_Plane *plane = NULL;
2086 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2088 EINA_LIST_REVERSE_FOREACH(output->planes, l, plane)
2090 if (!e_plane_render(plane))
2092 ERR("fail to e_plane_render.");
2101 e_output_commit(E_Output *output)
2103 E_Plane *plane = NULL, *fb_target = NULL;
2105 Eina_Bool fb_commit = EINA_FALSE;
2107 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2109 if (!output->config.enabled)
2111 WRN("E_Output disconnected");
2115 fb_target = e_output_fb_target_get(output);
2117 /* fetch the fb_target at first */
2118 fb_commit = e_plane_fetch(fb_target);
2119 // TODO: to be fixed. check fps of fb_target currently.
2120 if (fb_commit) _e_output_update_fps();
2122 if (output->zoom_set)
2125 EINA_LIST_FOREACH(output->planes, l, plane)
2127 /* skip the fb_target fetch because we do this previously */
2128 if (e_plane_is_fb_target(plane)) continue;
2129 if (!e_plane_is_unset_candidate(plane)) continue;
2131 e_plane_unset_try_set(plane, EINA_TRUE);
2133 /* if the plane is trying to unset,
2134 * 1. if fetching the fb is not available, continue.
2135 * 2. if fetching the fb is available, verify the unset commit check. */
2136 if (e_plane_is_unset_try(plane))
2138 if (!e_plane_unset_commit_check(plane, fb_commit))
2142 /* fetch the surface to the plane */
2143 if (!e_plane_fetch(plane)) continue;
2145 if (output->dpms == E_OUTPUT_DPMS_OFF)
2146 e_plane_unfetch(plane);
2148 if (e_plane_is_unset_try(plane))
2149 e_plane_unset_try_set(plane, EINA_FALSE);
2151 if (output->dpms == E_OUTPUT_DPMS_OFF)
2153 if (!e_plane_offscreen_commit(plane))
2154 ERR("fail to e_plane_offscreen_commit");
2158 if (!e_plane_commit(plane))
2159 ERR("fail to e_plane_commit");
2163 EINA_LIST_FOREACH(output->planes, l, plane)
2165 if (e_plane_is_fetch_retry(plane))
2167 if (!e_plane_fetch(plane)) continue;
2168 if (e_plane_is_fb_target(plane))
2170 fb_commit = EINA_TRUE;
2171 _e_output_update_fps();
2176 /* zoom commit only primary */
2177 if (!fb_commit) return EINA_TRUE;
2179 _e_output_zoom_rotating_check(output);
2182 if (output->dpms == E_OUTPUT_DPMS_OFF)
2184 if (!e_plane_offscreen_commit(fb_target))
2185 ERR("fail to e_plane_offscreen_commit");
2189 if (!e_plane_pp_commit(fb_target))
2190 ERR("fail to e_plane_pp_commit");
2196 EINA_LIST_FOREACH(output->planes, l, plane)
2198 /* skip the fb_target fetch because we do this previously */
2199 if (e_plane_is_fb_target(plane)) continue;
2201 /* if the plane is the candidate to unset,
2202 set the plane to be unset_try */
2203 if (e_plane_is_unset_candidate(plane))
2204 e_plane_unset_try_set(plane, EINA_TRUE);
2206 /* if the plane is trying to unset,
2207 * 1. if fetching the fb is not available, continue.
2208 * 2. if fetching the fb is available, verify the unset commit check. */
2209 if (e_plane_is_unset_try(plane))
2211 if (!e_plane_unset_commit_check(plane, fb_commit))
2215 /* fetch the surface to the plane */
2216 if (!e_plane_fetch(plane)) continue;
2218 if (e_plane_is_unset_try(plane))
2219 e_plane_unset_try_set(plane, EINA_FALSE);
2222 EINA_LIST_FOREACH(output->planes, l, plane)
2224 if (e_plane_is_fetch_retry(plane))
2226 if (!e_plane_fetch(plane)) continue;
2227 if (e_plane_is_fb_target(plane))
2229 fb_commit = EINA_TRUE;
2230 _e_output_update_fps();
2235 EINA_LIST_FOREACH(output->planes, l, plane)
2237 if (e_plane_is_unset_try(plane)) continue;
2239 if (output->dpms == E_OUTPUT_DPMS_OFF)
2241 if (!e_plane_offscreen_commit(plane))
2242 ERR("fail to e_plane_offscreen_commit");
2246 if (!e_plane_commit(plane))
2247 ERR("fail to e_plane_commit");
2256 e_output_find(const char *id)
2259 E_Comp_Screen *e_comp_screen;
2262 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
2263 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
2264 EINA_SAFETY_ON_NULL_RETURN_VAL(id, NULL);
2266 e_comp_screen = e_comp->e_comp_screen;
2268 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
2270 if (!strcmp(output->id, id)) return output;
2275 E_API const Eina_List *
2276 e_output_planes_get(E_Output *output)
2278 EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
2279 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, NULL);
2281 return output->planes;
2285 e_output_util_planes_print(void)
2287 Eina_List *l, *ll, *p_l;
2288 E_Output * output = NULL;
2289 E_Comp_Screen *e_comp_screen = NULL;
2291 EINA_SAFETY_ON_NULL_RETURN(e_comp);
2292 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
2294 e_comp_screen = e_comp->e_comp_screen;
2296 EINA_LIST_FOREACH_SAFE(e_comp_screen->outputs, l, ll, output)
2301 if (!output || !output->planes) continue;
2303 fprintf(stderr, "HWC in %s .. \n", output->id);
2304 fprintf(stderr, "HWC \tzPos \t on_plane \t\t\t\t on_prepare \t \n");
2306 EINA_LIST_REVERSE_FOREACH(output->planes, p_l, plane)
2309 if (ec) fprintf(stderr, "HWC \t[%d]%s\t %s (0x%08x)",
2311 plane->is_primary ? "--" : " ",
2312 ec->icccm.title, (unsigned int)ec->frame);
2314 ec = plane->prepare_ec;
2315 if (ec) fprintf(stderr, "\t\t\t %s (0x%08x)",
2316 ec->icccm.title, (unsigned int)ec->frame);
2317 fputc('\n', stderr);
2319 fputc('\n', stderr);
2324 e_output_is_fb_composing(E_Output *output)
2329 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2330 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
2332 EINA_LIST_FOREACH(output->planes, p_l, ep)
2334 if (e_plane_is_fb_target(ep))
2336 if(ep->ec == NULL) return EINA_TRUE;
2344 e_output_is_fb_full_compositing(E_Output *output)
2349 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2350 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
2352 EINA_LIST_FOREACH(output->planes, p_l, ep)
2353 if(ep->ec) return EINA_FALSE;
2359 e_output_fb_target_get(E_Output *output)
2364 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2365 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
2367 EINA_LIST_FOREACH(output->planes, p_l, ep)
2369 if (e_plane_is_fb_target(ep))
2377 e_output_default_fb_target_get(E_Output *output)
2382 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2383 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
2385 if (e_comp->hwc_ignore_primary)
2387 /* find lowest zpos graphic type layer */
2388 EINA_LIST_FOREACH(output->planes, p_l, ep)
2390 Eina_List *formats = NULL;
2391 Eina_List *formats_l = NULL;
2392 Eina_Bool available_rgb = EINA_FALSE;
2395 if (e_plane_type_get(ep) != E_PLANE_TYPE_GRAPHIC) continue;
2397 formats = e_plane_available_formats_get(ep);
2398 if (!formats) continue;
2400 EINA_LIST_FOREACH(formats, formats_l, format)
2402 if (*format == TBM_FORMAT_ARGB8888 ||
2403 *format == TBM_FORMAT_XRGB8888)
2405 available_rgb = EINA_TRUE;
2410 if (!available_rgb) continue;
2417 /* find primary layer */
2418 EINA_LIST_FOREACH(output->planes, p_l, ep)
2429 e_output_find_by_index(int index)
2432 E_Comp_Screen *e_comp_screen;
2435 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
2436 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
2438 e_comp_screen = e_comp->e_comp_screen;
2440 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
2442 if (output->index == index)
2450 e_output_plane_get_by_zpos(E_Output *output, int zpos)
2455 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2456 EINA_SAFETY_ON_NULL_RETURN_VAL(output->planes, EINA_FALSE);
2458 EINA_LIST_FOREACH(output->planes, p_l, ep)
2460 if (ep->zpos == zpos)
2468 e_output_zoom_set(E_Output *output, double zoomx, double zoomy, int cx, int cy)
2474 if (!e_comp_screen_pp_support())
2476 WRN("Comp Screen does not support the Zoom.");
2480 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
2482 e_output_size_get(output, &w, &h);
2483 angle = _e_output_zoom_get_angle(output);
2485 if (cx < 0 || cy < 0) return EINA_FALSE;
2486 if (zoomx <= 0 || zoomy <= 0) return EINA_FALSE;
2487 if (angle % 180 == 0)
2489 if (cx >= w || cy >= h) return EINA_FALSE;
2493 if (cx >= h || cy >= w) return EINA_FALSE;
2496 ep = e_output_fb_target_get(output);
2497 EINA_SAFETY_ON_NULL_RETURN_VAL(ep, EINA_FALSE);
2499 #ifdef ENABLE_HWC_MULTI
2500 e_comp_hwc_multi_plane_set(EINA_FALSE);
2503 output->zoom_conf.zoomx = zoomx;
2504 output->zoom_conf.zoomy = zoomy;
2505 output->zoom_conf.init_cx = cx;
2506 output->zoom_conf.init_cy = cy;
2507 output->zoom_conf.init_angle = angle;
2508 output->zoom_conf.current_angle = angle;
2510 _e_output_zoom_coordinate_cal_with_angle(output, angle);
2512 /* get the scaled rect */
2513 _e_output_zoom_scaled_rect_get(w, h, output->zoom_conf.zoomx, output->zoom_conf.zoomy,
2514 output->zoom_conf.adjusted_cx, output->zoom_conf.adjusted_cy, &output->zoom_conf.rect);
2516 if (!e_plane_zoom_set(ep, &output->zoom_conf.rect))
2518 ERR("e_plane_zoom_set failed.");
2519 #ifdef ENABLE_HWC_MULTI
2520 e_comp_hwc_multi_plane_set(EINA_TRUE);
2525 if (!_e_output_zoom_touch_set(output))
2526 ERR("fail _e_output_zoom_touch_set");
2528 if (!output->zoom_set) output->zoom_set = EINA_TRUE;
2529 DBG("zoom set output:%s, zoom(x:%f, y:%f, cx:%d, cy:%d) rect(x:%d, y:%d, w:%d, h:%d)",
2530 output->id, zoomx, zoomy, cx, cy,
2531 output->zoom_conf.rect.x, output->zoom_conf.rect.y, output->zoom_conf.rect.w, output->zoom_conf.rect.h);
2533 /* update the ecore_evas */
2534 _e_output_render_update(output);
2540 e_output_zoom_unset(E_Output *output)
2544 EINA_SAFETY_ON_NULL_RETURN(output);
2546 if (!output->zoom_set) return;
2548 ep = e_output_fb_target_get(output);
2549 EINA_SAFETY_ON_NULL_RETURN(ep);
2551 if (!_e_output_zoom_touch_unset(output))
2552 ERR("fail _e_output_zoom_touch_unset");
2554 output->zoom_conf.zoomx = 0;
2555 output->zoom_conf.zoomy = 0;
2556 output->zoom_conf.init_cx = 0;
2557 output->zoom_conf.init_cy = 0;
2558 output->zoom_conf.init_angle = 0;
2559 output->zoom_conf.current_angle = 0;
2560 output->zoom_conf.adjusted_cx = 0;
2561 output->zoom_conf.adjusted_cy = 0;
2562 output->zoom_conf.rect.x = 0;
2563 output->zoom_conf.rect.y = 0;
2564 output->zoom_conf.rect.w = 0;
2565 output->zoom_conf.rect.h = 0;
2567 e_plane_zoom_unset(ep);
2569 output->zoom_set = EINA_FALSE;
2571 #ifdef ENABLE_HWC_MULTI
2572 e_comp_hwc_multi_plane_set(EINA_TRUE);
2575 /* update the ecore_evas */
2576 _e_output_render_update(output);
2578 DBG("e_output_zoom_unset: output:%s", output->id);
2581 E_API E_Output_Hook *
2582 e_output_hook_add(E_Output_Hook_Point hookpoint, E_Output_Hook_Cb func, const void *data)
2586 EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_OUTPUT_HOOK_LAST, NULL);
2587 ch = E_NEW(E_Output_Hook, 1);
2588 if (!ch) return NULL;
2589 ch->hookpoint = hookpoint;
2591 ch->data = (void*)data;
2592 _e_output_hooks[hookpoint] = eina_inlist_append(_e_output_hooks[hookpoint], EINA_INLIST_GET(ch));
2597 e_output_hook_del(E_Output_Hook *ch)
2600 if (_e_output_hooks_walking == 0)
2602 _e_output_hooks[ch->hookpoint] = eina_inlist_remove(_e_output_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
2606 _e_output_hooks_delete++;
2610 e_output_capture(E_Output *output, tbm_surface_h tsurface, Eina_Bool auto_rotate, E_Output_Capture_Cb func, void *data)
2612 Eina_Bool ret = EINA_FALSE;
2613 tdm_capture *tcapture = NULL;
2615 if (e_output_dpms_get(output))
2617 func(output, tsurface, data);
2621 tcapture = _e_output_tdm_capture_create(output, TDM_CAPTURE_CAPABILITY_ONESHOT);
2624 ret = _e_output_tdm_capture_info_set(output, tcapture, tsurface, TDM_CAPTURE_TYPE_ONESHOT, auto_rotate);
2625 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
2627 ret = _e_output_tdm_capture(output, tcapture, tsurface, func, data);
2628 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
2632 ret = _e_output_capture(output, tsurface, auto_rotate);
2633 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
2635 DBG("capture done(%p)", tsurface);
2637 func(output, tsurface, data);
2644 tdm_capture_destroy(tcapture);
2650 e_output_stream_capture_queue(E_Output *output, tbm_surface_h tsurface, E_Output_Capture_Cb func, void *data)
2652 Eina_Bool ret = EINA_FALSE;
2653 tdm_capture *tcapture = NULL;
2654 tdm_error error = TDM_ERROR_NONE;
2656 if (output->stream_capture.possible_tdm_capture)
2658 if (!output->stream_capture.tcapture)
2660 tcapture = _e_output_tdm_capture_create(output, TDM_CAPTURE_CAPABILITY_STREAM);
2661 EINA_SAFETY_ON_NULL_RETURN_VAL(tcapture, EINA_FALSE);
2663 ret = _e_output_tdm_capture_info_set(output, tcapture, tsurface, TDM_CAPTURE_TYPE_STREAM, EINA_FALSE);
2664 EINA_SAFETY_ON_FALSE_GOTO(ret == EINA_TRUE, fail);
2666 error = tdm_capture_set_done_handler(tcapture,
2667 _e_output_tdm_stream_capture_done_handler, output);
2668 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
2670 output->stream_capture.tcapture = tcapture;
2672 DBG("create tcapture(%p)", tcapture);
2676 tcapture = output->stream_capture.tcapture;
2679 ret = _e_output_tdm_stream_capture(output, tcapture, tsurface, func, data);
2680 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == EINA_TRUE, EINA_FALSE);
2684 ret = _e_output_vblank_stream_capture(output, tsurface, func, data);
2685 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == EINA_TRUE, EINA_FALSE);
2691 tdm_capture_destroy(tcapture);
2697 e_output_stream_capture_dequeue(E_Output *output, tbm_surface_h tsurface)
2699 E_Output_Capture *cdata = NULL;
2701 cdata = _e_output_tdm_stream_capture_find_data(output, tsurface);
2703 if (!cdata) return EINA_FALSE;
2705 if (!cdata->in_using)
2707 output->stream_capture.data = eina_list_remove(output->stream_capture.data, cdata);
2709 tbm_surface_internal_unref(tsurface);
2713 cdata->dequeued = EINA_TRUE;
2719 e_output_stream_capture_start(E_Output *output)
2721 tdm_error error = TDM_ERROR_NONE;
2724 if (output->stream_capture.start) return EINA_TRUE;
2726 count = eina_list_count(output->stream_capture.data);
2729 ERR("no queued buffer");
2733 DBG("e_output stream capture start.");
2735 output->stream_capture.start = EINA_TRUE;
2737 if (output->stream_capture.possible_tdm_capture)
2739 if (e_output_dpms_get(output))
2741 if (!output->stream_capture.timer)
2742 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
2743 _e_output_stream_capture_cb_timeout, output);
2744 EINA_SAFETY_ON_NULL_GOTO(output->stream_capture.timer, fail);
2749 error = tdm_capture_commit(output->stream_capture.tcapture);
2750 EINA_SAFETY_ON_FALSE_GOTO(error == TDM_ERROR_NONE, fail);
2753 _e_output_watch_vblank(output);
2758 output->stream_capture.start = EINA_FALSE;
2764 e_output_stream_capture_stop(E_Output *output)
2766 E_Output_Capture *cdata = NULL;
2767 Eina_Bool capturing = EINA_FALSE;
2770 if (!output->stream_capture.start) return;
2772 output->stream_capture.start = EINA_FALSE;
2774 if (eina_list_count(output->stream_capture.data) == 0)
2776 if (!output->stream_capture.timer)
2778 output->stream_capture.timer = ecore_timer_add((double)1 / DUMP_FPS,
2779 _e_output_tdm_stream_capture_stop, output);
2784 if (!output->stream_capture.timer && !output->stream_capture.wait_vblank)
2786 EINA_LIST_FOREACH(output->stream_capture.data, l, cdata)
2788 if (cdata->in_using)
2789 capturing = EINA_TRUE;
2792 if (capturing == EINA_FALSE)
2794 EINA_LIST_FREE(output->stream_capture.data, cdata)
2796 tbm_surface_internal_unref(cdata->surface);
2801 if (output->stream_capture.tcapture)
2803 tdm_capture_destroy(output->stream_capture.tcapture);
2804 output->stream_capture.tcapture = NULL;
2808 DBG("e_output stream capture stop.");