45d972192ca6b2a39d244cf127a975f99759b00f
[platform/upstream/enlightenment.git] / src / bin / e_hwc_windows.c
1 #include "e.h"
2 #include "e_comp_screen_intern.h"
3 #include "services/e_service_quickpanel.h"
4
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>
9 # include <pixman.h>
10 # include <EGL/egl.h>
11
12 #define E_HWC_WINDOW_COMMIT_HANDLER_LOG_TIMEOUT 5.0
13
14 #define DBG_EVALUATE 1
15 #define DEFAULT_MAX_TRANSITION_FAILURES 3;
16
17 #ifndef CLEAR
18 #define CLEAR(x) memset(&(x), 0, sizeof (x))
19 #endif
20
21 #define EHWSERR(f, hwc, x...)                                 \
22    do                                                         \
23      {                                                        \
24         ELOGFE("HWC-WINS", "%2d|"f,                           \
25                NULL, (e_hwc_output_index_get(hwc)), ##x);     \
26      }                                                        \
27    while (0)
28
29 #define EHWSINF(f, ec, hwc, x...)                             \
30    do                                                         \
31      {                                                        \
32           ELOGF("HWC-WINS", "%2d|"f,                          \
33                 (ec), (e_hwc_output_index_get(hwc)), ##x);    \
34      }                                                        \
35    while (0)
36
37 #define EHWSTRACE(f, ec, hwc, x...)                           \
38    do                                                         \
39      {                                                        \
40         if (ehws_trace)                                       \
41           {                                                   \
42              ELOGF("HWC-WINS", "%2d|"f,                       \
43                    (ec), (e_hwc_output_index_get(hwc)), ##x); \
44           }                                                   \
45      }                                                        \
46    while (0)
47
48 #define ROUNDUP(s,c)        (((s) + (c-1)) & ~(c-1))
49
50 typedef struct _E_Hwc_Windows_Comp_Info E_Hwc_Windows_Comp_Info;
51
52 struct _E_Hwc_Windows_Comp_Info
53 {
54    E_Presentation_Time_Container presentation_container;
55    E_Hwc_Presentation_Callback_List presentation_callbacks;
56    Eina_Bool skip;
57    E_Egl_Sync *release_fence;
58    Eina_List *pending_update_list;
59
60    E_Comp_Wl_Tizen_Hwc_Feedback_List feedback_list;
61
62    Eina_List *rendered_windows;
63    Eina_List *rendered_buffers;
64 };
65
66 static Eina_Bool ehws_trace = EINA_FALSE;
67 static Eina_Bool ehws_dump_enable = EINA_FALSE;
68
69 static int E_EVENT_HWC_WINDOWS_COMP_INFO_FREE = -1;
70
71 static uint64_t ehws_comp_buffer_info_key;
72 #define EHWS_BUFFER_COMP_INFO_KEY  (unsigned long)(&ehws_comp_buffer_info_key)
73
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);
78
79 static E_Comp_Wl_Buffer *
80 _e_hwc_windows_comp_wl_buffer_get(E_Hwc_Window *hwc_window)
81 {
82    E_Client *ec = hwc_window->ec;
83    E_Comp_Wl_Client_Data *cdata;
84
85    if (!ec) return NULL;
86
87    cdata = e_client_cdata_get(ec);
88    if (!cdata) return NULL;
89
90    return cdata->buffer_ref.buffer;
91 }
92
93 static void
94 _e_hwc_windows_update_fps(E_Hwc *hwc)
95 {
96    if (e_comp->calc_fps)
97      {
98         double dt;
99         double tim = ecore_time_get();
100
101         dt = tim - hwc->frametimes[0];
102         hwc->frametimes[0] = tim;
103
104         hwc->time += dt;
105         hwc->cframes++;
106
107         if (hwc->lapse == 0.0)
108           {
109              hwc->lapse = tim;
110              hwc->flapse = hwc->cframes;
111           }
112         else if ((tim - hwc->lapse) >= 0.5)
113           {
114              hwc->fps = (hwc->cframes - hwc->flapse) / (tim - hwc->lapse);
115              hwc->lapse = tim;
116              hwc->flapse = hwc->cframes;
117              hwc->time = 0.0;
118           }
119      }
120 }
121
122 static E_Hwc_Window_Target *
123 _e_hwc_windows_root_target_hwc_window_get(E_Hwc *hwc)
124 {
125    E_Output *primary_output;
126
127    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
128
129    if (hwc->root_target_hwc_window)
130      {
131         return hwc->root_target_hwc_window;
132      }
133    else
134      {
135         EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
136         EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp->e_comp_screen, NULL);
137
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);
141
142         return primary_output->hwc->root_target_hwc_window;
143      }
144 }
145
146 static E_Hwc_Mode
147 _e_hwc_windows_hwc_mode_update(E_Hwc *hwc, int num_client, int num_device, int num_cursor, int num_video)
148 {
149    E_Hwc_Mode hwc_mode = E_HWC_MODE_NONE;
150    int num_visible = hwc->num_visible_windows;
151
152    /* check ui windows */
153    if (!num_visible)
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;
159    else
160      hwc_mode = E_HWC_MODE_HYBRID;
161
162    /* check video and cursor windows */
163    if ((num_video) || (num_cursor))
164      {
165         if (hwc_mode == E_HWC_MODE_NONE)
166           hwc_mode = E_HWC_MODE_HYBRID;
167      }
168
169    if (hwc->hwc_mode != hwc_mode)
170      {
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);
173         else
174           ecore_event_add(E_EVENT_COMPOSITOR_DISABLE, NULL, NULL, NULL);
175
176         hwc->hwc_mode  = hwc_mode;
177      }
178
179    return hwc_mode;
180 }
181
182 static void
183 _e_hwc_windows_comp_info_rendered_buffers_set(E_Hwc_Windows_Comp_Info *comp_info,
184                                               Eina_List *rendered_buffers)
185 {
186    E_Comp_Wl_Buffer_Ref *buffer_ref;
187
188    EINA_SAFETY_ON_NULL_RETURN(comp_info);
189
190    if (comp_info->rendered_buffers == rendered_buffers)
191      return;
192
193    if (comp_info->rendered_buffers)
194      {
195         if (eina_list_count(comp_info->rendered_buffers))
196           {
197              EINA_LIST_FREE(comp_info->rendered_buffers, buffer_ref)
198                {
199                   e_comp_wl_buffer_reference(buffer_ref, NULL);
200                   E_FREE(buffer_ref);
201                }
202           }
203      }
204
205    comp_info->rendered_buffers = rendered_buffers;
206 }
207
208 static void
209 _e_hwc_windows_comp_info_rendered_windows_set(E_Hwc_Windows_Comp_Info *comp_info,
210                                               Eina_List *rendered_windows)
211 {
212    E_Hwc_Window *hwc_window;
213
214    EINA_SAFETY_ON_NULL_RETURN(comp_info);
215
216    if (comp_info->rendered_windows == rendered_windows)
217      return;
218
219    if (comp_info->rendered_windows)
220      {
221         if (eina_list_count(comp_info->rendered_windows))
222           {
223              EINA_LIST_FREE(comp_info->rendered_windows, hwc_window)
224                e_hwc_window_unref(hwc_window);
225           }
226      }
227
228    comp_info->rendered_windows = rendered_windows;
229 }
230
231 static void
232 _e_hwc_windows_comp_info_free(void *data EINA_UNUSED, void *event)
233 {
234    E_Hwc_Windows_Comp_Info *comp_info;
235    E_Hwc_Window_Update_Data *update;
236
237    comp_info = (E_Hwc_Windows_Comp_Info *)event;
238    if (!comp_info) return;
239
240    EINA_LIST_FREE(comp_info->pending_update_list, update)
241      e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update);
242
243    _e_hwc_windows_comp_info_rendered_windows_set(comp_info, NULL);
244    _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
245
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);
249
250    E_FREE(comp_info);
251 }
252
253 static void
254 _e_hwc_windows_comp_info_cb_tbm_surface_destroy(void *data)
255 {
256    E_Hwc_Windows_Comp_Info *comp_info;
257
258    comp_info = (E_Hwc_Windows_Comp_Info *)data;
259    if (!comp_info) return;
260
261    ecore_event_add(E_EVENT_HWC_WINDOWS_COMP_INFO_FREE, comp_info,
262                    _e_hwc_windows_comp_info_free, NULL);
263 }
264
265 static E_Hwc_Windows_Comp_Info *
266 _e_hwc_windows_comp_info_get(tbm_surface_h tbm_surface)
267 {
268    E_Hwc_Windows_Comp_Info *comp_info = NULL;
269
270    if (!tbm_surface) return NULL;
271
272    tbm_surface_internal_get_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
273                                       (void**)&comp_info);
274
275    if (comp_info) return comp_info;
276
277    comp_info = E_NEW(E_Hwc_Windows_Comp_Info, 1);
278    EINA_SAFETY_ON_FALSE_RETURN_VAL(comp_info, NULL);
279
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);
283
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))
286      goto fail;
287
288    if (!tbm_surface_internal_set_user_data(tbm_surface, EHWS_BUFFER_COMP_INFO_KEY,
289                                            comp_info))
290      goto fail;
291
292    return comp_info;
293
294 fail:
295    if (comp_info)
296      free(comp_info);
297
298    return NULL;
299 }
300
301 static void
302 _e_hwc_windows_presentation_feedback_take(E_Hwc_Window *hwc_window)
303 {
304    E_Presentation_Time_Container *container;
305
306    if (hwc_window->is_target)
307      {
308         E_Hwc_Windows_Comp_Info *comp_info;
309
310         if (!hwc_window->current.buffer.tsurface) return;
311
312         comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
313         if (!comp_info) return;
314
315         container = &comp_info->presentation_container;
316      }
317    else
318      {
319         E_Client *ec;
320         E_Comp_Wl_Client_Data *cdata;
321
322         ec = hwc_window->ec;
323         if (!ec) return;
324         cdata = e_client_cdata_get(ec);
325         if (!cdata) return;
326
327         container = &cdata->presentation_container;
328      }
329
330    if (!container) return;
331
332    e_hwc_window_presentation_time_feedback_take(hwc_window, container);
333 }
334
335 static void
336 _e_hwc_windows_presentation_callback_take(E_Hwc_Window *hwc_window)
337 {
338    E_Hwc_Presentation_Callback_List *list;
339
340    if (hwc_window->is_target)
341      {
342         E_Hwc_Windows_Comp_Info *comp_info;
343
344         if (!hwc_window->current.buffer.tsurface) return;
345
346         comp_info = _e_hwc_windows_comp_info_get(hwc_window->current.buffer.tsurface);
347         if (!comp_info) return;
348
349         list = &comp_info->presentation_callbacks;
350      }
351    else
352      {
353         list = &hwc_window->pending_presentation_callbacks;
354      }
355
356    if (!list) return;
357
358    e_hwc_window_presentation_callback_take(hwc_window, list);
359 }
360
361 static void
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)
364 {
365    const Eina_List *l, *ll;
366    E_Hwc_Window *hwc_window;
367    E_Hwc_Window_Commit_Data *commit_data;
368
369    if (!eina_list_data_find(hwc->wins_commit_data_list, wins_commit_data))
370      {
371         EHWSERR("failed to find wins_commit_data:%p in wins_commit_data_list",
372                 hwc, wins_commit_data);
373         return;
374      }
375
376    if (wins_commit_data->target_commit_data)
377      {
378         hwc_window = wins_commit_data->target_commit_data->hwc_window;
379         e_hwc_window_presentation_time_feedback_present(hwc_window,
380                                                         sequence,
381                                                         tv_sec,
382                                                         tv_usec);
383         e_hwc_window_presentation_callback_call(hwc_window);
384
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.
388          */
389         e_hwc_window_commit_data_release(hwc_window, wins_commit_data->target_commit_data);
390      }
391
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)
394      {
395         hwc_window = commit_data->hwc_window;
396         if (hwc_window->is_target) continue;
397
398         e_hwc_window_presentation_time_feedback_present(hwc_window, sequence, tv_sec, tv_usec);
399         e_hwc_window_presentation_callback_call(hwc_window);
400
401         if (e_hwc_window_is_video(hwc_window) && hwc_window->ec)
402           {
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);
406           }
407
408         if (!e_hwc_window_commit_data_release(hwc_window, commit_data)) continue;
409      }
410
411     wins_commit_data->commit_data_list = eina_list_free(wins_commit_data->commit_data_list);
412
413     hwc->wins_commit_data_list = eina_list_remove(hwc->wins_commit_data_list, wins_commit_data);
414
415     _e_hwc_windows_commit_handler_timer_set(hwc, wins_commit_data, EINA_FALSE);
416     free(wins_commit_data);
417 }
418
419 static void
420 _e_hwc_windows_commit_handler(tdm_hwc *thwc, unsigned int sequence,
421                                   unsigned int tv_sec, unsigned int tv_usec,
422                                   void *user_data)
423 {
424    E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)user_data;
425    E_Hwc *hwc;
426
427    EINA_SAFETY_ON_NULL_RETURN(wins_commit_data);
428
429    hwc = wins_commit_data->hwc;
430    EINA_SAFETY_ON_NULL_RETURN(hwc);
431
432    if (wins_commit_data->commit_handler_log_timeout_set)
433      {
434         EHWSERR("Timeout commit handler is called wins_commit_data:%p",
435                 hwc, wins_commit_data);
436      }
437
438    EHWSTRACE("!!!!!!!! HWC Commit Handler !!!!!!!!", NULL, hwc);
439    TRACE_DS_MARK(_e_hwc_windows_commit_handler);
440
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);
445
446    _e_hwc_windows_commit_data_release(hwc, wins_commit_data, sequence, tv_sec, tv_usec);
447 }
448
449 static Eina_Bool
450 _e_hwc_windows_commit_handler_timeout(void *data)
451 {
452    E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)data;
453
454    if (!wins_commit_data) return ECORE_CALLBACK_CANCEL;
455
456    EHWSERR("Timeout wait commit wins_commit_data:%p",
457            wins_commit_data->hwc, wins_commit_data);
458
459    wins_commit_data->commit_handler_timer = NULL;
460
461    _e_hwc_windows_commit_handler(wins_commit_data->hwc->thwc, 0, 0, 0, wins_commit_data);
462
463    return ECORE_CALLBACK_CANCEL;
464 }
465
466 static Eina_Bool
467 _e_hwc_windows_commit_handler_log_timeout(void *data)
468 {
469    E_Hwc_Windows_Commit_Data *wins_commit_data = (E_Hwc_Windows_Commit_Data *)data;
470
471    if (!wins_commit_data) return ECORE_CALLBACK_CANCEL;
472
473    EHWSERR("Timeout wait commit wins_commit_data:%p",
474            wins_commit_data->hwc, wins_commit_data);
475
476    wins_commit_data->commit_handler_timer = NULL;
477    wins_commit_data->commit_handler_log_timeout_set = EINA_TRUE;
478
479    return ECORE_CALLBACK_CANCEL;
480 }
481
482 static void
483 _e_hwc_windows_commit_handler_timer_set(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data, Eina_Bool set)
484 {
485    if (wins_commit_data->commit_handler_timer)
486      {
487         ecore_timer_del(wins_commit_data->commit_handler_timer);
488         wins_commit_data->commit_handler_timer = NULL;
489      }
490
491    if (set)
492      {
493         if (e_comp->commit_handler_timer.use)
494           {
495              wins_commit_data->commit_handler_timer = ecore_timer_add(e_comp->commit_handler_timer.interval,
496                                                                       _e_hwc_windows_commit_handler_timeout,
497                                                                       wins_commit_data);
498           }
499         else
500           {
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,
503                                                                       wins_commit_data);
504              wins_commit_data->commit_handler_log_timeout_set = EINA_FALSE;
505           }
506      }
507 }
508
509 static E_Hwc_Windows_Commit_Data *
510 _e_hwc_windows_commit_data_acquire(E_Hwc *hwc)
511 {
512    const Eina_List *l;
513    E_Hwc_Window *hwc_window;
514    E_Hwc_Window_Commit_Data *commit_data;
515    E_Hwc_Windows_Commit_Data *wins_commit_data;
516
517    wins_commit_data = E_NEW(E_Hwc_Windows_Commit_Data, 1);
518    EINA_SAFETY_ON_NULL_RETURN_VAL(wins_commit_data, NULL);
519
520    wins_commit_data->hwc = hwc;
521
522    /* return TRUE when the number of the commit data is more than one */
523    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
524      {
525         if (hwc_window->is_root_target) continue;
526
527         commit_data = e_hwc_window_commit_data_acquire(hwc_window);
528         if (!commit_data)
529           {
530              if ((hwc->hwc_mode == E_HWC_MODE_FULL) &&
531                  (!e_hwc_window_is_on_hw_overlay(hwc_window)))
532                {
533                   _e_hwc_windows_presentation_callback_take(hwc_window);
534                   e_hwc_window_presentation_callback_call(hwc_window);
535                }
536
537              continue;
538           }
539
540         _e_hwc_windows_presentation_feedback_take(hwc_window);
541         _e_hwc_windows_presentation_callback_take(hwc_window);
542
543         if (ehws_dump_enable)
544           e_hwc_window_commit_data_buffer_dump(hwc_window, commit_data);
545
546         /* send frame event enlightenment doesn't send frame event in nocomp */
547         if (hwc_window->ec)
548           e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
549
550         if (hwc_window->is_target)
551           wins_commit_data->target_commit_data = commit_data;
552         else
553           wins_commit_data->commit_data_list = eina_list_append(wins_commit_data->commit_data_list,
554                                                                 commit_data);
555      }
556
557    if ((!wins_commit_data->commit_data_list) && (!wins_commit_data->target_commit_data))
558      {
559         free(wins_commit_data);
560         return NULL;
561      }
562
563    return wins_commit_data;
564 }
565
566 static void
567 _e_hwc_windows_offscreen_commit(E_Hwc *hwc)
568 {
569    E_Hwc_Window *hwc_window;
570    E_Hwc_Window *hwc_window_target;
571    Eina_List *l, *ll;
572    E_Hwc_Window_Commit_Data *commit_data;
573
574    hwc_window_target = (E_Hwc_Window *)hwc->target_hwc_window;
575    if (hwc_window_target)
576      {
577         commit_data = e_hwc_window_commit_data_acquire(hwc_window_target);
578         if (commit_data)
579           {
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);
584
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.
588               */
589              EHWSTRACE("!!!!!!!! HWC OffScreen Commit !!!!!!!!", NULL, hwc);
590              e_hwc_window_commit_data_release(hwc_window_target, commit_data);
591           }
592      }
593
594    EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
595      {
596         commit_data = NULL;
597
598         if (hwc_window->is_target) continue;
599
600         commit_data = e_hwc_window_commit_data_acquire(hwc_window);
601         if (!commit_data)
602           {
603              if ((hwc->hwc_mode == E_HWC_MODE_FULL) &&
604                  (!e_hwc_window_is_on_hw_overlay(hwc_window)))
605                {
606                   _e_hwc_windows_presentation_callback_take(hwc_window);
607                   e_hwc_window_presentation_callback_call(hwc_window);
608                }
609
610              continue;
611           }
612
613         EHWSTRACE("!!!!!!!! HWC OffScreen Commit !!!!!!!!", NULL, hwc);
614
615         /* send frame event enlightenment doesn't send frame event in nocomp */
616         if (hwc_window->ec)
617           e_pixmap_image_clear(hwc_window->ec->pixmap, 1);
618
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);
623
624         e_hwc_window_commit_data_release(hwc_window, commit_data);
625      }
626 }
627
628 static Eina_List *
629 _e_hwc_windows_target_window_rendered_windows_get(tbm_surface_h target_tsurface)
630 {
631    E_Hwc_Windows_Comp_Info *comp_info;
632
633    if (!target_tsurface) return NULL;
634
635    comp_info = _e_hwc_windows_comp_info_get(target_tsurface);
636    if (!comp_info) return NULL;
637
638    return comp_info->rendered_windows;
639 }
640
641 EINTERN void
642 e_hwc_windows_target_window_force_render(E_Hwc_Window_Target *target_hwc_window)
643 {
644    E_Hwc_Window_Target *root_target_hwc_window;
645    E_Hwc *hwc;
646    int w, h;
647
648    hwc = target_hwc_window->hwc;
649    EINA_SAFETY_ON_NULL_RETURN(hwc);
650
651    root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
652    EINA_SAFETY_ON_NULL_RETURN(root_target_hwc_window);
653
654    if (!root_target_hwc_window->ee) return;
655    if (!root_target_hwc_window->evas) return;
656
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);
659 }
660
661 static Eina_Bool
662 _e_hwc_windows_target_window_buffer_skip(E_Hwc *hwc)
663 {
664    E_Hwc_Window_Target *target_hwc_window;
665    E_Hwc_Window *hwc_window;
666    tdm_hwc *thwc;
667    tdm_region fb_damage;
668
669    target_hwc_window = hwc->target_hwc_window;
670    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
671
672    hwc_window = (E_Hwc_Window *)target_hwc_window;
673
674    thwc = hwc->thwc;
675    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
676
677    CLEAR(fb_damage);
678
679    if ((hwc_window->current.buffer.tsurface) &&
680        (hwc_window->current.buffer.tsurface != hwc_window->display.buffer.tsurface))
681      {
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);
686
687         e_hwc_windows_target_window_force_render(target_hwc_window);
688      }
689
690    if (hwc->root_target_hwc_window)
691      {
692         hwc_window = (E_Hwc_Window *)hwc->root_target_hwc_window;
693
694         if (hwc_window->current.buffer.tsurface)
695           e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, hwc_window->current.buffer.tsurface);
696
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);
700      }
701
702    return EINA_TRUE;
703 }
704
705 static void
706 _e_hwc_windows_target_window_queue_clear(E_Hwc_Window_Target *target_hwc_window)
707 {
708    E_Hwc_Window *hwc_window;
709    E_Hwc_Window_Queue_Buffer *queue_buffer;
710
711    hwc_window = (E_Hwc_Window *)target_hwc_window;
712
713    while ((queue_buffer = e_hwc_window_queue_buffer_acquire(hwc_window->queue)))
714      {
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);
717      }
718 }
719
720 static Eina_Bool
721 _e_hwc_windows_root_target_buffer_fetch(E_Hwc *hwc)
722 {
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;
730    uint32_t n_thw = 0;
731    const Eina_List *l;
732    int i;
733
734    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
735
736    target_hwc_window = hwc->root_target_hwc_window;
737    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
738
739    hwc_window = (E_Hwc_Window *)target_hwc_window;
740
741    if (!hwc_window->queue)
742      {
743         if (!_e_hwc_windows_target_window_queue_set(target_hwc_window))
744           {
745              EHWSERR("fail to _e_hwc_windows_target_window_queue_set", NULL);
746              return EINA_FALSE;
747           }
748      }
749
750    queue = hwc_window->queue;
751    EINA_SAFETY_ON_NULL_RETURN_VAL(queue, EINA_FALSE);
752
753    if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
754      {
755         /* acquire the surface */
756         queue_buffer = e_hwc_window_queue_buffer_acquire(queue);
757         if (!queue_buffer) return EINA_FALSE;
758
759         tsurface = queue_buffer->tsurface;
760         EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
761
762         comp_info = _e_hwc_windows_comp_info_get(tsurface);
763         if ((comp_info) && (comp_info->skip))
764           {
765              e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, tsurface);
766              e_hwc_window_queue_buffer_release(queue, queue_buffer);
767              return EINA_FALSE;
768           }
769
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);
773
774         if (ehws_trace)
775           {
776              rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(hwc_window->current.buffer.tsurface);
777              n_thw = eina_list_count(rendered_windows);
778              if (n_thw)
779                {
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));
783
784                   i = 0;
785                   EINA_LIST_FOREACH(rendered_windows, l, hw)
786                     {
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"));
791                     }
792                 }
793               else
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));
797           }
798      }
799    else
800      {
801         _e_hwc_windows_target_window_queue_clear(target_hwc_window);
802
803         if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
804
805         if (!e_hwc_window_display_or_commit_buffer_check(hwc_window, hwc_window->current.buffer.tsurface))
806           {
807              queue_buffer = e_hwc_window_queue_buffer_find(hwc_window->current.buffer.queue, hwc_window->current.buffer.tsurface);
808              if (queue_buffer)
809                e_hwc_windows_presentation_time_feedback_and_callback_take(hwc, hwc_window->current.buffer.tsurface);
810           }
811
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);
815
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));
819      }
820
821    return EINA_TRUE;
822 }
823
824 static Eina_Bool
825 _e_hwc_windows_target_buffer_fetch(E_Hwc *hwc)
826 {
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;
832    tdm_hwc *thwc;
833
834    thwc = hwc->thwc;
835    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
836
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;
840
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;
844
845    if (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE)
846      {
847         if (target_hwc_window->pp_queue)
848           queue_buffer = e_hwc_window_queue_buffer_acquire(target_hwc_window->pp_queue);
849         else
850           queue_buffer = root_hwc_window->current.queue_buffer_ref.buffer;
851
852         if (!queue_buffer) return EINA_FALSE;
853
854         tsurface = queue_buffer->tsurface;
855         EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
856
857         if (tsurface == hwc_window->current.buffer.tsurface) return EINA_FALSE;
858
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);
862
863         /* the damage isn't supported by hwc extension yet */
864         CLEAR(fb_damage);
865
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)))
868           {
869              int fence = e_egl_sync_fence_fd_dup(root_target_hwc_window->end_render_sync);
870              if (fence >= 0)
871                {
872                   tdm_hwc_set_client_target_acquire_fence(thwc, fence);
873                   close(fence);
874                }
875           }
876
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));
880      }
881    else
882      {
883         if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
884
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);
888
889         CLEAR(fb_damage);
890
891         tdm_hwc_set_client_target_buffer(thwc, NULL, fb_damage);
892
893         if (e_hwc_windows_fence_enabled_get(hwc))
894           tdm_hwc_set_client_target_acquire_fence(thwc, -1);
895
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));
899      }
900
901    return EINA_TRUE;
902 }
903
904 static Eina_Bool
905 _e_hwc_windows_target_window_rendered_windows_find(Eina_List *rendered_windows, E_Hwc_Window *hwc_window)
906 {
907    E_Hwc_Window *hw;
908    int n_thw;
909    const Eina_List *l;
910
911    if (!rendered_windows) return EINA_FALSE;
912    if (!hwc_window) return EINA_FALSE;
913
914    n_thw = eina_list_count(rendered_windows);
915    if (!n_thw) return EINA_FALSE;
916
917    EINA_LIST_FOREACH(rendered_windows, l, hw)
918      {
919        if (hw == hwc_window)
920          return EINA_TRUE;
921      }
922
923    return EINA_FALSE;
924 }
925
926 static Eina_Bool
927 _e_hwc_windows_target_window_rendered_window_has_no(E_Hwc *hwc, E_Hwc_Window *hwc_window, Eina_Bool all_target)
928 {
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;
933    const Eina_List *l;
934
935    target_hwc_window = hwc->target_hwc_window;
936    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
937
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);
940
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;
943
944    target_tsurface = target_hwc_window->hwc_window.current.buffer.tsurface;
945    if (!target_tsurface) return EINA_FALSE;
946
947    if (all_target)
948      {
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))
951           return EINA_TRUE;
952
953         EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, target_tsurface)
954           {
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))
957                return EINA_TRUE;
958           }
959      }
960    else
961      {
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))
964           return EINA_TRUE;
965      }
966
967    return EINA_FALSE;
968 }
969
970 static Eina_Bool
971 _e_hwc_windows_target_window_rendered_window_has(E_Hwc *hwc, E_Hwc_Window *hwc_window, Eina_Bool all_target)
972 {
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;
976    E_Hwc_Window *hw;
977    tbm_surface_h target_tsurface;
978    const Eina_List *l, *ll;
979    int n_thw;
980
981    target_hwc_window = hwc->target_hwc_window;
982    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
983
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);
986
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;
989
990    target_tsurface = target_hwc_window->hwc_window.current.buffer.tsurface;
991    if (!target_tsurface) return EINA_FALSE;
992
993    if (all_target)
994      {
995         rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
996
997         new_list = eina_list_clone(rendered_windows);
998
999         EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, target_tsurface)
1000           {
1001              rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
1002
1003              EINA_LIST_FOREACH(rendered_windows, ll, hw)
1004                {
1005                   if (!eina_list_data_find(new_list, hw))
1006                     new_list = eina_list_append(new_list, hw);
1007                }
1008           }
1009
1010         n_thw = eina_list_count(new_list);
1011         if (n_thw)
1012           {
1013              EINA_LIST_FOREACH(new_list, l, hw)
1014                {
1015                   if (hw == hwc_window)
1016                     {
1017                        eina_list_free(new_list);
1018                        return EINA_TRUE;
1019                     }
1020                }
1021           }
1022
1023         eina_list_free(new_list);
1024      }
1025    else
1026      {
1027         rendered_windows = _e_hwc_windows_target_window_rendered_windows_get(target_tsurface);
1028
1029         n_thw = eina_list_count(rendered_windows);
1030         if (n_thw)
1031           {
1032              EINA_LIST_FOREACH(rendered_windows, l, hw)
1033                if (hw == hwc_window) return EINA_TRUE;
1034           }
1035      }
1036
1037    return EINA_FALSE;
1038 }
1039
1040 static E_Client *
1041 _e_hwc_windows_client_get_from_object(Evas_Object *o, Eina_Bool *effect_client)
1042 {
1043    E_Client *ec = NULL;
1044    Evas_Object *ob, *cob;
1045    Eina_List *members;
1046    Eina_List *l;
1047    Eina_List *stack = NULL;
1048
1049    if (!o) return NULL;
1050
1051    if (effect_client)
1052      *effect_client = EINA_FALSE;
1053
1054    stack = eina_list_append(stack, o);
1055
1056    while (1)
1057      {
1058         ob = eina_list_last_data_get(stack);
1059         if (!ob) break;
1060
1061         ec = evas_object_data_get(ob, "E_Client");
1062         if (ec) break;
1063
1064         if (evas_object_smart_smart_get(ob))
1065           {
1066              if (evas_object_smart_data_get(ob))
1067                {
1068                   members = evas_object_smart_members_get(ob);
1069
1070                   EINA_LIST_FOREACH(members, l, cob)
1071                     stack = eina_list_append(stack, cob);
1072
1073                   if (members)
1074                     eina_list_free(members);
1075                }
1076           }
1077
1078         stack = eina_list_remove(stack, ob);
1079      }
1080
1081    eina_list_free(stack);
1082
1083    if (!(ec) && (evas_object_visible_get(o)))
1084      {
1085         ec = evas_object_data_get(o, "effect_client");
1086         if (effect_client)
1087           *effect_client = EINA_TRUE;
1088      }
1089
1090    return ec;
1091 }
1092
1093 static Eina_Bool
1094 _e_hwc_windows_client_fully_mask_get(E_Client *ec, int x, int y, int w, int h,
1095                                      int ee_w, int ee_h)
1096 {
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;
1101
1102    return EINA_TRUE;
1103 }
1104
1105 static Eina_List *
1106 _e_hwc_windows_visible_windows_list_get(E_Hwc *hwc)
1107 {
1108    Eina_List *windows_list = NULL;
1109    E_Hwc_Window *hwc_window;
1110    E_Client  *ec, *topmost_ec, *bottom = NULL;
1111    E_Zone *zone;
1112    Evas_Object *o;
1113    int ee_w, ee_h;
1114    int x, y, w, h, x1, x2, y1, y2;
1115    int r, g, b, a;
1116    int ui_skip = EINA_FALSE;
1117    int obscured_by_target = EINA_FALSE;
1118    const char *type;
1119    Eina_Bool effect_client;
1120    Evas_Render_Op render_op;
1121    E_Map *map;
1122
1123    ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &ee_w, &ee_h);
1124
1125    for (o = evas_object_top_get(e_comp->evas); o; o = evas_object_below_get(o))
1126      {
1127         ec = _e_hwc_windows_client_get_from_object(o, &effect_client);
1128         if (!ec)
1129           {
1130              if (obscured_by_target) continue;
1131              if (!evas_object_visible_get(o)) continue;
1132
1133              type = evas_object_type_get(o);
1134              if (!e_util_strcmp(type, "image"))
1135                {
1136                   evas_object_color_get(o, &r, &g, &b, &a);
1137                   evas_object_geometry_get(o, &x, &y, &w, &h);
1138
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;
1142                }
1143
1144              continue;
1145           }
1146
1147         hwc_window = ec->hwc_window;
1148         if (!hwc_window) continue;
1149
1150         e_hwc_window_name_set(hwc_window);
1151         hwc_window->obscured_by_target = obscured_by_target;
1152
1153         if (hwc)
1154           {
1155              zone = hwc_window->zone;
1156              if (!zone) continue;
1157              if (e_output_find(zone->output_id) != hwc->output) continue;
1158           }
1159
1160         if (eina_list_data_find(windows_list, hwc_window))
1161           continue;
1162
1163         // check clients to skip composite
1164         if (e_client_util_ignored_get(ec))
1165           {
1166              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1167              continue;
1168           }
1169
1170         if (ec->hwc_visible_skip)
1171           {
1172              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1173              continue;
1174           }
1175
1176         if (!evas_object_visible_get(ec->frame))
1177           {
1178              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1179              continue;
1180           }
1181
1182         e_client_geometry_get(ec, &x, &y, &w, &h);
1183
1184         if ((ec->is_cursor) && (evas_object_map_enable_get(ec->frame)))
1185           {
1186              map = e_client_map_get(ec);
1187              if (map)
1188                {
1189                   e_map_point_coord_get(map, 0, &x1, &y1, NULL);
1190                   e_map_point_coord_get(map, 2, &x2, &y2, NULL);
1191                   
1192                   x = MIN(x1, x2);
1193                   y = MIN(y1, y2);
1194                   w = MAX(x1, x2) - x;
1195                   h = MAX(y1, y2) - y;
1196
1197                   e_map_free(map);
1198                }
1199           }
1200
1201         if ((!effect_client) && (!e_comp_object_color_visible_get(ec->frame)))
1202           {
1203              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1204
1205              render_op = evas_object_render_op_get(ec->frame);
1206              if ((!ui_skip) &&
1207                  (render_op == EVAS_RENDER_COPY) &&
1208                  (_e_hwc_windows_client_fully_mask_get(ec, x, y, w, h, ee_w, ee_h)))
1209                {
1210                   ui_skip = EINA_TRUE;
1211                   bottom = ec;
1212                }
1213
1214              continue;
1215           }
1216
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))
1219           {
1220              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1221              continue;
1222           }
1223
1224         if (evas_object_data_get(ec->frame, "comp_skip"))
1225           {
1226              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1227              continue;
1228           }
1229
1230         /* skip all small clients except the video clients */
1231         if ((ec->w == 1 || ec->h == 1) && !e_hwc_window_is_video(hwc_window))
1232           {
1233              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
1234              continue;
1235           }
1236
1237         if (e_hwc_window_is_video(hwc_window))
1238           {
1239             if (!e_client_video_tbm_surface_get(ec))
1240               continue;
1241
1242             e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_VIDEO, EINA_TRUE);
1243           }
1244         else
1245           {
1246              if (ui_skip)
1247                {
1248                  /* check parent of subsurface is bottom ec */
1249                  if ((ec->comp_data) && (ec->comp_data->sub.data))
1250                    {
1251                       topmost_ec = e_comp_wl_topmost_parent_get(ec);
1252                       if (topmost_ec != bottom)
1253                         continue;
1254                    }
1255                  else
1256                    continue;
1257                }
1258           }
1259
1260         if (ec->is_cursor)
1261           {
1262              e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CURSOR, EINA_TRUE);
1263           }
1264
1265         windows_list = eina_list_append(windows_list, hwc_window);
1266
1267         if ((!ui_skip) &&
1268             (_e_hwc_windows_client_fully_mask_get(ec, x, y, w, h, ee_w, ee_h)))
1269           {
1270              ui_skip = EINA_TRUE;
1271              bottom = ec;
1272           }
1273      }
1274
1275    return windows_list;
1276 }
1277
1278 static Eina_Bool
1279 _e_hwc_windows_pending_update_data_enqueue(E_Hwc_Windows_Comp_Info *comp_info)
1280 {
1281    E_Hwc_Window_Update_Data *update;
1282
1283    EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1284
1285    EINA_LIST_FREE(comp_info->pending_update_list, update)
1286      e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
1287
1288    comp_info->pending_update_list = NULL;
1289
1290    e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1291
1292    return EINA_TRUE;
1293 }
1294
1295 static Eina_Bool
1296 _e_hwc_windows_pending_update_data_dequeue(E_Hwc_Window_Target *root_target_hwc_window,
1297                                            E_Hwc_Windows_Comp_Info *comp_info)
1298 {
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;
1303    E_Output *output;
1304    Eina_List *l;
1305
1306    EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1307    EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1308
1309    EINA_LIST_FREE(comp_info->pending_update_list, update)
1310      e_hwc_window_pending_update_data_enqueue(update->hwc_window, update);
1311
1312    e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1313
1314    EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1315      {
1316         if (!output->hwc) continue;
1317
1318         target_hwc_window = output->hwc->target_hwc_window;
1319         if (!target_hwc_window) continue;
1320
1321         EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
1322           {
1323              hwc_window->present_sync = EINA_FALSE;
1324
1325              update = e_hwc_window_pending_update_data_dequeue(hwc_window);
1326              if (update)
1327                {
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);
1331                }
1332
1333              if (hwc_window->ec)
1334                e_comp_wl_tizen_hwc_feedback_list_dequeue(hwc_window->ec, &comp_info->feedback_list);
1335
1336              e_object_unref(E_OBJECT(hwc_window));
1337           }
1338
1339      }
1340
1341    comp_info->pending_update_list = pending_update_list;
1342
1343    return EINA_TRUE;
1344 }
1345
1346 static Eina_Bool
1347 _e_hwc_windows_pending_update_data_clear(E_Hwc_Window_Target *root_target_hwc_window)
1348 {
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;
1354    Eina_List *l, *ll;
1355    E_Output *output;
1356
1357    EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1358
1359    EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1360      {
1361         if (!output->hwc) continue;
1362
1363         target_hwc_window = output->hwc->target_hwc_window;
1364         if (!target_hwc_window) continue;
1365
1366         EINA_LIST_FREE(target_hwc_window->present_sync_windows, hwc_window)
1367           {
1368              hwc_window->present_sync = EINA_FALSE;
1369              e_object_unref(E_OBJECT(hwc_window));
1370           }
1371      }
1372
1373    EINA_LIST_FOREACH_SAFE(root_target_hwc_window->rendering_tsurfaces, l, ll, tsurface)
1374      {
1375         comp_info = _e_hwc_windows_comp_info_get(tsurface);
1376         if (!comp_info) continue;
1377
1378         EINA_LIST_FREE(comp_info->pending_update_list, update)
1379           e_hwc_window_pending_update_data_dequeue_cancel(update->hwc_window, update);
1380
1381         e_comp_wl_tizen_hwc_feedback_list_enqueue(&comp_info->feedback_list);
1382      }
1383
1384    return EINA_TRUE;
1385 }
1386
1387 /* gets called as somebody modifies target_window's queue */
1388 static void
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)
1391 {
1392    E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1393    E_Hwc_Windows_Comp_Info *comp_info;
1394
1395    /* gets called as evas_renderer dequeues a new buffer from the queue */
1396    if (trace == TBM_SURFACE_QUEUE_TRACE_DEQUEUE)
1397      {
1398         if (!target_hwc_window->is_rendering) return;
1399
1400         EHWSTRACE("{%s} dequeue ts:%p", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window), tsurface);
1401
1402         target_hwc_window->dequeued_tsurface = tsurface;
1403
1404         if (!eina_list_data_find(target_hwc_window->rendering_tsurfaces, tsurface))
1405           {
1406              target_hwc_window->rendering_tsurfaces =
1407                eina_list_append(target_hwc_window->rendering_tsurfaces, tsurface);
1408           }
1409
1410         if (e_hwc_windows_fence_enabled_get(target_hwc_window->hwc))
1411           {
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);
1415           }
1416      }
1417
1418    if (trace == TBM_SURFACE_QUEUE_TRACE_ACQUIRE)
1419      {
1420         target_hwc_window->rendering_tsurfaces =
1421           eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface);
1422
1423         comp_info = _e_hwc_windows_comp_info_get(tsurface);
1424         if (comp_info)
1425           {
1426              _e_hwc_windows_pending_update_data_enqueue(comp_info);
1427              _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
1428           }
1429      }
1430
1431    /* tsurface has been released at the queue */
1432    if (trace == TBM_SURFACE_QUEUE_TRACE_RELEASE)
1433      {
1434         EHWSTRACE("{%s} release ts:%p", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window), tsurface);
1435
1436         target_hwc_window->rendering_tsurfaces =
1437           eina_list_remove(target_hwc_window->rendering_tsurfaces, tsurface);
1438
1439         comp_info = _e_hwc_windows_comp_info_get(tsurface);
1440         if (comp_info)
1441           {
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);
1445           }
1446      }
1447 }
1448
1449 /* gets called as evas_renderer enqueues a new buffer into the queue */
1450 static void
1451 _e_hwc_windows_target_window_surface_queue_acquirable_cb(tbm_surface_queue_h surface_queue, void *data)
1452 {
1453    E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1454    uint64_t value = 1;
1455    int ret;
1456
1457    ret = write(target_hwc_window->event_fd, &value, sizeof(value));
1458    if (ret == -1)
1459      EHWSERR("failed to send acquirable event:%m", NULL);
1460 }
1461
1462 /* gets called at the beginning of an ecore_main_loop iteration */
1463 static Eina_Bool
1464 _e_hwc_windows_target_window_render_finished_cb(void *data, Ecore_Fd_Handler *fd_handler)
1465 {
1466    int len;
1467    int fd;
1468    char buffer[64];
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;
1474
1475    fd = ecore_main_fd_handler_fd_get(fd_handler);
1476    if (fd < 0) return ECORE_CALLBACK_RENEW;
1477
1478    len = read(fd, buffer, sizeof(buffer));
1479    if (len == -1)
1480      EHWSERR("failed to read queue acquire event fd:%m", NULL);
1481
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;
1485
1486    acquirable_buffers = e_hwc_window_queue_acquirable_buffers_get(hwc_window->queue);
1487    if (!acquirable_buffers) return ECORE_CALLBACK_RENEW;
1488
1489    EINA_LIST_FREE(acquirable_buffers, queue_buffer)
1490      {
1491         if (!queue_buffer->tsurface) continue;
1492
1493         comp_info = _e_hwc_windows_comp_info_get(queue_buffer->tsurface);
1494         if (!comp_info) continue;
1495
1496         _e_hwc_windows_comp_info_rendered_buffers_set(comp_info, NULL);
1497      }
1498
1499    return ECORE_CALLBACK_RENEW;
1500 }
1501
1502 static void
1503 _e_hwc_windows_target_cb_pp_queue_destroy(struct wl_listener *listener, void *data)
1504 {
1505    E_Hwc_Window_Target *target_hwc_window;
1506
1507    target_hwc_window = container_of(listener, E_Hwc_Window_Target, pp_queue_destroy_listener);
1508    EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
1509
1510    if ((E_Hwc_Window_Queue *)data != target_hwc_window->pp_queue) return;
1511
1512    if (target_hwc_window->pp_queue_destroy_listener.notify)
1513      {
1514         wl_list_remove(&target_hwc_window->pp_queue_destroy_listener.link);
1515         target_hwc_window->pp_queue_destroy_listener.notify = NULL;
1516      }
1517
1518    target_hwc_window->pp_queue = NULL;
1519 }
1520
1521 static Eina_Bool
1522 _e_hwc_windows_target_window_pp_queue_set(E_Hwc_Window_Target *target_hwc_window, E_Hwc_Window_Queue *queue)
1523 {
1524    if (target_hwc_window->pp_queue == queue)
1525      return EINA_TRUE;
1526
1527    if (target_hwc_window->pp_queue)
1528      {
1529         wl_list_remove(&target_hwc_window->pp_queue_destroy_listener.link);
1530         target_hwc_window->pp_queue_destroy_listener.notify = NULL;
1531      }
1532
1533    if (queue)
1534      {
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;
1538      }
1539
1540    return EINA_TRUE;
1541 }
1542
1543 static void
1544 _e_hwc_windows_target_cb_queue_destroy(struct wl_listener *listener, void *data)
1545 {
1546    E_Hwc_Window *hwc_window;
1547
1548    hwc_window = container_of(listener, E_Hwc_Window, queue_destroy_listener);
1549    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1550
1551    if ((E_Hwc_Window_Queue *)data != hwc_window->queue) return;
1552
1553    hwc_window->queue = NULL;
1554 }
1555
1556 static Eina_Bool
1557 _e_hwc_windows_target_window_tbm_surface_queue_set(E_Hwc_Window_Target *target_hwc_window, tbm_surface_queue_h tqueue)
1558 {
1559    E_Hwc_Window_Queue *queue;
1560    int queue_size = 0;
1561
1562    EINA_SAFETY_ON_NULL_RETURN_VAL(tqueue, EINA_FALSE);
1563
1564    queue = e_hwc_window_queue_target_tbm_surface_queue_set((E_Hwc_Window *)target_hwc_window, tqueue);
1565    if (!queue) return EINA_FALSE;
1566
1567    if (((E_Hwc_Window *)target_hwc_window)->queue == queue) return EINA_TRUE;
1568
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;
1572
1573    queue_size = e_hwc_window_queue_size_get(queue);
1574    if (queue_size)
1575      {
1576         target_hwc_window->max_transition_failures =
1577            e_hwc_window_queue_size_get(((E_Hwc_Window *)target_hwc_window)->queue);
1578      }
1579    else
1580      {
1581         target_hwc_window->max_transition_failures = DEFAULT_MAX_TRANSITION_FAILURES;
1582      }
1583
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);
1592
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);
1597
1598    return EINA_TRUE;
1599 }
1600
1601 static Eina_Bool
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)
1604 {
1605    E_Hwc_Window_Queue *queue;
1606
1607    EINA_SAFETY_ON_NULL_RETURN_VAL(gsurface, EINA_FALSE);
1608
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;
1612
1613    if (((E_Hwc_Window *)target_hwc_window)->queue == queue) return EINA_TRUE;
1614
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;
1618
1619    target_hwc_window->max_transition_failures = DEFAULT_MAX_TRANSITION_FAILURES;
1620
1621    return EINA_TRUE;
1622 }
1623
1624 static Eina_Bool
1625 _e_hwc_windows_target_window_queue_set(E_Hwc_Window_Target *target_hwc_window)
1626 {
1627    E_Hwc *hwc = target_hwc_window->hwc;
1628    tbm_surface_queue_h tqueue;
1629    struct gbm_surface *gsurface;
1630    int width, height, format;
1631
1632    tqueue = e_hwc_tbm_surface_queue_get(hwc);
1633    if (tqueue)
1634      return _e_hwc_windows_target_window_tbm_surface_queue_set(target_hwc_window, tqueue);
1635
1636    gsurface = e_hwc_gbm_surface_get(hwc, &width, &height, &format);
1637    if (gsurface)
1638      return _e_hwc_windows_target_window_gbm_surface_set(target_hwc_window, gsurface, width, height, format);
1639
1640    EHWSERR("fail to get tbm_surface_queue and gbm_surface", hwc);
1641
1642    return EINA_FALSE;
1643 }
1644
1645 static Eina_Bool
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)
1648 {
1649    E_Hwc_Window_Target *target_hwc_window;
1650    E_Hwc_Window *hwc_window;
1651    E_Output *output;
1652    Eina_List *l, *l2, *ll2;
1653
1654    EINA_SAFETY_ON_NULL_RETURN_VAL(root_target_hwc_window, EINA_FALSE);
1655    EINA_SAFETY_ON_NULL_RETURN_VAL(comp_info, EINA_FALSE);
1656
1657    EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
1658      {
1659         if (!output->hwc) continue;
1660
1661         target_hwc_window = output->hwc->target_hwc_window;
1662         if (!target_hwc_window) continue;
1663
1664         EINA_LIST_FOREACH_SAFE(target_hwc_window->pending_presentation_cb_wins, l2, ll2, hwc_window)
1665           {
1666              if (!hwc_window->render_target) continue;
1667
1668              e_hwc_window_presentation_callback_pending_take_over(hwc_window,
1669                                                                   &comp_info->presentation_callbacks);
1670           }
1671      }
1672
1673    return EINA_TRUE;
1674 }
1675
1676 static void
1677 _e_hwc_windows_target_window_render_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1678 {
1679    E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1680    E_Hwc_Window *hwc_window;
1681    E_Hwc *hwc;
1682    E_Egl_Sync *egl_sync;
1683    Eina_List *l;
1684    int acquire_fence_fd = -1;
1685
1686    hwc = target_hwc_window->hwc;
1687    if (!e_hwc_windows_fence_enabled_get(hwc)) return;
1688
1689    EINA_LIST_FOREACH(hwc->visible_windows, l, hwc_window)
1690      {
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)
1694           continue;
1695
1696         acquire_fence_fd = e_client_explicit_sync_acquire_fence_fd_get(hwc_window->ec);
1697         if (acquire_fence_fd < 0) continue;
1698
1699         egl_sync = e_egl_sync_fence_create_with_fd(acquire_fence_fd);
1700         if (!egl_sync) continue;
1701
1702          if (!e_egl_sync_wait(egl_sync))
1703             ERR("Failed to wait on E_Egl_Sync");
1704
1705         e_egl_sync_destroy(egl_sync);
1706
1707         EHWSTRACE("EGL_WAIT_SYNC hwc_window(%p) is Done.", hwc_window->ec, hwc, hwc_window);
1708      }
1709 }
1710
1711 static void
1712 _e_hwc_windows_target_window_render_flush_pre_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1713 {
1714    E_Hwc_Window_Target *target_hwc_window = (E_Hwc_Window_Target *)data;
1715    E_Hwc *hwc;
1716
1717    hwc = target_hwc_window->hwc;
1718    if (!e_hwc_windows_fence_enabled_get(hwc)) return;
1719
1720    if (target_hwc_window->end_render_sync)
1721      {
1722         e_egl_sync_destroy(target_hwc_window->end_render_sync);
1723         target_hwc_window->end_render_sync = NULL;
1724      }
1725
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);
1729 }
1730
1731 static void
1732 _e_hwc_windows_target_window_render_flush_post_cb(void *data, Evas *e EINA_UNUSED, void *event_info EINA_UNUSED)
1733 {
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;
1742    Eina_List *l;
1743    Eina_Bool fence_enabled;
1744    E_Hwc_Window_Queue_Type queue_type;
1745    E_Client *ec;
1746    E_Comp_Wl_Client_Data *cdata;
1747
1748    EHWSTRACE("{%s} gets render_flush_post noti", NULL, target_hwc_window->hwc, e_hwc_window_name_get((E_Hwc_Window *)target_hwc_window));
1749
1750    if (!target_hwc_window->dequeued_tsurface)
1751      {
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);
1755
1756         _e_hwc_windows_pending_update_data_clear(target_hwc_window);
1757
1758         if (eina_list_count(target_hwc_window->rendered_windows))
1759           {
1760              EINA_LIST_FREE(target_hwc_window->rendered_windows, hwc_window)
1761                {
1762                   hwc_window->on_rendered_target = EINA_FALSE;
1763                   e_hwc_window_unref(hwc_window);
1764                }
1765           }
1766
1767         target_hwc_window->rendered_windows = NULL;
1768         return;
1769      }
1770
1771    comp_info = _e_hwc_windows_comp_info_get(target_hwc_window->dequeued_tsurface);
1772    if (!comp_info)
1773      {
1774         EHWSERR("fail to get comp_info tsurface:%p", target_hwc_window->hwc, target_hwc_window->dequeued_tsurface);
1775         return;
1776      }
1777
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);
1780
1781    visible_windows = _e_hwc_windows_visible_windows_list_get(NULL);
1782    EINA_LIST_FREE(visible_windows, hwc_window)
1783      {
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);
1788      }
1789
1790    fence_enabled = e_hwc_windows_fence_enabled_get(target_hwc_window->hwc);
1791
1792    EINA_LIST_FOREACH(target_hwc_window->rendered_windows, l, hwc_window)
1793      {
1794         if (!hwc_window->on_rendered_target) continue;
1795
1796         hwc_window->on_rendered_target = EINA_FALSE;
1797
1798         ec = hwc_window->ec;
1799         if (!ec) continue;
1800
1801         cdata = e_client_cdata_get(ec);
1802         if (cdata)
1803           e_presentation_time_container_feedback_merge(&comp_info->presentation_container,
1804                                                        &cdata->presentation_container);
1805
1806         buffer = e_pixmap_ref_resource_get(ec->pixmap);
1807         if (!buffer)
1808           buffer = _e_hwc_windows_comp_wl_buffer_get(hwc_window);
1809
1810         if (!buffer) continue;
1811
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.
1815          */
1816         if (!buffer->resource) continue;
1817
1818         if ((fence_enabled) && (buffer->buffer_release) && (target_hwc_window->end_render_sync))
1819           {
1820              int fence_fd = -1;
1821
1822              fence_fd = e_egl_sync_fence_fd_dup(target_hwc_window->end_render_sync);
1823              if (fence_fd != -1)
1824                {
1825                   if (!e_explicit_sync_buffer_release_fence_fd_set(buffer->buffer_release, fence_fd))
1826                     close(fence_fd);
1827
1828                   continue;
1829                }
1830              else
1831                EHWSERR("failed to dup native fence fd", target_hwc_window->hwc);
1832           }
1833
1834         buffer_ref = E_NEW(E_Comp_Wl_Buffer_Ref, 1);
1835         if (!buffer_ref) continue;
1836
1837         e_comp_wl_buffer_reference(buffer_ref, buffer);
1838         rendered_buffers = eina_list_append(rendered_buffers, buffer_ref);
1839      }
1840
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);
1844
1845    eina_list_free(target_hwc_window->rendered_windows);
1846    target_hwc_window->rendered_windows = NULL;
1847    target_hwc_window->dequeued_tsurface = NULL;
1848 }
1849
1850 static void
1851 _e_hwc_windows_target_window_free(E_Hwc_Window_Target *target_hwc_window)
1852 {
1853    E_Hwc_Window *hwc_window = (E_Hwc_Window *)target_hwc_window;
1854    E_Hwc_Window *present_sync_window, *presentation_cb_window;
1855
1856    if (target_hwc_window->evas)
1857      {
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);
1861
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);
1865
1866         evas_event_callback_del(target_hwc_window->evas,
1867                                 EVAS_CALLBACK_RENDER_PRE,
1868                                 _e_hwc_windows_target_window_render_pre_cb);
1869      }
1870
1871    if (target_hwc_window->event_hdlr)
1872      ecore_main_fd_handler_del(target_hwc_window->event_hdlr);
1873
1874    if (target_hwc_window->event_fd >= 0)
1875      close(target_hwc_window->event_fd);
1876
1877    EINA_LIST_FREE(target_hwc_window->present_sync_windows, present_sync_window)
1878      e_hwc_window_unref(present_sync_window);
1879
1880    EINA_LIST_FREE(target_hwc_window->pending_presentation_cb_wins, presentation_cb_window)
1881      e_hwc_window_unref(presentation_cb_window);
1882
1883    if (hwc_window->queue && hwc_window->queue->tqueue)
1884      tbm_surface_queue_destroy(hwc_window->queue->tqueue);
1885
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);
1889
1890    if (hwc_window->queue_destroy_listener.notify)
1891      {
1892         wl_list_remove(&hwc_window->queue_destroy_listener.link);
1893         hwc_window->queue_destroy_listener.notify = NULL;
1894      }
1895
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);
1899
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);
1903
1904    EHWSINF("Free target window", NULL, NULL);
1905
1906    E_FREE(target_hwc_window);
1907 }
1908
1909 static void
1910 _e_hwc_windows_pp_commit_handler(tdm_pp *pp, tbm_surface_h tsurface_src, tbm_surface_h tsurface_dst, void *user_data)
1911 {
1912    E_Hwc *hwc;
1913    E_Hwc_Window *hwc_window;
1914    E_Hwc_Window_Queue_Buffer *queue_buffer;
1915
1916    hwc = (E_Hwc *)user_data;
1917    EINA_SAFETY_ON_NULL_RETURN(hwc);
1918
1919    EHWSTRACE("!!!!!!!! HWC PP Commit Handler !!!!!!!!", NULL, hwc);
1920    EHWSTRACE("PP DON tsurface src:%p dst:%p", NULL, hwc, tsurface_src, tsurface_dst);
1921
1922    hwc->pp_commit = EINA_FALSE;
1923
1924    hwc_window = (E_Hwc_Window *)hwc->target_hwc_window;
1925    EINA_SAFETY_ON_FALSE_RETURN(hwc_window);
1926
1927    queue_buffer = e_hwc_window_queue_buffer_find(hwc->pp_queue, tsurface_dst);
1928    if (queue_buffer)
1929      {
1930         if (!e_hwc_window_queue_buffer_enqueue(hwc->pp_queue, queue_buffer))
1931           ERR("fail to e_hwc_window_queue_buffer_enqueue");
1932      }
1933    else
1934      ERR("fail to e_hwc_window_queue_buffer_find");
1935
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);
1938
1939    tbm_surface_internal_unref(tsurface_src);
1940    tbm_surface_internal_unref(tsurface_dst);
1941
1942    if (!hwc->pp_set)
1943      {
1944         if (hwc->tpp)
1945           {
1946              EHWSINF("PP Destroy tdm_pp:%p", NULL, hwc, hwc->tpp);
1947
1948              tdm_pp_destroy(hwc->tpp);
1949              hwc->tpp = NULL;
1950           }
1951
1952         e_hwc_window_buffer_set(&hwc->pp_update.buffer, NULL, NULL, 0);
1953      }
1954 }
1955
1956 static Eina_Bool
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)
1959 {
1960    tdm_info_pp pp_info;
1961    tdm_error ret = TDM_ERROR_NONE;
1962    unsigned int aligned_width_src = 0, aligned_width_dst = 0;
1963
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);
1966
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);
1969
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;
1977
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;
1985
1986    pp_info.transform = TDM_TRANSFORM_NORMAL;
1987    pp_info.sync = 0;
1988    pp_info.flags = 0;
1989
1990    ret = tdm_pp_set_info(hwc->tpp, &pp_info);
1991    EINA_SAFETY_ON_FALSE_RETURN_VAL(ret == TDM_ERROR_NONE, EINA_FALSE);
1992
1993    EHWSTRACE("PP Info  src(%d,%d)(%d,%d)size(%dx%d), dst(%d,%d)(%d,%d)size(%dx%d)",
1994              NULL, hwc,
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);
1999
2000    return EINA_TRUE;
2001 }
2002
2003 static void
2004 _e_hwc_windows_vblank_handler(tdm_output *output, unsigned int sequence,
2005                         unsigned int tv_sec, unsigned int tv_usec,
2006                         void *user_data)
2007 {
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;
2011    Eina_List *l;
2012
2013    EINA_SAFETY_ON_NULL_RETURN(hwc);
2014
2015    EHWSTRACE("!!!!!!!! HWC Vblank Handler!!!!!!!!", NULL, hwc);
2016
2017    _e_hwc_windows_wait_commit_set(hwc, EINA_FALSE);
2018
2019    if (!eina_list_count(hwc->wins_commit_data_list)) return;
2020
2021    wins_commit_data = eina_list_last_data_get(hwc->wins_commit_data_list);
2022    EINA_SAFETY_ON_NULL_RETURN(wins_commit_data);
2023
2024    if (!wins_commit_data->use_vblank_handler) return;
2025
2026    EINA_LIST_FOREACH(wins_commit_data->commit_data_list, l, commit_data)
2027      {
2028         if (!commit_data) continue;
2029         if (!commit_data->hwc_window) continue;
2030
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);
2033      }
2034
2035    wins_commit_data->vblank_done = EINA_TRUE;
2036 }
2037
2038 static void
2039 _e_hwc_windows_wait_commit_set(E_Hwc *hwc, Eina_Bool set)
2040 {
2041    if (hwc->wait_commit == set) return;
2042
2043    hwc->wait_commit = set;
2044 }
2045
2046 static Eina_Bool
2047 _e_hwc_windows_device_states_available_check(E_Hwc *hwc)
2048 {
2049    return hwc->device_state_available;
2050 }
2051
2052 static void
2053 _e_hwc_windows_status_print(E_Hwc *hwc, Eina_Bool with_target)
2054 {
2055    Eina_List *visible_windows = hwc->visible_windows;
2056    const Eina_List *l;
2057    E_Hwc_Window *hwc_window;
2058
2059    EHWSTRACE(" Device state available : %d", NULL, hwc,
2060              _e_hwc_windows_device_states_available_check(hwc));
2061
2062    EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2063      {
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));
2070      }
2071 }
2072
2073 static E_Hwc_Window *
2074 _e_hwc_windows_window_find_by_twin(E_Hwc *hwc, tdm_hwc_window *hwc_win)
2075 {
2076    Eina_List *l;
2077    E_Hwc_Window *hwc_window;
2078
2079    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
2080    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_win, NULL);
2081
2082    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2083      {
2084         if (hwc_window->thwc_window == hwc_win) return hwc_window;
2085      }
2086
2087    return NULL;
2088 }
2089
2090 static E_Hwc_Window_State
2091 _e_hwc_windows_window_state_get(tdm_hwc_window_composition composition_type)
2092 {
2093    E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
2094
2095    switch (composition_type)
2096      {
2097       case TDM_HWC_WIN_COMPOSITION_NONE:
2098         state = E_HWC_WINDOW_STATE_NONE;
2099         break;
2100       case TDM_HWC_WIN_COMPOSITION_CLIENT:
2101         state = E_HWC_WINDOW_STATE_CLIENT;
2102         break;
2103       case TDM_HWC_WIN_COMPOSITION_DEVICE:
2104         state = E_HWC_WINDOW_STATE_DEVICE;
2105         break;
2106       case TDM_HWC_WIN_COMPOSITION_CURSOR:
2107         state = E_HWC_WINDOW_STATE_CURSOR;
2108         break;
2109       case TDM_HWC_WIN_COMPOSITION_VIDEO:
2110         state = E_HWC_WINDOW_STATE_VIDEO;
2111         break;
2112       default:
2113         state = E_HWC_WINDOW_STATE_NONE;
2114         EHWSERR("unknown state of hwc_window", NULL);
2115      }
2116
2117    return state;
2118 }
2119
2120 static Eina_Bool
2121 _e_hwc_windows_transition_check(E_Hwc *hwc)
2122 {
2123    E_Hwc_Window *hwc_window;
2124    E_Hwc_Window_Target *target_hwc_window, *root_target_hwc_window;
2125    Eina_Bool transition = EINA_FALSE;
2126    const Eina_List *l;
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;
2131
2132    target_hwc_window = hwc->target_hwc_window;
2133    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
2134
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);
2137
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;
2140
2141    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2142      {
2143         E_Hwc_Window_Transition window_transition = E_HWC_WINDOW_TRANSITION_NONE_TO_NONE;
2144
2145         if (e_hwc_window_is_target(hwc_window)) continue;
2146         if (e_hwc_window_is_video(hwc_window)) continue;
2147
2148         if ((hwc_window->state == hwc_window->accepted_state) &&
2149             (e_hwc_window_transition_get(hwc_window) == E_HWC_WINDOW_TRANSITION_NONE_TO_NONE))
2150           continue;
2151
2152         if (hwc_window->transition_failures > root_target_hwc_window->max_transition_failures)
2153           continue;
2154
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;
2158         else
2159           target_window_changed = EINA_TRUE;
2160
2161         /* DEVICE -> CLIENT */
2162         if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) &&
2163             (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT))
2164           {
2165              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_DEVICE_TO_CLIENT);
2166
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;
2169
2170              display_state_changed = EINA_TRUE;
2171           }
2172         /* DEVICE -> NONE */
2173         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) &&
2174                  (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2175           {
2176              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_DEVICE_TO_NONE);
2177
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;
2180
2181              display_state_changed = EINA_TRUE;
2182           }
2183         /* CURSOR -> CLIENT */
2184         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR) &&
2185                  (hwc_window->state == E_HWC_WINDOW_STATE_CLIENT))
2186           {
2187              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CURSOR_TO_CLIENT);
2188
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;
2191
2192              display_state_changed = EINA_TRUE;
2193           }
2194         /* CURSOR -> NONE */
2195         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR) &&
2196                  (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2197           {
2198              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CURSOR_TO_NONE);
2199
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;
2202
2203              display_state_changed = EINA_TRUE;
2204           }
2205         /* CLIENT -> DEVICE */
2206         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2207                  (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE))
2208           {
2209              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_DEVICE);
2210
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;
2213
2214              display_state_changed = EINA_TRUE;
2215           }
2216         /* CLIENT -> CURSOR */
2217         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2218                  (hwc_window->state == E_HWC_WINDOW_STATE_CURSOR))
2219           {
2220              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_CURSOR);
2221
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;
2224
2225              display_state_changed = EINA_TRUE;
2226           }
2227         /* NONE -> DEVICE */
2228         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) &&
2229                  (hwc_window->state == E_HWC_WINDOW_STATE_DEVICE))
2230           {
2231              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_NONE_TO_DEVICE);
2232
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;
2235
2236              display_state_changed = EINA_TRUE;
2237           }
2238         /* NONE -> CURSOR */
2239         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) &&
2240                  (hwc_window->state == E_HWC_WINDOW_STATE_CURSOR))
2241           {
2242              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_NONE_TO_CURSOR);
2243
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;
2246
2247              display_state_changed = EINA_TRUE;
2248           }
2249         /* CLIENT -> NONE */
2250         else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT) &&
2251                  (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2252           {
2253              e_hwc_window_transition_set(hwc_window, E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE);
2254
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;
2257           }
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))
2260           {
2261              if (_e_hwc_windows_target_window_rendered_window_has_no(hwc, hwc_window, EINA_TRUE))
2262                {
2263                   window_transition = e_hwc_window_transition_get(hwc_window);
2264                   transition = EINA_TRUE;
2265                }
2266           }
2267
2268         if (window_transition)
2269           {
2270              if (target_window_changed)
2271                {
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);
2275                }
2276
2277              if (window_transition == E_HWC_WINDOW_TRANSITION_CLIENT_TO_NONE)
2278                {
2279                   client_to_none_transition = EINA_TRUE;
2280                   continue;
2281                }
2282
2283              transition = EINA_TRUE;
2284           }
2285      }
2286
2287     if ((display_state_changed) && (client_to_none_transition))
2288       transition = EINA_TRUE;
2289
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);
2293
2294     return transition;
2295 }
2296
2297 static Eina_Bool
2298 _e_hwc_windows_present_sync_check(E_Hwc *hwc)
2299 {
2300    E_Hwc_Window_Target *target_hwc_window;
2301
2302    if (!hwc->present_sync) return EINA_FALSE;
2303
2304    target_hwc_window = hwc->target_hwc_window;
2305    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
2306
2307    if (hwc->hwc_mode != E_HWC_MODE_FULL)
2308      {
2309         if ((((E_Hwc_Window *)target_hwc_window)->display.buffer.tsurface) ==
2310             (((E_Hwc_Window *)target_hwc_window)->current.buffer.tsurface))
2311           return EINA_TRUE;
2312      }
2313
2314     hwc->present_sync = EINA_FALSE;
2315
2316     return EINA_FALSE;
2317 }
2318
2319 static Eina_Bool
2320 _e_hwc_windows_validated_changes_update(E_Hwc *hwc, uint32_t num_changes)
2321 {
2322    E_Hwc_Window *hwc_window;
2323    E_Hwc_Window_Target *target_hwc_window;
2324    E_Hwc_Window_State state;
2325    tdm_error terror;
2326    tdm_hwc_window **changed_hwc_window = NULL;
2327    tdm_hwc_window_composition *composition_types = NULL;
2328    int i;
2329
2330    changed_hwc_window = E_NEW(tdm_hwc_window *, num_changes);
2331    EINA_SAFETY_ON_NULL_GOTO(changed_hwc_window, fail);
2332
2333    composition_types = E_NEW(tdm_hwc_window_composition, num_changes);
2334    EINA_SAFETY_ON_NULL_GOTO(composition_types, fail);
2335
2336    target_hwc_window = hwc->target_hwc_window;
2337    EINA_SAFETY_ON_NULL_GOTO(target_hwc_window, fail);
2338
2339    terror = tdm_hwc_get_changed_composition_types(hwc->thwc,
2340                                                   &num_changes, changed_hwc_window,
2341                                                   composition_types);
2342    if (terror != TDM_ERROR_NONE)
2343      {
2344         EHWSERR("failed to get changed composition types", hwc);
2345         goto fail;
2346      }
2347
2348    EHWSTRACE(" Changes NUM : %d", NULL, hwc, num_changes);
2349
2350    for (i = 0; i < num_changes; ++i)
2351      {
2352         hwc_window = _e_hwc_windows_window_find_by_twin(hwc, changed_hwc_window[i]);
2353         if (!hwc_window)
2354           {
2355              EHWSERR("cannot find the E_Hwc_Window by hwc hwc_window", hwc);
2356              goto fail;
2357           }
2358
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);
2362      }
2363
2364 #if DBG_EVALUATE
2365    EHWSTRACE(" Modified after HWC Validation:", NULL, hwc);
2366    _e_hwc_windows_status_print(hwc, EINA_FALSE);
2367 #endif
2368
2369    free(changed_hwc_window);
2370    free(composition_types);
2371
2372    return EINA_TRUE;
2373
2374 fail:
2375    if (changed_hwc_window) free(changed_hwc_window);
2376    if (composition_types) free(composition_types);
2377
2378    return EINA_FALSE;
2379 }
2380
2381 static Eina_Bool
2382 _e_hwc_windows_accept(E_Hwc *hwc)
2383 {
2384    E_Hwc_Window *hwc_window;
2385    E_Hwc_Window_State state;
2386    tdm_error terror = TDM_ERROR_NONE;
2387    const Eina_List *l;
2388
2389    /* accept changes */
2390    terror = tdm_hwc_accept_validation(hwc->thwc);
2391    if (terror != TDM_ERROR_NONE)
2392      {
2393         EHWSERR("failed to accept validation", hwc);
2394         return EINA_FALSE;
2395      }
2396
2397    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
2398      {
2399         if (e_hwc_window_is_target(hwc_window)) continue;
2400
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);
2405
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))
2408           {
2409              if (e_hwc_window_is_on_hw_overlay(hwc_window))
2410                 e_hwc_window_activate(hwc_window, NULL);
2411              else
2412                 e_hwc_window_deactivate(hwc_window);
2413           }
2414      }
2415
2416    /* _e_hwc_windows_accept */
2417    EHWSTRACE("======= HWC Accept Validation =======", NULL, hwc);
2418
2419    return EINA_TRUE;
2420 }
2421
2422 static Eina_Bool
2423 _e_hwc_windows_validate(E_Hwc *hwc, uint32_t *num_changes)
2424 {
2425    E_Output *output = hwc->output;
2426    tdm_error terror;
2427    tdm_output *toutput = output->toutput;
2428    tdm_hwc_window **thwc_windows = NULL;
2429    int i, n_thw;
2430    E_Hwc_Window *hwc_window;
2431    const Eina_List *l;
2432    Eina_List *visible_windows = hwc->visible_windows;
2433
2434 #if DBG_EVALUATE
2435    EHWSTRACE("======= HWC Request Validation to TDM HWC =====", NULL, hwc);
2436    _e_hwc_windows_status_print(hwc, EINA_FALSE);
2437 #endif
2438
2439    n_thw = eina_list_count(visible_windows);
2440    if (n_thw)
2441      {
2442         thwc_windows = E_NEW(tdm_hwc_window *, n_thw);
2443         EINA_SAFETY_ON_NULL_GOTO(thwc_windows, error);
2444
2445         i = 0;
2446         EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2447           thwc_windows[i++] = hwc_window->thwc_window;
2448      }
2449
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;
2453
2454    E_FREE(thwc_windows);
2455
2456    return EINA_TRUE;
2457
2458 error:
2459    EHWSERR("failed to validate the output(%p)", hwc, toutput);
2460    if (thwc_windows) E_FREE(thwc_windows);
2461
2462    return EINA_FALSE;
2463 }
2464
2465 static void
2466 _e_hwc_windows_visible_windows_states_update(E_Hwc *hwc)
2467 {
2468    Eina_List *visible_windows;
2469    Eina_List *l;
2470    E_Hwc_Window *hwc_window;
2471    E_Client *ec;
2472
2473    /* get the visible ecs */
2474    visible_windows = hwc->visible_windows;
2475
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))
2478      {
2479         /* check clients are able to use hwc */
2480         EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2481           {
2482              /* The video window set the TDM_HWC_WIN_COMPOSITION_VIDEO type. */
2483              if (e_hwc_window_is_video(hwc_window))
2484                {
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);
2487
2488                   continue;
2489                }
2490
2491               /* the cursor state is decided through finding the visible_windows. */
2492               if (e_hwc_window_is_cursor(hwc_window)) continue;
2493
2494              /* filter the visible clients which e20 prevent to shown by hw directly
2495                 by demand of e20 */
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);
2498              else
2499                {
2500                   ec = hwc_window->ec;
2501                   if (!ec) continue;
2502                   if (ec->redirected)
2503                     e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT, EINA_TRUE);
2504                   else
2505                     {
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));
2509                     }
2510                }
2511           }
2512      }
2513    else
2514      {
2515         EINA_LIST_FOREACH(visible_windows, l, hwc_window)
2516           {
2517              /* The video window set the TDM_HWC_WIN_COMPOSITION_VIDEO type. */
2518              if (e_hwc_window_is_video(hwc_window))
2519                {
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);
2522                   continue;
2523                }
2524
2525              ec = hwc_window->ec;
2526              if (!ec) continue;
2527              if (ec->redirected)
2528                {
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)" : "");
2533                }
2534              else
2535                {
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));
2539                }
2540           }
2541      }
2542 }
2543
2544 static Eina_Bool
2545 _e_hwc_windows_visible_windows_changed_check(E_Hwc *hwc, Eina_List *visible_windows, int visible_num)
2546 {
2547    Eina_List *prev_visible_windows;
2548    E_Hwc_Window *hw1, *hw2;
2549    int i;
2550
2551    prev_visible_windows = hwc->visible_windows;
2552
2553    if (!prev_visible_windows) return EINA_TRUE;
2554
2555    if (eina_list_count(prev_visible_windows) != visible_num)
2556      return EINA_TRUE;
2557
2558    for (i = 0; i < visible_num; i++)
2559      {
2560         hw1 = eina_list_nth(prev_visible_windows, i);
2561         hw2 = eina_list_nth(visible_windows, i);
2562         if (hw1 != hw2) return EINA_TRUE;
2563      }
2564
2565    return EINA_FALSE;
2566 }
2567
2568 static Eina_Bool
2569 _e_hwc_windows_visible_windows_update(E_Hwc *hwc)
2570 {
2571    E_Hwc_Window *hwc_window;
2572    Eina_List *l;
2573    Eina_List *visible_windows;
2574    int visible_num = 0;
2575    int zpos = 0;
2576
2577    /* get the visibile windows */
2578    visible_windows = _e_hwc_windows_visible_windows_list_get(hwc);
2579    if (!visible_windows && !hwc->visible_windows)
2580      return EINA_FALSE;
2581
2582    visible_num = eina_list_count(visible_windows);
2583
2584    if (!_e_hwc_windows_visible_windows_changed_check(hwc, visible_windows, visible_num))
2585      {
2586         eina_list_free(visible_windows);
2587         return EINA_FALSE;
2588      }
2589
2590   if (eina_list_count(hwc->visible_windows))
2591     {
2592        EINA_LIST_FREE(hwc->visible_windows, hwc_window)
2593          e_hwc_window_unref(hwc_window);
2594     }
2595
2596    /* store the current visible windows and the number of them */
2597    hwc->visible_windows = visible_windows;
2598    hwc->num_visible_windows = visible_num;
2599
2600    /* use the reverse iteration for assgining the zpos */
2601    EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
2602      {
2603         /* assign zpos */
2604         e_hwc_window_zpos_set(hwc_window, zpos++);
2605         e_hwc_window_ref(hwc_window);
2606      }
2607
2608    return EINA_TRUE;
2609 }
2610
2611 static Eina_Bool
2612 _e_hwc_windows_device_state_available_update(E_Hwc *hwc)
2613 {
2614    Eina_Bool available = EINA_TRUE;
2615
2616    /* make the full_gl_composite when the zoom is enabled */
2617    if (hwc->pp_set)
2618      {
2619         available = EINA_FALSE;
2620         goto finish;
2621      }
2622
2623    /* make the full_gl_composite when the mirror mode is enabled */
2624    if (eina_list_count(hwc->mirror_dst_hwc))
2625      {
2626         available = EINA_FALSE;
2627         goto finish;
2628      }
2629
2630    /* full composite is forced to be set */
2631    if (e_hwc_deactive_get(hwc))
2632      {
2633         available = EINA_FALSE;
2634         goto finish;
2635      }
2636
2637    /* hwc_window manager required full GLES composition */
2638    if (e_comp->nocomp_override > 0)
2639      {
2640         available = EINA_FALSE;
2641         goto finish;
2642      }
2643
2644 finish:
2645    if (hwc->device_state_available == available) return EINA_FALSE;
2646
2647    hwc->device_state_available = available;
2648
2649    return EINA_TRUE;
2650 }
2651
2652 static void
2653 _e_hwc_windows_pp_hwc_window_update(E_Hwc *hwc)
2654 {
2655    E_Hwc_Window *hwc_window;
2656    int w, h;
2657
2658    if (hwc->mirror_src_hwc)
2659      {
2660         hwc_window = (E_Hwc_Window *)hwc->mirror_src_hwc->target_hwc_window;
2661      }
2662    else
2663      {
2664         e_output_size_get(hwc->output, &w, &h);
2665
2666         if (hwc->num_visible_windows != 1)
2667           goto clear;
2668
2669         if (e_hwc_deactive_get(hwc))
2670           goto clear;
2671
2672         hwc_window = eina_list_nth(hwc->visible_windows, 0);
2673         if (!hwc_window)
2674           goto clear;
2675
2676         if ((tbm_surface_get_width(hwc_window->current.buffer.tsurface)) != w ||
2677             (tbm_surface_get_height(hwc_window->current.buffer.tsurface)) != h)
2678           goto clear;
2679
2680         if (!hwc_window->device_state_available)
2681           goto clear;
2682      }
2683
2684    if (hwc->pp_hwc_window != hwc_window)
2685      EHWSTRACE("Set pp_hwc_window:%p", NULL, hwc, hwc_window);
2686
2687    hwc->pp_hwc_window = hwc_window;
2688
2689    return;
2690
2691 clear:
2692    if (hwc->pp_hwc_window)
2693      EHWSTRACE("Unset pp_hwc_window", NULL, hwc);
2694
2695    hwc->pp_hwc_window = NULL;
2696 }
2697
2698 /* check if there is a need to update the output */
2699 static Eina_Bool
2700 _e_hwc_windows_changes_update(E_Hwc *hwc)
2701 {
2702    E_Hwc_Window *hwc_window;
2703    Eina_Bool update_changes = EINA_FALSE;
2704    const Eina_List *l, *ll;
2705
2706    if (hwc->property_changed)
2707      {
2708         hwc->property_changed = EINA_FALSE;
2709         update_changes = EINA_TRUE;
2710      }
2711
2712    /* update the the visible windows */
2713    if (_e_hwc_windows_visible_windows_update(hwc))
2714      update_changes = EINA_TRUE;
2715
2716   /* update the the visible windows */
2717    if (_e_hwc_windows_device_state_available_update(hwc))
2718      update_changes = EINA_TRUE;
2719
2720    EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2721      {
2722         if (e_hwc_window_is_target(hwc_window)) continue;
2723
2724         e_hwc_window_ref(hwc_window);
2725      }
2726
2727    EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2728      {
2729         if (e_hwc_window_is_target(hwc_window)) continue;
2730
2731         /* fetch the window buffer */
2732         if (e_hwc_window_buffer_fetch(hwc_window))
2733           update_changes = EINA_TRUE;
2734         else
2735           {
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);
2742           }
2743
2744         /* update the window's info */
2745         if (e_hwc_window_info_update(hwc_window))
2746           update_changes = EINA_TRUE;
2747
2748         /* update the window's props */
2749         if (e_hwc_window_prop_update(hwc_window))
2750           update_changes = EINA_TRUE;
2751
2752         if (e_hwc_window_device_state_available_update(hwc_window))
2753           update_changes = EINA_TRUE;
2754      }
2755
2756    EINA_LIST_FOREACH_SAFE(hwc->hwc_windows, l, ll, hwc_window)
2757      {
2758         if (e_hwc_window_is_target(hwc_window)) continue;
2759
2760         e_hwc_window_unref(hwc_window);
2761      }
2762
2763    if (hwc->primary_output)
2764      _e_hwc_windows_root_target_buffer_fetch(hwc);
2765
2766    if (hwc->pp_set)
2767      {
2768         _e_hwc_windows_pp_hwc_window_update(hwc);
2769         _e_hwc_windows_pp_commit(hwc);
2770      }
2771
2772    /* fetch the target buffer (try acquire) */
2773    if (_e_hwc_windows_target_buffer_fetch(hwc))
2774      update_changes = EINA_TRUE;
2775
2776    /* update the states of the visible windows when there is something to update */
2777    if (update_changes)
2778      {
2779         EHWSTRACE("======= HWC Update the Windows' Changes =====", NULL, hwc);
2780         _e_hwc_windows_visible_windows_states_update(hwc);
2781      }
2782
2783    return update_changes;
2784 }
2785
2786 static void
2787 _e_hwc_windows_target_state_set(E_Hwc_Window_Target *target_hwc_window, E_Hwc_Window_State state)
2788 {
2789    E_Hwc_Window *target_window = (E_Hwc_Window *)target_hwc_window;
2790
2791    if (target_window->is_root_target)
2792      {
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);
2795      }
2796
2797    e_hwc_window_state_set(target_window, state, EINA_FALSE);
2798    e_hwc_window_accepted_state_set(target_window, state);
2799 }
2800
2801 static pixman_format_code_t
2802 _e_hwc_windows_pixman_format_convert(tbm_format format)
2803 {
2804    switch(format)
2805      {
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;
2810       default:                  return 0;
2811      }
2812
2813    return 0;
2814 }
2815
2816 static void
2817 _e_hwc_windows_center_rect_get(int src_w, int src_h, int dst_w, int dst_h, Eina_Rectangle *fit)
2818 {
2819    float rw, rh;
2820
2821    if (src_w <= 0 || src_h <= 0 || dst_w <= 0 || dst_h <= 0 || !fit)
2822      return;
2823
2824    rw = (float)src_w / dst_w;
2825    rh = (float)src_h / dst_h;
2826
2827    if (rw > rh)
2828      {
2829         fit->w = dst_w;
2830         fit->h = src_h / rw;
2831         fit->x = 0;
2832         fit->y = (dst_h - fit->h) / 2;
2833      }
2834    else if (rw < rh)
2835      {
2836         fit->w = src_w / rh;
2837         fit->h = dst_h;
2838         fit->x = (dst_w - fit->w) / 2;
2839         fit->y = 0;
2840      }
2841    else
2842      {
2843         fit->w = dst_w;
2844         fit->h = dst_h;
2845         fit->x = 0;
2846         fit->y = 0;
2847      }
2848
2849    if (fit->x % 2)
2850      fit->x = fit->x - 1;
2851 }
2852
2853 static Eina_Bool
2854 _e_hwc_windows_capture_position_get(E_Hwc *hwc, int dst_w, int dst_h, Eina_Rectangle *fit)
2855 {
2856    int output_w = 0, output_h = 0;
2857
2858    e_output_size_get(hwc->output, &output_w, &output_h);
2859
2860    if (output_w == 0 || output_h == 0)
2861      return EINA_FALSE;
2862
2863    _e_hwc_windows_center_rect_get(output_w, output_h, dst_w, dst_h, fit);
2864
2865    return EINA_TRUE;
2866 }
2867
2868 static void
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)
2871 {
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;
2880
2881    EINA_SAFETY_ON_NULL_RETURN(src_rect);
2882    EINA_SAFETY_ON_NULL_RETURN(dst_rect);
2883
2884    ret = tbm_surface_map(src_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &src_tinfo);
2885    if (ret != TBM_SURFACE_ERROR_NONE)
2886      {
2887         EHWSERR("tbm_surface_map fails on src_tsurface", hwc);
2888         goto end;
2889      }
2890
2891    ret = tbm_surface_map(dst_tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &dst_tinfo);
2892    if (ret != TBM_SURFACE_ERROR_NONE)
2893      {
2894         EHWSERR("tbm_surface_map fails on dst_tsurface", hwc);
2895         goto src_unmap;
2896      }
2897
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);
2902
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);
2907
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);
2912
2913    scale_x = (double)src_rect->w / dst_rect->w;
2914    scale_y = (double)src_rect->h / dst_rect->h;
2915
2916    pixman_f_transform_init_identity(&ft);
2917
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);
2922
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);
2925
2926 free_img:
2927    if (src_img) pixman_image_unref(src_img);
2928    if (dst_img) pixman_image_unref(dst_img);
2929
2930    tbm_surface_unmap(dst_tsurface);
2931 src_unmap:
2932    tbm_surface_unmap(src_tsurface);
2933 end:
2934    return;
2935 }
2936
2937 static void
2938 _e_hwc_windows_buffer_clear(E_Hwc *hwc, tbm_surface_h tsurface)
2939 {
2940    tbm_surface_info_s tinfo = {0};
2941    int ret = TBM_SURFACE_ERROR_NONE;
2942    tbm_format format = 0;
2943
2944    ret = tbm_surface_map(tsurface, TBM_SURF_OPTION_READ | TBM_SURF_OPTION_WRITE, &tinfo);
2945    if (ret != TBM_SURFACE_ERROR_NONE)
2946      {
2947         EHWSERR("tbm_surface_map fail on tsurface", hwc);
2948         return;
2949      }
2950
2951    format = tbm_surface_get_format(tsurface);
2952    switch (format)
2953      {
2954       case TBM_FORMAT_ARGB8888:
2955       case TBM_FORMAT_XRGB8888:
2956         {
2957            int *ibuf = (int*)tinfo.planes[0].ptr;
2958            int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2959
2960            for (i = 0 ; i < size ; i++)
2961              ibuf[i] = 0xff000000;
2962         }
2963         break;
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));
2969         break;
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));
2974         break;
2975       case TBM_FORMAT_YUYV:
2976         {
2977            int *ibuf = (int*)tinfo.planes[0].ptr;
2978            int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2979
2980            for (i = 0 ; i < size ; i++)
2981              ibuf[i] = 0x10801080;
2982         }
2983         break;
2984       case TBM_FORMAT_UYVY:
2985         {
2986            int *ibuf = (int*)tinfo.planes[0].ptr;
2987            int i, size = tinfo.planes[0].stride * tinfo.height / 4;
2988
2989            for (i = 0 ; i < size ; i++)
2990              ibuf[i] = 0x80108010; /* YUYV -> 0xVYUY */
2991         }
2992         break;
2993       default:
2994         EHWSERR("can't clear %p buffer", hwc, tsurface);
2995         break;
2996      }
2997
2998    tbm_surface_unmap(tsurface);
2999 }
3000
3001 static E_Hwc_Window *
3002 _e_hwc_windows_visible_ui_window_bottom_get(E_Hwc *hwc)
3003 {
3004    E_Hwc_Window *hwc_window;
3005    Eina_List *l;
3006
3007    EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
3008      {
3009         if (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO)
3010           continue;
3011
3012         return hwc_window;
3013      }
3014
3015    return NULL;
3016 }
3017
3018 static E_Hwc_Window *
3019 _e_hwc_windows_below_transparent_window_find(E_Hwc *hwc)
3020 {
3021    E_Hwc_Window *hwc_window;
3022
3023    if (hwc->hwc_mode != E_HWC_MODE_HYBRID) return NULL;
3024
3025    hwc_window = _e_hwc_windows_visible_ui_window_bottom_get(hwc);
3026    if (!hwc_window) return NULL;
3027
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;
3031
3032    return hwc_window;
3033 }
3034
3035 static void
3036 _e_hwc_windows_below_transparent_window_update(E_Hwc *hwc)
3037 {
3038    E_Hwc_Window *hwc_window;
3039
3040    hwc_window = _e_hwc_windows_below_transparent_window_find(hwc);
3041    if (hwc_window)
3042      {
3043         if (hwc->below_transparent_window == hwc_window)
3044           return;
3045
3046         if (hwc->below_transparent_window)
3047           {
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;
3051           }
3052
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;
3056      }
3057    else
3058      {
3059         if (!hwc->below_transparent_window)
3060           return;
3061
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;
3065
3066         e_hwc_windows_present_sync(hwc);
3067      }
3068 }
3069
3070 /* evaluate the hwc_windows */
3071 static Eina_Bool
3072 _e_hwc_windows_evaluate(E_Hwc *hwc, E_Output_Display_Mode display_mode)
3073 {
3074    E_Hwc_Mode hwc_mode = E_HWC_MODE_NONE;
3075    E_Hwc_Window *hwc_window;
3076    const Eina_List *l;
3077    uint32_t num_changes;
3078    int num_client = 0, num_device = 0, num_video = 0, num_cursor = 0;
3079
3080    /* validate the visible hwc_windows' states*/
3081    if (!_e_hwc_windows_validate(hwc, &num_changes))
3082      {
3083         EHWSERR("_e_hwc_windows_validate failed", hwc);
3084         goto re_evaluate;
3085      }
3086
3087    /* update the valiated_changes if there are the composition changes after validation */
3088    if (num_changes)
3089      {
3090         if (!_e_hwc_windows_validated_changes_update(hwc, num_changes))
3091           {
3092              EHWSERR("_e_hwc_windows_validated_changes_update failed", hwc);
3093              goto re_evaluate;
3094           }
3095      }
3096
3097    /* constraints update and update the windows to be composited to the target_buffer */
3098    EINA_LIST_FOREACH(hwc->hwc_windows, l, hwc_window)
3099      {
3100         if (e_hwc_window_is_target(hwc_window)) continue;
3101
3102         e_hwc_window_constraints_update(hwc_window);
3103         e_hwc_window_rendered_window_update(hwc_window);
3104
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++;
3109      }
3110
3111    /* update the E_HWC_MODE */
3112    hwc_mode = _e_hwc_windows_hwc_mode_update(hwc, num_client, num_device, num_cursor ,num_video);
3113
3114    /* set the state of the target_window */
3115    if (hwc_mode == E_HWC_MODE_NONE)
3116      {
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);
3119      }
3120    else if (hwc_mode == E_HWC_MODE_HYBRID)
3121      {
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);
3124      }
3125    else
3126      {
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);
3129      }
3130
3131    _e_hwc_windows_below_transparent_window_update(hwc);
3132
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)))
3137      {
3138         _e_hwc_windows_target_window_buffer_skip(hwc);
3139
3140         if (!hwc->transition)
3141           {
3142              e_hwc_windows_target_window_force_render(hwc->target_hwc_window);
3143              hwc->transition = EINA_TRUE;
3144           }
3145
3146         goto re_evaluate;
3147      }
3148
3149    if (_e_hwc_windows_present_sync_check(hwc))
3150      {
3151         EHWSTRACE(" Not accpet display sync", NULL, hwc);
3152         goto re_evaluate;
3153      }
3154
3155    if (hwc_mode == E_HWC_MODE_FULL)
3156      {
3157         if (((E_Hwc_Window *)hwc->target_hwc_window)->current.buffer.tsurface)
3158           _e_hwc_windows_target_buffer_fetch(hwc);
3159      }
3160
3161    /* accept the result of the validation */
3162    if (!_e_hwc_windows_accept(hwc))
3163      {
3164         EHWSERR("_e_hwc_windows_validated_changes_update failed", hwc);
3165         goto re_evaluate;
3166      }
3167
3168    hwc->transition = EINA_FALSE;
3169    hwc->re_evaluate = EINA_FALSE;
3170
3171    return EINA_TRUE;
3172
3173 re_evaluate:
3174    EHWSTRACE("======= HWC NOT Accept Validation Yet !! =======", NULL, hwc);
3175
3176    hwc->re_evaluate = EINA_TRUE;
3177
3178    return EINA_FALSE;
3179 }
3180
3181 static Eina_Bool
3182 _e_hwc_windows_target_buffer_prepared(E_Hwc *hwc)
3183 {
3184    E_Hwc_Window *hwc_window;
3185
3186    hwc_window = (E_Hwc_Window *)hwc->target_hwc_window;
3187    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->target_hwc_window, EINA_FALSE);
3188
3189    if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
3190
3191    return EINA_TRUE;
3192 }
3193
3194 static void
3195 _e_hwc_windows_pp_rect_set(E_Hwc *hwc, Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
3196 {
3197    memcpy(&hwc->pp_src_rect, src_rect, sizeof(Eina_Rectangle));
3198    memcpy(&hwc->pp_dst_rect, dst_rect, sizeof(Eina_Rectangle));
3199 }
3200
3201 static Eina_Bool
3202 _e_hwc_windows_pp_update(E_Hwc *hwc)
3203 {
3204    E_Hwc_Window *hwc_window;
3205
3206    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3207
3208    if (hwc->pp_hwc_window)
3209      hwc_window = hwc->pp_hwc_window;
3210    else
3211      hwc_window = (E_Hwc_Window *)_e_hwc_windows_root_target_hwc_window_get(hwc);
3212
3213    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3214
3215    if (hwc_window->current.buffer.tsurface == hwc->pp_update.buffer.tsurface)
3216      return EINA_FALSE;
3217
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);
3221    else
3222      e_comp_wl_buffer_reference(&hwc->pp_update.buffer_ref, _e_hwc_windows_comp_wl_buffer_get(hwc_window));
3223
3224    e_hwc_window_buffer_set(&hwc->pp_update.buffer,
3225                            hwc_window->current.buffer.tsurface, hwc_window->current.buffer.queue, 0);
3226
3227    return EINA_TRUE;
3228 }
3229
3230 EINTERN Eina_Bool
3231 e_hwc_windows_init(void)
3232 {
3233    if (!e_hwc_window_init())
3234      {
3235         ERR("E_Hwc_Window init failed");
3236         return EINA_FALSE;
3237      }
3238
3239    if (!e_hwc_window_queue_init())
3240      {
3241         ERR("E_Hwc_Window_Queue init failed");
3242         e_hwc_window_deinit();
3243         return EINA_FALSE;
3244      }
3245
3246    return EINA_TRUE;
3247 }
3248
3249 EINTERN void
3250 e_hwc_windows_deinit(void)
3251 {
3252    e_hwc_window_queue_deinit();
3253    e_hwc_window_deinit();
3254 }
3255
3256 static void
3257 _e_hwc_windows_root_target_window_state_update(E_Hwc_Window_Target *root_target_hwc_window)
3258 {
3259    E_Output *output;
3260    Eina_List *l;
3261    E_Hwc_Window_State state;
3262    E_Hwc_Window_State root_state = E_HWC_WINDOW_STATE_NONE;
3263
3264    EINA_SAFETY_ON_NULL_RETURN(e_comp);
3265    EINA_SAFETY_ON_NULL_RETURN(e_comp->e_comp_screen);
3266
3267    EINA_LIST_FOREACH(e_comp->e_comp_screen->outputs, l, output)
3268      {
3269         if (!e_output_connected(output)) continue;
3270         if (!output->hwc) continue;
3271         if (!output->hwc->target_hwc_window) continue;
3272
3273         state = e_hwc_window_state_get((E_Hwc_Window *)output->hwc->target_hwc_window);
3274         if (state == E_HWC_WINDOW_STATE_DEVICE)
3275           {
3276              root_state = E_HWC_WINDOW_STATE_DEVICE;
3277              break;
3278           }
3279      }
3280
3281    _e_hwc_windows_target_state_set(root_target_hwc_window, root_state);
3282 }
3283
3284 EINTERN Eina_Bool
3285 e_hwc_windows_render(E_Hwc *hwc)
3286 {
3287    E_Hwc_Window_Target *target_hwc_window;
3288    E_Hwc_Window *target_window;
3289    EGLint egl_error;
3290
3291    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3292
3293    target_hwc_window = hwc->root_target_hwc_window;
3294    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3295
3296    target_window = (E_Hwc_Window *)target_hwc_window;
3297    EINA_SAFETY_ON_NULL_RETURN_VAL(target_window->queue, EINA_FALSE);
3298
3299    _e_hwc_windows_root_target_window_state_update(target_hwc_window);
3300
3301    if ((e_hwc_window_state_get(target_window) == E_HWC_WINDOW_STATE_NONE) ||
3302        ((hwc->pp_set) && (hwc->pp_hwc_window)))
3303      {
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);
3311
3312         return EINA_TRUE;
3313      }
3314
3315    if (e_hwc_norender_get(hwc) > 0)
3316      {
3317         EHWSTRACE("NoRender get. Do not ecore_evas_manual_render", NULL, hwc);
3318         return EINA_TRUE;
3319      }
3320
3321    if (e_hwc_window_queue_buffer_can_dequeue(target_window->queue))
3322      {
3323         TRACE_DS_BEGIN(MANUAL RENDER);
3324         target_hwc_window->is_rendering = EINA_TRUE;
3325         ecore_evas_manual_render(target_hwc_window->ee);
3326         if (e_comp->gl)
3327           {
3328              egl_error = eglGetError();
3329              if (egl_error != EGL_SUCCESS)
3330                ERR("EGL Error:%d in ecore_evas_manual_render", egl_error);
3331           }
3332         target_hwc_window->is_rendering = EINA_FALSE;
3333         TRACE_DS_END();
3334      }
3335
3336    return EINA_TRUE;
3337 }
3338
3339 static void
3340 _e_hwc_windows_release_fence_fd_update(E_Hwc *hwc)
3341 {
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;
3349    int i;
3350
3351    target_hwc_window = hwc->target_hwc_window;
3352    EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
3353
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))
3357      {
3358         comp_info = _e_hwc_windows_comp_info_get(hwc_window->display.buffer.tsurface);
3359         EINA_SAFETY_ON_NULL_RETURN(comp_info);
3360
3361         if (comp_info->release_fence)
3362           e_egl_sync_destroy(comp_info->release_fence);
3363
3364         comp_info->release_fence = e_egl_sync_fence_create_with_fd(hwc->commit_fence_fd);
3365
3366         e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
3367      }
3368
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);
3371
3372    if (!num_thwc_wins) return;
3373
3374    thwc_wins = E_NEW(tdm_hwc_window *, num_thwc_wins);
3375    EINA_SAFETY_ON_NULL_GOTO(thwc_wins, clean);
3376
3377    release_fences = E_NEW(int, num_thwc_wins);
3378    EINA_SAFETY_ON_NULL_GOTO(release_fences, clean);
3379
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);
3382
3383    for (i = 0; i < num_thwc_wins; i++)
3384      {
3385         hwc_window = _e_hwc_windows_window_find_by_twin(hwc, thwc_wins[i]);
3386
3387         if ((!hwc_window) ||
3388             (!hwc_window->display.buffer_ref.buffer) ||
3389             (!hwc_window->display.buffer_ref.buffer->buffer_release))
3390           {
3391              close(release_fences[i]);
3392              continue;
3393           }
3394
3395         if (!e_explicit_sync_buffer_release_fence_fd_set(hwc_window->display.buffer_ref.buffer->buffer_release,
3396                                                          release_fences[i]))
3397           {
3398              close(release_fences[i]);
3399              continue;
3400           }
3401
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);
3404      }
3405
3406 clean:
3407   if (thwc_wins) free(thwc_wins);
3408   if (release_fences) free(release_fences);
3409 }
3410
3411 static Eina_Bool
3412 _e_hwc_windows_pp_commit(E_Hwc *hwc)
3413 {
3414    E_Output *output;
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;
3418    E_Client *ec;
3419    E_Comp_Wl_Client_Data *cdata;
3420
3421    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3422
3423    if (hwc->pp_commit) return EINA_TRUE;
3424
3425    output = hwc->output;
3426    if (e_output_dpms_get(output))
3427      return EINA_TRUE;
3428
3429    if (!e_hwc_window_queue_buffer_can_dequeue(hwc->pp_queue)) return EINA_TRUE;
3430
3431    if (!_e_hwc_windows_pp_update(hwc)) return EINA_TRUE;
3432
3433    queue_buffer = e_hwc_window_queue_buffer_dequeue(hwc->pp_queue);
3434    if (!queue_buffer)
3435      {
3436         EHWSERR("fail e_hwc_window_queue_buffer_dequeue", hwc);
3437         return EINA_FALSE;
3438      }
3439
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);
3445
3446    if (hwc->tpp)
3447      {
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))
3450           {
3451              EHWSERR("fail _e_hwc_windows_pp_info_set", hwc);
3452              goto pp_fail;
3453           }
3454
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);
3459
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);
3463
3464         terror = tdm_pp_commit(hwc->tpp);
3465         EINA_SAFETY_ON_FALSE_GOTO(terror == TDM_ERROR_NONE, commit_fail);
3466
3467         hwc->pp_commit = EINA_TRUE;
3468      }
3469    else
3470      {
3471         /* sw copy */
3472         _e_hwc_windows_pixman_copy(hwc, hwc->pp_update.buffer.tsurface, queue_buffer->tsurface,
3473                                    &hwc->pp_src_rect, &hwc->pp_dst_rect);
3474
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);
3477
3478         /* enqueue buffer */
3479         e_hwc_window_queue_buffer_enqueue(hwc->pp_queue, queue_buffer);
3480      }
3481
3482    if (!hwc->mirror_src_hwc)
3483      {
3484         pp_comp_info = _e_hwc_windows_comp_info_get(queue_buffer->tsurface);
3485         if (pp_comp_info)
3486           {
3487              if (hwc->pp_hwc_window)
3488                {
3489                   ec = hwc->pp_hwc_window->ec;
3490                   cdata = e_client_cdata_get(ec);
3491                   if (ec && cdata)
3492                     e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
3493                                                                  &cdata->presentation_container);
3494
3495                   e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
3496                                                          &hwc->pp_hwc_window->pending_presentation_callbacks);
3497                }
3498              else
3499                {
3500                   comp_info = _e_hwc_windows_comp_info_get(hwc->pp_update.buffer.tsurface);
3501                   if (comp_info)
3502                     e_presentation_time_container_feedback_merge(&pp_comp_info->presentation_container,
3503                                                                  &comp_info->presentation_container);
3504
3505                   e_hwc_presentation_callback_list_merge(&pp_comp_info->presentation_callbacks,
3506                                                          &comp_info->presentation_callbacks);
3507                }
3508           }
3509      }
3510
3511    return EINA_TRUE;
3512
3513 commit_fail:
3514 attach_fail:
3515    tbm_surface_internal_unref(queue_buffer->tsurface);
3516    tbm_surface_internal_unref(hwc->pp_update.buffer.tsurface);
3517 pp_fail:
3518    if (queue_buffer)
3519      e_hwc_window_queue_buffer_release(hwc->pp_queue, queue_buffer);
3520
3521    EHWSERR("failed _e_hwc_windows_pp_data_commit", hwc);
3522
3523    hwc->pp_commit = EINA_FALSE;
3524
3525    return EINA_FALSE;
3526 }
3527
3528 static void
3529 _e_hwc_windows_sync_callback_call(E_Hwc *hwc)
3530 {
3531    E_Hwc_Sync_Callback *sync_callback;
3532    Eina_List *l, *ll;
3533
3534    EINA_LIST_FOREACH_SAFE(hwc->sync_callback_list, l, ll, sync_callback)
3535      e_hwc_sync_callback_call(sync_callback);
3536 }
3537
3538 static tdm_hwc_commit_interval
3539 _e_hwc_windows_commit_interval_get(E_Hwc *hwc)
3540 {
3541    tdm_error terror;
3542    tdm_hwc_commit_interval interval = TDM_HWC_COMMIT_INTERVAL_NONE;
3543
3544    terror = tdm_hwc_get_commit_interval(hwc->thwc, &interval);
3545    if (terror != TDM_ERROR_NONE)
3546      return TDM_HWC_COMMIT_INTERVAL_NONE;
3547
3548    return interval;
3549 }
3550
3551 static void
3552 _e_hwc_windows_commit_interval_update(E_Hwc *hwc, E_Hwc_Windows_Commit_Data *wins_commit_data)
3553 {
3554    tdm_hwc_commit_interval interval = TDM_HWC_COMMIT_INTERVAL_NONE;
3555    tdm_error terror = TDM_ERROR_NONE;
3556
3557    if (!hwc->wait_commit) return;
3558
3559    interval = _e_hwc_windows_commit_interval_get(hwc);
3560    if (interval == TDM_HWC_COMMIT_INTERVAL_VBLANK)
3561      {
3562         terror = tdm_output_wait_vblank(hwc->output->toutput, 1, 0, _e_hwc_windows_vblank_handler,
3563                                        (void *)hwc);
3564         if (terror != TDM_ERROR_NONE)
3565           {
3566              EHWSERR("fail to tdm_output_wait_vblank", hwc);
3567              return;
3568           }
3569
3570         wins_commit_data->use_vblank_handler = EINA_TRUE;
3571
3572         EHWSTRACE("!!!!!!!! HWC Vblank !!!!!!!!", NULL, hwc);
3573      }
3574 }
3575
3576 EINTERN Eina_Bool
3577 e_hwc_windows_commit(E_Hwc *hwc, E_Output_Display_Mode display_mode)
3578 {
3579    E_Output *output;
3580    tdm_error error = TDM_ERROR_NONE;
3581    int commit_fence_fd = -1;
3582    E_Hwc_Windows_Commit_Data *wins_commit_data;
3583
3584    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3585
3586    output = hwc->output;
3587    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
3588
3589    if (hwc->wait_commit) return EINA_TRUE;
3590
3591    if (e_hwc_norender_get(hwc) > 0)
3592      {
3593         EHWSTRACE("No Render get", NULL, hwc);
3594         return EINA_TRUE;
3595      }
3596
3597    TRACE_DS_BEGIN(e_hwc_windows_commit);
3598
3599    if (!_e_hwc_windows_changes_update(hwc))
3600      goto update_done;
3601
3602    if (output->fake_config)
3603      {
3604         _e_hwc_windows_offscreen_commit(hwc);
3605         goto update_done;
3606      }
3607
3608    if (!_e_hwc_windows_evaluate(hwc, display_mode))
3609      goto re_evaluate;
3610
3611    if (hwc->hwc_mode != E_HWC_MODE_FULL)
3612      {
3613         if (!_e_hwc_windows_target_buffer_prepared(hwc))
3614           goto re_evaluate;
3615      }
3616
3617    if ((output->dpms == E_OUTPUT_DPMS_OFF) || (output->set_dpms == E_OUTPUT_DPMS_OFF))
3618      {
3619         _e_hwc_windows_offscreen_commit(hwc);
3620         goto update_done;
3621      }
3622
3623    if (!(wins_commit_data = _e_hwc_windows_commit_data_acquire(hwc)))
3624      goto update_done;
3625
3626    EHWSTRACE("!!!!!!!! HWC Commit !!!!!!!!", NULL, hwc);
3627    _e_hwc_windows_update_fps(hwc);
3628
3629    _e_hwc_windows_wait_commit_set(hwc, EINA_TRUE);
3630
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);
3633
3634    error = tdm_hwc_commit(hwc->thwc, 0, _e_hwc_windows_commit_handler, wins_commit_data);
3635    if (error != TDM_ERROR_NONE)
3636      {
3637         EHWSERR("tdm_hwc_commit failed", hwc);
3638         _e_hwc_windows_commit_handler(hwc->thwc, 0, 0, 0, wins_commit_data);
3639         goto fail;
3640      }
3641
3642    _e_hwc_windows_commit_interval_update(hwc, wins_commit_data);
3643
3644    if (e_hwc_windows_fence_enabled_get(hwc))
3645      {
3646         error = tdm_hwc_get_commit_fence(hwc->thwc, &commit_fence_fd);
3647         if (error == TDM_ERROR_NONE)
3648           {
3649              if (hwc->commit_fence_fd >= 0)
3650                close(hwc->commit_fence_fd);
3651
3652              hwc->commit_fence_fd = commit_fence_fd;
3653              _e_hwc_windows_release_fence_fd_update(hwc);
3654           }
3655         else
3656           EHWSERR("tdm_hwc_get_commit_sync_fence_fd failed", hwc);
3657      }
3658
3659    /* send tizen_hwc_commit feedback committed */
3660    e_comp_wl_tizen_hwc_committed();
3661    _e_hwc_windows_sync_callback_call(hwc);
3662
3663    TRACE_DS_END();
3664    return EINA_TRUE;
3665
3666 update_done:
3667    if (!hwc->re_evaluate)
3668      {
3669         e_comp_wl_tizen_hwc_discarded();
3670         _e_hwc_windows_sync_callback_call(hwc);
3671      }
3672
3673    TRACE_DS_END();
3674    return EINA_TRUE;
3675
3676 re_evaluate:
3677    TRACE_DS_END();
3678    return EINA_TRUE;
3679
3680 fail:
3681    /* send tizen_hwc_commit feedback discarded */
3682    e_comp_wl_tizen_hwc_discarded();
3683    _e_hwc_windows_wait_commit_set(hwc, EINA_FALSE);
3684
3685    TRACE_DS_END();
3686    return EINA_FALSE;
3687 }
3688
3689 EINTERN Eina_Bool
3690 e_hwc_windows_ecore_evas_set(E_Hwc *hwc, Ecore_Evas *ee)
3691 {
3692    E_Hwc_Window_Target *target_hwc_window;
3693    Evas *evas;
3694    const char *name;
3695
3696    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3697
3698    if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
3699      return EINA_FALSE;
3700
3701    target_hwc_window = hwc->root_target_hwc_window;
3702    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3703
3704    name = ecore_evas_engine_name_get(ee);
3705    EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
3706
3707    evas = ecore_evas_get(ee);
3708    EINA_SAFETY_ON_NULL_RETURN_VAL(evas, EINA_FALSE);
3709
3710    if (!_e_hwc_windows_target_window_queue_set(target_hwc_window))
3711      {
3712         EHWSERR("fail to _e_hwc_windows_target_window_queue_set", NULL);
3713         return EINA_FALSE;
3714      }
3715
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))
3721      {
3722         ecore_evas_manual_render_set(ee, 1);
3723         ecore_evas_show(ee);
3724      }
3725
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);
3733
3734    evas_event_callback_add(evas,
3735                            EVAS_CALLBACK_RENDER_FLUSH_POST,
3736                            _e_hwc_windows_target_window_render_flush_post_cb,
3737                            target_hwc_window);
3738
3739    evas_event_callback_add(evas,
3740                            EVAS_CALLBACK_RENDER_FLUSH_PRE,
3741                            _e_hwc_windows_target_window_render_flush_pre_cb,
3742                            target_hwc_window);
3743
3744    evas_event_callback_add(evas,
3745                            EVAS_CALLBACK_RENDER_PRE,
3746                            _e_hwc_windows_target_window_render_pre_cb,
3747                            target_hwc_window);
3748
3749    ecore_evas_manual_render(target_hwc_window->ee);
3750
3751    return EINA_TRUE;
3752 }
3753
3754 EINTERN E_Hwc_Window_Target *
3755 e_hwc_windows_target_window_new(E_Hwc *hwc, Eina_Bool is_root_target)
3756 {
3757    E_Hwc_Window_Target *target_hwc_window;
3758    E_Hwc_Window *hwc_window;
3759
3760    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
3761    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->thwc, NULL);
3762
3763    if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
3764      return NULL;
3765
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);
3768
3769    hwc_window = (E_Hwc_Window *)target_hwc_window;
3770
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;
3776
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);
3780
3781    target_hwc_window->hwc = hwc;
3782    target_hwc_window->event_fd = -1;
3783
3784    hwc->hwc_windows = eina_list_append(hwc->hwc_windows, target_hwc_window);
3785
3786    return target_hwc_window;
3787 }
3788
3789 EINTERN void
3790 e_hwc_windows_target_window_del(E_Hwc_Window_Target *target_hwc_window)
3791 {
3792    E_Hwc *hwc;
3793
3794    EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
3795
3796    hwc = target_hwc_window->hwc;
3797    EINA_SAFETY_ON_NULL_RETURN(hwc);
3798
3799    hwc->hwc_windows = eina_list_remove(hwc->hwc_windows, hwc->target_hwc_window);
3800    e_object_del(E_OBJECT(hwc->target_hwc_window));
3801 }
3802
3803 EINTERN Eina_Bool
3804 e_hwc_windows_pp_commit_possible_check(E_Hwc *hwc)
3805 {
3806    if (!hwc->pp_set) return EINA_FALSE;
3807
3808    if (hwc->pp_tqueue)
3809      {
3810         if (!tbm_surface_queue_can_dequeue(hwc->pp_tqueue, 0))
3811           return EINA_FALSE;
3812      }
3813
3814    return EINA_TRUE;
3815 }
3816
3817 static void
3818 _e_hwc_windows_pp_aligned_value_get(E_Hwc *hwc, int *aligned_width, int *aligned_height)
3819 {
3820    if (hwc->pp_minw != -1)
3821      {
3822         if (hwc->pp_minw > *aligned_width)
3823           *aligned_width = hwc->pp_minw;
3824      }
3825
3826    if (hwc->pp_minh != -1)
3827      {
3828         if (hwc->pp_minh > *aligned_height)
3829           *aligned_height = hwc->pp_minh;
3830      }
3831
3832    if (hwc->pp_align != -1)
3833      *aligned_width = ROUNDUP(*aligned_width, hwc->pp_align);
3834
3835    if (hwc->pp_align_vertical != -1)
3836      *aligned_height = ROUNDUP(*aligned_height, hwc->pp_align_vertical);
3837 }
3838
3839 EINTERN Eina_Bool
3840 e_hwc_windows_pp_set(E_Hwc *hwc, Eina_Rectangle *src_rect, Eina_Rectangle *dst_rect)
3841 {
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;
3846    int w, h;
3847
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);
3851
3852    e_comp_screen = e_comp->e_comp_screen;
3853    EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp_screen, EINA_FALSE);
3854
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))
3859      return EINA_TRUE;
3860
3861    if (e_comp_screen_pp_support())
3862      {
3863         if (!hwc->tpp)
3864           {
3865              hwc->tpp = tdm_display_create_pp(e_comp_screen->tdisplay, &ret);
3866              EINA_SAFETY_ON_NULL_GOTO(hwc->tpp, fail);
3867
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);
3870
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,
3874                                                &hwc->pp_align);
3875              tdm_display_get_pp_preferred_align_vertical(e_comp_screen->tdisplay, &hwc->pp_align_vertical);
3876
3877              EHWSINF("PP Create tdm_pp:%p", NULL, hwc, hwc->tpp);
3878           }
3879      }
3880
3881    if (!hwc->pp_tqueue)
3882      {
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;
3886
3887         e_output_size_get(hwc->output, &w, &h);
3888
3889         if (e_comp_screen_pp_support())
3890           _e_hwc_windows_pp_aligned_value_get(hwc, &w, &h);
3891
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);
3895
3896         hwc->pp_queue = e_hwc_window_queue_get(hwc->pp_tqueue);
3897         EINA_SAFETY_ON_NULL_GOTO(hwc->pp_queue, fail);
3898
3899         EHWSINF("PP Create pp_tqueue:%p", NULL, hwc, hwc->pp_tqueue);
3900      }
3901
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);
3904
3905    _e_hwc_windows_pp_rect_set(hwc, src_rect, dst_rect);
3906
3907    hwc->pp_set = EINA_TRUE;
3908
3909    return EINA_TRUE;
3910
3911 fail:
3912    if (hwc->tpp)
3913      {
3914         tdm_pp_destroy(hwc->tpp);
3915         hwc->tpp = NULL;
3916      }
3917
3918    if (hwc->pp_tqueue)
3919      {
3920         tbm_surface_queue_destroy(hwc->pp_tqueue);
3921         hwc->pp_tqueue = NULL;
3922      }
3923
3924    return EINA_FALSE;
3925 }
3926
3927 EINTERN void
3928 e_hwc_windows_pp_unset(E_Hwc *hwc)
3929 {
3930    EINA_SAFETY_ON_NULL_RETURN(hwc);
3931
3932    CLEAR(hwc->pp_src_rect);
3933    CLEAR(hwc->pp_dst_rect);
3934
3935    hwc->pp_hwc_window = NULL;
3936    hwc->pp_set = EINA_FALSE;
3937
3938    if (hwc->pp_tqueue)
3939      {
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;
3944      }
3945
3946    if (!hwc->pp_commit)
3947      {
3948         if (hwc->tpp)
3949           {
3950              EHWSINF("PP Destroy tdm_pp:%p", NULL, hwc, hwc->tpp);
3951              tdm_pp_destroy(hwc->tpp);
3952              hwc->tpp = NULL;
3953           }
3954
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);
3958      }
3959
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);
3962 }
3963
3964 EINTERN Eina_Bool
3965 e_hwc_windows_zoom_set(E_Hwc *hwc, Eina_Rectangle *rect)
3966 {
3967    Eina_Rectangle dst_rect;
3968
3969    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3970    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->output, EINA_FALSE);
3971
3972    if (hwc->mirror_src_hwc)
3973      {
3974         ERR("not support zoom in mirror mode");
3975         return EINA_FALSE;
3976      }
3977
3978    memcpy(&hwc->zoom_rect, rect, sizeof(Eina_Rectangle));
3979
3980    dst_rect.x = 0;
3981    dst_rect.y = 0;
3982    dst_rect.w = hwc->output->config.geom.w;
3983    dst_rect.h = hwc->output->config.geom.h;
3984
3985    if (!e_hwc_windows_pp_set(hwc, rect, &dst_rect))
3986      {
3987         ERR("fail to e_hwc_windows_pp_set");
3988         return EINA_FALSE;
3989      }
3990
3991    hwc->zoom_enabled = EINA_TRUE;
3992
3993    return EINA_TRUE;
3994 }
3995
3996 EINTERN void
3997 e_hwc_windows_zoom_unset(E_Hwc *hwc)
3998 {
3999    EINA_SAFETY_ON_NULL_RETURN(hwc);
4000
4001    CLEAR(hwc->zoom_rect);
4002
4003    hwc->zoom_enabled = EINA_FALSE;
4004
4005    if (hwc->mirror_src_hwc)
4006      {
4007         ERR("not support zoom in mirror mode");
4008         return;
4009      }
4010
4011    e_hwc_windows_pp_unset(hwc);
4012 }
4013
4014 // add hwc_window to the render_list
4015 EINTERN void
4016 e_hwc_windows_rendered_window_add(E_Hwc_Window *hwc_window)
4017 {
4018    E_Hwc *hwc;
4019    E_Hwc_Window_Target *root_target_hwc_window;
4020    E_Client *ec;
4021
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);
4025
4026    if (hwc_window->on_rendered_target) return;
4027
4028    ec = hwc_window->ec;
4029    EINA_SAFETY_ON_NULL_RETURN(ec);
4030
4031    hwc = hwc_window->hwc;
4032    EINA_SAFETY_ON_NULL_RETURN(hwc);
4033
4034    root_target_hwc_window = _e_hwc_windows_root_target_hwc_window_get(hwc);
4035    EINA_SAFETY_ON_NULL_RETURN(root_target_hwc_window);
4036
4037    root_target_hwc_window->rendered_windows =
4038            eina_list_append(root_target_hwc_window->rendered_windows, hwc_window);
4039
4040    hwc_window->on_rendered_target = EINA_TRUE;
4041
4042    e_hwc_window_ref(hwc_window);
4043
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));
4046 }
4047
4048 EINTERN Eina_Bool
4049 e_hwc_windows_fps_get(E_Hwc *hwc, double *fps)
4050 {
4051    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4052
4053    if (hwc->old_fps == hwc->fps)
4054      return EINA_FALSE;
4055
4056    if (hwc->fps > 0.0)
4057      {
4058         *fps = hwc->fps;
4059         hwc->old_fps = hwc->fps;
4060         return EINA_TRUE;
4061      }
4062
4063    return EINA_FALSE;
4064 }
4065
4066 EINTERN Eina_Bool
4067 e_hwc_windows_get_available_properties(E_Hwc *hwc, const tdm_prop **props, int *count)
4068 {
4069    tdm_hwc *thwc;
4070    tdm_error ret = TDM_ERROR_OPERATION_FAILED;
4071
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);
4075
4076    thwc = hwc->thwc;
4077    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
4078
4079    ret = tdm_hwc_get_available_properties(thwc, props, count);
4080    EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
4081
4082    return EINA_TRUE;
4083 }
4084
4085 EINTERN Eina_Bool
4086 e_hwc_windows_get_video_available_properties(E_Hwc *hwc, const tdm_prop **props, int *count)
4087 {
4088    tdm_hwc *thwc;
4089    tdm_error ret = TDM_ERROR_OPERATION_FAILED;
4090
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);
4094
4095    thwc = hwc->thwc;
4096    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
4097
4098    ret = tdm_hwc_get_video_available_properties(thwc, props, count);
4099    EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
4100
4101    return EINA_TRUE;
4102 }
4103
4104 EINTERN void
4105 e_hwc_windows_trace_debug(Eina_Bool onoff)
4106 {
4107    if (onoff == ehws_trace) return;
4108    ehws_trace = onoff;
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");
4112 }
4113
4114 E_API void
4115 e_hwc_windows_debug_dump_start(void)
4116 {
4117    if (ehws_dump_enable) return;
4118
4119    ehws_dump_enable = EINA_TRUE;
4120 }
4121
4122 E_API void
4123 e_hwc_windows_debug_dump_stop(void)
4124 {
4125    if (!ehws_dump_enable) return;
4126
4127    ehws_dump_enable = EINA_FALSE;
4128 }
4129
4130 static int
4131 _e_hwc_windows_window_debug_cb_sort(const void *d1, const void *d2)
4132 {
4133    E_Hwc_Window *hwc_window1 = (E_Hwc_Window *)d1;
4134    E_Hwc_Window *hwc_window2 = (E_Hwc_Window *)d2;
4135
4136    if (!hwc_window1) return(1);
4137    if (!hwc_window2) return(-1);
4138
4139    return (hwc_window2->zpos - hwc_window1->zpos);
4140 }
4141
4142 static void
4143 _e_hwc_windows_window_debug_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4144 {
4145    Eldbus_Message_Iter *line_array;
4146    E_Hwc_Window *hwc_window;
4147    E_Comp_Screen *e_comp_screen;
4148    E_Output *output;
4149    E_Hwc *hwc;
4150    Eina_List *l, *l2, *l3;
4151    int idx = 0;
4152    char info_str[1024];
4153    char fmt_str[5];
4154    char flip = ' ';
4155    Eina_Bool vis_skip = EINA_FALSE;
4156    E_Hwc_Window_Update_Data *update;
4157    int pending_idx;
4158
4159    e_comp_screen = e_comp->e_comp_screen;
4160
4161    eldbus_message_iter_arguments_append(iter, "as", &line_array);
4162    if (!e_comp_screen)
4163      {
4164         eldbus_message_iter_basic_append(line_array,
4165                                          's',
4166                                          "e_comp_screen not initialized..");
4167         eldbus_message_iter_container_close(iter, line_array);
4168         return;
4169      }
4170
4171    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
4172      {
4173         if (!output) continue;
4174         if (!output->config.enabled) continue;
4175         if (!output->tdm_hwc) continue;
4176
4177         hwc = output->hwc;
4178         if (!output->hwc) continue;
4179
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);
4185
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         "===============================================================================================");
4195
4196         hwc->hwc_windows = eina_list_sort(hwc->hwc_windows, eina_list_count(hwc->hwc_windows), _e_hwc_windows_window_debug_cb_sort);
4197
4198         EINA_LIST_FOREACH(hwc->hwc_windows, l2, hwc_window)
4199           {
4200              if (!hwc_window) continue;
4201
4202              if ((cmd == E_HWC_WINS_DEBUG_CMD_VIS) && (hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE))
4203                continue;
4204              else if ((cmd == E_HWC_WINS_DEBUG_CMD_DV) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_DEVICE))
4205                continue;
4206              else if ((cmd == E_HWC_WINS_DEBUG_CMD_CL) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_CLIENT))
4207                continue;
4208              else if ((cmd == E_HWC_WINS_DEBUG_CMD_CS) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_CURSOR))
4209                continue;
4210              else if ((cmd == E_HWC_WINS_DEBUG_CMD_VD) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_VIDEO))
4211                continue;
4212              else if ((cmd == E_HWC_WINS_DEBUG_CMD_NO) && (hwc_window->accepted_state != E_HWC_WINDOW_STATE_NONE))
4213                continue;
4214
4215              if (hwc_window->ec)
4216                {
4217                   if ((hwc_window->ec->hwc_visible_skip) || (evas_object_data_get(hwc_window->ec->frame, "comp_skip")))
4218                     vis_skip = EINA_TRUE;
4219                }
4220
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));
4223              else
4224                snprintf(fmt_str, sizeof(fmt_str), "    ");
4225
4226              if (hwc_window->current.buffer.transform > TDM_TRANSFORM_270)
4227                flip = 'F';
4228              else
4229                flip = ' ';
4230
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",
4234                       ++idx,
4235                       e_client_util_win_get(hwc_window->ec),
4236                       (uintptr_t)hwc_window,
4237                       hwc_window->zpos,
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,
4249                       fmt_str,
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,
4254                       flip,
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);
4262
4263              pending_idx = 0;
4264
4265              EINA_LIST_FOREACH(hwc_window->pending_update_list, l3, update)
4266                {
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));
4269                   else
4270                     snprintf(fmt_str, sizeof(fmt_str), "    ");
4271
4272                   if (update->buffer.transform > TDM_TRANSFORM_270)
4273                     flip = 'F';
4274                   else
4275                     flip = ' ';
4276
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",
4281                            ++pending_idx,
4282                            (uintptr_t)update,
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,
4290                            fmt_str,
4291                            update->info.dst_pos.w,
4292                            update->info.dst_pos.h,
4293                            update->info.dst_pos.x,
4294                            update->info.dst_pos.y,
4295                            flip,
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);
4298                }
4299           }
4300
4301         eldbus_message_iter_basic_append(line_array, 's',
4302         "==========================================================================================="
4303         "===============================================================================================");
4304      }
4305
4306    eldbus_message_iter_container_close(iter, line_array);
4307 }
4308
4309 static void
4310 _e_hwc_windows_window_debug_commit_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4311 {
4312    Eldbus_Message_Iter *line_array;
4313    E_Comp_Screen *e_comp_screen;
4314    E_Output *output;
4315    E_Hwc *hwc;
4316    Eina_List *l, *l2;
4317    int idx = 0;
4318    int commit_idx = 0;
4319    char info_str[1024];
4320    E_Hwc_Windows_Commit_Data *wins_commit_data;
4321    E_Hwc_Window_Commit_Data *commit_data;
4322
4323    e_comp_screen = e_comp->e_comp_screen;
4324
4325    eldbus_message_iter_arguments_append(iter, "as", &line_array);
4326    if (!e_comp_screen)
4327      {
4328         eldbus_message_iter_basic_append(line_array,
4329                                          's',
4330                                          "e_comp_screen not initialized..");
4331         eldbus_message_iter_container_close(iter, line_array);
4332         return;
4333      }
4334
4335    EINA_LIST_FOREACH(e_comp_screen->outputs, l, output)
4336      {
4337         if (!output) continue;
4338         if (!output->config.enabled) continue;
4339         if (!output->tdm_hwc) continue;
4340
4341         hwc = output->hwc;
4342         if (!output->hwc) continue;
4343
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);
4349
4350         eldbus_message_iter_basic_append(line_array, 's',
4351         "==========================================================================================="
4352         "=====================");
4353         EINA_LIST_FOREACH(hwc->wins_commit_data_list, l, wins_commit_data)
4354           {
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);
4359
4360              commit_idx = 0;
4361
4362              if (wins_commit_data->target_commit_data)
4363                {
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);
4371                }
4372
4373              EINA_LIST_FOREACH(wins_commit_data->commit_data_list, l2, commit_data)
4374                {
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);
4381                }
4382           }
4383
4384         eldbus_message_iter_basic_append(line_array, 's',
4385         "==========================================================================================="
4386         "=====================");
4387      }
4388
4389    eldbus_message_iter_container_close(iter, line_array);
4390 }
4391
4392 EINTERN void
4393 e_hwc_windows_debug_info_get(Eldbus_Message_Iter *iter, E_Hwc_Wins_Debug_Cmd cmd)
4394 {
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);
4401 }
4402
4403 EINTERN Eina_Bool
4404 e_hwc_windows_mirror_set(E_Hwc *hwc, E_Hwc *src_hwc)
4405 {
4406    Eina_Rectangle src_rect, dst_rect;
4407
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);
4412
4413    if (hwc->zoom_enabled)
4414      {
4415         ERR("not support mirror in zoom mode");
4416         return EINA_FALSE;
4417      }
4418
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;
4423
4424    if (!_e_hwc_windows_capture_position_get(src_hwc,
4425                                             hwc->output->config.geom.w,
4426                                             hwc->output->config.geom.w,
4427                                             &dst_rect))
4428      {
4429         ERR("fail to _e_hwc_windows_capture_position_get");
4430         return EINA_FALSE;
4431      }
4432
4433    if (!e_hwc_windows_pp_set(hwc, &src_rect, &dst_rect))
4434      {
4435         EHWSERR("e_hwc_windows_pp_set failed", hwc);
4436         return EINA_FALSE;
4437      }
4438
4439    /* add mirror_src to the hwc*/
4440    hwc->mirror_src_hwc = src_hwc;
4441
4442    /* add mirror_dst list to the src_hwc */
4443    src_hwc->mirror_dst_hwc = eina_list_append(src_hwc->mirror_dst_hwc, hwc);
4444
4445    EHWSINF("e_hwc_windows_mirror_set src_hwc:%p", NULL, hwc, src_hwc);
4446
4447    return EINA_TRUE;
4448 }
4449
4450 EINTERN void
4451 e_hwc_windows_mirror_unset(E_Hwc *hwc)
4452 {
4453    E_Hwc *src_hwc;
4454
4455    EINA_SAFETY_ON_NULL_RETURN(hwc);
4456
4457    src_hwc = hwc->mirror_src_hwc;
4458    EINA_SAFETY_ON_NULL_RETURN(src_hwc);
4459
4460
4461    /* remove mirror_src at the hwc */
4462    hwc->mirror_src_hwc = NULL;
4463
4464    /* remove mirror_dst list at the src_hwc */
4465    src_hwc->mirror_dst_hwc = eina_list_remove(src_hwc->mirror_dst_hwc, hwc);
4466
4467    if (hwc->zoom_enabled)
4468      {
4469         ERR("not support mirror in zoom mode");
4470         return;
4471      }
4472
4473    e_hwc_windows_pp_unset(hwc);
4474
4475    EHWSINF("e_hwc_windows_mirror_unset", NULL, hwc);
4476 }
4477
4478 EINTERN Eina_Bool
4479 e_hwc_windows_present_sync(E_Hwc *hwc)
4480 {
4481    E_Hwc_Window_Target *root_target_hwc_window;
4482    E_Hwc_Windows_Comp_Info *comp_info;
4483    tbm_surface_h tsurface;
4484    Eina_List *l;
4485
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);
4488
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);
4491
4492    hwc->present_sync = EINA_TRUE;
4493
4494    EINA_LIST_FOREACH(root_target_hwc_window->rendering_tsurfaces, l, tsurface)
4495      {
4496         comp_info = _e_hwc_windows_comp_info_get(tsurface);
4497         if (!comp_info) continue;
4498
4499         comp_info->skip = EINA_TRUE;
4500      }
4501
4502    _e_hwc_windows_target_window_queue_clear(root_target_hwc_window);
4503
4504    _e_hwc_windows_target_window_buffer_skip(hwc);
4505
4506    EHWSINF("Present sync", NULL, hwc);
4507
4508    return EINA_TRUE;
4509 }
4510
4511 EINTERN void
4512 e_hwc_windows_client_type_override(E_Hwc *hwc)
4513 {
4514    E_Hwc_Window *hwc_window;
4515    Eina_List *l;
4516
4517    EINA_SAFETY_ON_NULL_RETURN(hwc);
4518
4519    EINA_LIST_REVERSE_FOREACH(hwc->visible_windows, l, hwc_window)
4520      {
4521         if (hwc_window->is_target) continue;
4522
4523         e_hwc_window_client_type_override(hwc_window);
4524      }
4525
4526    _e_hwc_windows_target_state_set(hwc->target_hwc_window, E_HWC_WINDOW_STATE_DEVICE);
4527 }
4528
4529 EINTERN Eina_Bool
4530 e_hwc_windows_fence_enabled_get(E_Hwc *hwc)
4531 {
4532    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
4533
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;
4537
4538    return EINA_TRUE;
4539 }
4540
4541 EINTERN void
4542 e_hwc_windows_presentation_time_feedback_and_callback_take(E_Hwc *hwc, tbm_surface_h tsurface)
4543 {
4544    E_Hwc_Windows_Comp_Info *comp_info;
4545    E_Hwc_Window_Target *target_hwc_window;
4546
4547    EINA_SAFETY_ON_NULL_RETURN(hwc);
4548    EINA_SAFETY_ON_NULL_RETURN(tsurface);
4549
4550    target_hwc_window = hwc->target_hwc_window;
4551    EINA_SAFETY_ON_NULL_RETURN(target_hwc_window);
4552
4553    comp_info = _e_hwc_windows_comp_info_get(tsurface);
4554    if (comp_info)
4555      {
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);
4560      }
4561 }