2 #include "e_comp_screen_intern.h"
3 #include "services/e_service_quickpanel.h"
5 # include <Evas_Engine_GL_Tbm.h>
6 # include <Evas_Engine_Software_Tbm.h>
7 # include <wayland-tbm-server.h>
8 # include <sys/eventfd.h>
12 #define E_HWC_WINDOW_COMMIT_HANDLER_LOG_TIMEOUT 5.0
14 #define DBG_EVALUATE 1
15 #define DEFAULT_MAX_TRANSITION_FAILURES 3;
18 #define CLEAR(x) memset(&(x), 0, sizeof (x))
21 #define EHWSERR(f, hwc, x...) \
24 ELOGFE("HWC-WINS", "%2d|"f, \
25 NULL, (e_hwc_output_index_get(hwc)), ##x); \
29 #define EHWSINF(f, ec, hwc, x...) \
32 ELOGF("HWC-WINS", "%2d|"f, \
33 (ec), (e_hwc_output_index_get(hwc)), ##x); \
37 #define EHWSTRACE(f, ec, hwc, x...) \
42 ELOGF("HWC-WINS", "%2d|"f, \
43 (ec), (e_hwc_output_index_get(hwc)), ##x); \
48 #define ROUNDUP(s,c) (((s) + (c-1)) & ~(c-1))
50 typedef struct _E_Hwc_Windows_Comp_Info E_Hwc_Windows_Comp_Info;
52 struct _E_Hwc_Windows_Comp_Info
54 E_Presentation_Time_Container presentation_container;
55 E_Hwc_Presentation_Callback_List presentation_callbacks;
57 E_Egl_Sync *release_fence;
58 Eina_List *pending_update_list;
60 E_Comp_Wl_Tizen_Hwc_Feedback_List feedback_list;
62 Eina_List *rendered_windows;
63 Eina_List *rendered_buffers;
66 static Eina_Bool ehws_trace = EINA_FALSE;
67 static Eina_Bool ehws_dump_enable = EINA_FALSE;
69 static int E_EVENT_HWC_WINDOWS_COMP_INFO_FREE = -1;
71 static uint64_t ehws_comp_buffer_info_key;
72 #define EHWS_BUFFER_COMP_INFO_KEY (unsigned long)(&ehws_comp_buffer_info_key)
74 static Eina_Bool _e_hwc_windows_target_window_queue_set(E_Hwc_Window_Target *target_hwc_window);
75 static void _e_hwc_windows_wait_commit_set(E_Hwc *hwc, Eina_Bool set);
76 static void _e_hwc_windows_commit_handler_timer_set(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data, Eina_Bool set);
77 static Eina_Bool _e_hwc_windows_pp_commit(E_Hwc *hwc);
79 static E_Comp_Wl_Buffer *
80 _e_hwc_windows_comp_wl_buffer_get(E_Hwc_Window *hwc_window)
82 E_Client *ec = hwc_window->ec;
83 E_Comp_Wl_Client_Data *cdata;
87 cdata = e_client_cdata_get(ec);
88 if (!cdata) return NULL;
90 return cdata->buffer_ref.buffer;
94 _e_hwc_windows_update_fps(E_Hwc *hwc)
99 double tim = ecore_time_get();
101 dt = tim - hwc->frametimes[0];
102 hwc->frametimes[0] = tim;
107 if (hwc->lapse == 0.0)
110 hwc->flapse = hwc->cframes;
112 else if ((tim - hwc->lapse) >= 0.5)
114 hwc->fps = (hwc->cframes - hwc->flapse) / (tim - hwc->lapse);
116 hwc->flapse = hwc->cframes;
122 static E_Hwc_Window_Target *
123 _e_hwc_windows_root_target_hwc_window_get(E_Hwc *hwc)
125 E_Output *primary_output;
127 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
129 if (hwc->root_target_hwc_window)
131 return hwc->root_target_hwc_window;
135 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
136 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
138 primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
139 EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, NULL);
140 EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output->hwc, NULL);
142 return primary_output->hwc->root_target_hwc_window;
147 _e_hwc_windows_hwc_mode_update(E_Hwc *hwc, int num_client, int num_device, int num_cursor, int num_video)
149 E_Hwc_Mode hwc_mode = E_HWC_MODE_NONE;
150 int num_visible = hwc->num_visible_windows;
152 /* check ui windows */
154 hwc_mode = E_HWC_MODE_NONE;
155 else if (!num_device)
156 hwc_mode = E_HWC_MODE_NONE;
157 else if ((!num_client) && (num_device))
158 hwc_mode = E_HWC_MODE_FULL;
160 hwc_mode = E_HWC_MODE_HYBRID;
162 /* check video and cursor windows */
163 if ((num_video) || (num_cursor))
165 if (hwc_mode == E_HWC_MODE_NONE)
166 hwc_mode = E_HWC_MODE_HYBRID;
169 if (hwc->hwc_mode != hwc_mode)
171 if (hwc_mode == E_HWC_MODE_HYBRID || hwc_mode == E_HWC_MODE_NONE)
172 ecore_event_add(E_EVENT_COMPOSITOR_ENABLE, NULL, NULL, NULL);
174 ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
176 hwc->hwc_mode = hwc_mode;
183 _e_hwc_windows_comp_info_rendered_buffers_set(E_Hwc_Windows_Comp_Info *comp_info,
184 Eina_List *rendered_buffers)
186 E_Comp_Wl_Buffer_Ref *buffer_ref;
188 EINA_SAFETY_ON_NULL_RETURN(comp_info);
190 if (comp_info->rendered_buffers == rendered_buffers)
193 if (comp_info->rendered_buffers)
195 if (eina_list_count(comp_info->rendered_buffers))
197 EINA_LIST_FREE(comp_info->rendered_buffers, buffer_ref)
199 e_comp_wl_buffer_reference(buffer_ref, NULL);
205 comp_info->rendered_buffers = rendered_buffers;
209 _e_hwc_windows_comp_info_rendered_windows_set(E_Hwc_Windows_Comp_Info *comp_info,
210 Eina_List *rendered_windows)
212 E_Hwc_Window *hwc_window;
214 EINA_SAFETY_ON_NULL_RETURN(comp_info);
216 if (comp_info->rendered_windows == rendered_windows)
219 if (comp_info->rendered_windows)
221 if (eina_list_count(comp_info->rendered_windows))
223 EINA_LIST_FREE(comp_info->rendered_windows, hwc_window)
224 e_hwc_window_unref(hwc_window);
228 comp_info->rendered_windows = rendered_windows;
232 _e_hwc_windows_comp_info_free(void *data EINA_UNUSED, void *event)
234 E_Hwc_Windows_Comp_Info *comp_info;
235 E_Hwc_Window_Update_Data *update;
237 comp_info = (E_Hwc_Windows_Comp_Info *)event;
238 if (!comp_info) return;
240 EINA_LIST_FREE(comp_info->pending_update_list, update)
241 e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update);
243 _e_hwc_windows_comp_info_rendered_windows_set(comp_info, NULL);
244 _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
246 e_presentation_time_container_finish(&comp_info->presentation_container);
247 e_hwc_presentation_callback_list_finish(&comp_info->presentation_callbacks);
248 e_comp_wl_tizen_hwc_feedback_list_finish(&comp_info->feedback_list);
254 _e_hwc_windows_comp_info_cb_tbm_surface_destroy(void *data)
256 E_Hwc_Windows_Comp_Info *comp_info;
258 comp_info = (E_Hwc_Windows_Comp_Info *)data;
259 if (!comp_info) return;
261 ecore_event_add(E_EVENT_HWC_WINDOWS_COMP_INFO_FREE, comp_info,
262 _e_hwc_windows_comp_info_free, NULL);
265 static E_Hwc_Windows_Comp_Info *
266 _e_hwc_windows_comp_info_get(tbm_surface_h tbm_surface)
268 E_Hwc_Windows_Comp_Info *comp_info = NULL;
270 if (!tbm_surface) return NULL;
272 tbm_surface_internal_get_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
275 if (comp_info) return comp_info;
277 comp_info = E_NEW(E_Hwc_Windows_Comp_Info, 1);
278 EINA_SAFETY_ON_FALSE_RETURN_VAL(comp_info, NULL);
280 e_presentation_time_container_init(&comp_info->presentation_container);
281 e_hwc_presentation_callback_list_init(&comp_info->presentation_callbacks);
282 e_comp_wl_tizen_hwc_feedback_list_init(&comp_info->feedback_list);
284 if (!tbm_surface_internal_add_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
285 _e_hwc_windows_comp_info_cb_tbm_surface_destroy))
288 if (!tbm_surface_internal_set_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
302 _e_hwc_windows_presentation_feedback_take(E_Hwc_Window *hwc_window)
304 E_Presentation_Time_Container *container;
306 if (hwc_window->is_target)
308 E_Hwc_Windows_Comp_Info *comp_info;
310 if (!hwc_window->current.buffer.tsurface) return;
312 comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
313 if (!comp_info) return;
315 container = &comp_info->presentation_container;
320 E_Comp_Wl_Client_Data *cdata;
324 cdata = e_client_cdata_get(ec);
327 container = &cdata->presentation_container;
330 if (!container) return;
332 e_hwc_window_presentation_time_feedback_take(hwc_window, container);
336 _e_hwc_windows_presentation_callback_take(E_Hwc_Window *hwc_window)
338 E_Hwc_Presentation_Callback_List *list;
340 if (hwc_window->is_target)
342 E_Hwc_Windows_Comp_Info *comp_info;
344 if (!hwc_window->current.buffer.tsurface) return;
346 comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
347 if (!comp_info) return;
349 list = &comp_info->presentation_callbacks;
353 list = &hwc_window->pending_presentation_callbacks;
358 e_hwc_window_presentation_callback_take(hwc_window, list);
362 _e_hwc_windows_commit_data_release(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data,
363 int sequence, unsigned int tv_sec, unsigned int tv_usec)
365 const Eina_List *l, *ll;
366 E_Hwc_Window *hwc_window;
367 E_Hwc_Window_Commit_Data *commit_data;
369 if (!eina_list_data_find(hwc->wins_commit_data_list, wins_commit_data))
371 EHWSERR("failed to find wins_commit_data:%p in wins_commit_data_list",
372 hwc, wins_commit_data);
376 if (wins_commit_data->target_commit_data)
378 hwc_window = wins_commit_data->target_commit_data->hwc_window;
379 e_hwc_window_presentation_time_feedback_present(hwc_window,
383 e_hwc_window_presentation_callback_call(hwc_window);
385 /* it is possible that other hwc_window is freed in
386 * _e_hwc_windows_rendered_windows_free.
387 * we must don't call commit_data_release of target_window in list.
389 e_hwc_window_commit_data_release(hwc_window, wins_commit_data->target_commit_data);
392 /* window_commit_data is freed in e_hwc_window_commit_data_release */
393 EINA_LIST_FOREACH_SAFE(wins_commit_data->commit_data_list, l, ll, commit_data)
395 hwc_window = commit_data->hwc_window;
396 if (hwc_window->is_target) continue;
398 e_hwc_window_presentation_time_feedback_present(hwc_window, sequence, tv_sec, tv_usec);
399 e_hwc_window_presentation_callback_call(hwc_window);
401 if (e_hwc_window_is_video(hwc_window) && hwc_window->ec)
403 if ((!wins_commit_data->use_vblank_handler) ||
404 (wins_commit_data->use_vblank_handler && !wins_commit_data->vblank_done))
405 e_client_video_commit_data_release(hwc_window->ec, sequence, tv_sec, tv_usec);
408 if (!e_hwc_window_commit_data_release(hwc_window, commit_data)) continue;
411 wins_commit_data->commit_data_list = eina_list_free(wins_commit_data->commit_data_list);
413 hwc->wins_commit_data_list = eina_list_remove(hwc->wins_commit_data_list, wins_commit_data);
415 _e_hwc_windows_commit_handler_timer_set(hwc, wins_commit_data, EINA_FALSE);
416 free(wins_commit_data);
420 _e_hwc_windows_commit_handler(tdm_hwc *thwc, unsigned int sequence,
421 unsigned int tv_sec, unsigned int tv_usec,
424 E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)user_data;
427 EINA_SAFETY_ON_NULL_RETURN(wins_commit_data);
429 hwc = wins_commit_data->hwc;
430 EINA_SAFETY_ON_NULL_RETURN(hwc);
432 if (wins_commit_data->commit_handler_log_timeout_set)
434 EHWSERR("Timeout commit handler is called wins_commit_data:%p",
435 hwc, wins_commit_data);
438 EHWSTRACE("!!!!!!!! HWC Commit Handler !!!!!!!!", NULL, hwc);
439 TRACE_DS_MARK(_e_hwc_windows_commit_handler);
441 /* 'wait_commit' is mechanism to make 'fetch and commit' no more than one time per a frame;
442 * a 'page flip' happened so it's time to allow to make 'fetch and commit' for the e_output */
443 if (!wins_commit_data->use_vblank_handler)
444 _e_hwc_windows_wait_commit_set(hwc, EINA_FALSE);
446 _e_hwc_windows_commit_data_release(hwc, wins_commit_data, sequence, tv_sec, tv_usec);
450 _e_hwc_windows_commit_handler_timeout(void *data)
452 E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)data;
454 if (!wins_commit_data) return ECORE_CALLBACK_CANCEL;
456 EHWSERR("Timeout wait commit wins_commit_data:%p",
457 wins_commit_data->hwc, wins_commit_data);
459 wins_commit_data->commit_handler_timer = NULL;
461 _e_hwc_windows_commit_handler(wins_commit_data->hwc->thwc, 0, 0, 0, wins_commit_data);
463 return ECORE_CALLBACK_CANCEL;
467 _e_hwc_windows_commit_handler_log_timeout(void *data)
469 E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)data;
471 if (!wins_commit_data) return ECORE_CALLBACK_CANCEL;
473 EHWSERR("Timeout wait commit wins_commit_data:%p",
474 wins_commit_data->hwc, wins_commit_data);
476 wins_commit_data->commit_handler_timer = NULL;
477 wins_commit_data->commit_handler_log_timeout_set = EINA_TRUE;
479 return ECORE_CALLBACK_CANCEL;
483 _e_hwc_windows_commit_handler_timer_set(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data, Eina_Bool set)
485 if (wins_commit_data->commit_handler_timer)
487 ecore_timer_del(wins_commit_data->commit_handler_timer);
488 wins_commit_data->commit_handler_timer = NULL;
493 if (e_comp->commit_handler_timer.use)
495 wins_commit_data->commit_handler_timer = ecore_timer_add(e_comp->commit_handler_timer.interval,
496 _e_hwc_windows_commit_handler_timeout,
501 wins_commit_data->commit_handler_timer = ecore_timer_add(E_HWC_WINDOW_COMMIT_HANDLER_LOG_TIMEOUT,
502 _e_hwc_windows_commit_handler_log_timeout,
504 wins_commit_data->commit_handler_log_timeout_set = EINA_FALSE;
509 static E_Hwc_Windows_Commit_Data *
510 _e_hwc_windows_commit_data_acquire(E_Hwc *hwc)
513 E_Hwc_Window *hwc_window;
514 E_Hwc_Window_Commit_Data *commit_data;
515 E_Hwc_Windows_Commit_Data *wins_commit_data;
517 wins_commit_data = E_NEW(E_Hwc_Windows_Commit_Data, 1);
518 EINA_SAFETY_ON_NULL_RETURN_VAL(wins_commit_data, NULL);
520 wins_commit_data->hwc = hwc;
522 /* return TRUE when the number of the commit data is more than one */
523 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
525 if (hwc_window->is_root_target) continue;
527 commit_data = e_hwc_window_commit_data_acquire(hwc_window);
530 if ((hwc->hwc_mode == E_HWC_MODE_FULL) &&
531 (!e_hwc_window_is_on_hw_overlay(hwc_window)))
533 _e_hwc_windows_presentation_callback_take(hwc_window);
534 e_hwc_window_presentation_callback_call(hwc_window);
540 _e_hwc_windows_presentation_feedback_take(hwc_window);
541 _e_hwc_windows_presentation_callback_take(hwc_window);
543 if (ehws_dump_enable)
544 e_hwc_window_commit_data_buffer_dump(hwc_window, commit_data);
546 /* send frame event enlightenment doesn't send frame event in nocomp */
548 e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
550 if (hwc_window->is_target)
551 wins_commit_data->target_commit_data = commit_data;
553 wins_commit_data->commit_data_list = eina_list_append(wins_commit_data->commit_data_list,
557 if ((!wins_commit_data->commit_data_list) && (!wins_commit_data->target_commit_data))
559 free(wins_commit_data);
563 return wins_commit_data;
567 _e_hwc_windows_offscreen_commit(E_Hwc *hwc)
569 E_Hwc_Window *hwc_window;
570 E_Hwc_Window *hwc_window_target;
572 E_Hwc_Window_Commit_Data *commit_data;
574 hwc_window_target = (E_Hwc_Window *)hwc->target_hwc_window;
575 if (hwc_window_target)
577 commit_data = e_hwc_window_commit_data_acquire(hwc_window_target);
580 _e_hwc_windows_presentation_feedback_take(hwc_window_target);
581 _e_hwc_windows_presentation_callback_take(hwc_window_target);
582 e_hwc_window_presentation_time_feedback_discard(hwc_window_target);
583 e_hwc_window_presentation_callback_call(hwc_window_target);
585 /* it is possible that other hwc_window is freed in
586 * _e_hwc_windows_rendered_windows_free.
587 * we must don't call commit_data_release of target_window in list.
589 EHWSTRACE("!!!!!!!! HWC OffScreen Commit !!!!!!!!", NULL, hwc);
590 e_hwc_window_commit_data_release(hwc_window_target, commit_data);
594 EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
598 if (hwc_window->is_target) continue;
600 commit_data = e_hwc_window_commit_data_acquire(hwc_window);
603 if ((hwc->hwc_mode == E_HWC_MODE_FULL) &&
604 (!e_hwc_window_is_on_hw_overlay(hwc_window)))
606 _e_hwc_windows_presentation_callback_take(hwc_window);
607 e_hwc_window_presentation_callback_call(hwc_window);
613 EHWSTRACE("!!!!!!!! HWC OffScreen Commit !!!!!!!!", NULL, hwc);
615 /* send frame event enlightenment doesn't send frame event in nocomp */
617 e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
619 _e_hwc_windows_presentation_feedback_take(hwc_window);
620 _e_hwc_windows_presentation_callback_take(hwc_window);
621 e_hwc_window_presentation_time_feedback_discard(hwc_window);
622 e_hwc_window_presentation_callback_call(hwc_window);
624 e_hwc_window_commit_data_release(hwc_window, commit_data);
629 _e_hwc_windows_target_window_rendered_windows_get(tbm_surface_h target_tsurface)
631 E_Hwc_Windows_Comp_Info *comp_info;
633 if (!target_tsurface) return NULL;
635 comp_info = _e_hwc_windows_comp_info_get(target_tsurface);
636 if (!comp_info) return NULL;
638 return comp_info->rendered_windows;
642 e_hwc_windows_target_window_force_render(E_Hwc_Window_Target *target_hwc_window)
644 E_Hwc_Window_Target *root_target_hwc_window;
648 hwc = target_hwc_window->hwc;
649 EINA_SAFETY_ON_NULL_RETURN(hwc);
651 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
652 EINA_SAFETY_ON_NULL_RETURN(root_target_hwc_window);
654 if (!root_target_hwc_window->ee) return;
655 if (!root_target_hwc_window->evas) return;
657 ecore_evas_geometry_get(root_target_hwc_window->ee, 0, 0, &w, &h);
658 evas_damage_rectangle_add(root_target_hwc_window->evas, 0, 0, w, h);
662 _e_hwc_windows_target_window_buffer_skip(E_Hwc *hwc)
664 E_Hwc_Window_Target *target_hwc_window;
665 E_Hwc_Window *hwc_window;
667 tdm_region fb_damage;
669 target_hwc_window = hwc->target_hwc_window;
670 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
672 hwc_window = (E_Hwc_Window *)target_hwc_window;
675 EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
679 if ((hwc_window->current.buffer.tsurface) &&
680 (hwc_window->current.buffer.tsurface != hwc_window->display.buffer.tsurface))
682 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, hwc_window->display.queue_buffer_ref.buffer);
683 e_hwc_window_buffer_set(&hwc_window->current.buffer, hwc_window->display.buffer.tsurface,
684 hwc_window->display.buffer.queue, hwc_window->display.buffer.transform);
685 tdm_hwc_set_client_target_buffer(thwc, hwc_window->display.buffer.tsurface, fb_damage);
687 e_hwc_windows_target_window_force_render(target_hwc_window);
690 if (hwc->root_target_hwc_window)
692 hwc_window = (E_Hwc_Window *)hwc->root_target_hwc_window;
694 if (hwc_window->current.buffer.tsurface)
695 e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, hwc_window->current.buffer.tsurface);
697 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, hwc_window->display.queue_buffer_ref.buffer);
698 e_hwc_window_buffer_set(&hwc_window->current.buffer, hwc_window->display.buffer.tsurface,
699 hwc_window->display.buffer.queue, hwc_window->display.buffer.transform);
706 _e_hwc_windows_target_window_queue_clear(E_Hwc_Window_Target *target_hwc_window)
708 E_Hwc_Window *hwc_window;
709 E_Hwc_Window_Queue_Buffer *queue_buffer;
711 hwc_window = (E_Hwc_Window *)target_hwc_window;
713 while ((queue_buffer = e_hwc_window_queue_buffer_acquire(hwc_window->queue)))
715 e_hwc_windows_presentation_time_feedback_and_callback_take(target_hwc_window->hwc, queue_buffer->tsurface);
716 e_hwc_window_queue_buffer_release(hwc_window->queue, queue_buffer);
721 _e_hwc_windows_root_target_buffer_fetch(E_Hwc *hwc)
723 E_Hwc_Window_Target *target_hwc_window;
724 E_Hwc_Window *hwc_window, *hw;
725 tbm_surface_h tsurface;
726 Eina_List *rendered_windows;
727 E_Hwc_Window_Queue_Buffer *queue_buffer;
728 E_Hwc_Windows_Comp_Info *comp_info;
729 E_Hwc_Window_Queue *queue;
734 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
736 target_hwc_window = hwc->root_target_hwc_window;
737 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
739 hwc_window = (E_Hwc_Window *)target_hwc_window;
741 if (!hwc_window->queue)
743 if (!_e_hwc_windows_target_window_queue_set(target_hwc_window))
745 EHWSERR("fail to _e_hwc_windows_target_window_queue_set", NULL);
750 queue = hwc_window->queue;
751 EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
753 if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
755 /* acquire the surface */
756 queue_buffer = e_hwc_window_queue_buffer_acquire(queue);
757 if (!queue_buffer) return EINA_FALSE;
759 tsurface = queue_buffer->tsurface;
760 EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
762 comp_info = _e_hwc_windows_comp_info_get(tsurface);
763 if ((comp_info) && (comp_info->skip))
765 e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, tsurface);
766 e_hwc_window_queue_buffer_release(queue, queue_buffer);
770 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, queue_buffer);
771 e_hwc_window_buffer_set(&hwc_window->current.buffer, tsurface, queue, 0);
772 e_hwc_window_info_update(hwc_window);
776 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(hwc_window->current.buffer.tsurface);
777 n_thw = eina_list_count(rendered_windows);
780 EHWSTRACE("FET {%s} ts:%p state:%s has hwc_windows to render below",
781 NULL, hwc, e_hwc_window_name_get(hwc_window), hwc_window->current.buffer.tsurface,
782 e_hwc_window_state_string_get(hwc_window->state));
785 EINA_LIST_FOREACH(rendered_windows, l, hw)
787 EHWSTRACE(" (%d) ehw:%p ts:%p - {%s} state:%s zpos:%d deleted:%s",
788 hwc_window->ec, hwc, i++, hw, hw->current.buffer.tsurface, e_hwc_window_name_get(hw),
789 e_hwc_window_state_string_get(hw->state), hwc_window->zpos,
790 (hwc_window->is_deleted ? "yes" : "no"));
794 EHWSTRACE("FET {%s} ts:%p state:%s has no hwc_windows to render",
795 NULL, hwc, e_hwc_window_name_get(hwc_window), hwc_window->current.buffer.tsurface,
796 e_hwc_window_state_string_get(hwc_window->state));
801 _e_hwc_windows_target_window_queue_clear(target_hwc_window);
803 if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
805 if (!e_hwc_window_display_or_commit_buffer_check(hwc_window, hwc_window->current.buffer.tsurface))
807 queue_buffer = e_hwc_window_queue_buffer_find(hwc_window->current.buffer.queue, hwc_window->current.buffer.tsurface);
809 e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, hwc_window->current.buffer.tsurface);
812 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, NULL);
813 e_hwc_window_buffer_set(&hwc_window->current.buffer, NULL, NULL, 0);
814 e_hwc_window_info_update(hwc_window);
816 EHWSTRACE("FET {%s} ts:%p state:%s",
817 NULL, hwc, e_hwc_window_name_get(hwc_window), hwc_window->current.buffer.tsurface,
818 e_hwc_window_state_string_get(hwc_window->state));
825 _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc)
827 E_Hwc_Window_Target *target_hwc_window, *root_target_hwc_window;
828 E_Hwc_Window *hwc_window, *root_hwc_window;
829 E_Hwc_Window_Queue_Buffer *queue_buffer;
830 tdm_region fb_damage;
831 tbm_surface_h tsurface;
835 EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
837 target_hwc_window = hwc->target_hwc_window;
838 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
839 hwc_window = (E_Hwc_Window *)target_hwc_window;
841 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
842 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
843 root_hwc_window = (E_Hwc_Window *)root_target_hwc_window;
845 if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
847 if (target_hwc_window->pp_queue)
848 queue_buffer = e_hwc_window_queue_buffer_acquire(target_hwc_window->pp_queue);
850 queue_buffer = root_hwc_window->current.queue_buffer_ref.buffer;
852 if (!queue_buffer) return EINA_FALSE;
854 tsurface = queue_buffer->tsurface;
855 EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
857 if (tsurface == hwc_window->current.buffer.tsurface) return EINA_FALSE;
859 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, queue_buffer);
860 e_hwc_window_buffer_set(&hwc_window->current.buffer, tsurface, queue_buffer->queue, 0);
861 e_hwc_window_info_update(hwc_window);
863 /* the damage isn't supported by hwc extension yet */
866 tdm_hwc_set_client_target_buffer(thwc, hwc_window->current.buffer.tsurface, fb_damage);
867 if ((root_target_hwc_window->end_render_sync) && (e_hwc_windows_fence_enabled_get(hwc)))
869 int fence = e_egl_sync_fence_fd_dup(root_target_hwc_window->end_render_sync);
872 tdm_hwc_set_client_target_acquire_fence(thwc, fence);
877 EHWSTRACE("FET {%s} ts:%p state:%s",
878 NULL, hwc, e_hwc_window_name_get(hwc_window),
879 hwc_window->current.buffer.tsurface, e_hwc_window_state_string_get(hwc_window->state));
883 if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
885 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, NULL);
886 e_hwc_window_buffer_set(&hwc_window->current.buffer, NULL, NULL, 0);
887 e_hwc_window_info_update(hwc_window);
891 tdm_hwc_set_client_target_buffer(thwc, NULL, fb_damage);
893 if (e_hwc_windows_fence_enabled_get(hwc))
894 tdm_hwc_set_client_target_acquire_fence(thwc, -1);
896 EHWSTRACE("FET {%s} ts:%p state:%s",
897 NULL, hwc, e_hwc_window_name_get(hwc_window),
898 hwc_window->current.buffer.tsurface, e_hwc_window_state_string_get(hwc_window->state));
905 _e_hwc_windows_target_window_rendered_windows_find(Eina_List *rendered_windows, E_Hwc_Window *hwc_window)
911 if (!rendered_windows) return EINA_FALSE;
912 if (!hwc_window) return EINA_FALSE;
914 n_thw = eina_list_count(rendered_windows);
915 if (!n_thw) return EINA_FALSE;
917 EINA_LIST_FOREACH(rendered_windows, l, hw)
919 if (hw == hwc_window)
927 _e_hwc_windows_target_window_rendered_window_has_no(E_Hwc *hwc, E_Hwc_Window *hwc_window, Eina_Bool all_target)
929 Eina_List *rendered_windows;
930 E_Hwc_Window_Target *target_hwc_window, *root_target_hwc_window;
931 E_Hwc_Window *target_window;
932 tbm_surface_h target_tsurface;
935 target_hwc_window = hwc->target_hwc_window;
936 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
938 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
939 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
941 target_window = (E_Hwc_Window *)target_hwc_window;
942 if (e_hwc_window_state_get(target_window) != E_HWC_WINDOW_STATE_DEVICE) return EINA_FALSE;
944 target_tsurface = target_hwc_window->hwc_window.current.buffer.tsurface;
945 if (!target_tsurface) return EINA_FALSE;
949 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
950 if (!_e_hwc_windows_target_window_rendered_windows_find(rendered_windows, hwc_window))
953 EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, target_tsurface)
955 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
956 if (!_e_hwc_windows_target_window_rendered_windows_find(rendered_windows, hwc_window))
962 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
963 if (!_e_hwc_windows_target_window_rendered_windows_find(rendered_windows, hwc_window))
971 _e_hwc_windows_target_window_rendered_window_has(E_Hwc *hwc, E_Hwc_Window *hwc_window, Eina_Bool all_target)
973 Eina_List *rendered_windows, *new_list;
974 E_Hwc_Window_Target *target_hwc_window, *root_target_hwc_window;;
975 E_Hwc_Window *target_window;
977 tbm_surface_h target_tsurface;
978 const Eina_List *l, *ll;
981 target_hwc_window = hwc->target_hwc_window;
982 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
984 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
985 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
987 target_window = (E_Hwc_Window *)target_hwc_window;
988 if (e_hwc_window_state_get(target_window) != E_HWC_WINDOW_STATE_DEVICE) return EINA_FALSE;
990 target_tsurface = target_hwc_window->hwc_window.current.buffer.tsurface;
991 if (!target_tsurface) return EINA_FALSE;
995 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
997 new_list = eina_list_clone(rendered_windows);
999 EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, target_tsurface)
1001 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
1003 EINA_LIST_FOREACH(rendered_windows, ll, hw)
1005 if (!eina_list_data_find(new_list, hw))
1006 new_list = eina_list_append(new_list, hw);
1010 n_thw = eina_list_count(new_list);
1013 EINA_LIST_FOREACH(new_list, l, hw)
1015 if (hw == hwc_window)
1017 eina_list_free(new_list);
1023 eina_list_free(new_list);
1027 rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
1029 n_thw = eina_list_count(rendered_windows);
1032 EINA_LIST_FOREACH(rendered_windows, l, hw)
1033 if (hw == hwc_window) return EINA_TRUE;
1041 _e_hwc_windows_client_get_from_object(Evas_Object *o, Eina_Bool *effect_client)
1043 E_Client *ec = NULL;
1044 Evas_Object *ob, *cob;
1047 Eina_List *stack = NULL;
1049 if (!o) return NULL;
1052 *effect_client = EINA_FALSE;
1054 stack = eina_list_append(stack, o);
1058 ob = eina_list_last_data_get(stack);
1061 ec = evas_object_data_get(ob, "E_Client");
1064 if (evas_object_smart_smart_get(ob))
1066 if (evas_object_smart_data_get(ob))
1068 members = evas_object_smart_members_get(ob);
1070 EINA_LIST_FOREACH(members, l, cob)
1071 stack = eina_list_append(stack, cob);
1074 eina_list_free(members);
1078 stack = eina_list_remove(stack, ob);
1081 eina_list_free(stack);
1083 if (!(ec) && (evas_object_visible_get(o)))
1085 ec = evas_object_data_get(o, "effect_client");
1087 *effect_client = EINA_TRUE;
1094 _e_hwc_windows_client_fully_mask_get(E_Client *ec, int x, int y, int w, int h,
1097 if (ec->argb) return EINA_FALSE;
1098 if (!E_CONTAINS(x, y, w, h, 0, 0, ee_w, ee_h)) return EINA_FALSE;
1099 if (e_comp_object_is_animating(ec->frame)) return EINA_FALSE;
1100 if (evas_object_data_get(ec->frame, "effect_running")) return EINA_FALSE;
1106 _e_hwc_windows_visible_windows_list_get(E_Hwc *hwc)
1108 Eina_List *windows_list = NULL;
1109 E_Hwc_Window *hwc_window;
1110 E_Client *ec, *topmost_ec, *bottom = NULL;
1114 int x, y, w, h, x1, x2, y1, y2;
1116 int ui_skip = EINA_FALSE;
1117 int obscured_by_target = EINA_FALSE;
1119 Eina_Bool effect_client;
1120 Evas_Render_Op render_op;
1123 ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &ee_w, &ee_h);
1125 for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
1127 ec = _e_hwc_windows_client_get_from_object(o, &effect_client);
1130 if (obscured_by_target) continue;
1131 if (!evas_object_visible_get(o)) continue;
1133 type = evas_object_type_get(o);
1134 if (!e_util_strcmp(type, "image"))
1136 evas_object_color_get(o, &r, &g, &b, &a);
1137 evas_object_geometry_get(o, &x, &y, &w, &h);
1139 if ((a > 0) && ((r > 0) || (g > 0) || (b > 0)) &&
1140 (E_INTERSECTS(0, 0, ee_w, ee_h, x, y, w, h)))
1141 obscured_by_target = EINA_TRUE;
1147 hwc_window = ec->hwc_window;
1148 if (!hwc_window) continue;
1150 e_hwc_window_name_set(hwc_window);
1151 hwc_window->obscured_by_target = obscured_by_target;
1155 zone = hwc_window->zone;
1156 if (!zone) continue;
1157 if (e_output_find(zone->output_id) != hwc->output) continue;
1160 if (eina_list_data_find(windows_list, hwc_window))
1163 // check clients to skip composite
1164 if (e_client_util_ignored_get(ec))
1166 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1170 if (ec->hwc_visible_skip)
1172 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1176 if (!evas_object_visible_get(ec->frame))
1178 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1182 e_client_geometry_get(ec, &x, &y, &w, &h);
1184 if ((ec->is_cursor) && (evas_object_map_enable_get(ec->frame)))
1186 map = e_client_map_get(ec);
1189 e_map_point_coord_get(map, 0, &x1, &y1, NULL);
1190 e_map_point_coord_get(map, 2, &x2, &y2, NULL);
1194 w = MAX(x1, x2) - x;
1195 h = MAX(y1, y2) - y;
1201 if ((!effect_client) && (!e_comp_object_color_visible_get(ec->frame)))
1203 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1205 render_op = evas_object_render_op_get(ec->frame);
1207 (render_op == EVAS_RENDER_COPY) &&
1208 (_e_hwc_windows_client_fully_mask_get(ec, x, y, w, h, ee_w, ee_h)))
1210 ui_skip = EINA_TRUE;
1217 // check geometry if located out of screen such as quick panel
1218 if (!E_INTERSECTS(0, 0, ee_w, ee_h, x, y, w, h))
1220 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1224 if (evas_object_data_get(ec->frame, "comp_skip"))
1226 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1230 /* skip all small clients except the video clients */
1231 if ((ec->w == 1 || ec->h == 1) && !e_hwc_window_is_video(hwc_window))
1233 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1237 if (e_hwc_window_is_video(hwc_window))
1239 if (!e_client_video_tbm_surface_get(ec))
1242 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO, EINA_TRUE);
1248 /* check parent of subsurface is bottom ec */
1249 if ((ec->comp_data) && (ec->comp_data->sub.data))
1251 topmost_ec = e_comp_wl_topmost_parent_get(ec);
1252 if (topmost_ec != bottom)
1262 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CURSOR, EINA_TRUE);
1265 windows_list = eina_list_append(windows_list, hwc_window);
1268 (_e_hwc_windows_client_fully_mask_get(ec, x, y, w, h, ee_w, ee_h)))
1270 ui_skip = EINA_TRUE;
1275 return windows_list;
1279 _e_hwc_windows_pending_update_data_enqueue(E_Hwc_Windows_Comp_Info *comp_info)
1281 E_Hwc_Window_Update_Data *update;
1283 EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1285 EINA_LIST_FREE(comp_info->pending_update_list, update)
1286 e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
1288 comp_info->pending_update_list = NULL;
1290 e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1296 _e_hwc_windows_pending_update_data_dequeue(E_Hwc_Window_Target *root_target_hwc_window,
1297 E_Hwc_Windows_Comp_Info *comp_info)
1299 E_Hwc_Window_Target *target_hwc_window;
1300 Eina_List *pending_update_list = NULL;
1301 E_Hwc_Window_Update_Data *update;
1302 E_Hwc_Window *hwc_window;
1306 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1307 EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1309 EINA_LIST_FREE(comp_info->pending_update_list, update)
1310 e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
1312 e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1314 EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1316 if (!output->hwc) continue;
1318 target_hwc_window = output->hwc->target_hwc_window;
1319 if (!target_hwc_window) continue;
1321 EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
1323 hwc_window->present_sync = EINA_FALSE;
1325 update = e_hwc_window_pending_update_data_dequeue(hwc_window);
1328 pending_update_list = eina_list_append(pending_update_list, update);
1329 if (e_hwc_window_is_video(hwc_window))
1330 e_client_video_commit_data_release(hwc_window->ec, 0, 0, 0);
1334 e_comp_wl_tizen_hwc_feedback_list_dequeue(hwc_window->ec, &comp_info->feedback_list);
1336 e_object_unref(E_OBJECT(hwc_window));
1341 comp_info->pending_update_list = pending_update_list;
1347 _e_hwc_windows_pending_update_data_clear(E_Hwc_Window_Target *root_target_hwc_window)
1349 E_Hwc_Window_Target *target_hwc_window;
1350 E_Hwc_Window *hwc_window;
1351 E_Hwc_Window_Update_Data *update;
1352 tbm_surface_h tsurface;
1353 E_Hwc_Windows_Comp_Info *comp_info;
1357 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1359 EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1361 if (!output->hwc) continue;
1363 target_hwc_window = output->hwc->target_hwc_window;
1364 if (!target_hwc_window) continue;
1366 EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
1368 hwc_window->present_sync = EINA_FALSE;
1369 e_object_unref(E_OBJECT(hwc_window));
1373 EINA_LIST_FOREACH_SAFE(root_target_hwc_window->rendering_tsurfaces, l, ll, tsurface)
1375 comp_info = _e_hwc_windows_comp_info_get(tsurface);
1376 if (!comp_info) continue;
1378 EINA_LIST_FREE(comp_info->pending_update_list, update)
1379 e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update);
1381 e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1387 /* gets called as somebody modifies target_window's queue */
1389 _e_hwc_windows_target_window_surface_queue_trace_cb(tbm_surface_queue_h surface_queue,
1390 tbm_surface_h tsurface, tbm_surface_queue_trace trace, void *data)
1392 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1393 E_Hwc_Windows_Comp_Info *comp_info;
1395 /* gets called as evas_renderer dequeues a new buffer from the queue */
1396 if (trace == TBM_SURFACE_QUEUE_TRACE_DEQUEUE)
1398 if (!target_hwc_window->is_rendering) return;
1400 EHWSTRACE("{%s} dequeue ts:%p", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window), tsurface);
1402 target_hwc_window->dequeued_tsurface = tsurface;
1404 if (!eina_list_data_find(target_hwc_window->rendering_tsurfaces, tsurface))
1406 target_hwc_window->rendering_tsurfaces =
1407 eina_list_append(target_hwc_window->rendering_tsurfaces, tsurface);
1410 if (e_hwc_windows_fence_enabled_get(target_hwc_window->hwc))
1412 comp_info = _e_hwc_windows_comp_info_get(target_hwc_window->dequeued_tsurface);
1413 if (comp_info && comp_info->release_fence)
1414 e_egl_sync_wait(comp_info->release_fence);
1418 if (trace == TBM_SURFACE_QUEUE_TRACE_ACQUIRE)
1420 target_hwc_window->rendering_tsurfaces =
1421 eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface);
1423 comp_info = _e_hwc_windows_comp_info_get(tsurface);
1426 _e_hwc_windows_pending_update_data_enqueue(comp_info);
1427 _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
1431 /* tsurface has been released at the queue */
1432 if (trace == TBM_SURFACE_QUEUE_TRACE_RELEASE)
1434 EHWSTRACE("{%s} release ts:%p", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window), tsurface);
1436 target_hwc_window->rendering_tsurfaces =
1437 eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface);
1439 comp_info = _e_hwc_windows_comp_info_get(tsurface);
1442 comp_info->skip = EINA_FALSE;
1443 _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
1444 _e_hwc_windows_comp_info_rendered_windows_set(comp_info, NULL);
1449 /* gets called as evas_renderer enqueues a new buffer into the queue */
1451 _e_hwc_windows_target_window_surface_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1453 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1457 ret = write(target_hwc_window->event_fd, &value, sizeof(value));
1459 EHWSERR("failed to send acquirable event:%m", NULL);
1462 /* gets called at the beginning of an ecore_main_loop iteration */
1464 _e_hwc_windows_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd_handler)
1469 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1470 E_Hwc_Window *hwc_window;
1471 Eina_List *acquirable_buffers;
1472 E_Hwc_Window_Queue_Buffer *queue_buffer;
1473 E_Hwc_Windows_Comp_Info *comp_info;
1475 fd = ecore_main_fd_handler_fd_get(fd_handler);
1476 if (fd < 0) return ECORE_CALLBACK_RENEW;
1478 len = read(fd, buffer, sizeof(buffer));
1480 EHWSERR("failed to read queue acquire event fd:%m", NULL);
1482 hwc_window = (E_Hwc_Window *)target_hwc_window;
1483 if (!hwc_window) return ECORE_CALLBACK_RENEW;
1484 if (!hwc_window->queue) return ECORE_CALLBACK_RENEW;
1486 acquirable_buffers = e_hwc_window_queue_acquirable_buffers_get(hwc_window->queue);
1487 if (!acquirable_buffers) return ECORE_CALLBACK_RENEW;
1489 EINA_LIST_FREE(acquirable_buffers, queue_buffer)
1491 if (!queue_buffer->tsurface) continue;
1493 comp_info = _e_hwc_windows_comp_info_get(queue_buffer->tsurface);
1494 if (!comp_info) continue;
1496 _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
1499 return ECORE_CALLBACK_RENEW;
1503 _e_hwc_windows_target_cb_pp_queue_destroy(struct wl_listener *listener, void *data)
1505 E_Hwc_Window_Target *target_hwc_window;
1507 target_hwc_window = container_of(listener, E_Hwc_Window_Target, pp_queue_destroy_listener);
1508 EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
1510 if ((E_Hwc_Window_Queue *)data != target_hwc_window->pp_queue) return;
1512 if (target_hwc_window->pp_queue_destroy_listener.notify)
1514 wl_list_remove(&target_hwc_window->pp_queue_destroy_listener.link);
1515 target_hwc_window->pp_queue_destroy_listener.notify = NULL;
1518 target_hwc_window->pp_queue = NULL;
1522 _e_hwc_windows_target_window_pp_queue_set(E_Hwc_Window_Target *target_hwc_window, E_Hwc_Window_Queue *queue)
1524 if (target_hwc_window->pp_queue == queue)
1527 if (target_hwc_window->pp_queue)
1529 wl_list_remove(&target_hwc_window->pp_queue_destroy_listener.link);
1530 target_hwc_window->pp_queue_destroy_listener.notify = NULL;
1535 wl_signal_add(&queue->destroy_signal, &target_hwc_window->pp_queue_destroy_listener);
1536 target_hwc_window->pp_queue_destroy_listener.notify = _e_hwc_windows_target_cb_pp_queue_destroy;
1537 target_hwc_window->pp_queue = queue;
1544 _e_hwc_windows_target_cb_queue_destroy(struct wl_listener *listener, void *data)
1546 E_Hwc_Window *hwc_window;
1548 hwc_window = container_of(listener, E_Hwc_Window, queue_destroy_listener);
1549 EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1551 if ((E_Hwc_Window_Queue *)data != hwc_window->queue) return;
1553 hwc_window->queue = NULL;
1557 _e_hwc_windows_target_window_tbm_surface_queue_set(E_Hwc_Window_Target *target_hwc_window, tbm_surface_queue_h tqueue)
1559 E_Hwc_Window_Queue *queue;
1562 EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
1564 queue = e_hwc_window_queue_target_tbm_surface_queue_set((E_Hwc_Window *)target_hwc_window, tqueue);
1565 if (!queue) return EINA_FALSE;
1567 if (((E_Hwc_Window *)target_hwc_window)->queue == queue) return EINA_TRUE;
1569 wl_signal_add(&queue->destroy_signal, &((E_Hwc_Window *)target_hwc_window)->queue_destroy_listener);
1570 ((E_Hwc_Window *)target_hwc_window)->queue_destroy_listener.notify = _e_hwc_windows_target_cb_queue_destroy;
1571 ((E_Hwc_Window *)target_hwc_window)->queue = queue;
1573 queue_size = e_hwc_window_queue_size_get(queue);
1576 target_hwc_window->max_transition_failures =
1577 e_hwc_window_queue_size_get(((E_Hwc_Window *)target_hwc_window)->queue);
1581 target_hwc_window->max_transition_failures = DEFAULT_MAX_TRANSITION_FAILURES;
1584 /* as evas_renderer has finished its work (to provide a composited buffer) it enqueues
1585 * the result buffer into this queue and acquirable cb gets called; this cb does nothing
1586 * except the writing into the event_fd object, this writing causes the new ecore_main loop
1587 * iteration to be triggered ('cause we've registered ecore_main fd handler to check this writing);
1588 * so it's just a way to inform E20's HWC that evas_renderer has done its work */
1589 tbm_surface_queue_add_acquirable_cb(queue->tqueue,
1590 _e_hwc_windows_target_window_surface_queue_acquirable_cb,
1591 (void *)target_hwc_window);
1593 /* TODO: we can use this call instead of an add_acquirable_cb and an add_dequeue_cb calls. */
1594 tbm_surface_queue_add_trace_cb(queue->tqueue,
1595 _e_hwc_windows_target_window_surface_queue_trace_cb,
1596 (void *)target_hwc_window);
1602 _e_hwc_windows_target_window_gbm_surface_set(E_Hwc_Window_Target *target_hwc_window, void *gsurface,
1603 int width, int height, int format)
1605 E_Hwc_Window_Queue *queue;
1607 EINA_SAFETY_ON_NULL_RETURN_VAL(gsurface, EINA_FALSE);
1609 queue = e_hwc_window_queue_target_gbm_surface_set((E_Hwc_Window *)target_hwc_window, gsurface,
1610 width, height, format);
1611 if (!queue) return EINA_FALSE;
1613 if (((E_Hwc_Window *)target_hwc_window)->queue == queue) return EINA_TRUE;
1615 wl_signal_add(&queue->destroy_signal, &((E_Hwc_Window *)target_hwc_window)->queue_destroy_listener);
1616 ((E_Hwc_Window *)target_hwc_window)->queue_destroy_listener.notify = _e_hwc_windows_target_cb_queue_destroy;
1617 ((E_Hwc_Window *)target_hwc_window)->queue = queue;
1619 target_hwc_window->max_transition_failures = DEFAULT_MAX_TRANSITION_FAILURES;
1625 _e_hwc_windows_target_window_queue_set(E_Hwc_Window_Target *target_hwc_window)
1627 E_Hwc *hwc = target_hwc_window->hwc;
1628 tbm_surface_queue_h tqueue;
1629 struct gbm_surface *gsurface;
1630 int width, height, format;
1632 tqueue = e_hwc_tbm_surface_queue_get(hwc);
1634 return _e_hwc_windows_target_window_tbm_surface_queue_set(target_hwc_window, tqueue);
1636 gsurface = e_hwc_gbm_surface_get(hwc, &width, &height, &format);
1638 return _e_hwc_windows_target_window_gbm_surface_set(target_hwc_window, gsurface, width, height, format);
1640 EHWSERR("fail to get tbm_surface_queue and gbm_surface", hwc);
1646 _e_hwc_windows_presentation_callback_comp_take_over(E_Hwc_Window_Target *root_target_hwc_window,
1647 E_Hwc_Windows_Comp_Info *comp_info)
1649 E_Hwc_Window_Target *target_hwc_window;
1650 E_Hwc_Window *hwc_window;
1652 Eina_List *l, *l2, *ll2;
1654 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1655 EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1657 EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1659 if (!output->hwc) continue;
1661 target_hwc_window = output->hwc->target_hwc_window;
1662 if (!target_hwc_window) continue;
1664 EINA_LIST_FOREACH_SAFE(target_hwc_window->pending_presentation_cb_wins, l2, ll2, hwc_window)
1666 if (!hwc_window->render_target) continue;
1668 e_hwc_window_presentation_callback_pending_take_over(hwc_window,
1669 &comp_info->presentation_callbacks);
1677 _e_hwc_windows_target_window_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1679 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1680 E_Hwc_Window *hwc_window;
1682 E_Egl_Sync *egl_sync;
1684 int acquire_fence_fd = -1;
1686 hwc = target_hwc_window->hwc;
1687 if (!e_hwc_windows_fence_enabled_get(hwc)) return;
1689 EINA_LIST_FOREACH(hwc->visible_windows, l, hwc_window)
1691 if (hwc_window->is_deleted) continue;
1692 if (!hwc_window->ec) continue;
1693 if (e_hwc_window_accepted_state_get(hwc_window) != E_HWC_WINDOW_STATE_CLIENT)
1696 acquire_fence_fd = e_client_explicit_sync_acquire_fence_fd_get(hwc_window->ec);
1697 if (acquire_fence_fd < 0) continue;
1699 egl_sync = e_egl_sync_fence_create_with_fd(acquire_fence_fd);
1700 if (!egl_sync) continue;
1702 if (!e_egl_sync_wait(egl_sync))
1703 ERR("Failed to wait on E_Egl_Sync");
1705 e_egl_sync_destroy(egl_sync);
1707 EHWSTRACE("EGL_WAIT_SYNC hwc_window(%p) is Done.", hwc_window->ec, hwc, hwc_window);
1712 _e_hwc_windows_target_window_render_flush_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1714 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1717 hwc = target_hwc_window->hwc;
1718 if (!e_hwc_windows_fence_enabled_get(hwc)) return;
1720 if (target_hwc_window->end_render_sync)
1722 e_egl_sync_destroy(target_hwc_window->end_render_sync);
1723 target_hwc_window->end_render_sync = NULL;
1726 target_hwc_window->end_render_sync = e_egl_sync_fence_create();
1727 if (!target_hwc_window->end_render_sync)
1728 EHWSERR("Failed to create E_Egl_Sync", hwc);
1732 _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1734 E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1735 E_Hwc_Window *hwc_window;
1736 E_Comp_Wl_Buffer_Ref *buffer_ref;
1737 E_Comp_Wl_Buffer *buffer;
1738 E_Hwc_Windows_Comp_Info *comp_info;
1739 Eina_List *rendered_buffers = NULL;
1740 Eina_List *rendered_windows;
1741 Eina_List *visible_windows;
1743 Eina_Bool fence_enabled;
1744 E_Hwc_Window_Queue_Type queue_type;
1746 E_Comp_Wl_Client_Data *cdata;
1748 EHWSTRACE("{%s} gets render_flush_post noti", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window));
1750 if (!target_hwc_window->dequeued_tsurface)
1752 queue_type = e_hwc_window_queue_type_get(((E_Hwc_Window *)target_hwc_window)->queue);
1753 if (queue_type == E_HWC_WINDOW_QUEUE_TYPE_TBM_SURFACE_QUEUE)
1754 EHWSINF("flush_post_cb is called but tsurface isn't dequeued", NULL, target_hwc_window->hwc);
1756 _e_hwc_windows_pending_update_data_clear(target_hwc_window);
1758 if (eina_list_count(target_hwc_window->rendered_windows))
1760 EINA_LIST_FREE(target_hwc_window->rendered_windows, hwc_window)
1762 hwc_window->on_rendered_target = EINA_FALSE;
1763 e_hwc_window_unref(hwc_window);
1767 target_hwc_window->rendered_windows = NULL;
1771 comp_info = _e_hwc_windows_comp_info_get(target_hwc_window->dequeued_tsurface);
1774 EHWSERR("fail to get comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface);
1778 _e_hwc_windows_pending_update_data_dequeue(target_hwc_window, comp_info);
1779 _e_hwc_windows_presentation_callback_comp_take_over(target_hwc_window, comp_info);
1781 visible_windows = _e_hwc_windows_visible_windows_list_get(NULL);
1782 EINA_LIST_FREE(visible_windows, hwc_window)
1784 if ((!hwc_window->is_video) &&
1785 (hwc_window->render_target) &&
1786 (!hwc_window->on_rendered_target))
1787 e_hwc_windows_rendered_window_add(hwc_window);
1790 fence_enabled = e_hwc_windows_fence_enabled_get(target_hwc_window->hwc);
1792 EINA_LIST_FOREACH(target_hwc_window->rendered_windows, l, hwc_window)
1794 if (!hwc_window->on_rendered_target) continue;
1796 hwc_window->on_rendered_target = EINA_FALSE;
1798 ec = hwc_window->ec;
1801 cdata = e_client_cdata_get(ec);
1803 e_presentation_time_container_feedback_merge(&comp_info->presentation_container,
1804 &cdata->presentation_container);
1806 buffer = e_pixmap_ref_resource_get(ec->pixmap);
1808 buffer = _e_hwc_windows_comp_wl_buffer_get(hwc_window);
1810 if (!buffer) continue;
1812 /* if reference buffer created by server, server deadlock is occurred.
1813 beacause tbm_surface_internal_unref is called in user_data delete callback.
1814 tbm_surface doesn't allow it.
1816 if (!buffer->resource) continue;
1818 if ((fence_enabled) && (buffer->buffer_release) && (target_hwc_window->end_render_sync))
1822 fence_fd = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
1825 if (!e_explicit_sync_buffer_release_fence_fd_set(buffer->buffer_release, fence_fd))
1831 EHWSERR("failed to dup native fence fd", target_hwc_window->hwc);
1834 buffer_ref = E_NEW(E_Comp_Wl_Buffer_Ref, 1);
1835 if (!buffer_ref) continue;
1837 e_comp_wl_buffer_reference(buffer_ref, buffer);
1838 rendered_buffers = eina_list_append(rendered_buffers, buffer_ref);
1841 rendered_windows = eina_list_clone(target_hwc_window->rendered_windows);
1842 _e_hwc_windows_comp_info_rendered_windows_set(comp_info, rendered_windows);
1843 _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, rendered_buffers);
1845 eina_list_free(target_hwc_window->rendered_windows);
1846 target_hwc_window->rendered_windows = NULL;
1847 target_hwc_window->dequeued_tsurface = NULL;
1851 _e_hwc_windows_target_window_free(E_Hwc_Window_Target *target_hwc_window)
1853 E_Hwc_Window *hwc_window = (E_Hwc_Window *)target_hwc_window;
1854 E_Hwc_Window *present_sync_window, *presentation_cb_window;
1856 if (target_hwc_window->evas)
1858 evas_event_callback_del(target_hwc_window->evas,
1859 EVAS_CALLBACK_RENDER_FLUSH_POST,
1860 _e_hwc_windows_target_window_render_flush_post_cb);
1862 evas_event_callback_del(target_hwc_window->evas,
1863 EVAS_CALLBACK_RENDER_FLUSH_PRE,
1864 _e_hwc_windows_target_window_render_flush_pre_cb);
1866 evas_event_callback_del(target_hwc_window->evas,
1867 EVAS_CALLBACK_RENDER_PRE,
1868 _e_hwc_windows_target_window_render_pre_cb);
1871 if (target_hwc_window->event_hdlr)
1872 ecore_main_fd_handler_del(target_hwc_window->event_hdlr);
1874 if (target_hwc_window->event_fd >= 0)
1875 close(target_hwc_window->event_fd);
1877 EINA_LIST_FREE(target_hwc_window->present_sync_windows, present_sync_window)
1878 e_hwc_window_unref(present_sync_window);
1880 EINA_LIST_FREE(target_hwc_window->pending_presentation_cb_wins, presentation_cb_window)
1881 e_hwc_window_unref(presentation_cb_window);
1883 if (hwc_window->queue && hwc_window->queue->tqueue)
1884 tbm_surface_queue_destroy(hwc_window->queue->tqueue);
1886 e_presentation_time_container_finish(&hwc_window->presentation_container);
1887 e_hwc_presentation_callback_list_finish(&hwc_window->pending_presentation_callbacks);
1888 e_hwc_presentation_callback_list_finish(&hwc_window->presentation_callbacks);
1890 if (hwc_window->queue_destroy_listener.notify)
1892 wl_list_remove(&hwc_window->queue_destroy_listener.link);
1893 hwc_window->queue_destroy_listener.notify = NULL;
1896 e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, NULL);
1897 e_hwc_window_queue_buffer_reference(&hwc_window->commit.queue_buffer_ref, NULL);
1898 e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
1900 e_hwc_window_buffer_set(&hwc_window->current.buffer, NULL, NULL, 0);
1901 e_hwc_window_buffer_set(&hwc_window->commit.buffer, NULL, NULL, 0);
1902 e_hwc_window_buffer_set(&hwc_window->display.buffer, NULL, NULL, 0);
1904 EHWSINF("Free target window", NULL, NULL);
1906 E_FREE(target_hwc_window);
1910 _e_hwc_windows_pp_commit_handler(tdm_pp *pp, tbm_surface_h tsurface_src, tbm_surface_h tsurface_dst, void *user_data)
1913 E_Hwc_Window *hwc_window;
1914 E_Hwc_Window_Queue_Buffer *queue_buffer;
1916 hwc = (E_Hwc *)user_data;
1917 EINA_SAFETY_ON_NULL_RETURN(hwc);
1919 EHWSTRACE("!!!!!!!! HWC PP Commit Handler !!!!!!!!", NULL, hwc);
1920 EHWSTRACE("PP DON tsurface src:%p dst:%p", NULL, hwc, tsurface_src, tsurface_dst);
1922 hwc->pp_commit = EINA_FALSE;
1924 hwc_window = (E_Hwc_Window *)hwc->target_hwc_window;
1925 EINA_SAFETY_ON_FALSE_RETURN(hwc_window);
1927 queue_buffer = e_hwc_window_queue_buffer_find(hwc->pp_queue, tsurface_dst);
1930 if (!e_hwc_window_queue_buffer_enqueue(hwc->pp_queue, queue_buffer))
1931 ERR("fail to e_hwc_window_queue_buffer_enqueue");
1934 ERR("fail to e_hwc_window_queue_buffer_find");
1936 e_hwc_window_queue_buffer_reference(&hwc->pp_update.queue_buffer_ref, NULL);
1937 e_comp_wl_buffer_reference(&hwc->pp_update.buffer_ref, NULL);
1939 tbm_surface_internal_unref(tsurface_src);
1940 tbm_surface_internal_unref(tsurface_dst);
1946 EHWSINF("PP Destroy tdm_pp:%p", NULL, hwc, hwc->tpp);
1948 tdm_pp_destroy(hwc->tpp);
1952 e_hwc_window_buffer_set(&hwc->pp_update.buffer, NULL, NULL, 0);
1957 _e_hwc_windows_pp_info_set(E_Hwc *hwc, tbm_surface_h src, tbm_surface_h dst,
1958 Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
1960 tdm_info_pp pp_info;
1961 tdm_error ret = TDM_ERROR_NONE;
1962 unsigned int aligned_width_src = 0, aligned_width_dst = 0;
1964 aligned_width_src = e_comp_wl_tbm_aligned_width_get(src);
1965 EINA_SAFETY_ON_FALSE_RETURN_VAL(aligned_width_src != 0, EINA_FALSE);
1967 aligned_width_dst = e_comp_wl_tbm_aligned_width_get(dst);
1968 EINA_SAFETY_ON_FALSE_RETURN_VAL(aligned_width_dst != 0, EINA_FALSE);
1970 pp_info.src_config.size.h = aligned_width_src;
1971 pp_info.src_config.size.v = tbm_surface_get_height(src);
1972 pp_info.src_config.format = tbm_surface_get_format(src);
1973 pp_info.src_config.pos.x = src_rect->x;
1974 pp_info.src_config.pos.y = src_rect->y;
1975 pp_info.src_config.pos.w = src_rect->w;
1976 pp_info.src_config.pos.h = src_rect->h;
1978 pp_info.dst_config.size.h = aligned_width_dst;
1979 pp_info.dst_config.size.v = tbm_surface_get_height(dst);
1980 pp_info.dst_config.format = tbm_surface_get_format(dst);
1981 pp_info.dst_config.pos.x = dst_rect->x;
1982 pp_info.dst_config.pos.y = dst_rect->y;
1983 pp_info.dst_config.pos.w = dst_rect->w;
1984 pp_info.dst_config.pos.h = dst_rect->h;
1986 pp_info.transform = TDM_TRANSFORM_NORMAL;
1990 ret = tdm_pp_set_info(hwc->tpp, &pp_info);
1991 EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
1993 EHWSTRACE("PP Info src(%d,%d)(%d,%d)size(%dx%d), dst(%d,%d)(%d,%d)size(%dx%d)",
1995 pp_info.src_config.pos.x, pp_info.src_config.pos.y, pp_info.src_config.pos.w, pp_info.src_config.pos.h,
1996 pp_info.src_config.size.h, pp_info.src_config.size.v,
1997 pp_info.dst_config.pos.x, pp_info.dst_config.pos.y, pp_info.dst_config.pos.w, pp_info.dst_config.pos.h,
1998 pp_info.dst_config.size.h, pp_info.dst_config.size.v);
2004 _e_hwc_windows_vblank_handler(tdm_output *output, unsigned int sequence,
2005 unsigned int tv_sec, unsigned int tv_usec,
2008 E_Hwc *hwc = (E_Hwc *)user_data;
2009 E_Hwc_Windows_Commit_Data *wins_commit_data;
2010 E_Hwc_Window_Commit_Data *commit_data;
2013 EINA_SAFETY_ON_NULL_RETURN(hwc);
2015 EHWSTRACE("!!!!!!!! HWC Vblank Handler!!!!!!!!", NULL, hwc);
2017 _e_hwc_windows_wait_commit_set(hwc, EINA_FALSE);
2019 if (!eina_list_count(hwc->wins_commit_data_list)) return;
2021 wins_commit_data = eina_list_last_data_get(hwc->wins_commit_data_list);
2022 EINA_SAFETY_ON_NULL_RETURN(wins_commit_data);
2024 if (!wins_commit_data->use_vblank_handler) return;
2026 EINA_LIST_FOREACH(wins_commit_data->commit_data_list, l, commit_data)
2028 if (!commit_data) continue;
2029 if (!commit_data->hwc_window) continue;
2031 if (e_hwc_window_is_video(commit_data->hwc_window) && commit_data->hwc_window->ec)
2032 e_client_video_commit_data_release(commit_data->hwc_window->ec, sequence, tv_sec, tv_usec);
2035 wins_commit_data->vblank_done = EINA_TRUE;
2039 _e_hwc_windows_wait_commit_set(E_Hwc *hwc, Eina_Bool set)
2041 if (hwc->wait_commit == set) return;
2043 hwc->wait_commit = set;
2047 _e_hwc_windows_device_states_available_check(E_Hwc *hwc)
2049 return hwc->device_state_available;
2053 _e_hwc_windows_status_print(E_Hwc *hwc, Eina_Bool with_target)
2055 Eina_List *visible_windows = hwc->visible_windows;
2057 E_Hwc_Window *hwc_window;
2059 EHWSTRACE(" Device state available : %d", NULL, hwc,
2060 _e_hwc_windows_device_states_available_check(hwc));
2062 EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2064 EHWSTRACE(" ehw:%p ts:%p - {%s} state:%s zpos:%d deleted:%s restrict:%s",
2065 hwc_window->ec, hwc, hwc_window,
2066 hwc_window->current.buffer.tsurface, e_hwc_window_name_get(hwc_window),
2067 e_hwc_window_state_string_get(hwc_window->state),
2068 hwc_window->zpos, hwc_window->is_deleted ? "yes" : "no",
2069 e_hwc_window_restriction_string_get(hwc_window));
2073 static E_Hwc_Window *
2074 _e_hwc_windows_window_find_by_twin(E_Hwc *hwc, tdm_hwc_window *hwc_win)
2077 E_Hwc_Window *hwc_window;
2079 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
2080 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_win, NULL);
2082 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2084 if (hwc_window->thwc_window == hwc_win) return hwc_window;
2090 static E_Hwc_Window_State
2091 _e_hwc_windows_window_state_get(tdm_hwc_window_composition composition_type)
2093 E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
2095 switch (composition_type)
2097 case TDM_HWC_WIN_COMPOSITION_NONE:
2098 state = E_HWC_WINDOW_STATE_NONE;
2100 case TDM_HWC_WIN_COMPOSITION_CLIENT:
2101 state = E_HWC_WINDOW_STATE_CLIENT;
2103 case TDM_HWC_WIN_COMPOSITION_DEVICE:
2104 state = E_HWC_WINDOW_STATE_DEVICE;
2106 case TDM_HWC_WIN_COMPOSITION_CURSOR:
2107 state = E_HWC_WINDOW_STATE_CURSOR;
2109 case TDM_HWC_WIN_COMPOSITION_VIDEO:
2110 state = E_HWC_WINDOW_STATE_VIDEO;
2113 state = E_HWC_WINDOW_STATE_NONE;
2114 EHWSERR("unknown state of hwc_window", NULL);
2121 _e_hwc_windows_transition_check(E_Hwc *hwc)
2123 E_Hwc_Window *hwc_window;
2124 E_Hwc_Window_Target *target_hwc_window, *root_target_hwc_window;
2125 Eina_Bool transition = EINA_FALSE;
2127 Eina_Bool display_state_changed = EINA_FALSE;
2128 Eina_Bool target_window_changed = EINA_FALSE;
2129 Eina_Bool client_to_none_transition = EINA_FALSE;
2130 E_Hwc_Window_Queue_Type queue_type;
2132 target_hwc_window = hwc->target_hwc_window;
2133 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
2135 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
2136 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
2138 queue_type = e_hwc_window_queue_type_get(((E_Hwc_Window *)root_target_hwc_window)->queue);
2139 if (queue_type == E_HWC_WINDOW_QUEUE_TYPE_GBM_SURFACE) return EINA_FALSE;
2141 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2143 E_Hwc_Window_Transition window_transition = E_HWC_WINDOW_TRANSITION_NONE_TO_NONE;
2145 if (e_hwc_window_is_target(hwc_window)) continue;
2146 if (e_hwc_window_is_video(hwc_window)) continue;
2148 if ((hwc_window->state == hwc_window->accepted_state) &&
2149 (e_hwc_window_transition_get(hwc_window) == E_HWC_WINDOW_TRANSITION_NONE_TO_NONE))
2152 if (hwc_window->transition_failures > root_target_hwc_window->max_transition_failures)
2155 if ((((E_Hwc_Window *)target_hwc_window)->display.buffer.tsurface) ==
2156 (((E_Hwc_Window *)target_hwc_window)->current.buffer.tsurface))
2157 transition = EINA_TRUE;
2159 target_window_changed = EINA_TRUE;
2161 /* DEVICE -> CLIENT */
2162 if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) &&
2163 (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT))
2165 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT);
2167 if (!_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_FALSE))
2168 window_transition = E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT;
2170 display_state_changed = EINA_TRUE;
2172 /* DEVICE -> NONE */
2173 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) &&
2174 (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2176 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_DEVICE_TO_NONE);
2178 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2179 window_transition = E_HWC_WINDOW_TRANSITION_DEVICE_TO_NONE;
2181 display_state_changed = EINA_TRUE;
2183 /* CURSOR -> CLIENT */
2184 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR) &&
2185 (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT))
2187 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CURSOR_TO_CLIENT);
2189 if (!_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_FALSE))
2190 window_transition = E_HWC_WINDOW_TRANSITION_CURSOR_TO_CLIENT;
2192 display_state_changed = EINA_TRUE;
2194 /* CURSOR -> NONE */
2195 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR) &&
2196 (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2198 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CURSOR_TO_NONE);
2200 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2201 window_transition = E_HWC_WINDOW_TRANSITION_CURSOR_TO_NONE;
2203 display_state_changed = EINA_TRUE;
2205 /* CLIENT -> DEVICE */
2206 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2207 (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE))
2209 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_DEVICE);
2211 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2212 window_transition = E_HWC_WINDOW_TRANSITION_CLIENT_TO_DEVICE;
2214 display_state_changed = EINA_TRUE;
2216 /* CLIENT -> CURSOR */
2217 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2218 (hwc_window->state == E_HWC_WINDOW_STATE_CURSOR))
2220 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_CURSOR);
2222 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2223 window_transition = E_HWC_WINDOW_TRANSITION_CLIENT_TO_CURSOR;
2225 display_state_changed = EINA_TRUE;
2227 /* NONE -> DEVICE */
2228 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) &&
2229 (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE))
2231 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_NONE_TO_DEVICE);
2233 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2234 window_transition = E_HWC_WINDOW_TRANSITION_NONE_TO_DEVICE;
2236 display_state_changed = EINA_TRUE;
2238 /* NONE -> CURSOR */
2239 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) &&
2240 (hwc_window->state == E_HWC_WINDOW_STATE_CURSOR))
2242 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_NONE_TO_CURSOR);
2244 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2245 window_transition = E_HWC_WINDOW_TRANSITION_NONE_TO_CURSOR;
2247 display_state_changed = EINA_TRUE;
2249 /* CLIENT -> NONE */
2250 else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2251 (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2253 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE);
2255 if (_e_hwc_windows_target_window_rendered_window_has(hwc, hwc_window, EINA_TRUE))
2256 window_transition = E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE;
2258 else if ((e_hwc_window_transition_get(hwc_window) != E_HWC_WINDOW_TRANSITION_NONE_TO_NONE) &&
2259 (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT))
2261 if (_e_hwc_windows_target_window_rendered_window_has_no(hwc, hwc_window, EINA_TRUE))
2263 window_transition = e_hwc_window_transition_get(hwc_window);
2264 transition = EINA_TRUE;
2268 if (window_transition)
2270 if (target_window_changed)
2272 hwc_window->transition_failures++;
2273 EHWSINF("Increase hwc_window:%p transition failures:%d",
2274 hwc_window->ec, hwc, hwc_window, hwc_window->transition_failures);
2277 if (window_transition == E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE)
2279 client_to_none_transition = EINA_TRUE;
2283 transition = EINA_TRUE;
2287 if ((display_state_changed) && (client_to_none_transition))
2288 transition = EINA_TRUE;
2290 if (transition && target_window_changed)
2291 EHWSINF("hwc transition display_state_change:%d client_to_none_transition:%d",
2292 NULL, hwc, display_state_changed, client_to_none_transition);
2298 _e_hwc_windows_present_sync_check(E_Hwc *hwc)
2300 E_Hwc_Window_Target *target_hwc_window;
2302 if (!hwc->present_sync) return EINA_FALSE;
2304 target_hwc_window = hwc->target_hwc_window;
2305 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
2307 if (hwc->hwc_mode != E_HWC_MODE_FULL)
2309 if ((((E_Hwc_Window *)target_hwc_window)->display.buffer.tsurface) ==
2310 (((E_Hwc_Window *)target_hwc_window)->current.buffer.tsurface))
2314 hwc->present_sync = EINA_FALSE;
2320 _e_hwc_windows_validated_changes_update(E_Hwc *hwc, uint32_t num_changes)
2322 E_Hwc_Window *hwc_window;
2323 E_Hwc_Window_Target *target_hwc_window;
2324 E_Hwc_Window_State state;
2326 tdm_hwc_window **changed_hwc_window = NULL;
2327 tdm_hwc_window_composition *composition_types = NULL;
2330 changed_hwc_window = E_NEW(tdm_hwc_window *, num_changes);
2331 EINA_SAFETY_ON_NULL_GOTO(changed_hwc_window, fail);
2333 composition_types = E_NEW(tdm_hwc_window_composition, num_changes);
2334 EINA_SAFETY_ON_NULL_GOTO(composition_types, fail);
2336 target_hwc_window = hwc->target_hwc_window;
2337 EINA_SAFETY_ON_NULL_GOTO(target_hwc_window, fail);
2339 terror = tdm_hwc_get_changed_composition_types(hwc->thwc,
2340 &num_changes, changed_hwc_window,
2342 if (terror != TDM_ERROR_NONE)
2344 EHWSERR("failed to get changed composition types", hwc);
2348 EHWSTRACE(" Changes NUM : %d", NULL, hwc, num_changes);
2350 for (i = 0; i < num_changes; ++i)
2352 hwc_window = _e_hwc_windows_window_find_by_twin(hwc, changed_hwc_window[i]);
2355 EHWSERR("cannot find the E_Hwc_Window by hwc hwc_window", hwc);
2359 /* update the state with the changed compsition */
2360 state = _e_hwc_windows_window_state_get(composition_types[i]);
2361 e_hwc_window_state_set(hwc_window, state, EINA_TRUE);
2365 EHWSTRACE(" Modified after HWC Validation:", NULL, hwc);
2366 _e_hwc_windows_status_print(hwc, EINA_FALSE);
2369 free(changed_hwc_window);
2370 free(composition_types);
2375 if (changed_hwc_window) free(changed_hwc_window);
2376 if (composition_types) free(composition_types);
2382 _e_hwc_windows_accept(E_Hwc *hwc)
2384 E_Hwc_Window *hwc_window;
2385 E_Hwc_Window_State state;
2386 tdm_error terror = TDM_ERROR_NONE;
2389 /* accept changes */
2390 terror = tdm_hwc_accept_validation(hwc->thwc);
2391 if (terror != TDM_ERROR_NONE)
2393 EHWSERR("failed to accept validation", hwc);
2397 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2399 if (e_hwc_window_is_target(hwc_window)) continue;
2401 /* update the accepted_state */
2402 state = e_hwc_window_state_get(hwc_window);
2403 e_hwc_window_accepted_state_set(hwc_window, state);
2404 e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_NONE_TO_NONE);
2406 /* notify the hwc_window that it will be displayed on hw layer */
2407 if (!hwc_window->queue && !e_hwc_window_is_video(hwc_window))
2409 if (e_hwc_window_is_on_hw_overlay(hwc_window))
2410 e_hwc_window_activate(hwc_window, NULL);
2412 e_hwc_window_deactivate(hwc_window);
2416 /* _e_hwc_windows_accept */
2417 EHWSTRACE("======= HWC Accept Validation =======", NULL, hwc);
2423 _e_hwc_windows_validate(E_Hwc *hwc, uint32_t *num_changes)
2425 E_Output *output = hwc->output;
2427 tdm_output *toutput = output->toutput;
2428 tdm_hwc_window **thwc_windows = NULL;
2430 E_Hwc_Window *hwc_window;
2432 Eina_List *visible_windows = hwc->visible_windows;
2435 EHWSTRACE("======= HWC Request Validation to TDM HWC =====", NULL, hwc);
2436 _e_hwc_windows_status_print(hwc, EINA_FALSE);
2439 n_thw = eina_list_count(visible_windows);
2442 thwc_windows = E_NEW(tdm_hwc_window *, n_thw);
2443 EINA_SAFETY_ON_NULL_GOTO(thwc_windows, error);
2446 EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2447 thwc_windows[i++] = hwc_window->thwc_window;
2450 /* make hwc extension choose which clients will own hw overlays */
2451 terror = tdm_hwc_validate(hwc->thwc, thwc_windows, n_thw, num_changes);
2452 if (terror != TDM_ERROR_NONE) goto error;
2454 E_FREE(thwc_windows);
2459 EHWSERR("failed to validate the output(%p)", hwc, toutput);
2460 if (thwc_windows) E_FREE(thwc_windows);
2466 _e_hwc_windows_visible_windows_states_update(E_Hwc *hwc)
2468 Eina_List *visible_windows;
2470 E_Hwc_Window *hwc_window;
2473 /* get the visible ecs */
2474 visible_windows = hwc->visible_windows;
2476 /* check if e20 forces to set that all window has TDM_HWC_WIN_COMPOSITION_CLIENT types */
2477 if (_e_hwc_windows_device_states_available_check(hwc))
2479 /* check clients are able to use hwc */
2480 EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2482 /* The video window set the TDM_HWC_WIN_COMPOSITION_VIDEO type. */
2483 if (e_hwc_window_is_video(hwc_window))
2485 if (!e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO, EINA_TRUE))
2486 EHWSERR("cannot update E_Hwc_Window(%p)", hwc, hwc_window);
2491 /* the cursor state is decided through finding the visible_windows. */
2492 if (e_hwc_window_is_cursor(hwc_window)) continue;
2494 /* filter the visible clients which e20 prevent to shown by hw directly
2496 if (e_hwc_window_device_state_available_get(hwc_window))
2497 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_DEVICE, EINA_TRUE);
2500 ec = hwc_window->ec;
2503 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT, EINA_TRUE);
2506 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_DEVICE, EINA_TRUE);
2507 EHWSTRACE(" ehw:%p - {%s} is Force hwc_acceptable(Redirected FALSE)",
2508 hwc_window->ec, hwc, hwc_window, e_hwc_window_name_get(hwc_window));
2515 EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2517 /* The video window set the TDM_HWC_WIN_COMPOSITION_VIDEO type. */
2518 if (e_hwc_window_is_video(hwc_window))
2520 if (!e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO, EINA_TRUE))
2521 EHWSERR("cannot update E_Hwc_Window(%p)", hwc, hwc_window);
2525 ec = hwc_window->ec;
2529 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT, EINA_TRUE);
2530 EHWSTRACE(" ehw:%p - {%s} is Force hwc_unacceptable%s",
2531 hwc_window->ec, hwc, hwc_window, e_hwc_window_name_get(hwc_window),
2532 hwc->pp_set ? "(PP applied)" : "");
2536 e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_DEVICE, EINA_TRUE);
2537 EHWSTRACE(" ehw:%p - {%s} is Force hwc_acceptable(Redirected FALSE)",
2538 hwc_window->ec, hwc, hwc_window, e_hwc_window_name_get(hwc_window));
2545 _e_hwc_windows_visible_windows_changed_check(E_Hwc *hwc, Eina_List *visible_windows, int visible_num)
2547 Eina_List *prev_visible_windows;
2548 E_Hwc_Window *hw1, *hw2;
2551 prev_visible_windows = hwc->visible_windows;
2553 if (!prev_visible_windows) return EINA_TRUE;
2555 if (eina_list_count(prev_visible_windows) != visible_num)
2558 for (i = 0; i < visible_num; i++)
2560 hw1 = eina_list_nth(prev_visible_windows, i);
2561 hw2 = eina_list_nth(visible_windows, i);
2562 if (hw1 != hw2) return EINA_TRUE;
2569 _e_hwc_windows_visible_windows_update(E_Hwc *hwc)
2571 E_Hwc_Window *hwc_window;
2573 Eina_List *visible_windows;
2574 int visible_num = 0;
2577 /* get the visibile windows */
2578 visible_windows = _e_hwc_windows_visible_windows_list_get(hwc);
2579 if (!visible_windows && !hwc->visible_windows)
2582 visible_num = eina_list_count(visible_windows);
2584 if (!_e_hwc_windows_visible_windows_changed_check(hwc, visible_windows, visible_num))
2586 eina_list_free(visible_windows);
2590 if (eina_list_count(hwc->visible_windows))
2592 EINA_LIST_FREE(hwc->visible_windows, hwc_window)
2593 e_hwc_window_unref(hwc_window);
2596 /* store the current visible windows and the number of them */
2597 hwc->visible_windows = visible_windows;
2598 hwc->num_visible_windows = visible_num;
2600 /* use the reverse iteration for assgining the zpos */
2601 EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
2604 e_hwc_window_zpos_set(hwc_window, zpos++);
2605 e_hwc_window_ref(hwc_window);
2612 _e_hwc_windows_device_state_available_update(E_Hwc *hwc)
2614 Eina_Bool available = EINA_TRUE;
2616 /* make the full_gl_composite when the zoom is enabled */
2619 available = EINA_FALSE;
2623 /* make the full_gl_composite when the mirror mode is enabled */
2624 if (eina_list_count(hwc->mirror_dst_hwc))
2626 available = EINA_FALSE;
2630 /* full composite is forced to be set */
2631 if (e_hwc_deactive_get(hwc))
2633 available = EINA_FALSE;
2637 /* hwc_window manager required full GLES composition */
2638 if (e_comp->nocomp_override > 0)
2640 available = EINA_FALSE;
2645 if (hwc->device_state_available == available) return EINA_FALSE;
2647 hwc->device_state_available = available;
2653 _e_hwc_windows_pp_hwc_window_update(E_Hwc *hwc)
2655 E_Hwc_Window *hwc_window;
2658 if (hwc->mirror_src_hwc)
2660 hwc_window = (E_Hwc_Window *)hwc->mirror_src_hwc->target_hwc_window;
2664 e_output_size_get(hwc->output, &w, &h);
2666 if (hwc->num_visible_windows != 1)
2669 if (e_hwc_deactive_get(hwc))
2672 hwc_window = eina_list_nth(hwc->visible_windows, 0);
2676 if ((tbm_surface_get_width(hwc_window->current.buffer.tsurface)) != w ||
2677 (tbm_surface_get_height(hwc_window->current.buffer.tsurface)) != h)
2680 if (!hwc_window->device_state_available)
2684 if (hwc->pp_hwc_window != hwc_window)
2685 EHWSTRACE("Set pp_hwc_window:%p", NULL, hwc, hwc_window);
2687 hwc->pp_hwc_window = hwc_window;
2692 if (hwc->pp_hwc_window)
2693 EHWSTRACE("Unset pp_hwc_window", NULL, hwc);
2695 hwc->pp_hwc_window = NULL;
2698 /* check if there is a need to update the output */
2700 _e_hwc_windows_changes_update(E_Hwc *hwc)
2702 E_Hwc_Window *hwc_window;
2703 Eina_Bool update_changes = EINA_FALSE;
2704 const Eina_List *l, *ll;
2706 if (hwc->property_changed)
2708 hwc->property_changed = EINA_FALSE;
2709 update_changes = EINA_TRUE;
2712 /* update the the visible windows */
2713 if (_e_hwc_windows_visible_windows_update(hwc))
2714 update_changes = EINA_TRUE;
2716 /* update the the visible windows */
2717 if (_e_hwc_windows_device_state_available_update(hwc))
2718 update_changes = EINA_TRUE;
2720 EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2722 if (e_hwc_window_is_target(hwc_window)) continue;
2724 e_hwc_window_ref(hwc_window);
2727 EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2729 if (e_hwc_window_is_target(hwc_window)) continue;
2731 /* fetch the window buffer */
2732 if (e_hwc_window_buffer_fetch(hwc_window))
2733 update_changes = EINA_TRUE;
2736 /* sometimes client add frame cb without buffer attach */
2737 if ((hwc_window->ec) &&
2738 (hwc_window->ec->pixmap) &&
2739 (e_pixmap_type_get(hwc_window->ec->pixmap) == E_PIXMAP_TYPE_WL) &&
2740 (hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE))
2741 e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
2744 /* update the window's info */
2745 if (e_hwc_window_info_update(hwc_window))
2746 update_changes = EINA_TRUE;
2748 /* update the window's props */
2749 if (e_hwc_window_prop_update(hwc_window))
2750 update_changes = EINA_TRUE;
2752 if (e_hwc_window_device_state_available_update(hwc_window))
2753 update_changes = EINA_TRUE;
2756 EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2758 if (e_hwc_window_is_target(hwc_window)) continue;
2760 e_hwc_window_unref(hwc_window);
2763 if (hwc->primary_output)
2764 _e_hwc_windows_root_target_buffer_fetch(hwc);
2768 _e_hwc_windows_pp_hwc_window_update(hwc);
2769 _e_hwc_windows_pp_commit(hwc);
2772 /* fetch the target buffer (try acquire) */
2773 if (_e_hwc_windows_target_buffer_fetch(hwc))
2774 update_changes = EINA_TRUE;
2776 /* update the states of the visible windows when there is something to update */
2779 EHWSTRACE("======= HWC Update the Windows' Changes =====", NULL, hwc);
2780 _e_hwc_windows_visible_windows_states_update(hwc);
2783 return update_changes;
2787 _e_hwc_windows_target_state_set(E_Hwc_Window_Target *target_hwc_window, E_Hwc_Window_State state)
2789 E_Hwc_Window *target_window = (E_Hwc_Window *)target_hwc_window;
2791 if (target_window->is_root_target)
2793 if ((state == E_HWC_WINDOW_STATE_NONE) && (e_hwc_window_state_get(target_window) != state))
2794 _e_hwc_windows_pending_update_data_clear(target_hwc_window);
2797 e_hwc_window_state_set(target_window, state, EINA_FALSE);
2798 e_hwc_window_accepted_state_set(target_window, state);
2801 static pixman_format_code_t
2802 _e_hwc_windows_pixman_format_convert(tbm_format format)
2806 case TBM_FORMAT_ARGB8888: return PIXMAN_a8r8g8b8;
2807 case TBM_FORMAT_XRGB8888: return PIXMAN_x8r8g8b8;
2808 case TBM_FORMAT_ABGR8888: return PIXMAN_a8b8g8r8;
2809 case TBM_FORMAT_XBGR8888: return PIXMAN_x8b8g8r8;
2817 _e_hwc_windows_center_rect_get(int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
2821 if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
2824 rw = (float)src_w / dst_w;
2825 rh = (float)src_h / dst_h;
2830 fit->h = src_h / rw;
2832 fit->y = (dst_h - fit->h) / 2;
2836 fit->w = src_w / rh;
2838 fit->x = (dst_w - fit->w) / 2;
2850 fit->x = fit->x - 1;
2854 _e_hwc_windows_capture_position_get(E_Hwc *hwc, int dst_w, int dst_h, Eina_Rectangle *fit)
2856 int output_w = 0, output_h = 0;
2858 e_output_size_get(hwc->output, &output_w, &output_h);
2860 if (output_w == 0 || output_h == 0)
2863 _e_hwc_windows_center_rect_get(output_w, output_h, dst_w, dst_h, fit);
2869 _e_hwc_windows_pixman_copy(E_Hwc *hwc, tbm_surface_h src_tsurface, tbm_surface_h dst_tsurface,
2870 Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
2872 pixman_image_t *src_img = NULL, *dst_img = NULL;
2873 pixman_format_code_t src_format, dst_format;
2874 double scale_x, scale_y;
2875 pixman_transform_t t;
2876 struct pixman_f_transform ft;
2877 tbm_surface_info_s src_tinfo = {0};
2878 tbm_surface_info_s dst_tinfo = {0};
2879 int ret = TBM_SURFACE_ERROR_NONE;
2881 EINA_SAFETY_ON_NULL_RETURN(src_rect);
2882 EINA_SAFETY_ON_NULL_RETURN(dst_rect);
2884 ret = tbm_surface_map(src_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &src_tinfo);
2885 if (ret != TBM_SURFACE_ERROR_NONE)
2887 EHWSERR("tbm_surface_map fails on src_tsurface", hwc);
2891 ret = tbm_surface_map(dst_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &dst_tinfo);
2892 if (ret != TBM_SURFACE_ERROR_NONE)
2894 EHWSERR("tbm_surface_map fails on dst_tsurface", hwc);
2898 src_format = _e_hwc_windows_pixman_format_convert(tbm_surface_get_format(src_tsurface));
2899 EINA_SAFETY_ON_FALSE_RETURN(src_format);
2900 dst_format = _e_hwc_windows_pixman_format_convert(tbm_surface_get_format(dst_tsurface));
2901 EINA_SAFETY_ON_FALSE_RETURN(dst_format);
2903 src_img = pixman_image_create_bits(src_format, src_tinfo.width, src_tinfo.height,
2904 (uint32_t*)src_tinfo.planes[0].ptr,
2905 src_tinfo.planes[0].stride);
2906 EINA_SAFETY_ON_NULL_GOTO(src_img, free_img);
2908 dst_img = pixman_image_create_bits(dst_format, dst_tinfo.width, dst_tinfo.height,
2909 (uint32_t*)dst_tinfo.planes[0].ptr,
2910 dst_tinfo.planes[0].stride);
2911 EINA_SAFETY_ON_NULL_GOTO(dst_img, free_img);
2913 scale_x = (double)src_rect->w / dst_rect->w;
2914 scale_y = (double)src_rect->h / dst_rect->h;
2916 pixman_f_transform_init_identity(&ft);
2918 pixman_f_transform_scale(&ft, NULL, scale_x, scale_y);
2919 pixman_f_transform_translate(&ft, NULL, src_rect->x, src_rect->y);
2920 pixman_transform_from_pixman_f_transform(&t, &ft);
2921 pixman_image_set_transform(src_img, &t);
2923 pixman_image_composite(PIXMAN_OP_SRC, src_img, NULL, dst_img, 0, 0, 0, 0,
2924 dst_rect->x, dst_rect->y, dst_rect->w, dst_rect->h);
2927 if (src_img) pixman_image_unref(src_img);
2928 if (dst_img) pixman_image_unref(dst_img);
2930 tbm_surface_unmap(dst_tsurface);
2932 tbm_surface_unmap(src_tsurface);
2938 _e_hwc_windows_buffer_clear(E_Hwc *hwc, tbm_surface_h tsurface)
2940 tbm_surface_info_s tinfo = {0};
2941 int ret = TBM_SURFACE_ERROR_NONE;
2942 tbm_format format = 0;
2944 ret = tbm_surface_map(tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &tinfo);
2945 if (ret != TBM_SURFACE_ERROR_NONE)
2947 EHWSERR("tbm_surface_map fail on tsurface", hwc);
2951 format = tbm_surface_get_format(tsurface);
2954 case TBM_FORMAT_ARGB8888:
2955 case TBM_FORMAT_XRGB8888:
2957 int *ibuf = (int*)tinfo.planes[0].ptr;
2958 int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2960 for (i = 0 ; i < size ; i++)
2961 ibuf[i] = 0xff000000;
2964 case TBM_FORMAT_YVU420:
2965 case TBM_FORMAT_YUV420:
2966 memset((char*)tinfo.planes[0].ptr + tinfo.planes[0].offset, 0x10, tinfo.planes[0].stride * tinfo.height);
2967 memset((char*)tinfo.planes[1].ptr + tinfo.planes[1].offset, 0x80, tinfo.planes[1].stride * (tinfo.height >> 1));
2968 memset((char*)tinfo.planes[2].ptr + tinfo.planes[2].offset, 0x80, tinfo.planes[2].stride * (tinfo.height >> 1));
2970 case TBM_FORMAT_NV12:
2971 case TBM_FORMAT_NV21:
2972 memset((char*)tinfo.planes[0].ptr + tinfo.planes[0].offset, 0x10, tinfo.planes[0].stride * tinfo.height);
2973 memset((char*)tinfo.planes[1].ptr + tinfo.planes[1].offset, 0x80, tinfo.planes[1].stride * (tinfo.height >> 1));
2975 case TBM_FORMAT_YUYV:
2977 int *ibuf = (int*)tinfo.planes[0].ptr;
2978 int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2980 for (i = 0 ; i < size ; i++)
2981 ibuf[i] = 0x10801080;
2984 case TBM_FORMAT_UYVY:
2986 int *ibuf = (int*)tinfo.planes[0].ptr;
2987 int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2989 for (i = 0 ; i < size ; i++)
2990 ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */
2994 EHWSERR("can't clear %p buffer", hwc, tsurface);
2998 tbm_surface_unmap(tsurface);
3001 static E_Hwc_Window *
3002 _e_hwc_windows_visible_ui_window_bottom_get(E_Hwc *hwc)
3004 E_Hwc_Window *hwc_window;
3007 EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
3009 if (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO)
3018 static E_Hwc_Window *
3019 _e_hwc_windows_below_transparent_window_find(E_Hwc *hwc)
3021 E_Hwc_Window *hwc_window;
3023 if (hwc->hwc_mode != E_HWC_MODE_HYBRID) return NULL;
3025 hwc_window = _e_hwc_windows_visible_ui_window_bottom_get(hwc);
3026 if (!hwc_window) return NULL;
3028 if (hwc_window->state != E_HWC_WINDOW_STATE_DEVICE) return NULL;
3029 if (!hwc_window->ec) return NULL;
3030 if (hwc_window->ec->argb) return NULL;
3036 _e_hwc_windows_below_transparent_window_update(E_Hwc *hwc)
3038 E_Hwc_Window *hwc_window;
3040 hwc_window = _e_hwc_windows_below_transparent_window_find(hwc);
3043 if (hwc->below_transparent_window == hwc_window)
3046 if (hwc->below_transparent_window)
3048 e_hwc_window_below_transparent_obj_set(hwc->below_transparent_window, EINA_FALSE);
3049 e_hwc_window_unref(hwc->below_transparent_window);
3050 hwc->below_transparent_window = NULL;
3053 e_hwc_window_below_transparent_obj_set(hwc_window, EINA_TRUE);
3054 e_hwc_window_ref(hwc_window);
3055 hwc->below_transparent_window = hwc_window;
3059 if (!hwc->below_transparent_window)
3062 e_hwc_window_below_transparent_obj_set(hwc->below_transparent_window, EINA_FALSE);
3063 e_hwc_window_unref(hwc->below_transparent_window);
3064 hwc->below_transparent_window = NULL;
3066 e_hwc_windows_present_sync(hwc);
3070 /* evaluate the hwc_windows */
3072 _e_hwc_windows_evaluate(E_Hwc *hwc, E_Output_Display_Mode display_mode)
3074 E_Hwc_Mode hwc_mode = E_HWC_MODE_NONE;
3075 E_Hwc_Window *hwc_window;
3077 uint32_t num_changes;
3078 int num_client = 0, num_device = 0, num_video = 0, num_cursor = 0;
3080 /* validate the visible hwc_windows' states*/
3081 if (!_e_hwc_windows_validate(hwc, &num_changes))
3083 EHWSERR("_e_hwc_windows_validate failed", hwc);
3087 /* update the valiated_changes if there are the composition changes after validation */
3090 if (!_e_hwc_windows_validated_changes_update(hwc, num_changes))
3092 EHWSERR("_e_hwc_windows_validated_changes_update failed", hwc);
3097 /* constraints update and update the windows to be composited to the target_buffer */
3098 EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
3100 if (e_hwc_window_is_target(hwc_window)) continue;
3102 e_hwc_window_constraints_update(hwc_window);
3103 e_hwc_window_rendered_window_update(hwc_window);
3105 if (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT) num_client++;
3106 if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE) num_device++;
3107 if (hwc_window->state == E_HWC_WINDOW_STATE_CURSOR) num_cursor++;
3108 if (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO) num_video++;
3111 /* update the E_HWC_MODE */
3112 hwc_mode = _e_hwc_windows_hwc_mode_update(hwc, num_client, num_device, num_cursor ,num_video);
3114 /* set the state of the target_window */
3115 if (hwc_mode == E_HWC_MODE_NONE)
3117 EHWSTRACE(" HWC_MODE is NONE composition", NULL, hwc);
3118 _e_hwc_windows_target_state_set(hwc->target_hwc_window, E_HWC_WINDOW_STATE_DEVICE);
3120 else if (hwc_mode == E_HWC_MODE_HYBRID)
3122 EHWSTRACE(" HWC_MODE is HYBRID composition", NULL, hwc);
3123 _e_hwc_windows_target_state_set(hwc->target_hwc_window, E_HWC_WINDOW_STATE_DEVICE);
3127 EHWSTRACE(" HWC_MODE is FULL HW composition", NULL, hwc);
3128 _e_hwc_windows_target_state_set(hwc->target_hwc_window, E_HWC_WINDOW_STATE_NONE);
3131 _e_hwc_windows_below_transparent_window_update(hwc);
3133 /* skip the target_buffer when the window is on trainsition of the composition */
3134 if ((hwc_mode != E_HWC_MODE_FULL) &&
3135 (!hwc->pp_set) && (display_mode != E_OUTPUT_DISPLAY_MODE_MIRROR) &&
3136 (_e_hwc_windows_transition_check(hwc)))
3138 _e_hwc_windows_target_window_buffer_skip(hwc);
3140 if (!hwc->transition)
3142 e_hwc_windows_target_window_force_render(hwc->target_hwc_window);
3143 hwc->transition = EINA_TRUE;
3149 if (_e_hwc_windows_present_sync_check(hwc))
3151 EHWSTRACE(" Not accpet display sync", NULL, hwc);
3155 if (hwc_mode == E_HWC_MODE_FULL)
3157 if (((E_Hwc_Window *)hwc->target_hwc_window)->current.buffer.tsurface)
3158 _e_hwc_windows_target_buffer_fetch(hwc);
3161 /* accept the result of the validation */
3162 if (!_e_hwc_windows_accept(hwc))
3164 EHWSERR("_e_hwc_windows_validated_changes_update failed", hwc);
3168 hwc->transition = EINA_FALSE;
3169 hwc->re_evaluate = EINA_FALSE;
3174 EHWSTRACE("======= HWC NOT Accept Validation Yet !! =======", NULL, hwc);
3176 hwc->re_evaluate = EINA_TRUE;
3182 _e_hwc_windows_target_buffer_prepared(E_Hwc *hwc)
3184 E_Hwc_Window *hwc_window;
3186 hwc_window = (E_Hwc_Window *)hwc->target_hwc_window;
3187 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->target_hwc_window, EINA_FALSE);
3189 if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
3195 _e_hwc_windows_pp_rect_set(E_Hwc *hwc, Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
3197 memcpy(&hwc->pp_src_rect, src_rect, sizeof(Eina_Rectangle));
3198 memcpy(&hwc->pp_dst_rect, dst_rect, sizeof(Eina_Rectangle));
3202 _e_hwc_windows_pp_update(E_Hwc *hwc)
3204 E_Hwc_Window *hwc_window;
3206 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3208 if (hwc->pp_hwc_window)
3209 hwc_window = hwc->pp_hwc_window;
3211 hwc_window = (E_Hwc_Window *)_e_hwc_windows_root_target_hwc_window_get(hwc);
3213 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3215 if (hwc_window->current.buffer.tsurface == hwc->pp_update.buffer.tsurface)
3218 if (e_hwc_window_is_target(hwc_window))
3219 e_hwc_window_queue_buffer_reference(&hwc->pp_update.queue_buffer_ref,
3220 hwc_window->current.queue_buffer_ref.buffer);
3222 e_comp_wl_buffer_reference(&hwc->pp_update.buffer_ref, _e_hwc_windows_comp_wl_buffer_get(hwc_window));
3224 e_hwc_window_buffer_set(&hwc->pp_update.buffer,
3225 hwc_window->current.buffer.tsurface, hwc_window->current.buffer.queue, 0);
3231 e_hwc_windows_init(void)
3233 if (!e_hwc_window_init())
3235 ERR("E_Hwc_Window init failed");
3239 if (!e_hwc_window_queue_init())
3241 ERR("E_Hwc_Window_Queue init failed");
3242 e_hwc_window_deinit();
3250 e_hwc_windows_deinit(void)
3252 e_hwc_window_queue_deinit();
3253 e_hwc_window_deinit();
3257 _e_hwc_windows_root_target_window_state_update(E_Hwc_Window_Target *root_target_hwc_window)
3261 E_Hwc_Window_State state;
3262 E_Hwc_Window_State root_state = E_HWC_WINDOW_STATE_NONE;
3264 EINA_SAFETY_ON_NULL_RETURN(e_comp);
3265 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
3267 EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
3269 if (!e_output_connected(output)) continue;
3270 if (!output->hwc) continue;
3271 if (!output->hwc->target_hwc_window) continue;
3273 state = e_hwc_window_state_get((E_Hwc_Window *)output->hwc->target_hwc_window);
3274 if (state == E_HWC_WINDOW_STATE_DEVICE)
3276 root_state = E_HWC_WINDOW_STATE_DEVICE;
3281 _e_hwc_windows_target_state_set(root_target_hwc_window, root_state);
3285 e_hwc_windows_render(E_Hwc *hwc)
3287 E_Hwc_Window_Target *target_hwc_window;
3288 E_Hwc_Window *target_window;
3291 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3293 target_hwc_window = hwc->root_target_hwc_window;
3294 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3296 target_window = (E_Hwc_Window *)target_hwc_window;
3297 EINA_SAFETY_ON_NULL_RETURN_VAL(target_window->queue, EINA_FALSE);
3299 _e_hwc_windows_root_target_window_state_update(target_hwc_window);
3301 if ((e_hwc_window_state_get(target_window) == E_HWC_WINDOW_STATE_NONE) ||
3302 ((hwc->pp_set) && (hwc->pp_hwc_window)))
3304 /* evas_norender is needed for preventing memory leak
3305 because evas_object is freed in manual render
3306 even if evas_object_del is called
3307 and it is also needed for processing input event of evas
3308 because input event is sent in manual_render */
3309 if (!hwc->wait_commit)
3310 evas_norender(target_hwc_window->evas);
3315 if (e_hwc_norender_get(hwc) > 0)
3317 EHWSTRACE("NoRender get. Do not ecore_evas_manual_render", NULL, hwc);
3321 if (e_hwc_window_queue_buffer_can_dequeue(target_window->queue))
3323 TRACE_DS_BEGIN(MANUAL RENDER);
3324 target_hwc_window->is_rendering = EINA_TRUE;
3325 ecore_evas_manual_render(target_hwc_window->ee);
3328 egl_error = eglGetError();
3329 if (egl_error != EGL_SUCCESS)
3330 ERR("EGL Error:%d in ecore_evas_manual_render", egl_error);
3332 target_hwc_window->is_rendering = EINA_FALSE;
3340 _e_hwc_windows_release_fence_fd_update(E_Hwc *hwc)
3342 E_Hwc_Window *hwc_window;
3343 E_Hwc_Window_Target *target_hwc_window;
3344 E_Hwc_Windows_Comp_Info *comp_info;
3345 tdm_hwc_window **thwc_wins = NULL;
3346 int *release_fences = NULL;
3347 uint32_t num_thwc_wins = 0;
3348 tdm_error ret = TDM_ERROR_NONE;
3351 target_hwc_window = hwc->target_hwc_window;
3352 EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
3354 hwc_window = (E_Hwc_Window *)target_hwc_window;
3355 if ((hwc_window->display.buffer.tsurface) &&
3356 (hwc_window->display.buffer.tsurface != hwc_window->commit.buffer.tsurface))
3358 comp_info = _e_hwc_windows_comp_info_get(hwc_window->display.buffer.tsurface);
3359 EINA_SAFETY_ON_NULL_RETURN(comp_info);
3361 if (comp_info->release_fence)
3362 e_egl_sync_destroy(comp_info->release_fence);
3364 comp_info->release_fence = e_egl_sync_fence_create_with_fd(hwc->commit_fence_fd);
3366 e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
3369 ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, NULL, NULL);
3370 EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
3372 if (!num_thwc_wins) return;
3374 thwc_wins = E_NEW(tdm_hwc_window *, num_thwc_wins);
3375 EINA_SAFETY_ON_NULL_GOTO(thwc_wins, clean);
3377 release_fences = E_NEW(int, num_thwc_wins);
3378 EINA_SAFETY_ON_NULL_GOTO(release_fences, clean);
3380 ret = tdm_hwc_get_release_fences(hwc->thwc, &num_thwc_wins, thwc_wins, release_fences);
3381 EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, clean);
3383 for (i = 0; i < num_thwc_wins; i++)
3385 hwc_window = _e_hwc_windows_window_find_by_twin(hwc, thwc_wins[i]);
3387 if ((!hwc_window) ||
3388 (!hwc_window->display.buffer_ref.buffer) ||
3389 (!hwc_window->display.buffer_ref.buffer->buffer_release))
3391 close(release_fences[i]);
3395 if (!e_explicit_sync_buffer_release_fence_fd_set(hwc_window->display.buffer_ref.buffer->buffer_release,
3398 close(release_fences[i]);
3402 e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
3403 e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
3407 if (thwc_wins) free(thwc_wins);
3408 if (release_fences) free(release_fences);
3412 _e_hwc_windows_pp_commit(E_Hwc *hwc)
3415 E_Hwc_Window_Queue_Buffer *queue_buffer;
3416 E_Hwc_Windows_Comp_Info *pp_comp_info, *comp_info;
3417 tdm_error terror = TDM_ERROR_NONE;
3419 E_Comp_Wl_Client_Data *cdata;
3421 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3423 if (hwc->pp_commit) return EINA_TRUE;
3425 output = hwc->output;
3426 if (e_output_dpms_get(output))
3429 if (!e_hwc_window_queue_buffer_can_dequeue(hwc->pp_queue)) return EINA_TRUE;
3431 if (!_e_hwc_windows_pp_update(hwc)) return EINA_TRUE;
3433 queue_buffer = e_hwc_window_queue_buffer_dequeue(hwc->pp_queue);
3436 EHWSERR("fail e_hwc_window_queue_buffer_dequeue", hwc);
3440 if ((hwc->pp_dst_rect.x != 0) ||
3441 (hwc->pp_dst_rect.y != 0) ||
3442 (hwc->pp_dst_rect.w != tbm_surface_get_width(queue_buffer->tsurface)) ||
3443 (hwc->pp_dst_rect.h != tbm_surface_get_height(queue_buffer->tsurface)))
3444 _e_hwc_windows_buffer_clear(hwc, queue_buffer->tsurface);
3448 if (!_e_hwc_windows_pp_info_set(hwc, hwc->pp_update.buffer.tsurface, queue_buffer->tsurface,
3449 &hwc->pp_src_rect, &hwc->pp_dst_rect))
3451 EHWSERR("fail _e_hwc_windows_pp_info_set", hwc);
3455 tbm_surface_internal_ref(queue_buffer->tsurface);
3456 tbm_surface_internal_ref(hwc->pp_update.buffer.tsurface);
3457 terror = tdm_pp_attach(hwc->tpp, hwc->pp_update.buffer.tsurface, queue_buffer->tsurface);
3458 EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, attach_fail);
3460 EHWSTRACE("!!!!!!!! HWC PP Commit !!!!!!!!", NULL, hwc);
3461 EHWSTRACE("PP COM src_tsurface:%p dst_tsurface:%p tqueue:%p pp_hwc_window:%p", NULL, hwc,
3462 hwc->pp_update.buffer.tsurface, queue_buffer->tsurface, hwc->pp_tqueue, hwc->pp_hwc_window);
3464 terror = tdm_pp_commit(hwc->tpp);
3465 EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, commit_fail);
3467 hwc->pp_commit = EINA_TRUE;
3472 _e_hwc_windows_pixman_copy(hwc, hwc->pp_update.buffer.tsurface, queue_buffer->tsurface,
3473 &hwc->pp_src_rect, &hwc->pp_dst_rect);
3475 EHWSTRACE("PP Pixman src_tsurface:%p dst_tsurface:%p tqueue:%p pp_hwc_window:%p", NULL, hwc,
3476 hwc->pp_update.buffer.tsurface, queue_buffer->tsurface, hwc->pp_tqueue, hwc->pp_hwc_window);
3478 /* enqueue buffer */
3479 e_hwc_window_queue_buffer_enqueue(hwc->pp_queue, queue_buffer);
3482 if (!hwc->mirror_src_hwc)
3484 pp_comp_info = _e_hwc_windows_comp_info_get(queue_buffer->tsurface);
3487 if (hwc->pp_hwc_window)
3489 ec = hwc->pp_hwc_window->ec;
3490 cdata = e_client_cdata_get(ec);
3492 e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
3493 &cdata->presentation_container);
3495 e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
3496 &hwc->pp_hwc_window->pending_presentation_callbacks);
3500 comp_info = _e_hwc_windows_comp_info_get(hwc->pp_update.buffer.tsurface);
3502 e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
3503 &comp_info->presentation_container);
3505 e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
3506 &comp_info->presentation_callbacks);
3515 tbm_surface_internal_unref(queue_buffer->tsurface);
3516 tbm_surface_internal_unref(hwc->pp_update.buffer.tsurface);
3519 e_hwc_window_queue_buffer_release(hwc->pp_queue, queue_buffer);
3521 EHWSERR("failed _e_hwc_windows_pp_data_commit", hwc);
3523 hwc->pp_commit = EINA_FALSE;
3529 _e_hwc_windows_sync_callback_call(E_Hwc *hwc)
3531 E_Hwc_Sync_Callback *sync_callback;
3534 EINA_LIST_FOREACH_SAFE(hwc->sync_callback_list, l, ll, sync_callback)
3535 e_hwc_sync_callback_call(sync_callback);
3538 static tdm_hwc_commit_interval
3539 _e_hwc_windows_commit_interval_get(E_Hwc *hwc)
3542 tdm_hwc_commit_interval interval = TDM_HWC_COMMIT_INTERVAL_NONE;
3544 terror = tdm_hwc_get_commit_interval(hwc->thwc, &interval);
3545 if (terror != TDM_ERROR_NONE)
3546 return TDM_HWC_COMMIT_INTERVAL_NONE;
3552 _e_hwc_windows_commit_interval_update(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data)
3554 tdm_hwc_commit_interval interval = TDM_HWC_COMMIT_INTERVAL_NONE;
3555 tdm_error terror = TDM_ERROR_NONE;
3557 if (!hwc->wait_commit) return;
3559 interval = _e_hwc_windows_commit_interval_get(hwc);
3560 if (interval == TDM_HWC_COMMIT_INTERVAL_VBLANK)
3562 terror = tdm_output_wait_vblank(hwc->output->toutput, 1, 0, _e_hwc_windows_vblank_handler,
3564 if (terror != TDM_ERROR_NONE)
3566 EHWSERR("fail to tdm_output_wait_vblank", hwc);
3570 wins_commit_data->use_vblank_handler = EINA_TRUE;
3572 EHWSTRACE("!!!!!!!! HWC Vblank !!!!!!!!", NULL, hwc);
3577 e_hwc_windows_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
3580 tdm_error error = TDM_ERROR_NONE;
3581 int commit_fence_fd = -1;
3582 E_Hwc_Windows_Commit_Data *wins_commit_data;
3584 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3586 output = hwc->output;
3587 EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3589 if (hwc->wait_commit) return EINA_TRUE;
3591 if (e_hwc_norender_get(hwc) > 0)
3593 EHWSTRACE("No Render get", NULL, hwc);
3597 TRACE_DS_BEGIN(e_hwc_windows_commit);
3599 if (!_e_hwc_windows_changes_update(hwc))
3602 if (output->fake_config)
3604 _e_hwc_windows_offscreen_commit(hwc);
3608 if (!_e_hwc_windows_evaluate(hwc, display_mode))
3611 if (hwc->hwc_mode != E_HWC_MODE_FULL)
3613 if (!_e_hwc_windows_target_buffer_prepared(hwc))
3617 if ((output->dpms == E_OUTPUT_DPMS_OFF) || (output->set_dpms == E_OUTPUT_DPMS_OFF))
3619 _e_hwc_windows_offscreen_commit(hwc);
3623 if (!(wins_commit_data = _e_hwc_windows_commit_data_acquire(hwc)))
3626 EHWSTRACE("!!!!!!!! HWC Commit !!!!!!!!", NULL, hwc);
3627 _e_hwc_windows_update_fps(hwc);
3629 _e_hwc_windows_wait_commit_set(hwc, EINA_TRUE);
3631 _e_hwc_windows_commit_handler_timer_set(hwc, wins_commit_data, EINA_TRUE);
3632 hwc->wins_commit_data_list = eina_list_append(hwc->wins_commit_data_list, wins_commit_data);
3634 error = tdm_hwc_commit(hwc->thwc, 0, _e_hwc_windows_commit_handler, wins_commit_data);
3635 if (error != TDM_ERROR_NONE)
3637 EHWSERR("tdm_hwc_commit failed", hwc);
3638 _e_hwc_windows_commit_handler(hwc->thwc, 0, 0, 0, wins_commit_data);
3642 _e_hwc_windows_commit_interval_update(hwc, wins_commit_data);
3644 if (e_hwc_windows_fence_enabled_get(hwc))
3646 error = tdm_hwc_get_commit_fence(hwc->thwc, &commit_fence_fd);
3647 if (error == TDM_ERROR_NONE)
3649 if (hwc->commit_fence_fd >= 0)
3650 close(hwc->commit_fence_fd);
3652 hwc->commit_fence_fd = commit_fence_fd;
3653 _e_hwc_windows_release_fence_fd_update(hwc);
3656 EHWSERR("tdm_hwc_get_commit_sync_fence_fd failed", hwc);
3659 /* send tizen_hwc_commit feedback committed */
3660 e_comp_wl_tizen_hwc_committed();
3661 _e_hwc_windows_sync_callback_call(hwc);
3667 if (!hwc->re_evaluate)
3669 e_comp_wl_tizen_hwc_discarded();
3670 _e_hwc_windows_sync_callback_call(hwc);
3681 /* send tizen_hwc_commit feedback discarded */
3682 e_comp_wl_tizen_hwc_discarded();
3683 _e_hwc_windows_wait_commit_set(hwc, EINA_FALSE);
3690 e_hwc_windows_ecore_evas_set(E_Hwc *hwc, Ecore_Evas *ee)
3692 E_Hwc_Window_Target *target_hwc_window;
3696 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3698 if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
3701 target_hwc_window = hwc->root_target_hwc_window;
3702 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3704 name = ecore_evas_engine_name_get(ee);
3705 EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
3707 evas = ecore_evas_get(ee);
3708 EINA_SAFETY_ON_NULL_RETURN_VAL(evas, EINA_FALSE);
3710 if (!_e_hwc_windows_target_window_queue_set(target_hwc_window))
3712 EHWSERR("fail to _e_hwc_windows_target_window_queue_set", NULL);
3716 if(!strcmp("gl_drm_tbm", name) ||
3717 !strcmp("drm_tbm", name) ||
3718 !strcmp("gl_tbm", name) ||
3719 !strcmp("software_tbm", name) ||
3720 !strcmp("gl_tbm_ES", name))
3722 ecore_evas_manual_render_set(ee, 1);
3723 ecore_evas_show(ee);
3726 target_hwc_window->ee = ee;
3727 target_hwc_window->evas = evas;
3728 target_hwc_window->event_fd = eventfd(0, EFD_NONBLOCK);
3729 target_hwc_window->event_hdlr =
3730 ecore_main_fd_handler_add(target_hwc_window->event_fd, ECORE_FD_READ,
3731 _e_hwc_windows_target_window_render_finished_cb,
3732 (void *)target_hwc_window, NULL, NULL);
3734 evas_event_callback_add(evas,
3735 EVAS_CALLBACK_RENDER_FLUSH_POST,
3736 _e_hwc_windows_target_window_render_flush_post_cb,
3739 evas_event_callback_add(evas,
3740 EVAS_CALLBACK_RENDER_FLUSH_PRE,
3741 _e_hwc_windows_target_window_render_flush_pre_cb,
3744 evas_event_callback_add(evas,
3745 EVAS_CALLBACK_RENDER_PRE,
3746 _e_hwc_windows_target_window_render_pre_cb,
3749 ecore_evas_manual_render(target_hwc_window->ee);
3754 EINTERN E_Hwc_Window_Target *
3755 e_hwc_windows_target_window_new(E_Hwc *hwc, Eina_Bool is_root_target)
3757 E_Hwc_Window_Target *target_hwc_window;
3758 E_Hwc_Window *hwc_window;
3760 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
3761 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->thwc, NULL);
3763 if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
3766 target_hwc_window = E_OBJECT_ALLOC(E_Hwc_Window_Target, E_HWC_WINDOW_TYPE, _e_hwc_windows_target_window_free);
3767 EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, NULL);
3769 hwc_window = (E_Hwc_Window *)target_hwc_window;
3771 hwc_window->is_root_target = is_root_target;
3772 hwc_window->is_target = EINA_TRUE;
3773 hwc_window->state = E_HWC_WINDOW_STATE_DEVICE;
3774 hwc_window->accepted_state = E_HWC_WINDOW_STATE_DEVICE;
3775 hwc_window->hwc = hwc;
3777 e_presentation_time_container_init(&hwc_window->presentation_container);
3778 e_hwc_presentation_callback_list_init(&hwc_window->pending_presentation_callbacks);
3779 e_hwc_presentation_callback_list_init(&hwc_window->presentation_callbacks);
3781 target_hwc_window->hwc = hwc;
3782 target_hwc_window->event_fd = -1;
3784 hwc->hwc_windows = eina_list_append(hwc->hwc_windows, target_hwc_window);
3786 return target_hwc_window;
3790 e_hwc_windows_target_window_del(E_Hwc_Window_Target *target_hwc_window)
3794 EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
3796 hwc = target_hwc_window->hwc;
3797 EINA_SAFETY_ON_NULL_RETURN(hwc);
3799 hwc->hwc_windows = eina_list_remove(hwc->hwc_windows, hwc->target_hwc_window);
3800 e_object_del(E_OBJECT(hwc->target_hwc_window));
3804 e_hwc_windows_pp_commit_possible_check(E_Hwc *hwc)
3806 if (!hwc->pp_set) return EINA_FALSE;
3810 if (!tbm_surface_queue_can_dequeue(hwc->pp_tqueue, 0))
3818 _e_hwc_windows_pp_aligned_value_get(E_Hwc *hwc, int *aligned_width, int *aligned_height)
3820 if (hwc->pp_minw != -1)
3822 if (hwc->pp_minw > *aligned_width)
3823 *aligned_width = hwc->pp_minw;
3826 if (hwc->pp_minh != -1)
3828 if (hwc->pp_minh > *aligned_height)
3829 *aligned_height = hwc->pp_minh;
3832 if (hwc->pp_align != -1)
3833 *aligned_width = ROUNDUP(*aligned_width, hwc->pp_align);
3835 if (hwc->pp_align_vertical != -1)
3836 *aligned_height = ROUNDUP(*aligned_height, hwc->pp_align_vertical);
3840 e_hwc_windows_pp_set(E_Hwc *hwc, Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
3842 E_Hwc_Window_Target *root_target_hwc_window;
3843 E_Hwc_Window *hwc_window;
3844 E_Comp_Screen *e_comp_screen;
3845 tdm_error ret = TDM_ERROR_NONE;
3848 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3849 EINA_SAFETY_ON_NULL_RETURN_VAL(src_rect, EINA_FALSE);
3850 EINA_SAFETY_ON_NULL_RETURN_VAL(dst_rect, EINA_FALSE);
3852 e_comp_screen = e_comp->e_comp_screen;
3853 EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
3855 if ((hwc->pp_src_rect.x == src_rect->x) && (hwc->pp_src_rect.y == src_rect->y) &&
3856 (hwc->pp_src_rect.w == src_rect->w) && (hwc->pp_src_rect.h == src_rect->h) &&
3857 (hwc->pp_dst_rect.x == dst_rect->x) && (hwc->pp_dst_rect.y == dst_rect->y) &&
3858 (hwc->pp_dst_rect.w == dst_rect->w) && (hwc->pp_dst_rect.h == dst_rect->h))
3861 if (e_comp_screen_pp_support())
3865 hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
3866 EINA_SAFETY_ON_NULL_GOTO(hwc->tpp, fail);
3868 ret = tdm_pp_set_done_handler(hwc->tpp, _e_hwc_windows_pp_commit_handler, hwc);
3869 EINA_SAFETY_ON_FALSE_GOTO(ret == TDM_ERROR_NONE, fail);
3871 tdm_display_get_pp_available_size(e_comp_screen->tdisplay,
3872 &hwc->pp_minw, &hwc->pp_minh,
3873 &hwc->pp_maxw, &hwc->pp_maxh,
3875 tdm_display_get_pp_preferred_align_vertical(e_comp_screen->tdisplay, &hwc->pp_align_vertical);
3877 EHWSINF("PP Create tdm_pp:%p", NULL, hwc, hwc->tpp);
3881 if (!hwc->pp_tqueue)
3883 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
3884 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
3885 hwc_window = (E_Hwc_Window *)root_target_hwc_window;
3887 e_output_size_get(hwc->output, &w, &h);
3889 if (e_comp_screen_pp_support())
3890 _e_hwc_windows_pp_aligned_value_get(hwc, &w, &h);
3892 //TODO: Does e20 get the buffer flags from the tdm backend?
3893 hwc->pp_tqueue = tbm_surface_queue_create(3, w, h, hwc_window->queue->format, TBM_BO_SCANOUT);
3894 EINA_SAFETY_ON_NULL_GOTO(hwc->pp_tqueue, fail);
3896 hwc->pp_queue = e_hwc_window_queue_get(hwc->pp_tqueue);
3897 EINA_SAFETY_ON_NULL_GOTO(hwc->pp_queue, fail);
3899 EHWSINF("PP Create pp_tqueue:%p", NULL, hwc, hwc->pp_tqueue);
3902 _e_hwc_windows_target_window_pp_queue_set(hwc->target_hwc_window, hwc->pp_queue);
3903 e_hwc_windows_target_window_force_render(hwc->target_hwc_window);
3905 _e_hwc_windows_pp_rect_set(hwc, src_rect, dst_rect);
3907 hwc->pp_set = EINA_TRUE;
3914 tdm_pp_destroy(hwc->tpp);
3920 tbm_surface_queue_destroy(hwc->pp_tqueue);
3921 hwc->pp_tqueue = NULL;
3928 e_hwc_windows_pp_unset(E_Hwc *hwc)
3930 EINA_SAFETY_ON_NULL_RETURN(hwc);
3932 CLEAR(hwc->pp_src_rect);
3933 CLEAR(hwc->pp_dst_rect);
3935 hwc->pp_hwc_window = NULL;
3936 hwc->pp_set = EINA_FALSE;
3940 EHWSINF("PP Destroy pp_tqueue:%p", NULL, hwc, hwc->pp_tqueue);
3941 hwc->pp_queue = NULL;
3942 tbm_surface_queue_destroy(hwc->pp_tqueue);
3943 hwc->pp_tqueue = NULL;
3946 if (!hwc->pp_commit)
3950 EHWSINF("PP Destroy tdm_pp:%p", NULL, hwc, hwc->tpp);
3951 tdm_pp_destroy(hwc->tpp);
3955 e_hwc_window_queue_buffer_reference(&hwc->pp_update.queue_buffer_ref, NULL);
3956 e_comp_wl_buffer_reference(&hwc->pp_update.buffer_ref, NULL);
3957 e_hwc_window_buffer_set(&hwc->pp_update.buffer, NULL, NULL, 0);
3960 _e_hwc_windows_target_window_pp_queue_set(hwc->target_hwc_window, NULL);
3961 e_hwc_windows_target_window_force_render(hwc->target_hwc_window);
3965 e_hwc_windows_zoom_set(E_Hwc *hwc, Eina_Rectangle *rect)
3967 Eina_Rectangle dst_rect;
3969 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3970 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->output, EINA_FALSE);
3972 if (hwc->mirror_src_hwc)
3974 ERR("not support zoom in mirror mode");
3978 memcpy(&hwc->zoom_rect, rect, sizeof(Eina_Rectangle));
3982 dst_rect.w = hwc->output->config.geom.w;
3983 dst_rect.h = hwc->output->config.geom.h;
3985 if (!e_hwc_windows_pp_set(hwc, rect, &dst_rect))
3987 ERR("fail to e_hwc_windows_pp_set");
3991 hwc->zoom_enabled = EINA_TRUE;
3997 e_hwc_windows_zoom_unset(E_Hwc *hwc)
3999 EINA_SAFETY_ON_NULL_RETURN(hwc);
4001 CLEAR(hwc->zoom_rect);
4003 hwc->zoom_enabled = EINA_FALSE;
4005 if (hwc->mirror_src_hwc)
4007 ERR("not support zoom in mirror mode");
4011 e_hwc_windows_pp_unset(hwc);
4014 // add hwc_window to the render_list
4016 e_hwc_windows_rendered_window_add(E_Hwc_Window *hwc_window)
4019 E_Hwc_Window_Target *root_target_hwc_window;
4022 EINA_SAFETY_ON_NULL_RETURN(hwc_window);
4023 EINA_SAFETY_ON_NULL_RETURN(e_comp);
4024 EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
4026 if (hwc_window->on_rendered_target) return;
4028 ec = hwc_window->ec;
4029 EINA_SAFETY_ON_NULL_RETURN(ec);
4031 hwc = hwc_window->hwc;
4032 EINA_SAFETY_ON_NULL_RETURN(hwc);
4034 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
4035 EINA_SAFETY_ON_NULL_RETURN(root_target_hwc_window);
4037 root_target_hwc_window->rendered_windows =
4038 eina_list_append(root_target_hwc_window->rendered_windows, hwc_window);
4040 hwc_window->on_rendered_target = EINA_TRUE;
4042 e_hwc_window_ref(hwc_window);
4044 EHWSTRACE(" add ehw:%p ts:%p to the render_list - {%s}", ec, hwc, hwc_window,
4045 hwc_window->current.buffer.tsurface, e_hwc_window_name_get(hwc_window));
4049 e_hwc_windows_fps_get(E_Hwc *hwc, double *fps)
4051 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4053 if (hwc->old_fps == hwc->fps)
4059 hwc->old_fps = hwc->fps;
4067 e_hwc_windows_get_available_properties(E_Hwc *hwc, const tdm_prop **props, int *count)
4070 tdm_error ret = TDM_ERROR_OPERATION_FAILED;
4072 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4073 EINA_SAFETY_ON_NULL_RETURN_VAL(props, EINA_FALSE);
4074 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
4077 EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
4079 ret = tdm_hwc_get_available_properties(thwc, props, count);
4080 EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
4086 e_hwc_windows_get_video_available_properties(E_Hwc *hwc, const tdm_prop **props, int *count)
4089 tdm_error ret = TDM_ERROR_OPERATION_FAILED;
4091 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4092 EINA_SAFETY_ON_NULL_RETURN_VAL(props, EINA_FALSE);
4093 EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
4096 EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
4098 ret = tdm_hwc_get_video_available_properties(thwc, props, count);
4099 EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
4105 e_hwc_windows_trace_debug(Eina_Bool onoff)
4107 if (onoff == ehws_trace) return;
4109 e_hwc_window_trace_debug(onoff);
4110 e_hwc_window_queue_trace_debug(onoff);
4111 INF("EHWS: hwc trace_debug is %s", onoff?"ON":"OFF");
4115 e_hwc_windows_debug_dump_start(void)
4117 if (ehws_dump_enable) return;
4119 ehws_dump_enable = EINA_TRUE;
4123 e_hwc_windows_debug_dump_stop(void)
4125 if (!ehws_dump_enable) return;
4127 ehws_dump_enable = EINA_FALSE;
4131 _e_hwc_windows_window_debug_cb_sort(const void *d1, const void *d2)
4133 E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
4134 E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
4136 if (!hwc_window1) return(1);
4137 if (!hwc_window2) return(-1);
4139 return (hwc_window2->zpos - hwc_window1->zpos);
4143 _e_hwc_windows_window_debug_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4145 Eldbus_Message_Iter *line_array;
4146 E_Hwc_Window *hwc_window;
4147 E_Comp_Screen *e_comp_screen;
4150 Eina_List *l, *l2, *l3;
4152 char info_str[1024];
4155 Eina_Bool vis_skip = EINA_FALSE;
4156 E_Hwc_Window_Update_Data *update;
4159 e_comp_screen = e_comp->e_comp_screen;
4161 eldbus_message_iter_arguments_append(iter, "as", &line_array);
4164 eldbus_message_iter_basic_append(line_array,
4166 "e_comp_screen not initialized..");
4167 eldbus_message_iter_container_close(iter, line_array);
4171 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
4173 if (!output) continue;
4174 if (!output->config.enabled) continue;
4175 if (!output->tdm_hwc) continue;
4178 if (!output->hwc) continue;
4180 snprintf(info_str, sizeof(info_str),
4181 "HWC:%p mode:%d wait_commit:%d deactive:%d transition:%d norender:%d mirror_source:%d",
4182 hwc, hwc->hwc_mode, hwc->wait_commit, hwc->hwc_deactive, hwc->transition, hwc->norender,
4183 eina_list_count(hwc->mirror_dst_hwc) ? 1 : 0);
4184 eldbus_message_iter_basic_append(line_array, 's', info_str);
4186 eldbus_message_iter_basic_append(line_array, 's',
4187 "==========================================================================================="
4188 "===============================================================================================");
4189 eldbus_message_iter_basic_append(line_array, 's',
4190 " No Win_ID Hwc_win zpos ST AC_ST ACTI TRANSI tsurface src_size src_pos"
4191 " FMT dst_pos TRANSF DP_tsurface Queue wl_tbm_queue vis_skip restriction");
4192 eldbus_message_iter_basic_append(line_array, 's',
4193 "==========================================================================================="
4194 "===============================================================================================");
4196 hwc->hwc_windows = eina_list_sort(hwc->hwc_windows, eina_list_count(hwc->hwc_windows), _e_hwc_windows_window_debug_cb_sort);
4198 EINA_LIST_FOREACH(hwc->hwc_windows, l2, hwc_window)
4200 if (!hwc_window) continue;
4202 if ((cmd == E_HWC_WINS_DEBUG_CMD_VIS) && (hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE))
4204 else if ((cmd == E_HWC_WINS_DEBUG_CMD_DV) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_DEVICE))
4206 else if ((cmd == E_HWC_WINS_DEBUG_CMD_CL) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_CLIENT))
4208 else if ((cmd == E_HWC_WINS_DEBUG_CMD_CS) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_CURSOR))
4210 else if ((cmd == E_HWC_WINS_DEBUG_CMD_VD) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_VIDEO))
4212 else if ((cmd == E_HWC_WINS_DEBUG_CMD_NO) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_NONE))
4217 if ((hwc_window->ec->hwc_visible_skip) || (evas_object_data_get(hwc_window->ec->frame, "comp_skip")))
4218 vis_skip = EINA_TRUE;
4221 if (hwc_window->current.info.src_config.format)
4222 snprintf(fmt_str, sizeof(fmt_str), "%c%c%c%c", FOURCC_STR(hwc_window->current.info.src_config.format));
4224 snprintf(fmt_str, sizeof(fmt_str), " ");
4226 if (hwc_window->current.buffer.transform > TDM_TRANSFORM_270)
4231 snprintf(info_str, sizeof(info_str),
4232 "%3d 0x%08zx 0x%08zx %4d %s %s %s %s 0x%08zx %04dx%04d %04dx%04d+%04d+%04d"
4233 " %4s %04dx%04d+%04d+%04d %c%3d 0x%08zx 0x%08zx 0x%08zx %6s %s",
4235 e_client_util_win_get(hwc_window->ec),
4236 (uintptr_t)hwc_window,
4238 e_hwc_window_state_string_get(hwc_window->state),
4239 e_hwc_window_state_string_get(hwc_window->accepted_state),
4240 hwc_window->accepted_state ? "A" : "D",
4241 e_hwc_window_transition_string_get(hwc_window->transition),
4242 (uintptr_t)hwc_window->current.buffer.tsurface,
4243 hwc_window->current.info.src_config.size.h,
4244 hwc_window->current.info.src_config.size.v,
4245 hwc_window->current.info.src_config.pos.w,
4246 hwc_window->current.info.src_config.pos.h,
4247 hwc_window->current.info.src_config.pos.x,
4248 hwc_window->current.info.src_config.pos.y,
4250 hwc_window->current.info.dst_pos.w,
4251 hwc_window->current.info.dst_pos.h,
4252 hwc_window->current.info.dst_pos.x,
4253 hwc_window->current.info.dst_pos.y,
4255 (hwc_window->current.buffer.transform < 4) ? hwc_window->current.buffer.transform * 90 : (hwc_window->current.buffer.transform - 4) * 90,
4256 (uintptr_t)hwc_window->display.buffer.tsurface,
4257 (uintptr_t)hwc_window->queue,
4258 hwc_window->ec ? (uintptr_t)e_comp_wl_tbm_client_queue_get(hwc_window->ec) : 0,
4259 vis_skip ? "TRUE" : "FALSE",
4260 e_hwc_window_restriction_string_get(hwc_window));
4261 eldbus_message_iter_basic_append(line_array, 's', info_str);
4265 EINA_LIST_FOREACH(hwc_window->pending_update_list, l3, update)
4267 if (update->info.src_config.format)
4268 snprintf(fmt_str, sizeof(fmt_str), "%c%c%c%c", FOURCC_STR(update->info.src_config.format));
4270 snprintf(fmt_str, sizeof(fmt_str), " ");
4272 if (update->buffer.transform > TDM_TRANSFORM_270)
4277 snprintf(info_str, sizeof(info_str),
4278 " └─ [%2d] Pending Update_Data(0x%08zx) --------------"
4279 " 0x%08zx %04dx%04d %04dx%04d+%04d+%04d"
4280 " %4s %04dx%04d+%04d+%04d %c%3d",
4283 (uintptr_t)update->buffer.tsurface,
4284 update->info.src_config.size.h,
4285 update->info.src_config.size.v,
4286 update->info.src_config.pos.w,
4287 update->info.src_config.pos.h,
4288 update->info.src_config.pos.x,
4289 update->info.src_config.pos.y,
4291 update->info.dst_pos.w,
4292 update->info.dst_pos.h,
4293 update->info.dst_pos.x,
4294 update->info.dst_pos.y,
4296 (update->buffer.transform < 4) ? update->buffer.transform * 90 : (update->buffer.transform - 4) * 90);
4297 eldbus_message_iter_basic_append(line_array, 's', info_str);
4301 eldbus_message_iter_basic_append(line_array, 's',
4302 "==========================================================================================="
4303 "===============================================================================================");
4306 eldbus_message_iter_container_close(iter, line_array);
4310 _e_hwc_windows_window_debug_commit_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4312 Eldbus_Message_Iter *line_array;
4313 E_Comp_Screen *e_comp_screen;
4319 char info_str[1024];
4320 E_Hwc_Windows_Commit_Data *wins_commit_data;
4321 E_Hwc_Window_Commit_Data *commit_data;
4323 e_comp_screen = e_comp->e_comp_screen;
4325 eldbus_message_iter_arguments_append(iter, "as", &line_array);
4328 eldbus_message_iter_basic_append(line_array,
4330 "e_comp_screen not initialized..");
4331 eldbus_message_iter_container_close(iter, line_array);
4335 EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
4337 if (!output) continue;
4338 if (!output->config.enabled) continue;
4339 if (!output->tdm_hwc) continue;
4342 if (!output->hwc) continue;
4344 snprintf(info_str, sizeof(info_str),
4345 "HWC:%p mode:%d wait_commit:%d deactive:%d transition:%d norender:%d mirror_source:%d",
4346 hwc, hwc->hwc_mode, hwc->wait_commit, hwc->hwc_deactive, hwc->transition, hwc->norender,
4347 eina_list_count(hwc->mirror_dst_hwc) ? 1 : 0);
4348 eldbus_message_iter_basic_append(line_array, 's', info_str);
4350 eldbus_message_iter_basic_append(line_array, 's',
4351 "==========================================================================================="
4352 "=====================");
4353 EINA_LIST_FOREACH(hwc->wins_commit_data_list, l, wins_commit_data)
4355 snprintf(info_str, sizeof(info_str),
4356 "[%2d] Wins_Commit_Data(%p) target_commit_data(%p) commit_data_list(%p)",
4357 ++idx, wins_commit_data, wins_commit_data->target_commit_data, wins_commit_data->commit_data_list);
4358 eldbus_message_iter_basic_append(line_array, 's', info_str);
4362 if (wins_commit_data->target_commit_data)
4364 snprintf(info_str, sizeof(info_str),
4365 " └─ [%2d] Commit_Data(%p) hwc_window(%p):target tsurface(%p) queue(%p)",
4366 ++commit_idx, wins_commit_data->target_commit_data,
4367 wins_commit_data->target_commit_data->hwc_window,
4368 wins_commit_data->target_commit_data->buffer.tsurface,
4369 wins_commit_data->target_commit_data->buffer.queue);
4370 eldbus_message_iter_basic_append(line_array, 's', info_str);
4373 EINA_LIST_FOREACH(wins_commit_data->commit_data_list, l2, commit_data)
4375 snprintf(info_str, sizeof(info_str),
4376 " └─ [%2d] Commit_Data(%p) hwc_window(%p):win(0x%zx) tsurface(%p) queue(%p)",
4377 ++commit_idx, commit_data, commit_data->hwc_window,
4378 e_client_util_win_get(commit_data->hwc_window->ec),
4379 commit_data->buffer.tsurface, commit_data->buffer.queue);
4380 eldbus_message_iter_basic_append(line_array, 's', info_str);
4384 eldbus_message_iter_basic_append(line_array, 's',
4385 "==========================================================================================="
4386 "=====================");
4389 eldbus_message_iter_container_close(iter, line_array);
4393 e_hwc_windows_debug_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4395 if (cmd == E_HWC_WINS_DEBUG_CMD_QUEUE)
4396 e_hwc_window_queue_debug_info_get(iter);
4397 else if (cmd >= E_HWC_WINS_DEBUG_CMD_VIS && cmd <= E_HWC_WINS_DEBUG_CMD_NO)
4398 _e_hwc_windows_window_debug_info_get(iter, cmd);
4399 else if (cmd == E_HWC_WINS_DEBUG_CMD_COMMIT)
4400 _e_hwc_windows_window_debug_commit_info_get(iter, cmd);
4404 e_hwc_windows_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc)
4406 Eina_Rectangle src_rect, dst_rect;
4408 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4409 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->output, EINA_FALSE);
4410 EINA_SAFETY_ON_NULL_RETURN_VAL(src_hwc, EINA_FALSE);
4411 EINA_SAFETY_ON_NULL_RETURN_VAL(src_hwc->output, EINA_FALSE);
4413 if (hwc->zoom_enabled)
4415 ERR("not support mirror in zoom mode");
4419 src_rect.x = src_hwc->output->config.geom.x;
4420 src_rect.y = src_hwc->output->config.geom.y;
4421 src_rect.w = src_hwc->output->config.geom.w;
4422 src_rect.h = src_hwc->output->config.geom.h;
4424 if (!_e_hwc_windows_capture_position_get(src_hwc,
4425 hwc->output->config.geom.w,
4426 hwc->output->config.geom.w,
4429 ERR("fail to _e_hwc_windows_capture_position_get");
4433 if (!e_hwc_windows_pp_set(hwc, &src_rect, &dst_rect))
4435 EHWSERR("e_hwc_windows_pp_set failed", hwc);
4439 /* add mirror_src to the hwc*/
4440 hwc->mirror_src_hwc = src_hwc;
4442 /* add mirror_dst list to the src_hwc */
4443 src_hwc->mirror_dst_hwc = eina_list_append(src_hwc->mirror_dst_hwc, hwc);
4445 EHWSINF("e_hwc_windows_mirror_set src_hwc:%p", NULL, hwc, src_hwc);
4451 e_hwc_windows_mirror_unset(E_Hwc *hwc)
4455 EINA_SAFETY_ON_NULL_RETURN(hwc);
4457 src_hwc = hwc->mirror_src_hwc;
4458 EINA_SAFETY_ON_NULL_RETURN(src_hwc);
4461 /* remove mirror_src at the hwc */
4462 hwc->mirror_src_hwc = NULL;
4464 /* remove mirror_dst list at the src_hwc */
4465 src_hwc->mirror_dst_hwc = eina_list_remove(src_hwc->mirror_dst_hwc, hwc);
4467 if (hwc->zoom_enabled)
4469 ERR("not support mirror in zoom mode");
4473 e_hwc_windows_pp_unset(hwc);
4475 EHWSINF("e_hwc_windows_mirror_unset", NULL, hwc);
4479 e_hwc_windows_present_sync(E_Hwc *hwc)
4481 E_Hwc_Window_Target *root_target_hwc_window;
4482 E_Hwc_Windows_Comp_Info *comp_info;
4483 tbm_surface_h tsurface;
4486 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4487 EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc->hwc_policy == E_HWC_POLICY_WINDOWS, EINA_FALSE);
4489 root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
4490 EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
4492 hwc->present_sync = EINA_TRUE;
4494 EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, tsurface)
4496 comp_info = _e_hwc_windows_comp_info_get(tsurface);
4497 if (!comp_info) continue;
4499 comp_info->skip = EINA_TRUE;
4502 _e_hwc_windows_target_window_queue_clear(root_target_hwc_window);
4504 _e_hwc_windows_target_window_buffer_skip(hwc);
4506 EHWSINF("Present sync", NULL, hwc);
4512 e_hwc_windows_client_type_override(E_Hwc *hwc)
4514 E_Hwc_Window *hwc_window;
4517 EINA_SAFETY_ON_NULL_RETURN(hwc);
4519 EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
4521 if (hwc_window->is_target) continue;
4523 e_hwc_window_client_type_override(hwc_window);
4526 _e_hwc_windows_target_state_set(hwc->target_hwc_window, E_HWC_WINDOW_STATE_DEVICE);
4530 e_hwc_windows_fence_enabled_get(E_Hwc *hwc)
4532 EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4534 if (!hwc->tdm_hwc_fence) return EINA_FALSE;
4535 if (!e_egl_sync_enabled_get()) return EINA_FALSE;
4536 if (!e_explicit_sync_enabled_get()) return EINA_FALSE;
4542 e_hwc_windows_presentation_time_feedback_and_callback_take(E_Hwc *hwc, tbm_surface_h tsurface)
4544 E_Hwc_Windows_Comp_Info *comp_info;
4545 E_Hwc_Window_Target *target_hwc_window;
4547 EINA_SAFETY_ON_NULL_RETURN(hwc);
4548 EINA_SAFETY_ON_NULL_RETURN(tsurface);
4550 target_hwc_window = hwc->target_hwc_window;
4551 EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
4553 comp_info = _e_hwc_windows_comp_info_get(tsurface);
4556 e_hwc_window_presentation_time_feedback_take((E_Hwc_Window *)target_hwc_window,
4557 &comp_info->presentation_container);
4558 e_hwc_window_presentation_callback_take((E_Hwc_Window *)target_hwc_window,
4559 &comp_info->presentation_callbacks);