ab83cde8464110e8ad1ebe3e84a8f671c2a2b775
[platform/upstream/enlightenment.git] / src / bin / e_hwc_window.c
1 #include "e_hwc_window_intern.h"
2 #include "e_hwc_windows_intern.h"
3 #include "e_hwc_intern.h"
4 #include "e_hwc_window_queue_intern.h"
5 #include "e_comp_wl_buffer_intern.h"
6 #include "e_comp_wl_intern.h"
7 #include "e_comp_wl_subsurface_intern.h"
8 #include "e_comp_wl_tbm_intern.h"
9 #include "e_pointer_intern.h"
10 #include "e_pixmap_intern.h"
11 #include "e_presentation_time_intern.h"
12 #include "services/e_service_quickpanel_intern.h"
13 #include "e_policy_private_data.h"
14 #include "e_policy_visibility_intern.h"
15 #include "e_client_video_intern.h"
16 #include "e_client_intern.h"
17 #include "e_comp_object_intern.h"
18 #include "e_utils_intern.h"
19
20 #include <pixman.h>
21 #include <wayland-tbm-server.h>
22 #include <presentation-time-server-protocol.h>
23
24 #ifndef CLEAR
25 #define CLEAR(x) memset(&(x), 0, sizeof (x))
26 #endif
27
28 #define EHWERR(f, ec, hwc, ehw, x...)                                  \
29    do                                                                  \
30      {                                                                 \
31         if (!ehw)                                                      \
32           ELOGFE("HWC-WIN", "%2d|"f,                                   \
33                  (ec), (e_hwc_output_index_get(hwc)), ##x);            \
34         else                                                           \
35           ELOGFE("HWC-WIN", "%2d|ehw:%8p|"f,                           \
36                  (ec), (e_hwc_output_index_get(hwc)), (ehw), ##x);     \
37      }                                                                 \
38    while (0)
39
40 #define EHWINF(f, ec, hwc, ehw, x...)                                  \
41    do                                                                  \
42      {                                                                 \
43         if (!ehw)                                                      \
44           ELOGF("HWC-WIN", "%2d|"f,                                    \
45                 (ec), (e_hwc_output_index_get(hwc)), ##x);             \
46         else                                                           \
47           ELOGF("HWC-WIN", "%2d|ehw:%8p|"f,                            \
48                 (ec), (e_hwc_output_index_get(hwc)), (ehw), ##x);      \
49      }                                                                 \
50    while (0)
51
52 #define EHWTRACE(f, ec, hwc, ehw, x... )\
53    do                                                                  \
54      {                                                                 \
55         if (ehw_trace)                                                 \
56           {                                                            \
57              if (!ehw)                                                 \
58                ELOGF("HWC-WIN", "%2d|"f,                               \
59                      (ec), (e_hwc_output_index_get(hwc)), ##x);        \
60              else                                                      \
61                ELOGF("HWC-WIN", "%2d|ehw:%8p|"f,                       \
62                      (ec), (e_hwc_output_index_get(hwc)), (ehw), ##x); \
63           }                                                            \
64      }                                                                 \
65    while (0)
66
67 typedef enum _E_Hwc_Window_Restriction
68 {
69    E_HWC_WINDOW_RESTRICTION_NONE,
70    E_HWC_WINDOW_RESTRICTION_DELETED,
71    E_HWC_WINDOW_RESTRICTION_OVERRIDE,
72    E_HWC_WINDOW_RESTRICTION_ANIMATING,
73    E_HWC_WINDOW_RESTRICTION_BUFFER,
74    E_HWC_WINDOW_RESTRICTION_VIEWPORT,
75    E_HWC_WINDOW_RESTRICTION_NEVER_HWC,
76    E_HWC_WINDOW_RESTRICTION_TRANSFORM,
77    E_HWC_WINDOW_RESTRICTION_BUFFER_TYPE,
78    E_HWC_WINDOW_RESTRICTION_OUTPUT,
79    E_HWC_WINDOW_RESTRICTION_MIN_WIDTH,
80    E_HWC_WINDOW_RESTRICTION_MIN_HEIGHT,
81    E_HWC_WINDOW_RESTRICTION_TOUCH_PRESS,
82    E_HWC_WINDOW_RESTRICTION_OUTPUT_TRANSFORM,
83    E_HWC_WINDOW_RESTRICTION_CONTENT_IMAGE,
84    E_HWC_WINDOW_RESTRICTION_QUICKPANEL_OPEN,
85    E_HWC_WINDOW_RESTRICTION_PIXMAP_RESOURCE,
86    E_HWC_WINDOW_RESTRICTION_OBSCURED_BY_TARGET,
87    E_HWC_WINDOW_RESTRICTION_IMAGE_FILTER,
88    E_HWC_WINDOW_RESTRICTION_DESK_GEOMETRY,
89    E_HWC_WINDOW_RESTRICTION_EFFECT_RUNNING,
90    E_HWC_WINDOW_RESTRICTION_RENDER_UPDATE_LOCK,
91    E_HWC_WINDOW_RESTRICTION_DESK_ZOOM,
92    E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA,
93    E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION,
94    E_HWC_WINDOW_RESTRICTION_ZONE,
95    E_HWC_WINDOW_RESTRICTION_QUEUE_UNSET_WAITING,
96 } E_Hwc_Window_Restriction;
97
98 static Eina_Bool ehw_trace = EINA_FALSE;
99 static Eina_List *hwc_window_client_hooks = NULL;
100 static Eina_List *hwc_window_comp_wl_hooks = NULL;
101 static Eina_List *hwc_window_event_hdlrs = NULL;
102 static Eina_List *hwc_window_comp_object_hooks = NULL;
103
104 static int _e_hwc_window_hooks_delete = 0;
105 static int _e_hwc_window_hooks_walking = 0;
106
107 typedef struct _Hwc_Window_Prop
108 {
109    unsigned int id;
110    char name[TDM_NAME_LEN];
111    tdm_value value;
112 } Hwc_Window_Prop;
113
114 static Eina_Inlist *_e_hwc_window_hooks[] =
115 {
116    [E_HWC_WINDOW_HOOK_ACCEPTED_STATE_SET] = NULL,
117 };
118
119 static void
120 _e_hwc_window_hooks_clean(void)
121 {
122    Eina_Inlist *l;
123    E_Hwc_Window_Hook *ch;
124    unsigned int x;
125    for (x = 0; x < E_HWC_WINDOW_HOOK_LAST; x++)
126      EINA_INLIST_FOREACH_SAFE(_e_hwc_window_hooks[x], l, ch)
127        {
128           if (!ch->delete_me) continue;
129           _e_hwc_window_hooks[x] = eina_inlist_remove(_e_hwc_window_hooks[x], EINA_INLIST_GET(ch));
130           free(ch);
131        }
132 }
133
134 static void
135 _e_hwc_window_hook_call(E_Hwc_Window_Hook_Point hookpoint, E_Hwc_Window *hwc_window)
136 {
137    E_Hwc_Window_Hook *ch;
138
139    _e_hwc_window_hooks_walking++;
140    EINA_INLIST_FOREACH(_e_hwc_window_hooks[hookpoint], ch)
141      {
142         if (ch->delete_me) continue;
143         ch->func(ch->data, hwc_window);
144      }
145    _e_hwc_window_hooks_walking--;
146    if ((_e_hwc_window_hooks_walking == 0) && (_e_hwc_window_hooks_delete > 0))
147      _e_hwc_window_hooks_clean();
148 }
149
150 static E_Comp_Wl_Buffer *
151 _e_hwc_window_comp_wl_buffer_get(E_Hwc_Window *hwc_window)
152 {
153    E_Client *ec = hwc_window->ec;
154    E_Comp_Wl_Client_Data *cdata;
155
156    if (!ec) return NULL;
157
158    cdata = e_client_cdata_get(ec);
159    if (!cdata) return NULL;
160
161    return cdata->buffer_ref.buffer;
162 }
163
164 static tdm_hwc_window_composition
165 _get_composition_type(E_Hwc_Window_State state)
166 {
167    tdm_hwc_window_composition composition_type = TDM_HWC_WIN_COMPOSITION_NONE;
168
169    switch (state)
170      {
171       case E_HWC_WINDOW_STATE_NONE:
172         composition_type = TDM_HWC_WIN_COMPOSITION_NONE;
173         break;
174       case E_HWC_WINDOW_STATE_CLIENT:
175         composition_type = TDM_HWC_WIN_COMPOSITION_CLIENT;
176         break;
177       case E_HWC_WINDOW_STATE_DEVICE:
178         composition_type = TDM_HWC_WIN_COMPOSITION_DEVICE;
179         break;
180       case E_HWC_WINDOW_STATE_CURSOR:
181         composition_type = TDM_HWC_WIN_COMPOSITION_CURSOR;
182         break;
183       case E_HWC_WINDOW_STATE_VIDEO:
184         composition_type = TDM_HWC_WIN_COMPOSITION_VIDEO;
185         break;
186       default:
187         composition_type = TDM_HWC_WIN_COMPOSITION_NONE;
188         EHWERR("unknown state of hwc_window", NULL, NULL, NULL);
189      }
190
191    return composition_type;
192 }
193
194 static void
195 _e_hwc_window_buffer_cb_queue_destroy(struct wl_listener *listener, void *data)
196 {
197    E_Hwc_Window_Buffer *window_buffer;
198
199    window_buffer = container_of(listener, E_Hwc_Window_Buffer, queue_destroy_listener);
200    EINA_SAFETY_ON_NULL_RETURN(window_buffer);
201
202    if ((E_Hwc_Window_Queue *)data != window_buffer->queue) return;
203
204    if (window_buffer->queue_destroy_listener.notify)
205      {
206         wl_list_remove(&window_buffer->queue_destroy_listener.link);
207         window_buffer->queue_destroy_listener.notify = NULL;
208      }
209
210    window_buffer->queue = NULL;
211 }
212
213 EINTERN void
214 e_hwc_window_buffer_set(E_Hwc_Window_Buffer *window_buffer,
215                         tbm_surface_h tsurface,
216                         E_Hwc_Window_Queue *queue,
217                         int transform)
218 {
219    EINA_SAFETY_ON_NULL_RETURN(window_buffer);
220
221    if (window_buffer->queue != queue)
222      {
223         if (window_buffer->queue_destroy_listener.notify)
224           {
225              wl_list_remove(&window_buffer->queue_destroy_listener.link);
226              window_buffer->queue_destroy_listener.notify = NULL;
227           }
228
229         if (queue)
230           {
231              wl_signal_add(&queue->destroy_signal, &window_buffer->queue_destroy_listener);
232              window_buffer->queue_destroy_listener.notify = _e_hwc_window_buffer_cb_queue_destroy;
233           }
234      }
235
236    if (queue)
237      window_buffer->from_queue = EINA_TRUE;
238    else
239      window_buffer->from_queue = EINA_FALSE;
240
241    window_buffer->queue = queue;
242    window_buffer->transform = transform;
243
244    if (window_buffer->tsurface)
245      tbm_surface_internal_unref(window_buffer->tsurface);
246
247    window_buffer->tsurface = tsurface;
248    if (tsurface)
249      tbm_surface_internal_ref(tsurface);
250 }
251
252 static void
253 _e_hwc_window_cb_queue_destroy(struct wl_listener *listener, void *data)
254 {
255    E_Hwc_Window *hwc_window;
256
257    hwc_window = container_of(listener, E_Hwc_Window, queue_destroy_listener);
258    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
259
260    if ((E_Hwc_Window_Queue *)data != hwc_window->queue) return;
261
262    if (hwc_window->queue_destroy_listener.notify)
263      {
264         wl_list_remove(&hwc_window->queue_destroy_listener.link);
265         hwc_window->queue_destroy_listener.notify = NULL;
266      }
267
268    hwc_window->queue = NULL;
269    hwc_window->constraints &= ~TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE;
270 }
271
272 static Eina_Bool
273 _e_hwc_window_buffer_queue_set(E_Hwc_Window *hwc_window)
274 {
275    E_Hwc_Window_Queue *queue;
276
277    queue = e_hwc_window_queue_user_set(hwc_window);
278    if (!queue)
279      {
280         EHWERR("fail to e_hwc_window_queue_user_set", hwc_window->ec, hwc_window->hwc, hwc_window);
281         hwc_window->queue = NULL;
282         return EINA_FALSE;
283      }
284
285    if (hwc_window->queue_destroy_listener.notify)
286      {
287         wl_list_remove(&hwc_window->queue_destroy_listener.link);
288         hwc_window->queue_destroy_listener.notify = NULL;
289      }
290
291    wl_signal_add(&queue->destroy_signal, &hwc_window->queue_destroy_listener);
292    hwc_window->queue_destroy_listener.notify = _e_hwc_window_cb_queue_destroy;
293    hwc_window->queue = queue;
294
295    EHWTRACE("Set constranints BUFFER_QUEUE -- {%s}",
296             hwc_window->ec, hwc_window->hwc, hwc_window, e_client_util_name_get(hwc_window->ec));
297
298    return EINA_TRUE;
299 }
300
301 static void
302 _e_hwc_window_buffer_queue_unset(E_Hwc_Window *hwc_window)
303 {
304    /* reset the TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE */
305    if (hwc_window->queue)
306      {
307         e_hwc_window_queue_user_unset(hwc_window->queue, hwc_window);
308
309         if (hwc_window->queue_destroy_listener.notify)
310           {
311              wl_list_remove(&hwc_window->queue_destroy_listener.link);
312              hwc_window->queue_destroy_listener.notify = NULL;
313           }
314
315         hwc_window->queue = NULL;
316      }
317
318     EHWTRACE("Unset constraints BUFFER_QUEUE - {%s}",
319               hwc_window->ec, hwc_window->hwc, hwc_window, e_client_util_name_get(hwc_window->ec));
320 }
321
322 EINTERN void
323 e_hwc_window_constraints_reset(E_Hwc_Window *hwc_window)
324 {
325    if (hwc_window->is_target) return;
326
327    _e_hwc_window_buffer_queue_unset(hwc_window);
328
329    hwc_window->constraints = TDM_HWC_WIN_CONSTRAINT_NONE;
330
331    EHWTRACE("Reset constraints - {%s}",
332             hwc_window->ec, hwc_window->hwc, hwc_window, e_client_util_name_get(hwc_window->ec));
333 }
334
335 static tbm_surface_h
336 _e_hwc_window_client_surface_acquire(E_Hwc_Window *hwc_window)
337 {
338    E_Comp_Wl_Buffer *buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
339    E_Comp_Wl_Data *wl_comp_data = (E_Comp_Wl_Data *)e_comp->wl_comp_data;
340    tbm_surface_h tsurface = NULL;
341
342    if (!buffer) return NULL;
343
344    switch (buffer->type)
345      {
346        case E_COMP_WL_BUFFER_TYPE_SHM:
347        case E_COMP_WL_BUFFER_TYPE_SINGLE_PIXEL:
348          break;
349        case E_COMP_WL_BUFFER_TYPE_NATIVE:
350        case E_COMP_WL_BUFFER_TYPE_VIDEO:
351          tsurface = wayland_tbm_server_get_surface(wl_comp_data->tbm.server, buffer->resource);
352          break;
353        case E_COMP_WL_BUFFER_TYPE_TBM:
354          tsurface = buffer->tbm_surface;
355          break;
356        default:
357          EHWERR("not supported buffer type:%d", hwc_window->ec, hwc_window->hwc, hwc_window, buffer->type);
358          break;
359      }
360
361    return tsurface;
362 }
363
364 static void
365 _e_hwc_window_cb_cursor_buffer_destroy(struct wl_listener *listener, void *data)
366 {
367    E_Hwc_Window *hwc_window;
368
369    hwc_window = container_of(listener, E_Hwc_Window, cursor_buffer_destroy_listener);
370    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
371
372    if ((E_Comp_Wl_Buffer *)data != hwc_window->cursor.buffer) return;
373
374    if (hwc_window->cursor_buffer_destroy_listener.notify)
375      {
376         wl_list_remove(&hwc_window->cursor_buffer_destroy_listener.link);
377         hwc_window->cursor_buffer_destroy_listener.notify = NULL;
378      }
379
380    hwc_window->cursor.buffer = NULL;
381 }
382
383 static Eina_Bool
384 _e_hwc_window_cursor_image_update(E_Hwc_Window *hwc_window)
385 {
386    E_Client *ec = hwc_window->ec;
387    E_Comp_Wl_Buffer *buffer;
388    E_Pointer *pointer;
389    int img_w, img_h, img_stride;
390    void *img_ptr = NULL;
391    tdm_error error;
392
393    pointer = e_pointer_get(ec);
394    buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
395    if (!buffer || !pointer)
396      {
397         if (hwc_window->cursor.img_ptr)
398           {
399              if (hwc_window->cursor_buffer_destroy_listener.notify)
400                {
401                   wl_list_remove(&hwc_window->cursor_buffer_destroy_listener.link);
402                   hwc_window->cursor_buffer_destroy_listener.notify = NULL;
403                }
404
405              hwc_window->cursor.buffer = NULL;
406              hwc_window->cursor.rotation = 0;
407              hwc_window->cursor.img_ptr = NULL;
408              hwc_window->cursor.img_w = 0;
409              hwc_window->cursor.img_h = 0;
410              hwc_window->cursor.img_stride = 0;
411
412              error = tdm_hwc_window_set_cursor_image(hwc_window->thwc_window, 0, 0, 0, NULL);
413              if (error != TDM_ERROR_NONE)
414                {
415                   EHWERR("fail to set cursor image to thwc(%p)", hwc_window->ec, hwc_window->hwc, hwc_window, hwc_window->thwc_window);
416                   return EINA_FALSE;
417                }
418
419              return EINA_TRUE;
420           }
421
422         return EINA_FALSE;
423      }
424
425    /* cursor image is the shm image from the wl_clients */
426    if (buffer->type == E_COMP_WL_BUFFER_TYPE_SHM)
427      {
428         img_ptr = wl_shm_buffer_get_data(buffer->shm_buffer);
429         if (!img_ptr)
430           {
431              EHWERR("Failed get data shm buffer", hwc_window->ec, hwc_window->hwc, hwc_window);
432              return EINA_FALSE;
433           }
434         img_w = wl_shm_buffer_get_width(buffer->shm_buffer);
435         img_h = wl_shm_buffer_get_height(buffer->shm_buffer);
436         img_stride = wl_shm_buffer_get_stride(buffer->shm_buffer);
437      }
438    else
439      {
440         E_Comp_Wl_Client_Data *cdata = e_client_cdata_get(ec);
441         EHWERR("unkown buffer type:%d", NULL, hwc_window->hwc, hwc_window, cdata->buffer_ref.buffer->type);
442         return EINA_FALSE;
443      }
444
445    /* no changes, no need to update the cursor image */
446    if ((hwc_window->cursor.buffer == buffer) &&
447        (hwc_window->cursor.rotation == pointer->rotation))
448      return EINA_FALSE;
449
450    error = tdm_hwc_window_set_cursor_image(hwc_window->thwc_window, img_w, img_h, img_stride, img_ptr);
451    if (error != TDM_ERROR_NONE)
452      {
453         EHWERR("fail to set cursor image to thwc(%p)", hwc_window->ec, hwc_window->hwc, hwc_window, hwc_window->thwc_window);
454         return EINA_FALSE;
455      }
456
457    if (hwc_window->cursor_buffer_destroy_listener.notify)
458      {
459         wl_list_remove(&hwc_window->cursor_buffer_destroy_listener.link);
460         hwc_window->cursor_buffer_destroy_listener.notify = NULL;
461      }
462
463    hwc_window->cursor.buffer = buffer;
464    wl_signal_add(&buffer->destroy_signal, &hwc_window->cursor_buffer_destroy_listener);
465    hwc_window->cursor_buffer_destroy_listener.notify = _e_hwc_window_cb_cursor_buffer_destroy;
466    hwc_window->cursor.rotation = pointer->rotation;
467    hwc_window->cursor.img_ptr = img_ptr;
468    hwc_window->cursor.img_w = img_w;
469    hwc_window->cursor.img_h = img_h;
470    hwc_window->cursor.img_stride = img_stride;
471
472    return EINA_TRUE;
473 }
474
475 static void
476 _e_hwc_window_cursor_position_get(E_Pointer *ptr, E_Output *output, int width, int height, unsigned int *x, unsigned int *y)
477 {
478    int rotation;
479    int hot_x, hot_y;
480    float ratio_w, ratio_h;
481
482    rotation = ptr->rotation;
483
484    hot_x = ptr->hot.x;
485    hot_y = ptr->hot.y;
486
487    if (e_config->cursor_configured_output_resolution.use)
488      {
489         ratio_w = (float)output->config.geom.w / (float)e_config->cursor_configured_output_resolution.w;
490         ratio_h = (float)output->config.geom.h / (float)e_config->cursor_configured_output_resolution.h;
491
492         if ((ratio_w > 1.0) && (ratio_h > 1.0))
493           {
494              hot_x = (int)((float)hot_x * (float)ratio_w);
495              hot_y = (int)((float)hot_y * (float)ratio_h);
496           }
497      }
498
499    switch (rotation)
500      {
501       case 0:
502         *x = ptr->x - hot_x;
503         *y = ptr->y - hot_y;
504         break;
505       case 90:
506         *x = ptr->x - hot_y;
507         *y = ptr->y + hot_x - width;
508         break;
509       case 180:
510         *x = ptr->x + hot_x - width;
511         *y = ptr->y + hot_y - height;
512         break;
513       case 270:
514         *x = ptr->x + hot_y - height;
515         *y = ptr->y - hot_x;
516         break;
517       default:
518         *x = ptr->x - hot_x;
519         *y = ptr->y - hot_y;
520         break;
521      }
522 }
523
524 static void
525 _e_hwc_window_update_fps(E_Hwc_Window *hwc_window)
526 {
527    if (e_comp->calc_fps)
528      {
529         double dt;
530         double tim = ecore_time_get();
531
532         dt = tim - hwc_window->fps.frametimes[0];
533         hwc_window->fps.frametimes[0] = tim;
534
535         hwc_window->fps.time += dt;
536         hwc_window->fps.cframes++;
537
538         if (hwc_window->fps.lapse == 0.0)
539           {
540              hwc_window->fps.lapse = tim;
541              hwc_window->fps.flapse = hwc_window->fps.cframes;
542           }
543         else if ((tim - hwc_window->fps.lapse) >= 0.5)
544           {
545              hwc_window->fps.fps = (hwc_window->fps.cframes - hwc_window->fps.flapse) /
546                                    (tim - hwc_window->fps.lapse);
547              hwc_window->fps.lapse = tim;
548              hwc_window->fps.flapse = hwc_window->fps.cframes;
549              hwc_window->fps.time = 0.0;
550           }
551      }
552 }
553
554 static void
555 _e_hwc_window_cb_zone_del(void *data, void *obj)
556 {
557    E_Hwc_Window *hwc_window = (E_Hwc_Window *)data;
558
559    hwc_window->zone_delfn = NULL;
560    hwc_window->zone = NULL;
561 }
562
563 static void
564 _e_hwc_window_zone_set(E_Hwc_Window *hwc_window, E_Zone *zone)
565 {
566    if (hwc_window->zone == zone) return;
567
568    if (hwc_window->zone)
569      {
570         if (hwc_window->zone_delfn)
571           {
572              e_object_delfn_del(E_OBJECT(hwc_window->zone), hwc_window->zone_delfn);
573              hwc_window->zone_delfn = NULL;
574           }
575
576         hwc_window->zone = NULL;
577      }
578
579    if (zone)
580      {
581         hwc_window->zone_delfn = e_object_delfn_add(E_OBJECT(zone),
582                                                     _e_hwc_window_cb_zone_del,
583                                                     hwc_window);
584         hwc_window->zone = zone;
585      }
586 }
587
588 static void
589 _e_hwc_window_free(E_Hwc_Window *hwc_window)
590 {
591    E_Hwc *hwc;
592    Hwc_Window_Prop *prop;
593
594    EHWINF("Free", NULL, hwc_window->hwc, hwc_window);
595
596    hwc = hwc_window->hwc;
597    if (hwc)
598      hwc->hwc_windows = eina_list_remove(hwc->hwc_windows, hwc_window);
599
600    e_presentation_time_container_finish(&hwc_window->presentation_container);
601    e_hwc_presentation_callback_list_finish(&hwc_window->pending_presentation_callbacks);
602    e_hwc_presentation_callback_list_finish(&hwc_window->presentation_callbacks);
603
604    if(hwc_window->prop_list)
605      {
606         EINA_LIST_FREE(hwc_window->prop_list, prop)
607           {
608              free(prop);
609           }
610      }
611
612    if (hwc_window->thwc_window)
613      tdm_hwc_window_destroy(hwc_window->thwc_window);
614
615    if (hwc_window->cqueue)
616      wayland_tbm_server_client_queue_set_destroy_cb(hwc_window->cqueue,
617                                                     NULL,
618                                                     NULL);
619
620    _e_hwc_window_zone_set(hwc_window, NULL);
621
622    if (hwc_window->cursor_buffer_destroy_listener.notify)
623      {
624         wl_list_remove(&hwc_window->cursor_buffer_destroy_listener.link);
625         hwc_window->cursor_buffer_destroy_listener.notify = NULL;
626      }
627
628    if (hwc_window->queue_destroy_listener.notify)
629      {
630         wl_list_remove(&hwc_window->queue_destroy_listener.link);
631         hwc_window->queue_destroy_listener.notify = NULL;
632      }
633
634    e_comp_wl_buffer_reference(&hwc_window->current.buffer_ref, NULL);
635    e_comp_wl_buffer_reference(&hwc_window->commit.buffer_ref, NULL);
636    e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
637
638    e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, NULL);
639    e_hwc_window_queue_buffer_reference(&hwc_window->commit.queue_buffer_ref, NULL);
640    e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
641
642    e_hwc_window_buffer_set(&hwc_window->current.buffer, NULL, NULL, 0);
643    e_hwc_window_buffer_set(&hwc_window->commit.buffer, NULL, NULL, 0);
644    e_hwc_window_buffer_set(&hwc_window->display.buffer, NULL, NULL, 0);
645
646    E_FREE(hwc_window);
647 }
648
649 static void
650 _e_hwc_window_del(E_Hwc_Window *hwc_window)
651 {
652    E_Client *ec;
653
654    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
655
656    EHWINF("Del", hwc_window->ec, hwc_window->hwc, hwc_window);
657
658    ec = hwc_window->ec;
659    EINA_SAFETY_ON_NULL_RETURN(ec);
660
661    ec->hwc_window = NULL;
662    hwc_window->ec = NULL;
663    hwc_window->is_deleted = EINA_TRUE;
664
665    /* if delfn is called, ec_delfn should be set null
666     * before we get here */
667    if (hwc_window->ec_delfn)
668      {
669         e_object_delfn_del(E_OBJECT(ec), hwc_window->ec_delfn);
670         hwc_window->ec_delfn = NULL;
671      }
672
673    if (hwc_window->queue)
674      {
675         e_hwc_window_queue_user_unset(hwc_window->queue, hwc_window);
676
677         if (hwc_window->queue_destroy_listener.notify)
678           {
679              wl_list_remove(&hwc_window->queue_destroy_listener.link);
680              hwc_window->queue_destroy_listener.notify = NULL;
681           }
682
683         hwc_window->queue = NULL;
684      }
685
686    e_hwc_window_below_transparent_obj_set(hwc_window, EINA_FALSE);
687    e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_NONE, EINA_TRUE);
688
689    e_object_del(E_OBJECT(hwc_window));
690 }
691
692 static void
693 _e_hwc_window_cb_ec_free(void *data, void *obj)
694 {
695    E_Client *ec = (E_Client *)obj;
696
697    EINA_SAFETY_ON_NULL_RETURN(ec);
698
699    if (ec->hwc_window)
700      {
701         /* if delfn is called, ec_delfn should be set null */
702         ec->hwc_window->ec_delfn = NULL;
703         _e_hwc_window_del(ec->hwc_window);
704      }
705 }
706
707 static E_Hwc_Window *
708 _e_hwc_window_new(E_Hwc *hwc, E_Client *ec, E_Hwc_Window_State state)
709 {
710    E_Hwc_Window *hwc_window;
711    tdm_hwc *thwc;;
712    tdm_error error;
713
714    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
715    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
716    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), NULL);
717
718    if (ec->hwc_window) goto end;
719
720    thwc = hwc->thwc;
721    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc, EINA_FALSE);
722
723    hwc_window = E_OBJECT_ALLOC(E_Hwc_Window, E_HWC_WINDOW_TYPE, _e_hwc_window_free);
724    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
725
726    hwc_window->hwc = hwc;
727    hwc_window->zpos = E_HWC_WINDOW_ZPOS_NONE;
728    hwc_window->render_target = EINA_TRUE;
729    hwc_window->device_state_available = EINA_TRUE;
730
731    hwc_window->thwc_window = tdm_hwc_create_window(thwc, &error);
732    if (error != TDM_ERROR_NONE)
733      {
734         EHWERR("cannot create tdm_hwc_window for thwc(%p)", hwc_window->ec, hwc_window->hwc, hwc_window, thwc);
735         E_FREE(hwc_window);
736         return NULL;
737      }
738
739    /* cursor window */
740    if (e_policy_client_is_cursor(ec))
741      hwc_window->is_cursor = EINA_TRUE;
742
743    /* set the hwc window to the e client */
744    hwc_window->ec = ec;
745    hwc_window->ec_delfn = e_object_delfn_add(E_OBJECT(ec),
746                                              _e_hwc_window_cb_ec_free,
747                                              NULL);
748    ec->hwc_window = hwc_window;
749
750    hwc->hwc_windows = eina_list_append(hwc->hwc_windows, hwc_window);
751
752    e_presentation_time_container_init(&hwc_window->presentation_container);
753    e_hwc_presentation_callback_list_init(&hwc_window->pending_presentation_callbacks);
754    e_hwc_presentation_callback_list_init(&hwc_window->presentation_callbacks);
755
756    EHWINF("is created on eout:%p, video:%d cursor:%d",
757           hwc_window->ec, hwc_window->hwc, hwc_window, hwc->output,
758           hwc_window->is_video, hwc_window->is_cursor);
759
760 end:
761    /* video window */
762    if (state == E_HWC_WINDOW_STATE_VIDEO)
763      ec->hwc_window->is_video = EINA_TRUE;
764
765    e_hwc_window_state_set(ec->hwc_window, state, EINA_TRUE);
766
767    return ec->hwc_window;
768 }
769
770 static void
771 _e_hwc_window_client_cb_del(void *data EINA_UNUSED, E_Client *ec)
772 {
773    E_Hwc_Window *hwc_window;
774    E_Output *output;
775    E_Zone *zone;
776
777    EINA_SAFETY_ON_NULL_RETURN(ec);
778
779    if (!(hwc_window = ec->hwc_window)) return;
780
781    zone = hwc_window->zone;
782    EINA_SAFETY_ON_NULL_RETURN(zone);
783    EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
784
785    output = e_output_find(zone->output_id);
786    EINA_SAFETY_ON_NULL_RETURN(output);
787
788    /* If an e_client belongs to the e_output managed by hwc_plane policy,
789     * there's no need to deal with hwc_windows. */
790    if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
791      return;
792
793    if (e_hwc_window_is_video(hwc_window)) return;
794
795    e_hwc_window_client_type_override(hwc_window);
796 }
797
798 static void
799 _e_hwc_window_client_subsurface_present_sync(E_Client *ec)
800 {
801    E_Hwc_Window_State state;
802    Eina_List *l;
803    E_Client *subc;
804
805    if (!ec->hwc_window) return;
806
807    state = e_hwc_window_accepted_state_get(ec->hwc_window);
808    if ((state == E_HWC_WINDOW_STATE_DEVICE) || (state == E_HWC_WINDOW_STATE_VIDEO))
809      e_hwc_window_present_sync(ec->hwc_window);
810
811    EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
812      {
813         if (!subc->hwc_window) continue;
814         _e_hwc_window_client_subsurface_present_sync(subc);
815      }
816
817    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
818      {
819         if (!subc->hwc_window) continue;
820         _e_hwc_window_client_subsurface_present_sync(subc);
821      }
822 }
823
824 static void
825 _e_hwc_window_client_cb_transform_change(void *data EINA_UNUSED, E_Client *ec)
826 {
827    E_Output *output;
828    E_Zone *zone;
829    E_Client *topmost;
830    Eina_List *l;
831    E_Client *subc;
832    E_Hwc_Window_State state;
833    E_Hwc_Window *hwc_window;
834
835    EINA_SAFETY_ON_NULL_RETURN(ec);
836
837    if (!(hwc_window = ec->hwc_window)) return;
838
839    zone = hwc_window->zone;
840    EINA_SAFETY_ON_NULL_RETURN(zone);
841    EINA_SAFETY_ON_NULL_RETURN(zone->output_id);
842
843    output = e_output_find(zone->output_id);
844    EINA_SAFETY_ON_NULL_RETURN(output);
845
846    /* If an e_client belongs to the e_output managed by hwc_plane policy,
847     * there's no need to deal with hwc_windows. */
848    if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES) return;
849
850    if (!e_comp_wl_video_subsurface_has(ec) && !e_comp_wl_normal_subsurface_has(ec))
851      return;
852
853    topmost = e_comp_wl_topmost_parent_get(ec);
854    if (topmost != ec) return;
855
856    /* if window is device state, sync is not needed */
857    state = e_hwc_window_accepted_state_get(ec->hwc_window);
858    if (state != E_HWC_WINDOW_STATE_CLIENT) return;
859
860    EINA_LIST_FOREACH(ec->comp_data->sub.below_list_pending, l, subc)
861      {
862         if (!subc->hwc_window) continue;
863         _e_hwc_window_client_subsurface_present_sync(subc);
864      }
865
866    EINA_LIST_FOREACH(ec->comp_data->sub.below_list, l, subc)
867      {
868         if (!subc->hwc_window) continue;
869         _e_hwc_window_client_subsurface_present_sync(subc);
870      }
871 }
872
873 static Eina_Bool
874 _e_hwc_window_client_cb_zone_set(void *data, int type, void *event)
875 {
876    E_Event_Client_Zone_Set *ev;
877    E_Client *ec;
878    E_Zone *zone;
879    E_Output *output;
880    E_Hwc_Window *hwc_window;
881    Eina_Bool is_video = EINA_FALSE;
882
883    ev = event;
884    EINA_SAFETY_ON_NULL_RETURN_VAL(ev, ECORE_CALLBACK_PASS_ON);
885
886    ec = ev->ec;
887    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, ECORE_CALLBACK_PASS_ON);
888
889    zone = ev->zone;
890    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, ECORE_CALLBACK_PASS_ON);
891    EINA_SAFETY_ON_NULL_RETURN_VAL(zone->output_id, ECORE_CALLBACK_PASS_ON);
892
893    output = e_output_find(zone->output_id);
894    EINA_SAFETY_ON_NULL_RETURN_VAL(output, ECORE_CALLBACK_PASS_ON);
895
896    /* If an e_client belongs to the e_output managed by hwc_plane policy,
897     * there's no need to deal with hwc_windows. */
898    if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
899      return ECORE_CALLBACK_PASS_ON;
900
901    if (e_object_is_del(E_OBJECT(ec)))
902      return ECORE_CALLBACK_PASS_ON;
903
904    hwc_window = ec->hwc_window;
905    if (hwc_window)
906      {
907         if (hwc_window->hwc == output->hwc) goto done;
908
909         is_video = e_hwc_window_is_video(hwc_window);
910         _e_hwc_window_del(hwc_window);
911      }
912
913    hwc_window = _e_hwc_window_new(output->hwc, ec, E_HWC_WINDOW_STATE_NONE);
914    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, ECORE_CALLBACK_PASS_ON);
915
916    if (is_video) e_hwc_window_video_set(hwc_window, is_video);
917
918    EHWINF("set on eout:%p, zone_id:%d",
919           ec, hwc_window->hwc, hwc_window, output, zone->id);
920
921 done:
922    _e_hwc_window_zone_set(hwc_window, zone);
923
924    return ECORE_CALLBACK_PASS_ON;
925 }
926
927 static void
928 _e_hwc_window_cb_subsurface_synchronized_commit(void *data, E_Client *ec)
929 {
930    E_Client *parent;
931    E_Hwc_Window_State state;
932    Eina_Bool need_sync = EINA_FALSE;
933
934    EINA_SAFETY_ON_NULL_RETURN(ec);
935    if ((!ec->hwc_window) || (!e_comp_wl_subsurface_check(ec))) return;
936
937    state = e_hwc_window_accepted_state_get(ec->hwc_window);
938    if ((state != E_HWC_WINDOW_STATE_DEVICE) && (state != E_HWC_WINDOW_STATE_VIDEO))
939      return;
940
941    parent = e_comp_wl_subsurface_parent_get(ec);
942    while (parent)
943      {
944         state = e_hwc_window_accepted_state_get(parent->hwc_window);
945         if (state == E_HWC_WINDOW_STATE_CLIENT)
946           {
947              need_sync = EINA_TRUE;
948              break;
949           }
950
951         if (!e_comp_wl_subsurface_check(parent))
952             break;
953
954         parent = e_comp_wl_subsurface_parent_get(parent);
955      }
956
957    if (need_sync)
958      e_hwc_window_present_sync(ec->hwc_window);
959 }
960
961 static Eina_Bool
962 _e_hwc_window_cb_update_lock_set(void *data, E_Client *ec)
963 {
964    E_Hwc_Window *hwc_window;
965
966    if (e_object_is_del(E_OBJECT(ec))) return EINA_TRUE;
967
968    hwc_window = ec->hwc_window;
969    if (!hwc_window) return EINA_TRUE;
970
971    e_hwc_window_client_type_override(hwc_window);
972
973    return EINA_TRUE;
974 }
975
976 EINTERN Eina_Bool
977 e_hwc_window_init(void)
978 {
979    E_LIST_HOOK_APPEND(hwc_window_client_hooks, E_CLIENT_HOOK_DEL,
980                       _e_hwc_window_client_cb_del, NULL);
981    E_LIST_HOOK_APPEND(hwc_window_client_hooks, E_CLIENT_HOOK_TRANSFORM_CHANGE,
982                       _e_hwc_window_client_cb_transform_change, NULL);
983    E_LIST_HANDLER_APPEND(hwc_window_event_hdlrs, E_EVENT_CLIENT_ZONE_SET,
984                          _e_hwc_window_client_cb_zone_set, NULL);
985    E_COMP_WL_HOOK_APPEND(hwc_window_comp_wl_hooks, E_COMP_WL_HOOK_SUBSURFACE_SYNCHRONIZED_COMMIT,
986                          _e_hwc_window_cb_subsurface_synchronized_commit, NULL);
987    E_COMP_COMP_HOOK_APPEND(hwc_window_comp_object_hooks, E_COMP_OBJECT_HOOK_RENDER_UPDATE_LOCK_SET,
988                            _e_hwc_window_cb_update_lock_set, NULL);
989
990    return EINA_TRUE;
991 }
992
993 EINTERN void
994 e_hwc_window_deinit(void)
995 {
996    E_FREE_LIST(hwc_window_client_hooks, e_client_hook_del);
997    E_FREE_LIST(hwc_window_event_hdlrs, ecore_event_handler_del);
998    E_FREE_LIST(hwc_window_comp_wl_hooks, e_comp_wl_hook_del);
999    E_FREE_LIST(hwc_window_comp_object_hooks, e_comp_object_hook_del);
1000 }
1001
1002 EINTERN E_Hwc_Window *
1003 e_hwc_window_get(E_Hwc *hwc, E_Client *ec)
1004 {
1005    E_Hwc_Window *hwc_window;
1006
1007    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
1008    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
1009
1010    if (ec->hwc_window)
1011      return ec->hwc_window;
1012
1013    hwc_window = _e_hwc_window_new(hwc, ec, E_HWC_WINDOW_STATE_NONE);
1014    if (!hwc_window)
1015      {
1016         EHWERR("failed to e_hwc_window_new", ec, hwc, NULL);
1017         return NULL;
1018      }
1019
1020    return hwc_window;
1021 }
1022
1023 EINTERN Eina_Bool
1024 e_hwc_window_zpos_set(E_Hwc_Window *hwc_window, int zpos)
1025 {
1026    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1027
1028    if (hwc_window->zpos != zpos) hwc_window->zpos = zpos;
1029
1030    return EINA_TRUE;
1031 }
1032
1033 EINTERN int
1034 e_hwc_window_zpos_get(E_Hwc_Window *hwc_window)
1035 {
1036    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1037
1038    if (hwc_window->state == E_HWC_WINDOW_STATE_NONE) return -999;
1039
1040    return hwc_window->zpos;
1041 }
1042
1043 EINTERN Eina_Bool
1044 e_hwc_window_composition_update(E_Hwc_Window *hwc_window)
1045 {
1046    tdm_hwc_window *thwc_window;
1047    tdm_hwc_window_composition composition_type;
1048    tdm_error error;
1049
1050    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1051
1052    if (e_hwc_window_is_target(hwc_window))
1053      {
1054         EHWERR("target window cannot update at e_hwc_window_composition_update", hwc_window->ec, hwc_window->hwc, hwc_window);
1055         return EINA_FALSE;
1056      }
1057
1058    thwc_window = hwc_window->thwc_window;
1059    EINA_SAFETY_ON_NULL_RETURN_VAL(thwc_window, EINA_FALSE);
1060
1061    /* set composition type */
1062    composition_type = _get_composition_type(hwc_window->state);
1063    error = tdm_hwc_window_set_composition_type(hwc_window->thwc_window, composition_type);
1064    EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
1065
1066    return EINA_TRUE;
1067 }
1068
1069 EINTERN Eina_Bool
1070 e_hwc_window_is_target(E_Hwc_Window *hwc_window)
1071 {
1072    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1073
1074    return hwc_window->is_target;
1075 }
1076
1077 EINTERN Eina_Bool
1078 e_hwc_window_is_video(E_Hwc_Window *hwc_window)
1079 {
1080    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1081
1082    return hwc_window->is_video;
1083 }
1084
1085 EINTERN Eina_Bool
1086 e_hwc_window_is_cursor(E_Hwc_Window *hwc_window)
1087 {
1088    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1089
1090    return hwc_window->is_cursor;
1091 }
1092
1093 EINTERN Eina_Bool
1094 e_hwc_window_video_set(E_Hwc_Window *hwc_window, Eina_Bool set)
1095 {
1096    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1097
1098    hwc_window->is_video = set;
1099
1100    return EINA_TRUE;
1101 }
1102
1103 static Eina_Bool
1104 _e_hwc_window_cursor_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
1105 {
1106    E_Hwc *hwc;
1107    E_Output *output;
1108    E_Client *ec;
1109    E_Pointer *pointer;
1110    E_Zone *zone;
1111    int rotation;
1112
1113    if (!e_hwc_window_is_cursor(hwc_window)) return EINA_FALSE;
1114
1115    hwc = hwc_window->hwc;
1116    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1117
1118    output = hwc->output;
1119    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1120
1121    ec = hwc_window->ec;
1122    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1123    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
1124
1125    zone = hwc_window->zone;
1126    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1127
1128    pointer = e_pointer_get(ec);
1129    if (!pointer) return EINA_TRUE;
1130
1131    hwc_win_info->src_config.format = TBM_FORMAT_ARGB8888;
1132    hwc_win_info->src_config.pos.x = 0;
1133    hwc_win_info->src_config.pos.y = 0;
1134    hwc_win_info->src_config.pos.w = hwc_window->cursor.img_w;
1135    hwc_win_info->src_config.pos.h = hwc_window->cursor.img_h;
1136
1137    hwc_win_info->src_config.size.h = hwc_window->cursor.img_stride >> 2;
1138    EINA_SAFETY_ON_TRUE_RETURN_VAL(hwc_win_info->src_config.size.h == 0, EINA_FALSE);
1139    hwc_win_info->src_config.size.v = hwc_window->cursor.img_h;
1140
1141    _e_hwc_window_cursor_position_get(pointer, output,
1142                                      hwc_win_info->src_config.pos.w,
1143                                      hwc_win_info->src_config.pos.h,
1144                                      &hwc_win_info->dst_pos.x,
1145                                      &hwc_win_info->dst_pos.y);
1146
1147    if (output->config.rotation > 0)
1148      {
1149         int bw, bh;
1150         int dst_x, dst_y;
1151
1152         e_pixmap_size_get(ec->pixmap, &bw, &bh);
1153         e_comp_wl_rect_convert(zone->w, zone->h,
1154                                output->config.rotation / 90, 1,
1155                                hwc_win_info->dst_pos.x, hwc_win_info->dst_pos.y,
1156                                bw, bh,
1157                                &dst_x, &dst_y,
1158                                NULL, NULL);
1159
1160         hwc_win_info->dst_pos.x = dst_x;
1161         hwc_win_info->dst_pos.y = dst_y;
1162      }
1163
1164    hwc_win_info->dst_pos.x -= zone->x;
1165    hwc_win_info->dst_pos.y -= zone->y;
1166
1167    hwc_win_info->dst_pos.w = hwc_window->cursor.img_w;
1168    hwc_win_info->dst_pos.h = hwc_window->cursor.img_h;
1169
1170    rotation = (hwc_window->cursor.rotation + output->config.rotation) % 360;
1171    switch (rotation)
1172      {
1173       case 0:
1174         hwc_win_info->transform = TDM_TRANSFORM_NORMAL;
1175         break;
1176       case 90:
1177         hwc_win_info->transform = TDM_TRANSFORM_90;
1178         break;
1179       case 180:
1180         hwc_win_info->transform = TDM_TRANSFORM_180;
1181         break;
1182       case 270:
1183         hwc_win_info->transform = TDM_TRANSFORM_270;
1184         break;
1185       default:
1186         hwc_win_info->transform = TDM_TRANSFORM_NORMAL;
1187         break;
1188      }
1189
1190    return EINA_TRUE;
1191 }
1192
1193 static Eina_Bool
1194 _e_hwc_window_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
1195 {
1196    E_Hwc *hwc;
1197    E_Output *output;
1198    E_Client *ec;
1199    tbm_surface_h tsurface;
1200    tbm_surface_info_s surf_info = {0};
1201    E_Zone *zone;
1202    int transform;
1203    int x, y, w, h;
1204
1205    ec = hwc_window->ec;
1206    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1207    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
1208
1209    hwc = hwc_window->hwc;
1210    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1211
1212    zone = hwc_window->zone;
1213    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1214
1215    output = hwc->output;
1216    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1217
1218    tsurface = hwc_window->current.buffer.tsurface;
1219    if (!tsurface) return EINA_TRUE;
1220
1221    tbm_surface_get_info(tsurface, &surf_info);
1222
1223    hwc_win_info->src_config.format = surf_info.format;
1224    hwc_win_info->src_config.pos.x = 0;
1225    hwc_win_info->src_config.pos.y = 0;
1226    hwc_win_info->src_config.pos.w = surf_info.width;
1227    hwc_win_info->src_config.pos.h = surf_info.height;
1228
1229    hwc_win_info->src_config.size.h = e_comp_wl_tbm_aligned_width_get(tsurface);
1230    EINA_SAFETY_ON_TRUE_RETURN_VAL(hwc_win_info->src_config.size.h == 0, EINA_FALSE);
1231    hwc_win_info->src_config.size.v = surf_info.height;
1232
1233    e_client_geometry_get(ec, &x, &y, &w, &h);
1234
1235    hwc_win_info->dst_pos.x = x - zone->x;
1236    hwc_win_info->dst_pos.y = y - zone->y;
1237
1238    if (output->config.rotation > 0)
1239      {
1240         int bw, bh;
1241         int dst_x, dst_y;
1242
1243         e_pixmap_size_get(ec->pixmap, &bw, &bh);
1244         e_comp_wl_rect_convert(zone->w, zone->h,
1245                                output->config.rotation / 90, 1,
1246                                hwc_win_info->dst_pos.x, hwc_win_info->dst_pos.y,
1247                                bw, bh,
1248                                &dst_x, &dst_y,
1249                                NULL, NULL);
1250
1251         hwc_win_info->dst_pos.x = dst_x;
1252         hwc_win_info->dst_pos.y = dst_y;
1253      }
1254
1255    transform = e_comp_wl_output_buffer_transform_get(ec);
1256    switch (transform)
1257      {
1258       case WL_OUTPUT_TRANSFORM_90:
1259       case WL_OUTPUT_TRANSFORM_FLIPPED_90:
1260       case WL_OUTPUT_TRANSFORM_270:
1261       case WL_OUTPUT_TRANSFORM_FLIPPED_270:
1262         hwc_win_info->dst_pos.w = h;
1263         hwc_win_info->dst_pos.h = w;
1264         break;
1265       default:
1266         hwc_win_info->dst_pos.w = w;
1267         hwc_win_info->dst_pos.h = h;
1268         break;
1269      }
1270
1271    hwc_win_info->transform = TDM_TRANSFORM_NORMAL;
1272
1273    return EINA_TRUE;
1274 }
1275
1276 static Eina_Bool
1277 _e_hwc_window_target_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
1278 {
1279    E_Output *output;
1280    tbm_surface_h tsurface;
1281    tbm_surface_info_s surf_info = {0};
1282
1283    if (!e_hwc_window_is_target(hwc_window)) return EINA_FALSE;
1284
1285    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
1286
1287    output = hwc_window->hwc->output;
1288    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1289
1290    tsurface = hwc_window->current.buffer.tsurface;
1291    if (!tsurface) return EINA_TRUE;
1292
1293    tbm_surface_get_info(tsurface, &surf_info);
1294
1295    hwc_win_info->src_config.size.h = e_comp_wl_tbm_aligned_width_get(tsurface);
1296    EINA_SAFETY_ON_TRUE_RETURN_VAL(hwc_win_info->src_config.size.h == 0, EINA_FALSE);
1297    hwc_win_info->src_config.size.v = surf_info.height;
1298    hwc_win_info->src_config.format = surf_info.format;
1299
1300    if ((hwc_window->hwc->pp_queue) && (output->display_mode == E_OUTPUT_DISPLAY_MODE_MIRROR))
1301      {
1302         hwc_win_info->src_config.pos.x = 0;
1303         hwc_win_info->src_config.pos.y = 0;
1304         hwc_win_info->src_config.pos.w = surf_info.width;
1305         hwc_win_info->src_config.pos.h = surf_info.height;
1306         hwc_win_info->dst_pos.x = 0;
1307         hwc_win_info->dst_pos.y = 0;
1308         hwc_win_info->dst_pos.w = surf_info.width;
1309         hwc_win_info->dst_pos.h = surf_info.height;
1310      }
1311    else
1312      {
1313         hwc_win_info->src_config.pos.x = output->config.geom.x;
1314         hwc_win_info->src_config.pos.y = output->config.geom.y;
1315         hwc_win_info->src_config.pos.w = output->config.geom.w;
1316         hwc_win_info->src_config.pos.h = output->config.geom.h;
1317         hwc_win_info->dst_pos.x = 0;
1318         hwc_win_info->dst_pos.y = 0;
1319         hwc_win_info->dst_pos.w = output->config.geom.w;
1320         hwc_win_info->dst_pos.h = output->config.geom.h;
1321      }
1322
1323    // TODO: need to calculation with ec(window) rotation and output->config.rotation?
1324    hwc_win_info->transform = TDM_TRANSFORM_NORMAL;
1325
1326    return EINA_TRUE;
1327 }
1328
1329 static Eina_Bool
1330 _e_hwc_window_video_info_get(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
1331 {
1332    E_Client *ec;
1333    E_Client_Video_Info vinfo;
1334    E_Zone *zone;
1335    E_Hwc *hwc;
1336
1337    if (!e_hwc_window_is_video(hwc_window)) return EINA_FALSE;
1338
1339    ec = hwc_window->ec;
1340    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1341    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
1342
1343    hwc = hwc_window->hwc;
1344    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1345
1346    zone = hwc_window->zone;
1347    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1348
1349    if (!e_client_video_info_get(ec, &vinfo))
1350      {
1351         EHWERR("Video window does not get the video info", hwc_window->ec, hwc_window->hwc, hwc_window);
1352         return EINA_FALSE;
1353      }
1354
1355    vinfo.dst_pos.x -= zone->x;
1356    vinfo.dst_pos.y -= zone->y;
1357
1358    memcpy(&hwc_win_info->src_config, &vinfo.src_config, sizeof(tdm_info_config));
1359    memcpy(&hwc_win_info->dst_pos, &vinfo.dst_pos, sizeof(tdm_pos));
1360    hwc_win_info->transform = vinfo.transform;
1361
1362    return EINA_TRUE;
1363 }
1364
1365 static Eina_Bool
1366 _e_hwc_window_info_set(E_Hwc_Window *hwc_window, tdm_hwc_window_info *hwc_win_info)
1367 {
1368    tdm_error error;
1369
1370    if (!memcmp(&hwc_window->current.info, hwc_win_info, sizeof(tdm_hwc_window_info)))
1371      return EINA_FALSE;
1372
1373    memcpy(&hwc_window->current.info, hwc_win_info, sizeof(tdm_hwc_window_info));
1374
1375    if (e_hwc_window_is_target(hwc_window))
1376      {
1377         EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
1378
1379         error = tdm_hwc_set_client_target_buffer_info(hwc_window->hwc->thwc, &hwc_window->current.info);
1380         if (error == TDM_ERROR_NOT_IMPLEMENTED)
1381           {
1382              EHWINF("tdm_hwc_set_client_target_buffer_info not implement",
1383                     hwc_window->ec, hwc_window->hwc, hwc_window);
1384              return EINA_TRUE;
1385           }
1386
1387         EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
1388      }
1389    else
1390      {
1391         EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->thwc_window, EINA_FALSE);
1392
1393         error = tdm_hwc_window_set_info(hwc_window->thwc_window, &hwc_window->current.info);
1394         EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
1395      }
1396
1397    EHWTRACE("INF src(%dx%d+%d+%d size:%dx%d fmt:%c%c%c%c) dst(%dx%d+%d+%d) trans(%d)",
1398              hwc_window->ec, hwc_window->hwc, hwc_window,
1399              hwc_window->current.info.src_config.pos.w, hwc_window->current.info.src_config.pos.h,
1400              hwc_window->current.info.src_config.pos.x, hwc_window->current.info.src_config.pos.y,
1401              hwc_window->current.info.src_config.size.h, hwc_window->current.info.src_config.size.v,
1402              EHW_FOURCC_STR(hwc_window->current.info.src_config.format),
1403              hwc_window->current.info.dst_pos.w, hwc_window->current.info.dst_pos.h,
1404              hwc_window->current.info.dst_pos.x, hwc_window->current.info.dst_pos.y,
1405              hwc_window->current.info.transform);
1406
1407    return EINA_TRUE;
1408 }
1409
1410 EINTERN Eina_Bool
1411 e_hwc_window_info_update(E_Hwc_Window *hwc_window)
1412 {
1413    tdm_hwc_window_info hwc_win_info = {0};
1414    E_Client *ec;
1415
1416    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1417
1418    if (hwc_window->is_deleted) return EINA_FALSE;
1419
1420    if (hwc_window->is_target)
1421      {
1422         if (!_e_hwc_window_target_info_get(hwc_window, &hwc_win_info))
1423           {
1424              EHWERR("fail to _e_hwc_window_target_info_get",
1425                     hwc_window->ec, hwc_window->hwc, hwc_window);
1426              return EINA_FALSE;
1427           }
1428      }
1429    else
1430      {
1431         ec = hwc_window->ec;
1432         if (!ec) return EINA_FALSE;
1433
1434         if (e_object_is_del(E_OBJECT(ec))) return EINA_FALSE;
1435
1436         if ((hwc_window->present_sync) || (eina_list_count(hwc_window->pending_update_list)))
1437           return EINA_FALSE;
1438
1439         if (e_hwc_window_is_cursor(hwc_window))
1440           {
1441              if (!_e_hwc_window_cursor_info_get(hwc_window, &hwc_win_info))
1442                {
1443                   EHWERR("fail to _e_hwc_window_cursor_info_get",
1444                          hwc_window->ec, hwc_window->hwc, hwc_window);
1445                   return EINA_FALSE;
1446                }
1447           }
1448         else if (e_hwc_window_is_video(hwc_window))
1449           {
1450              if (!_e_hwc_window_video_info_get(hwc_window, &hwc_win_info))
1451                {
1452                   EHWERR("fail to _e_hwc_window_video_info_get",
1453                          hwc_window->ec, hwc_window->hwc, hwc_window);
1454                   return EINA_FALSE;
1455                }
1456           }
1457         else
1458           {
1459              if (!_e_hwc_window_info_get(hwc_window, &hwc_win_info))
1460                {
1461                   EHWERR("fail to _e_hwc_window_info_get",
1462                          hwc_window->ec, hwc_window->hwc, hwc_window);
1463                   return EINA_FALSE;
1464                }
1465           }
1466      }
1467
1468    return _e_hwc_window_info_set(hwc_window, &hwc_win_info);
1469 }
1470
1471 EINTERN Eina_Bool
1472 e_hwc_window_display_or_commit_buffer_check(E_Hwc_Window *hwc_window, tbm_surface_h tsurface)
1473 {
1474    E_Hwc *hwc;
1475    E_Hwc_Window_Commit_Data *commit_data;
1476    Eina_List *l;
1477
1478    hwc = hwc_window->hwc;
1479    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1480    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1481    EINA_SAFETY_ON_NULL_RETURN_VAL(tsurface, EINA_FALSE);
1482
1483    if (hwc_window->display.buffer.tsurface == tsurface) return EINA_TRUE;
1484
1485    EINA_LIST_FOREACH(hwc_window->commit_data_list, l, commit_data)
1486      {
1487         if (commit_data->buffer.tsurface == tsurface)
1488           return EINA_TRUE;
1489      }
1490
1491    if (hwc->pp_update.buffer.tsurface == tsurface)
1492      return EINA_TRUE;
1493
1494    return EINA_FALSE;
1495 }
1496
1497 static Eina_Bool
1498 _e_hwc_window_buffer_set(E_Hwc_Window *hwc_window, tbm_surface_h tsurface,
1499                          E_Comp_Wl_Buffer *comp_buffer, E_Hwc_Window_Queue *queue)
1500 {
1501    E_Hwc_Window_Queue_Buffer *queue_buffer = NULL, *queue_buffer2 = NULL;
1502    tdm_error error = TDM_ERROR_NONE;
1503    int acquire_fence_fd;
1504
1505    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->thwc_window, EINA_FALSE);
1506
1507    if (hwc_window->current.buffer.tsurface == tsurface) return EINA_FALSE;
1508
1509    if (tsurface && queue)
1510      {
1511         queue_buffer = e_hwc_window_queue_buffer_find(queue, tsurface);
1512         if (queue_buffer)
1513           {
1514             e_hwc_window_queue_buffer_enqueue(queue, queue_buffer);
1515             queue_buffer2 = e_hwc_window_queue_buffer_acquire(queue);
1516             while (queue_buffer != queue_buffer2)
1517               {
1518                   e_hwc_window_queue_buffer_release(queue, queue_buffer2);
1519                   queue_buffer2 = e_hwc_window_queue_buffer_acquire(queue);
1520                   if (!queue_buffer2)
1521                     {
1522                       EHWERR("fail to acquire buffer:%p tsurface:%p",
1523                           hwc_window->ec, hwc_window->hwc, hwc_window,
1524                           queue_buffer, queue_buffer->tsurface);
1525                       return EINA_FALSE;
1526                     }
1527               }
1528           }
1529      }
1530
1531    EHWTRACE("FET ts:%10p - {%s} state:%s zpos:%d deleted:%s cursor:%d video:%d",
1532             hwc_window->ec, hwc_window->hwc, hwc_window,
1533             tsurface, e_hwc_window_name_get(hwc_window),
1534             e_hwc_window_state_string_get(hwc_window->state),
1535             hwc_window->zpos, (hwc_window->is_deleted ? "yes" : "no"),
1536             e_hwc_window_is_cursor(hwc_window), e_hwc_window_is_video(hwc_window));
1537
1538    if (tsurface)
1539      {
1540         e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, queue_buffer);
1541         e_hwc_window_buffer_set(&hwc_window->current.buffer, tsurface, queue,
1542                                 comp_buffer ? comp_buffer->transform : 0);
1543      }
1544    else
1545      {
1546         e_hwc_window_queue_buffer_reference(&hwc_window->current.queue_buffer_ref, NULL);
1547         e_hwc_window_buffer_set(&hwc_window->current.buffer, NULL, NULL, 0);
1548      }
1549
1550    error = tdm_hwc_window_set_buffer(hwc_window->thwc_window, hwc_window->current.buffer.tsurface);
1551    EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
1552
1553    if ((hwc_window->ec) && e_hwc_windows_fence_enabled_get(hwc_window->hwc))
1554      {
1555         acquire_fence_fd = e_client_explicit_sync_acquire_fence_fd_get(hwc_window->ec);
1556         error = tdm_hwc_window_set_acquire_fence(hwc_window->thwc_window, acquire_fence_fd);
1557         EINA_SAFETY_ON_TRUE_RETURN_VAL(error != TDM_ERROR_NONE, EINA_FALSE);
1558      }
1559
1560    return EINA_TRUE;
1561 }
1562
1563 EINTERN Eina_Bool
1564 e_hwc_window_buffer_fetch(E_Hwc_Window *hwc_window)
1565 {
1566    tbm_surface_h tsurface;
1567    E_Client *ec;
1568    E_Comp_Wl_Buffer *comp_buffer;
1569
1570    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1571    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
1572
1573    if (e_hwc_window_is_cursor(hwc_window))
1574      {
1575         if (!_e_hwc_window_cursor_image_update(hwc_window))
1576           return EINA_FALSE;
1577
1578         EHWTRACE("FET img_ptr:%p - {%s} state:%s zpos:%d deleted:%s",
1579                  hwc_window->ec, hwc_window->hwc, hwc_window,
1580                  hwc_window->cursor.img_ptr, e_hwc_window_name_get(hwc_window),
1581                  e_hwc_window_state_string_get(hwc_window->state),
1582                  hwc_window->zpos, (hwc_window->is_deleted ? "yes" : "no"));
1583
1584         return EINA_TRUE;
1585      }
1586
1587    if ((hwc_window->present_sync) || (eina_list_count(hwc_window->pending_update_list)))
1588      return EINA_FALSE;
1589
1590    ec = hwc_window->ec;
1591
1592    if ((hwc_window->is_deleted) || (!ec) || e_object_is_del(E_OBJECT(ec)))
1593      {
1594         tsurface = NULL;
1595      }
1596    /* for video we set buffer in the video module */
1597    else if (e_hwc_window_is_video(hwc_window))
1598      {
1599         tsurface = e_client_video_tbm_surface_get(hwc_window->ec);
1600      }
1601    else
1602      {
1603         /* acquire the surface */
1604         tsurface = _e_hwc_window_client_surface_acquire(hwc_window);
1605      }
1606
1607   comp_buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
1608
1609   return _e_hwc_window_buffer_set(hwc_window, tsurface, comp_buffer, hwc_window->queue);
1610 }
1611
1612 EINTERN Eina_Bool
1613 e_hwc_window_prop_update(E_Hwc_Window *hwc_window)
1614 {
1615    Hwc_Window_Prop *prop;
1616    Eina_Bool ret = EINA_FALSE;
1617
1618    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1619
1620    EINA_LIST_FREE(hwc_window->prop_list, prop)
1621      {
1622         if (!e_hwc_window_set_property(hwc_window, prop->id, prop->name, prop->value, EINA_TRUE))
1623           EHWERR("cannot update prop", hwc_window->ec, hwc_window->hwc, hwc_window);
1624         free(prop);
1625         ret = EINA_TRUE;
1626      }
1627
1628    return ret;
1629 }
1630
1631 EINTERN E_Hwc_Window_Commit_Data *
1632 e_hwc_window_commit_data_acquire(E_Hwc_Window *hwc_window)
1633 {
1634    E_Hwc_Window_Commit_Data *commit_data;
1635    E_Comp_Wl_Buffer *comp_buffer;
1636
1637    if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CURSOR)
1638      {
1639         if (!hwc_window->cursor.buffer) return NULL;
1640         if ((hwc_window->cursor.buffer == hwc_window->commit.buffer_ref.buffer) &&
1641             (!memcmp(&hwc_window->current.info, &hwc_window->commit.info, sizeof(tdm_hwc_window_info))))
1642           return NULL;
1643
1644         commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
1645         EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, EINA_FALSE);
1646
1647         memcpy(&commit_data->info, &hwc_window->current.info, sizeof(tdm_hwc_window_info));
1648         e_comp_wl_buffer_reference(&commit_data->buffer_ref,
1649                                    _e_hwc_window_comp_wl_buffer_get(hwc_window));
1650
1651         _e_hwc_window_update_fps(hwc_window);
1652      }
1653    else if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) ||
1654             (hwc_window->accepted_state == E_HWC_WINDOW_STATE_VIDEO))
1655      {
1656         if (!hwc_window->current.buffer.tsurface) return EINA_FALSE;
1657         if ((hwc_window->current.buffer.tsurface == hwc_window->commit.buffer.tsurface) &&
1658             (!memcmp(&hwc_window->current.info, &hwc_window->commit.info, sizeof(tdm_hwc_window_info))))
1659           return NULL;
1660
1661         commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
1662         EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, NULL);
1663
1664         memcpy(&commit_data->info, &hwc_window->current.info, sizeof(tdm_hwc_window_info));
1665
1666         e_hwc_window_queue_buffer_reference(&commit_data->queue_buffer_ref, hwc_window->current.queue_buffer_ref.buffer);
1667
1668         if (e_hwc_window_is_video(hwc_window))
1669           {
1670              comp_buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
1671              if ((comp_buffer) &&
1672                  (comp_buffer->tbm_surface == hwc_window->current.buffer.tsurface))
1673                e_comp_wl_buffer_reference(&commit_data->buffer_ref, comp_buffer);
1674           }
1675         else if (!e_hwc_window_is_target(hwc_window))
1676           {
1677              e_comp_wl_buffer_reference(&commit_data->buffer_ref,
1678                                         _e_hwc_window_comp_wl_buffer_get(hwc_window));
1679           }
1680
1681         e_hwc_window_buffer_set(&commit_data->buffer, hwc_window->current.buffer.tsurface,
1682                                 hwc_window->current.buffer.queue, hwc_window->current.buffer.transform);
1683
1684         _e_hwc_window_update_fps(hwc_window);
1685      }
1686    else
1687      {
1688         if (e_hwc_window_is_cursor(hwc_window))
1689           {
1690              tdm_hwc_window_info info;
1691
1692              CLEAR(info);
1693
1694              if (!memcmp(&hwc_window->commit.info, &info, sizeof(tdm_hwc_window_info)))
1695                return NULL;
1696           }
1697         else
1698           {
1699              if (!hwc_window->commit.buffer.tsurface)
1700                return NULL;
1701           }
1702
1703         commit_data = E_NEW(E_Hwc_Window_Commit_Data, 1);
1704         EINA_SAFETY_ON_NULL_RETURN_VAL(commit_data, NULL);
1705
1706         e_hwc_window_buffer_set(&commit_data->buffer, NULL, NULL, 0);
1707      }
1708
1709    EHWTRACE("COM data:%p ts:%p - {%s} state:%s zpos:%d",
1710             hwc_window->ec, hwc_window->hwc, hwc_window,
1711             commit_data, commit_data->buffer.tsurface,
1712             e_hwc_window_name_get(hwc_window),
1713             e_hwc_window_state_string_get(hwc_window->state),
1714             hwc_window->zpos);
1715
1716    commit_data->hwc_window = hwc_window;
1717    e_hwc_window_ref(hwc_window);
1718
1719    /* set latest commit_data */
1720    memcpy(&hwc_window->commit.info, &commit_data->info, sizeof(tdm_hwc_window_info));
1721
1722    e_hwc_window_queue_buffer_reference(&hwc_window->commit.queue_buffer_ref, commit_data->queue_buffer_ref.buffer);
1723    e_comp_wl_buffer_reference(&hwc_window->commit.buffer_ref, commit_data->buffer_ref.buffer);
1724    e_hwc_window_buffer_set(&hwc_window->commit.buffer, commit_data->buffer.tsurface,
1725                            commit_data->buffer.queue, commit_data->buffer.transform);
1726
1727    hwc_window->commit_data_list = eina_list_append(hwc_window->commit_data_list, commit_data);
1728
1729    return commit_data;
1730 }
1731
1732 EINTERN void
1733 e_hwc_window_presentation_time_feedback_take(E_Hwc_Window *hwc_window,
1734                                              E_Presentation_Time_Container *container)
1735 {
1736    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1737    EINA_SAFETY_ON_NULL_RETURN(container);
1738
1739    e_presentation_time_container_feedback_merge(&hwc_window->presentation_container,
1740                                                 container);
1741 }
1742
1743 EINTERN void
1744 e_hwc_window_presentation_time_feedback_present(E_Hwc_Window *hwc_window,
1745                                                 uint64_t sequence,
1746                                                 uint64_t tv_sec,
1747                                                 uint64_t tv_usec)
1748 {
1749    E_Output *output;
1750    unsigned int flags =
1751       WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION;
1752
1753    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1754
1755    if (!eina_list_count(hwc_window->presentation_container.presentation_feedbacks))
1756      return;
1757
1758    EINA_SAFETY_ON_NULL_GOTO(hwc_window->hwc, discard);
1759
1760    output = hwc_window->hwc->output;
1761    EINA_SAFETY_ON_NULL_GOTO(output, discard);
1762
1763    if ((sequence) || (tv_sec) || (tv_usec))
1764      flags |= WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK;
1765
1766    if (!hwc_window->is_target)
1767      flags |= WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY;
1768
1769    e_presentation_time_container_feedback_present(&hwc_window->presentation_container,
1770                                                   output,
1771                                                   tv_sec,
1772                                                   tv_usec * 1000,
1773                                                   sequence,
1774                                                   flags);
1775    return;
1776
1777 discard:
1778    e_presentation_time_container_feedback_discard(&hwc_window->presentation_container);
1779 }
1780
1781 EINTERN void
1782 e_hwc_window_presentation_time_feedback_discard(E_Hwc_Window *hwc_window)
1783 {
1784    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
1785
1786    e_presentation_time_container_feedback_discard(&hwc_window->presentation_container);
1787 }
1788
1789 EINTERN Eina_Bool
1790 e_hwc_window_commit_data_release(E_Hwc_Window *hwc_window, E_Hwc_Window_Commit_Data *commit_data)
1791 {
1792    tbm_surface_h tsurface;
1793    E_Hwc_Window_Queue *queue;
1794    E_Hwc_Window_Queue_Buffer *queue_buffer;
1795
1796    /* we don't have data to release */
1797    if (!commit_data) return EINA_FALSE;
1798
1799    if (!eina_list_data_find(hwc_window->commit_data_list, commit_data))
1800      {
1801         EHWERR("failed to find commit_data:%p in commit_data_list",
1802                hwc_window->ec, hwc_window->hwc, hwc_window, commit_data);
1803         return EINA_FALSE;
1804      }
1805
1806    tsurface = commit_data->buffer.tsurface;
1807    queue = commit_data->buffer.queue;
1808    queue_buffer = commit_data->queue_buffer_ref.buffer;
1809
1810    EHWTRACE("DON data:%p ts:%p - {%s} state:%s zpos:%d",
1811             hwc_window->ec, hwc_window->hwc, hwc_window,
1812             commit_data, tsurface, e_hwc_window_name_get(hwc_window),
1813             e_hwc_window_state_string_get(hwc_window->state),
1814             hwc_window->zpos);
1815
1816    if (e_hwc_window_is_cursor(hwc_window))
1817      {
1818         tdm_hwc_window_info info;
1819
1820         CLEAR(info);
1821
1822         if (memcmp(&commit_data->info, &info, sizeof(tdm_hwc_window_info)))
1823           {
1824              e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref,
1825                                         commit_data->buffer_ref.buffer);
1826
1827              if (!memcmp(&hwc_window->display.info, &info, sizeof(tdm_hwc_window_info)))
1828                e_hwc_window_ref(hwc_window);
1829
1830              memcpy(&hwc_window->display.info, &commit_data->info, sizeof(tdm_hwc_window_info));
1831           }
1832         else
1833           {
1834              e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
1835
1836              if (memcmp(&hwc_window->display.info, &info, sizeof(tdm_hwc_window_info)))
1837                e_hwc_window_unref(hwc_window);
1838
1839              CLEAR(hwc_window->display.info);
1840           }
1841
1842         e_comp_wl_buffer_reference(&commit_data->buffer_ref, NULL);
1843         hwc_window->commit_data_list = eina_list_remove(hwc_window->commit_data_list, commit_data);
1844         free(commit_data);
1845         e_hwc_window_unref(hwc_window);
1846
1847         return EINA_TRUE;
1848      }
1849
1850    if (!tsurface)
1851      {
1852         if (hwc_window->display.buffer.tsurface)
1853           e_hwc_window_unref(hwc_window);
1854
1855         e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, NULL);
1856         e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, NULL);
1857         e_hwc_window_buffer_set(&hwc_window->display.buffer, NULL, NULL, 0);
1858
1859         CLEAR(hwc_window->display.info);
1860      }
1861    else
1862      {
1863         if (hwc_window->display.buffer.tsurface)
1864           e_hwc_window_unref(hwc_window);
1865
1866         e_hwc_window_queue_buffer_reference(&hwc_window->display.queue_buffer_ref, queue_buffer);
1867         e_comp_wl_buffer_reference(&hwc_window->display.buffer_ref, commit_data->buffer_ref.buffer);
1868         e_hwc_window_buffer_set(&hwc_window->display.buffer, tsurface, queue, commit_data->buffer.transform);
1869
1870         memcpy(&hwc_window->display.info, &commit_data->info, sizeof(tdm_hwc_window_info));
1871
1872         e_hwc_window_ref(hwc_window);
1873      }
1874
1875    e_hwc_window_queue_buffer_reference(&commit_data->queue_buffer_ref, NULL);
1876    e_comp_wl_buffer_reference(&commit_data->buffer_ref, NULL);
1877    e_hwc_window_buffer_set(&commit_data->buffer, NULL, NULL, 0);
1878
1879    hwc_window->commit_data_list = eina_list_remove(hwc_window->commit_data_list, commit_data);
1880    free(commit_data);
1881    e_hwc_window_unref(hwc_window);
1882
1883    return EINA_TRUE;
1884 }
1885
1886 static void
1887 _e_hwc_window_cqueue_destroy_cb(struct wayland_tbm_client_queue *cqueue, void *data)
1888 {
1889    E_Hwc_Window *hwc_window = (E_Hwc_Window *)data;
1890
1891    hwc_window->cqueue = NULL;
1892 }
1893
1894 EINTERN Eina_Bool
1895 e_hwc_window_activate(E_Hwc_Window *hwc_window, E_Hwc_Window_Queue *queue)
1896 {
1897    struct wayland_tbm_client_queue *cqueue;
1898    int flush = 0;
1899    int queue_size = 0, queue_width = 0, queue_height = 0;
1900
1901    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1902    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->ec, EINA_FALSE);
1903
1904    if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED)
1905      return EINA_TRUE;
1906
1907    if (e_hwc_window_is_cursor(hwc_window)) return EINA_TRUE;
1908
1909    if (queue)
1910      {
1911         flush = 1;
1912         queue_size = tbm_surface_queue_get_size(queue->tqueue);
1913         queue_width = tbm_surface_queue_get_width(queue->tqueue);
1914         queue_height = tbm_surface_queue_get_height(queue->tqueue);
1915      }
1916
1917    cqueue = e_comp_wl_tbm_client_queue_get(hwc_window->ec);
1918    if (cqueue)
1919      {
1920         wayland_tbm_server_client_queue_activate(cqueue, 0, queue_size,
1921                                                  queue_width, queue_height, flush);
1922         wayland_tbm_server_client_queue_set_destroy_cb(cqueue,
1923                                                        _e_hwc_window_cqueue_destroy_cb,
1924                                                        hwc_window);
1925         hwc_window->cqueue = cqueue;
1926      }
1927
1928    EHWINF("Activate -- ehwq:%p {%s}",
1929           hwc_window->ec, hwc_window->hwc, hwc_window, queue,
1930           e_hwc_window_name_get(hwc_window));
1931
1932    hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_ACTIVATED;
1933
1934    return EINA_TRUE;
1935 }
1936
1937 EINTERN Eina_Bool
1938 e_hwc_window_deactivate(E_Hwc_Window *hwc_window)
1939 {
1940    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1941    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->ec, EINA_FALSE);
1942
1943    if (hwc_window->activation_state == E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED)
1944      return EINA_TRUE;
1945
1946    if (e_hwc_window_is_cursor(hwc_window)) return EINA_TRUE;
1947
1948    if (hwc_window->cqueue)
1949      {
1950         wayland_tbm_server_client_queue_deactivate(hwc_window->cqueue);
1951         wayland_tbm_server_client_queue_set_destroy_cb(hwc_window->cqueue,
1952                                                        NULL,
1953                                                        NULL);
1954         hwc_window->cqueue = NULL;
1955      }
1956
1957    EHWINF("Deactivate - {%s}",
1958           hwc_window->ec, hwc_window->hwc, hwc_window,
1959           e_hwc_window_name_get(hwc_window));
1960
1961    hwc_window->activation_state = E_HWC_WINDOW_ACTIVATION_STATE_DEACTIVATED;
1962
1963    return EINA_TRUE;
1964 }
1965
1966 EINTERN Eina_Bool
1967 e_hwc_window_is_on_hw_overlay(E_Hwc_Window *hwc_window)
1968 {
1969    E_Hwc_Window_State accepted_state = E_HWC_WINDOW_STATE_NONE;
1970    E_Hwc_Window_State state = E_HWC_WINDOW_STATE_NONE;
1971
1972    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1973
1974    accepted_state = hwc_window->accepted_state;
1975    state = hwc_window->state;
1976
1977    if ((accepted_state == E_HWC_WINDOW_STATE_DEVICE) ||
1978        (accepted_state == E_HWC_WINDOW_STATE_CURSOR) ||
1979        (accepted_state == E_HWC_WINDOW_STATE_VIDEO))
1980      {
1981         if (accepted_state == state)
1982           return EINA_TRUE;
1983      }
1984
1985    return EINA_FALSE;
1986 }
1987
1988 EINTERN tbm_surface_h
1989 e_hwc_window_displaying_surface_get(E_Hwc_Window *hwc_window)
1990 {
1991    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
1992
1993    return hwc_window->display.buffer.tsurface;
1994 }
1995
1996 EINTERN Eina_Bool
1997 e_hwc_window_accepted_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state)
1998 {
1999    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2000
2001    if (hwc_window->accepted_state != state)
2002      {
2003         hwc_window->accepted_state = state;
2004
2005         if (hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE)
2006           hwc_window->zpos = E_HWC_WINDOW_ZPOS_NONE;
2007
2008         EHWINF("Set Accepted state:%s - {%s}",
2009                 hwc_window->ec, hwc_window->hwc, hwc_window, e_hwc_window_state_string_get(state),
2010                 e_hwc_window_name_get(hwc_window));
2011
2012      }
2013
2014    _e_hwc_window_hook_call(E_HWC_WINDOW_HOOK_ACCEPTED_STATE_SET, hwc_window);
2015
2016    return EINA_TRUE;
2017 }
2018
2019 EINTERN E_Hwc_Window_State
2020 e_hwc_window_accepted_state_get(E_Hwc_Window *hwc_window)
2021 {
2022    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
2023
2024    return hwc_window->accepted_state;
2025 }
2026
2027 EINTERN Eina_Bool
2028 e_hwc_window_state_set(E_Hwc_Window *hwc_window, E_Hwc_Window_State state, Eina_Bool composition_update)
2029 {
2030    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2031
2032    if (hwc_window->state == state) return EINA_TRUE;
2033
2034    if (((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) && (state == E_HWC_WINDOW_STATE_CLIENT)) ||
2035        ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_DEVICE) && (state == E_HWC_WINDOW_STATE_NONE)))
2036      e_hwc_window_constraints_reset(hwc_window);
2037
2038    hwc_window->state = state;
2039
2040    /* update the composition type */
2041    if (composition_update)
2042      {
2043         if (!e_hwc_window_composition_update(hwc_window))
2044           EHWERR("Cannot update window composition", hwc_window->ec, hwc_window->hwc, hwc_window);
2045      }
2046
2047    /* zpos is -999 at state none */
2048    if (state == E_HWC_WINDOW_STATE_NONE)
2049      e_hwc_window_zpos_set(hwc_window, -999);
2050
2051    return EINA_TRUE;
2052 }
2053
2054 EINTERN E_Hwc_Window_State
2055 e_hwc_window_state_get(E_Hwc_Window *hwc_window)
2056 {
2057    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, E_HWC_WINDOW_STATE_NONE);
2058
2059    return hwc_window->state;
2060 }
2061
2062 EINTERN Eina_Bool
2063 e_hwc_window_device_state_available_get(E_Hwc_Window *hwc_window)
2064 {
2065    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2066
2067    return hwc_window->device_state_available;
2068 }
2069
2070 static Eina_Bool
2071 _e_hwc_window_client_transform_device_state_available_get(E_Client *ec)
2072 {
2073    E_Map *map;
2074    int x[4], y[4], z[4];
2075    int i;
2076
2077    if (!e_client_transform_core_enable_get(ec))
2078      return EINA_TRUE;
2079
2080    map = e_client_map_get(ec);
2081    if (!map) return EINA_TRUE;
2082
2083    for (i = 0; i < 4; i++)
2084      {
2085         if (!e_map_point_coord_get(map, i, &x[i], &y[i], &z[i]))
2086           {
2087              e_map_free(map);
2088              return EINA_FALSE;
2089           }
2090      }
2091
2092    e_map_free(map);
2093
2094    /* check 2D */
2095    if ((z[0] != z[1]) || (z[0] != z[2]) || (z[0] != z[3]))
2096      return EINA_FALSE;
2097
2098    /* check rectangle */
2099    if ((x[0] != x[3]) || (x[1] != x[2]))
2100      return EINA_FALSE;
2101
2102    if ((y[0] != y[1]) || (y[2] != y[3]))
2103      return EINA_FALSE;
2104
2105    return EINA_TRUE;
2106 }
2107
2108 // if ec has invalid buffer or scaled( transformed ) or forced composite(never_hwc)
2109 EINTERN Eina_Bool
2110 e_hwc_window_device_state_available_update(E_Hwc_Window *hwc_window)
2111 {
2112    E_Client *ec;
2113    E_Comp_Wl_Client_Data *cdata;
2114    E_Pixmap *pixmap;
2115    E_Output *eout;
2116    int minw = 0, minh = 0;
2117    int transform;
2118    Eina_Bool available = EINA_TRUE;
2119    E_Hwc_Window_Restriction restriction = E_HWC_WINDOW_RESTRICTION_NONE;
2120    E_Desk *desk;
2121    E_Zone *zone;
2122    int alpha;
2123    Evas_Render_Op render_op;
2124
2125    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2126
2127    ec = hwc_window->ec;
2128
2129    if ((hwc_window->is_deleted) || (!ec) || e_object_is_del(E_OBJECT(ec)))
2130      {
2131         restriction = E_HWC_WINDOW_RESTRICTION_DELETED;
2132         available = EINA_FALSE;
2133         goto finish;
2134      }
2135
2136    if (ec->comp_override > 0)
2137      {
2138         restriction = E_HWC_WINDOW_RESTRICTION_OVERRIDE;
2139         available = EINA_FALSE;
2140         goto finish;
2141      }
2142
2143    if (hwc_window->obscured_by_target)
2144      {
2145         restriction = E_HWC_WINDOW_RESTRICTION_OBSCURED_BY_TARGET;
2146         available = EINA_FALSE;
2147         goto finish;
2148      }
2149
2150    if (e_comp_object_is_animating(ec->frame))
2151      {
2152         restriction = E_HWC_WINDOW_RESTRICTION_ANIMATING;
2153         available = EINA_FALSE;
2154         goto finish;
2155      }
2156
2157    if (evas_object_data_get(ec->frame, "effect_running"))
2158      {
2159         restriction = E_HWC_WINDOW_RESTRICTION_EFFECT_RUNNING;
2160         available = EINA_FALSE;
2161         goto finish;
2162      }
2163
2164    cdata = e_client_cdata_get(ec);
2165    if ((!cdata) || (!cdata->buffer_ref.buffer))
2166      {
2167         restriction = E_HWC_WINDOW_RESTRICTION_BUFFER;
2168         available = EINA_FALSE;
2169         goto finish;
2170      }
2171
2172    pixmap = ec->pixmap;
2173    if ((!pixmap) || (!e_pixmap_resource_get(pixmap)))
2174      {
2175         restriction = E_HWC_WINDOW_RESTRICTION_PIXMAP_RESOURCE;
2176         available = EINA_FALSE;
2177         goto finish;
2178      }
2179
2180    if ((cdata->width_from_buffer != cdata->width_from_viewport) ||
2181        (cdata->height_from_buffer != cdata->height_from_viewport))
2182      {
2183         restriction = E_HWC_WINDOW_RESTRICTION_VIEWPORT;
2184         available = EINA_FALSE;
2185         goto finish;
2186      }
2187
2188    if (cdata->never_hwc)
2189      {
2190         restriction = E_HWC_WINDOW_RESTRICTION_NEVER_HWC;
2191         available = EINA_FALSE;
2192         goto finish;
2193      }
2194
2195    if (!_e_hwc_window_client_transform_device_state_available_get(ec))
2196      {
2197         restriction = E_HWC_WINDOW_RESTRICTION_TRANSFORM;
2198         available = EINA_FALSE;
2199         goto finish;
2200      }
2201
2202    switch (cdata->buffer_ref.buffer->type)
2203      {
2204       case E_COMP_WL_BUFFER_TYPE_NATIVE:
2205       case E_COMP_WL_BUFFER_TYPE_TBM:
2206          break;
2207       case E_COMP_WL_BUFFER_TYPE_SHM:
2208          if (!e_util_strcmp("wl_pointer-cursor", ec->icccm.window_role))
2209            break;
2210       default:
2211         restriction = E_HWC_WINDOW_RESTRICTION_BUFFER_TYPE;
2212         available = EINA_FALSE;
2213         goto finish;
2214      }
2215
2216    zone = hwc_window->zone;
2217    if (!zone)
2218      {
2219         restriction = E_HWC_WINDOW_RESTRICTION_ZONE;
2220         available = EINA_FALSE;
2221         goto finish;
2222      }
2223
2224    eout = e_output_find(zone->output_id);
2225    if (!eout)
2226      {
2227         restriction = E_HWC_WINDOW_RESTRICTION_OUTPUT;
2228         available = EINA_FALSE;
2229         goto finish;
2230      }
2231
2232    tdm_output_get_available_size(eout->toutput, &minw, &minh, NULL, NULL, NULL);
2233
2234    if ((minw > 0) && (minw > cdata->buffer_ref.buffer->w))
2235      {
2236         restriction = E_HWC_WINDOW_RESTRICTION_MIN_WIDTH;
2237         available = EINA_FALSE;
2238         goto finish;
2239      }
2240
2241    if ((minh > 0) && (minh > cdata->buffer_ref.buffer->h))
2242      {
2243         restriction = E_HWC_WINDOW_RESTRICTION_MIN_HEIGHT;
2244         available = EINA_FALSE;
2245         goto finish;
2246      }
2247
2248    desk = e_desk_current_get(zone);
2249    if (desk)
2250      {
2251         if ((desk->geom.x != zone->x) || (desk->geom.y != zone->y) ||
2252             (desk->geom.w != zone->w) || (desk->geom.h != zone->h))
2253           {
2254              restriction = E_HWC_WINDOW_RESTRICTION_DESK_GEOMETRY;
2255              available = EINA_FALSE;
2256              goto finish;
2257           }
2258      }
2259
2260    transform = e_comp_wl_output_buffer_transform_get(ec);
2261    if ((eout->config.rotation / 90) != transform)
2262      {
2263         restriction = E_HWC_WINDOW_RESTRICTION_OUTPUT_TRANSFORM;
2264         available = EINA_FALSE;
2265         goto finish;
2266      }
2267
2268    // if ec->frame is not for client buffer (e.g. launchscreen)
2269    if (e_comp_object_content_type_get(ec->frame) != E_COMP_OBJECT_CONTENT_TYPE_INT_IMAGE)
2270      {
2271         restriction = E_HWC_WINDOW_RESTRICTION_CONTENT_IMAGE;
2272         available = EINA_FALSE;
2273         goto finish;
2274      }
2275
2276    if (e_comp_object_image_filter_get(ec->frame) != E_COMP_IMAGE_FILTER_NONE)
2277      {
2278         restriction = E_HWC_WINDOW_RESTRICTION_IMAGE_FILTER;
2279         available = EINA_FALSE;
2280         goto finish;
2281      }
2282
2283    // if there is a ec which is lower than quickpanel and quickpanel is opened.
2284    if (E_POLICY_QUICKPANEL_LAYER >= evas_object_layer_get(ec->frame))
2285      {
2286         // check whether quickpanel is open than break
2287         if (e_qps_visible_get())
2288           {
2289              restriction = E_HWC_WINDOW_RESTRICTION_QUICKPANEL_OPEN;
2290              available = EINA_FALSE;
2291              goto finish;
2292           }
2293      }
2294
2295    if (e_comp_object_render_update_lock_get(ec->frame))
2296      {
2297         restriction = E_HWC_WINDOW_RESTRICTION_RENDER_UPDATE_LOCK;
2298         available = EINA_FALSE;
2299         goto finish;
2300      }
2301
2302    if (e_client_desk_zoom_enable_get(ec))
2303      {
2304         restriction = E_HWC_WINDOW_RESTRICTION_DESK_ZOOM;
2305         available = EINA_FALSE;
2306         goto finish;
2307      }
2308
2309    e_comp_object_color_get(ec->frame, NULL, NULL, NULL, &alpha);
2310    if (alpha != 255)
2311      {
2312         restriction = E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA;
2313         available = EINA_FALSE;
2314         goto finish;
2315      }
2316
2317    render_op = e_comp_object_render_op_get(ec->frame);
2318    if (render_op != EVAS_RENDER_BLEND)
2319      {
2320         restriction = E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION;
2321         available = EINA_FALSE;
2322         goto finish;
2323      }
2324
2325    if (hwc_window->queue_unset_waiting)
2326      {
2327         restriction = E_HWC_WINDOW_RESTRICTION_QUEUE_UNSET_WAITING;
2328         available = EINA_FALSE;
2329         goto finish;
2330      }
2331
2332 finish:
2333    hwc_window->restriction = restriction;
2334
2335    if (hwc_window->device_state_available == available) return EINA_FALSE;
2336
2337    hwc_window->device_state_available = available;
2338
2339    return EINA_TRUE;
2340 }
2341
2342 EINTERN Eina_Bool
2343 e_hwc_window_constraints_update(E_Hwc_Window *hwc_window)
2344 {
2345    tdm_error terror;
2346    int constraints;
2347    struct wayland_tbm_client_queue *cqueue;
2348
2349    EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc_window, EINA_FALSE);
2350    EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc_window->thwc_window, EINA_FALSE);
2351
2352    /* get the constraints from libtdm */
2353    terror = tdm_hwc_window_get_constraints(hwc_window->thwc_window, &constraints);
2354    EINA_SAFETY_ON_TRUE_RETURN_VAL(terror != TDM_ERROR_NONE, EINA_FALSE);
2355
2356    if (hwc_window->constraints == constraints) return EINA_TRUE;
2357
2358    if (constraints)
2359      {
2360         if (constraints & TDM_HWC_WIN_CONSTRAINT_BUFFER_QUEUE)
2361           {
2362              cqueue = e_comp_wl_tbm_client_queue_get(hwc_window->ec);
2363              if (!cqueue) return EINA_FALSE;
2364
2365              if (!_e_hwc_window_buffer_queue_set(hwc_window))
2366                {
2367                   EHWERR("fail to _e_hwc_window_buffer_queue_set", hwc_window->ec, hwc_window->hwc, hwc_window);
2368                   return EINA_FALSE;
2369                }
2370           }
2371         else
2372           _e_hwc_window_buffer_queue_unset(hwc_window);
2373
2374         EHWTRACE("Set constranints:%x -- {%s}",
2375                   hwc_window->ec, hwc_window->hwc, hwc_window, constraints, e_client_util_name_get(hwc_window->ec));
2376
2377         hwc_window->constraints = constraints;
2378      }
2379    else
2380      e_hwc_window_constraints_reset(hwc_window);
2381
2382    return EINA_TRUE;
2383 }
2384
2385 static Eina_Bool
2386 _e_hwc_window_client_recover(E_Hwc_Window *hwc_window, Eina_Bool *clear_attach)
2387 {
2388    E_Comp_Wl_Buffer *recover_buffer;
2389    E_Comp_Wl_Buffer *comp_wl_buffer;
2390    tbm_surface_h tsurface;
2391    E_Client *ec;
2392    Eina_Bool new_buffer = EINA_FALSE;
2393
2394    if (hwc_window->is_deleted) return EINA_FALSE;
2395
2396    ec = hwc_window->ec;
2397    if (!ec) return EINA_FALSE;
2398
2399    comp_wl_buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
2400
2401    if ((!comp_wl_buffer) &&
2402        (!evas_object_visible_get(ec->frame)) &&
2403        (ec->exp_iconify.buffer_flush) &&
2404        (e_policy_visibility_client_is_iconic(ec)))
2405     return EINA_FALSE;
2406
2407    if (!comp_wl_buffer)
2408      {
2409         tsurface = e_hwc_window_displaying_surface_get(hwc_window);
2410         if (!tsurface) return EINA_FALSE;
2411
2412         recover_buffer = e_comp_wl_buffer_create_with_tbm_surface(tsurface);
2413         EINA_SAFETY_ON_NULL_RETURN_VAL(recover_buffer, EINA_FALSE);
2414
2415         recover_buffer->transform = hwc_window->display.buffer.transform;
2416         new_buffer = EINA_TRUE;
2417      }
2418    else
2419      recover_buffer = comp_wl_buffer;
2420
2421    EHWTRACE("Recover ts:%p - {%s}",
2422             hwc_window->ec, hwc_window->hwc, hwc_window, recover_buffer->tbm_surface,
2423             e_hwc_window_name_get(hwc_window));
2424
2425    /* force update */
2426    if (e_client_cdata_get(ec))
2427      e_comp_wl_surface_attach(ec, recover_buffer);
2428    else
2429      {
2430         /* to avoid resource leak */
2431         if (new_buffer)
2432           e_comp_wl_buffer_destroy(recover_buffer);
2433      }
2434
2435    e_hwc_window_buffer_fetch(hwc_window);
2436
2437    if (clear_attach)
2438      {
2439         if (!comp_wl_buffer)
2440           *clear_attach = EINA_TRUE;
2441         else
2442           *clear_attach = EINA_FALSE;
2443      }
2444
2445    return EINA_TRUE;
2446 }
2447
2448 static Eina_Bool
2449 _e_hwc_window_rendered_window_set(E_Hwc_Window *hwc_window, Eina_Bool set)
2450 {
2451    E_Client *ec;
2452    Eina_Bool ret;
2453    Eina_Bool clear_attach = EINA_FALSE;
2454
2455    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2456
2457    if (hwc_window->is_deleted) return EINA_FALSE;
2458
2459    ec = hwc_window->ec;
2460    if (!ec) return EINA_FALSE;
2461
2462    if (hwc_window->render_target == set) return EINA_TRUE;
2463
2464    if (set)
2465      {
2466         ret = _e_hwc_window_client_recover(hwc_window, &clear_attach);
2467
2468         if (hwc_window->ec->redirected)
2469           {
2470              e_comp_object_redirected_set(ec->frame, EINA_TRUE);
2471
2472              e_pixmap_image_refresh(ec->pixmap);
2473              e_comp_object_damage(ec->frame, 0, 0, ec->w, ec->h);
2474              e_comp_object_dirty(ec->frame);
2475              e_comp_object_render(ec->frame);
2476
2477              if (!ret)
2478                e_comp_object_render_update_del(ec->frame);
2479
2480              e_hwc_windows_present_sync(hwc_window->hwc);
2481
2482              EHWTRACE("Redirect - {%s}",
2483                       hwc_window->ec, hwc_window->hwc, hwc_window, e_hwc_window_name_get(hwc_window));
2484           }
2485
2486         if (clear_attach && e_client_cdata_get(ec))
2487           e_comp_wl_surface_attach(ec, NULL);
2488      }
2489    else
2490      {
2491         if (hwc_window->ec->redirected)
2492           {
2493              e_comp_object_redirected_set(ec->frame, EINA_FALSE);
2494
2495              e_hwc_windows_present_sync(hwc_window->hwc);
2496
2497              EHWTRACE("Unredirect - {%s}",
2498                       hwc_window->ec, hwc_window->hwc, hwc_window, e_hwc_window_name_get(hwc_window));
2499           }
2500      }
2501
2502    hwc_window->render_target = set;
2503
2504    return EINA_TRUE;
2505 }
2506
2507 EINTERN Eina_Bool
2508 e_hwc_window_rendered_window_update(E_Hwc_Window *hwc_window)
2509 {
2510    E_Client *ec;
2511    E_Hwc_Window_State state;
2512
2513    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2514
2515    if (hwc_window->is_deleted) return EINA_TRUE;
2516
2517    ec = hwc_window->ec;
2518    if (!ec) return EINA_TRUE;
2519
2520    state = e_hwc_window_state_get(hwc_window);
2521
2522    switch(state)
2523      {
2524        case E_HWC_WINDOW_STATE_DEVICE:
2525        case E_HWC_WINDOW_STATE_CURSOR:
2526          _e_hwc_window_rendered_window_set(hwc_window, EINA_FALSE);
2527          break;
2528        case E_HWC_WINDOW_STATE_CLIENT:
2529        case E_HWC_WINDOW_STATE_NONE:
2530          _e_hwc_window_rendered_window_set(hwc_window, EINA_TRUE);
2531          break;
2532        case E_HWC_WINDOW_STATE_VIDEO:
2533        default:
2534          break;
2535      }
2536
2537    return EINA_TRUE;
2538 }
2539
2540 EINTERN void
2541 e_hwc_window_client_type_override(E_Hwc_Window *hwc_window)
2542 {
2543    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
2544
2545    if (hwc_window->is_target) return;
2546    if (hwc_window->is_video) return;
2547
2548    if ((hwc_window->state == E_HWC_WINDOW_STATE_CLIENT) ||
2549        (hwc_window->state == E_HWC_WINDOW_STATE_VIDEO) ||
2550        (hwc_window->state == E_HWC_WINDOW_STATE_NONE))
2551      return;
2552
2553    if (hwc_window->ec && !hwc_window->ec->redirected)
2554      return;
2555
2556    e_hwc_window_device_state_available_update(hwc_window);
2557    e_hwc_window_state_set(hwc_window, E_HWC_WINDOW_STATE_CLIENT, EINA_TRUE);
2558    e_hwc_window_constraints_reset(hwc_window);
2559    e_hwc_window_rendered_window_update(hwc_window);
2560
2561    EHWTRACE("set client override", hwc_window->ec, hwc_window->hwc, hwc_window);
2562 }
2563
2564 EINTERN const char*
2565 e_hwc_window_state_string_get(E_Hwc_Window_State hwc_window_state)
2566 {
2567     switch (hwc_window_state)
2568     {
2569      case E_HWC_WINDOW_STATE_NONE:
2570        return "NO"; // None
2571      case E_HWC_WINDOW_STATE_CLIENT:
2572        return "CL"; // Client
2573      case E_HWC_WINDOW_STATE_DEVICE:
2574        return "DV"; // Device
2575      case E_HWC_WINDOW_STATE_VIDEO:
2576        return "VD"; // Video
2577      case E_HWC_WINDOW_STATE_CURSOR:
2578        return "CS"; // Cursor
2579      default:
2580        return "UNKNOWN";
2581     }
2582 }
2583
2584 EINTERN const char*
2585 e_hwc_window_restriction_string_get(E_Hwc_Window *hwc_window)
2586 {
2587    if (!hwc_window) return "UNKNOWN";
2588
2589    switch (hwc_window->restriction)
2590     {
2591      case E_HWC_WINDOW_RESTRICTION_NONE:
2592        return "none";
2593      case E_HWC_WINDOW_RESTRICTION_DELETED:
2594        return "deleted";
2595      case E_HWC_WINDOW_RESTRICTION_OVERRIDE:
2596        return "override";
2597      case E_HWC_WINDOW_RESTRICTION_ANIMATING:
2598        return "animating";
2599      case E_HWC_WINDOW_RESTRICTION_BUFFER:
2600        return "buffer";
2601      case E_HWC_WINDOW_RESTRICTION_VIEWPORT:
2602        return "viewport";
2603      case E_HWC_WINDOW_RESTRICTION_NEVER_HWC:
2604        return "never hwc";
2605      case E_HWC_WINDOW_RESTRICTION_TRANSFORM:
2606        return "window transform";
2607      case E_HWC_WINDOW_RESTRICTION_BUFFER_TYPE:
2608        return "buffer type";
2609      case E_HWC_WINDOW_RESTRICTION_OUTPUT:
2610        return "output";
2611      case E_HWC_WINDOW_RESTRICTION_MIN_WIDTH:
2612        return "min width";
2613      case E_HWC_WINDOW_RESTRICTION_MIN_HEIGHT:
2614        return "min height";
2615      case E_HWC_WINDOW_RESTRICTION_TOUCH_PRESS:
2616        return "touch press";
2617      case E_HWC_WINDOW_RESTRICTION_OUTPUT_TRANSFORM:
2618        return "output transform";
2619      case E_HWC_WINDOW_RESTRICTION_CONTENT_IMAGE:
2620        return "content image";
2621      case E_HWC_WINDOW_RESTRICTION_QUICKPANEL_OPEN:
2622        return "quickpanel open";
2623      case E_HWC_WINDOW_RESTRICTION_PIXMAP_RESOURCE:
2624        return "pixmap resource";
2625      case E_HWC_WINDOW_RESTRICTION_OBSCURED_BY_TARGET:
2626        return "obscured by target";
2627      case E_HWC_WINDOW_RESTRICTION_IMAGE_FILTER:
2628        return "image filter";
2629      case E_HWC_WINDOW_RESTRICTION_DESK_GEOMETRY:
2630        return "desk geometry";
2631      case E_HWC_WINDOW_RESTRICTION_EFFECT_RUNNING:
2632        return "effect running";
2633      case E_HWC_WINDOW_RESTRICTION_RENDER_UPDATE_LOCK:
2634        return "render update lock";
2635      case E_HWC_WINDOW_RESTRICTION_DESK_ZOOM:
2636        return "desk zoom";
2637      case E_HWC_WINDOW_RESTRICTION_BLEND_ALPHA:
2638        return "blend alpha";
2639      case E_HWC_WINDOW_RESTRICTION_BLEND_EQUATION:
2640        return "blend equation";
2641      case E_HWC_WINDOW_RESTRICTION_ZONE:
2642        return "zone";
2643      case E_HWC_WINDOW_RESTRICTION_QUEUE_UNSET_WAITING:
2644        return "queue unset waiting";
2645      default:
2646        return "UNKNOWN";
2647     }
2648 }
2649
2650 EINTERN const char*
2651 e_hwc_window_name_get(E_Hwc_Window *hwc_window)
2652 {
2653    const char *name;
2654
2655    if (!hwc_window)
2656      return "UNKNOWN";
2657
2658    if (hwc_window->is_root_target)
2659      return "@ROOT TARGET WINDOW@";
2660
2661    if (hwc_window->is_target)
2662      return "@TARGET WINDOW@";
2663
2664    if (!hwc_window->ec)
2665      return "UNKNOWN";
2666
2667    name = e_client_util_name_get(hwc_window->ec);
2668    if (!name)
2669      return "UNKNOWN";
2670
2671    return name;
2672 }
2673
2674 EINTERN void
2675 e_hwc_window_name_set(E_Hwc_Window *hwc_window)
2676 {
2677    const char *name;
2678    tdm_error ret;
2679    Eina_Bool no_name = EINA_FALSE;
2680
2681    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
2682
2683    if (hwc_window->set_name) return;
2684
2685    name = e_client_util_name_get(hwc_window->ec);
2686    if (!name)
2687      {
2688         name = "UNKNOWN";
2689         no_name = EINA_TRUE;
2690      }
2691
2692    ret = tdm_hwc_window_set_name(hwc_window->thwc_window, name);
2693    EINA_SAFETY_ON_TRUE_RETURN(ret != TDM_ERROR_NONE);
2694
2695    /* the name may be set later */
2696    if (no_name) return;
2697
2698    hwc_window->set_name = EINA_TRUE;
2699 }
2700
2701 EINTERN Eina_Bool
2702 e_hwc_window_set_property(E_Hwc_Window *hwc_window, unsigned int id, const char *name, tdm_value value, Eina_Bool force)
2703 {
2704    E_Client *ec;
2705    const Eina_List *l;
2706    Hwc_Window_Prop *prop;
2707    tdm_error ret;
2708
2709    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2710
2711    ec = hwc_window->ec;
2712    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
2713    EINA_SAFETY_ON_TRUE_RETURN_VAL(e_object_is_del(E_OBJECT(ec)), EINA_FALSE);
2714
2715    if (force)
2716      {
2717         /* set the property on the fly */
2718         ret = tdm_hwc_window_set_property(hwc_window->thwc_window, id, value);
2719         EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, ret);
2720
2721         EHWTRACE("Set Property: property(%s) value(%d) - {%s}",
2722                  hwc_window->ec, hwc_window->hwc, hwc_window,
2723                  name, (unsigned int)value.u32,
2724                  e_hwc_window_name_get(hwc_window));
2725      }
2726    else
2727      {
2728         /* change the vaule of the property if prop_list already has the property */
2729         EINA_LIST_FOREACH(hwc_window->prop_list, l, prop)
2730           {
2731              if (!strncmp(name, prop->name, TDM_NAME_LEN))
2732                {
2733                   EHWTRACE("Change Property: property(%s) update value(%d -> %d) - {%s}",
2734                            hwc_window->ec, hwc_window->hwc, hwc_window,
2735                            prop->name, (unsigned int)prop->value.u32, (unsigned int)value.u32,
2736                            e_hwc_window_name_get(hwc_window));
2737                   prop->value.u32 = value.u32;
2738                   return EINA_TRUE;
2739                }
2740           }
2741
2742         /* store the properties and commit at the hwc_commit time */
2743         prop = calloc(1, sizeof(Hwc_Window_Prop));
2744         EINA_SAFETY_ON_NULL_RETURN_VAL(prop, EINA_FALSE);
2745         prop->value.u32 = value.u32;
2746         prop->id = id;
2747         memcpy(prop->name, name, sizeof(TDM_NAME_LEN));
2748         hwc_window->prop_list = eina_list_append(hwc_window->prop_list, prop);
2749
2750         EHWTRACE("Set Property: property(%s) value(%d) - {%s}",
2751                  hwc_window->ec, hwc_window->hwc, hwc_window,
2752                  prop->name, (unsigned int)value.u32,
2753                  e_hwc_window_name_get(hwc_window));
2754      }
2755
2756    return EINA_TRUE;
2757 }
2758
2759 EINTERN Eina_Bool
2760 e_hwc_window_get_property(E_Hwc_Window *hwc_window, unsigned int id, tdm_value *value)
2761 {
2762    tdm_error ret;
2763
2764    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2765    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
2766
2767    ret = tdm_hwc_window_get_property(hwc_window->thwc_window, id, value);
2768    EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, EINA_FALSE);
2769
2770    return EINA_TRUE;
2771 }
2772
2773 EINTERN E_Hwc_Window_Update_Data *
2774 e_hwc_window_pending_update_data_dequeue(E_Hwc_Window *hwc_window)
2775 {
2776    tdm_hwc_window_info hwc_win_info = {0, };
2777    E_Client *ec;
2778    E_Hwc_Window_Update_Data *update;
2779    E_Comp_Wl_Buffer *comp_buffer;
2780    tbm_surface_h tsurface;
2781
2782    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
2783    EINA_SAFETY_ON_TRUE_RETURN_VAL(hwc_window->is_target, NULL);
2784
2785    /* not support cursor */
2786    if (e_hwc_window_is_cursor(hwc_window)) return NULL;
2787
2788    ec = hwc_window->ec;
2789
2790    if ((hwc_window->is_deleted) || (!ec) || e_object_is_del(E_OBJECT(ec)))
2791      return NULL;
2792
2793    if (e_hwc_window_is_video(hwc_window))
2794      {
2795         if (!_e_hwc_window_video_info_get(hwc_window, &hwc_win_info))
2796           {
2797              EHWERR("fail to _e_hwc_window_video_info_get",
2798                     hwc_window->ec, hwc_window->hwc, hwc_window);
2799              return EINA_FALSE;
2800           }
2801
2802         tsurface = e_client_video_tbm_surface_get(hwc_window->ec);
2803      }
2804    else
2805      {
2806         if (!_e_hwc_window_info_get(hwc_window, &hwc_win_info))
2807           {
2808              EHWERR("fail to _e_hwc_window_info_get",
2809                     hwc_window->ec, hwc_window->hwc, hwc_window);
2810              return EINA_FALSE;
2811           }
2812
2813         tsurface = _e_hwc_window_client_surface_acquire(hwc_window);
2814      }
2815
2816    update = E_NEW(E_Hwc_Window_Update_Data, 1);
2817    EINA_SAFETY_ON_NULL_RETURN_VAL(update, NULL);
2818
2819    e_hwc_window_ref(hwc_window);
2820    update->hwc_window = hwc_window;
2821
2822    comp_buffer = _e_hwc_window_comp_wl_buffer_get(hwc_window);
2823
2824    memcpy(&update->info, &hwc_win_info, sizeof(tdm_hwc_window_info));
2825    e_hwc_window_buffer_set(&update->buffer, tsurface, hwc_window->queue,
2826                            comp_buffer ? comp_buffer->transform : 0);
2827    e_comp_wl_buffer_reference(&update->buffer_ref, comp_buffer);
2828
2829    EHWTRACE("PEN DEQ:%p ts:%10p src(%dx%d+%d+%d size:%dx%d fmt:%c%c%c%c) dst(%dx%d+%d+%d) trans(%d)",
2830             hwc_window->ec, hwc_window->hwc, hwc_window,
2831             update,
2832             tsurface,
2833             update->info.src_config.pos.w, update->info.src_config.pos.h,
2834             update->info.src_config.pos.x, update->info.src_config.pos.y,
2835             update->info.src_config.size.h, update->info.src_config.size.v,
2836             EHW_FOURCC_STR(update->info.src_config.format),
2837             update->info.dst_pos.w, update->info.dst_pos.h,
2838             update->info.dst_pos.x, update->info.dst_pos.y,
2839             update->info.transform);
2840
2841    hwc_window->pending_update_list = eina_list_append(hwc_window->pending_update_list, update);
2842
2843    return update;
2844 }
2845
2846 EINTERN Eina_Bool
2847 e_hwc_window_pending_update_data_dequeue_cancel(E_Hwc_Window *hwc_window, E_Hwc_Window_Update_Data *update)
2848 {
2849    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2850    EINA_SAFETY_ON_NULL_RETURN_VAL(update, EINA_FALSE);
2851
2852    EHWTRACE("PEN CAN:%p ts:%10p src(%dx%d+%d+%d size:%dx%d fmt:%c%c%c%c) dst(%dx%d+%d+%d) trans(%d)",
2853             hwc_window->ec, hwc_window->hwc, hwc_window,
2854             update,
2855             update->buffer.tsurface,
2856             update->info.src_config.pos.w, update->info.src_config.pos.h,
2857             update->info.src_config.pos.x, update->info.src_config.pos.y,
2858             update->info.src_config.size.h, update->info.src_config.size.v,
2859             EHW_FOURCC_STR(update->info.src_config.format),
2860             update->info.dst_pos.w, update->info.dst_pos.h,
2861             update->info.dst_pos.x, update->info.dst_pos.y,
2862             update->info.transform);
2863
2864    e_comp_wl_buffer_reference(&update->buffer_ref, NULL);
2865    e_hwc_window_buffer_set(&update->buffer, NULL, NULL, 0);
2866
2867    hwc_window->pending_update_list = eina_list_remove(hwc_window->pending_update_list, update);
2868
2869    if (update->hwc_window)
2870      e_hwc_window_unref(update->hwc_window);
2871
2872    E_FREE(update);
2873
2874    return EINA_TRUE;
2875 }
2876
2877 EINTERN Eina_Bool
2878 e_hwc_window_pending_update_data_enqueue(E_Hwc_Window *hwc_window, E_Hwc_Window_Update_Data *update)
2879 {
2880    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2881    EINA_SAFETY_ON_NULL_RETURN_VAL(update, EINA_FALSE);
2882
2883    EHWTRACE("PEN ENQ:%p ts:%10p src(%dx%d+%d+%d size:%dx%d fmt:%c%c%c%c) dst(%dx%d+%d+%d) trans(%d)",
2884             hwc_window->ec, hwc_window->hwc, hwc_window,
2885             update,
2886             update->buffer.tsurface,
2887             update->info.src_config.pos.w, update->info.src_config.pos.h,
2888             update->info.src_config.pos.x, update->info.src_config.pos.y,
2889             update->info.src_config.size.h, update->info.src_config.size.v,
2890             EHW_FOURCC_STR(update->info.src_config.format),
2891             update->info.dst_pos.w, update->info.dst_pos.h,
2892             update->info.dst_pos.x, update->info.dst_pos.y,
2893             update->info.transform);
2894
2895    _e_hwc_window_info_set(hwc_window, &update->info);
2896    _e_hwc_window_buffer_set(hwc_window, update->buffer.tsurface,
2897                             update->buffer_ref.buffer, update->buffer.queue);
2898
2899    e_comp_wl_buffer_reference(&update->buffer_ref, NULL);
2900    e_hwc_window_buffer_set(&update->buffer, NULL, NULL, 0);
2901
2902    hwc_window->pending_update_list = eina_list_remove(hwc_window->pending_update_list, update);
2903
2904    if (update->hwc_window)
2905      e_hwc_window_unref(update->hwc_window);
2906
2907    E_FREE(update);
2908
2909    return EINA_TRUE;
2910 }
2911
2912 EINTERN Eina_Bool
2913 e_hwc_window_pending_update_data_has(E_Hwc_Window *hwc_window)
2914 {
2915    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2916
2917    if (eina_list_count(hwc_window->pending_update_list))
2918      return EINA_TRUE;
2919
2920    return EINA_FALSE;
2921 }
2922
2923 EINTERN Eina_Bool
2924 e_hwc_window_present_sync(E_Hwc_Window *hwc_window)
2925 {
2926    E_Hwc_Window_Target *target_hwc_window;
2927    E_Hwc_Window_State state;
2928
2929    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
2930    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
2931
2932    target_hwc_window = hwc_window->hwc->target_hwc_window;
2933    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
2934
2935    if (e_hwc_window_is_cursor(hwc_window))
2936      {
2937         EHWERR("cursor doesn't support present sync", hwc_window->ec, hwc_window->hwc, hwc_window);
2938         return EINA_FALSE;
2939      }
2940
2941    /* if gl compositor is disabled, present sync isn't needed */
2942    state = e_hwc_window_accepted_state_get((E_Hwc_Window *)target_hwc_window);
2943    if (state == E_HWC_WINDOW_STATE_NONE)
2944       return EINA_TRUE;
2945
2946    if (hwc_window->present_sync) return EINA_TRUE;
2947
2948    hwc_window->present_sync = EINA_TRUE;
2949
2950    if (!eina_list_data_find(target_hwc_window->present_sync_windows, hwc_window))
2951      {
2952         target_hwc_window->present_sync_windows = eina_list_append(target_hwc_window->present_sync_windows,
2953                                                                    hwc_window);
2954         e_hwc_window_ref(hwc_window);
2955      }
2956
2957    e_hwc_windows_target_window_force_render(target_hwc_window);
2958
2959    EHWINF("Present Sync", hwc_window->ec, hwc_window->hwc, hwc_window);
2960
2961    return EINA_TRUE;
2962 }
2963
2964 EINTERN E_Hwc_Window_Hook *
2965 e_hwc_window_hook_add(E_Hwc_Window_Hook_Point hookpoint, E_Hwc_Window_Hook_Cb func, const void *data)
2966 {
2967    E_Hwc_Window_Hook *ch;
2968
2969    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_HWC_WINDOW_HOOK_LAST, NULL);
2970    ch = E_NEW(E_Hwc_Window_Hook, 1);
2971    if (!ch) return NULL;
2972    ch->hookpoint = hookpoint;
2973    ch->func = func;
2974    ch->data = (void*)data;
2975    _e_hwc_window_hooks[hookpoint] = eina_inlist_append(_e_hwc_window_hooks[hookpoint],
2976                                                        EINA_INLIST_GET(ch));
2977    return ch;
2978 }
2979
2980 EINTERN void
2981 e_hwc_window_hook_del(E_Hwc_Window_Hook *ch)
2982 {
2983    ch->delete_me = 1;
2984    if (_e_hwc_window_hooks_walking == 0)
2985      {
2986         _e_hwc_window_hooks[ch->hookpoint] = eina_inlist_remove(_e_hwc_window_hooks[ch->hookpoint],
2987                                                                 EINA_INLIST_GET(ch));
2988         free(ch);
2989      }
2990    else
2991      _e_hwc_window_hooks_delete++;
2992 }
2993
2994 EINTERN void
2995 e_hwc_window_trace_debug(Eina_Bool onoff)
2996 {
2997    if (onoff == ehw_trace) return;
2998    ehw_trace = onoff;
2999    INF("EHW: hwc trace_debug is %s", onoff?"ON":"OFF");
3000 }
3001
3002 EINTERN void
3003 e_hwc_window_commit_data_buffer_dump(E_Hwc_Window *hwc_window, E_Hwc_Window_Commit_Data *commit_data)
3004 {
3005    tbm_surface_h capturable_tsurface;
3006    char fname[64];
3007
3008    EINA_SAFETY_ON_FALSE_RETURN(hwc_window);
3009    EINA_SAFETY_ON_FALSE_RETURN(commit_data);
3010
3011    if (!commit_data->buffer.tsurface) return;
3012
3013    if (hwc_window->is_target)
3014      snprintf(fname, sizeof(fname), "hwc_commit_composite_%p",
3015               hwc_window);
3016    else
3017      snprintf(fname, sizeof(fname), "hwc_commit_0x%08zx_%p",
3018               e_client_util_win_get(hwc_window->ec), hwc_window);
3019
3020    capturable_tsurface = e_comp_wl_tbm_capturable_buffer_get(commit_data->buffer.tsurface);
3021    EINA_SAFETY_ON_NULL_RETURN(capturable_tsurface);
3022
3023    tbm_surface_internal_dump_buffer(capturable_tsurface,
3024                                     fname);
3025    tbm_surface_internal_unref(capturable_tsurface);
3026 }
3027
3028 EINTERN Eina_Bool
3029 e_hwc_window_fps_get(E_Hwc_Window *hwc_window, double *fps)
3030 {
3031    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3032
3033    if (hwc_window->fps.old_fps == hwc_window->fps.fps)
3034      return EINA_FALSE;
3035
3036    if (hwc_window->fps.fps > 0.0)
3037      {
3038         *fps = hwc_window->fps.fps;
3039         hwc_window->fps.old_fps = hwc_window->fps.fps;
3040         return EINA_TRUE;
3041      }
3042
3043    return EINA_FALSE;
3044 }
3045
3046 EINTERN void
3047 e_hwc_window_ref(E_Hwc_Window *hwc_window)
3048 {
3049   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
3050
3051   e_object_ref(E_OBJECT(hwc_window));
3052 }
3053
3054 EINTERN void
3055 e_hwc_window_unref(E_Hwc_Window *hwc_window)
3056 {
3057   EINA_SAFETY_ON_NULL_RETURN(hwc_window);
3058
3059   e_object_unref(E_OBJECT(hwc_window));
3060 }
3061
3062 EINTERN Eina_Bool
3063 e_hwc_window_presentation_callback_pending_set(E_Hwc_Window *hwc_window, E_Hwc_Presentation_Callback *callback)
3064 {
3065    E_Hwc_Window_Target *target_hwc_window;
3066    E_Hwc *hwc;
3067
3068    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3069
3070    hwc = hwc_window->hwc;
3071    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3072
3073    target_hwc_window = hwc->target_hwc_window;
3074    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3075
3076    if ((hwc_window->accepted_state == E_HWC_WINDOW_STATE_NONE) ||
3077        (hwc_window->accepted_state == E_HWC_WINDOW_STATE_CLIENT))
3078      e_hwc_windows_target_window_force_render(hwc->target_hwc_window);
3079
3080    if (!e_hwc_presentation_callback_list_set(&hwc_window->pending_presentation_callbacks, callback))
3081      {
3082         EHWERR("fail to e_hwc_presentation_callback_list_set", hwc_window->ec, hwc_window->hwc, hwc_window);
3083         return EINA_FALSE;
3084      }
3085
3086    if (!eina_list_data_find(target_hwc_window->pending_presentation_cb_wins, hwc_window))
3087      {
3088         target_hwc_window->pending_presentation_cb_wins =
3089           eina_list_append(target_hwc_window->pending_presentation_cb_wins, hwc_window);
3090
3091         e_hwc_window_ref(hwc_window);
3092      }
3093
3094    return EINA_TRUE;
3095 }
3096
3097 EINTERN Eina_Bool
3098 e_hwc_window_presentation_callback_pending_take_over(E_Hwc_Window *hwc_window,
3099                                                      E_Hwc_Presentation_Callback_List *dst_list)
3100 {
3101    E_Hwc_Window_Target *target_hwc_window;
3102    E_Hwc *hwc;
3103
3104    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3105    EINA_SAFETY_ON_NULL_RETURN_VAL(dst_list, EINA_FALSE);
3106
3107    hwc = hwc_window->hwc;
3108    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3109
3110    target_hwc_window = hwc->target_hwc_window;
3111    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3112
3113    if (eina_list_data_find(target_hwc_window->pending_presentation_cb_wins, hwc_window))
3114      {
3115         target_hwc_window->pending_presentation_cb_wins =
3116           eina_list_remove(target_hwc_window->pending_presentation_cb_wins, hwc_window);
3117
3118         e_hwc_window_unref(hwc_window);
3119      }
3120
3121    e_hwc_presentation_callback_list_merge(dst_list,
3122                                           &hwc_window->pending_presentation_callbacks);
3123
3124    return EINA_TRUE;
3125 }
3126
3127 EINTERN Eina_Bool
3128 e_hwc_window_presentation_callback_take(E_Hwc_Window *hwc_window,
3129                                         E_Hwc_Presentation_Callback_List *src_list)
3130 {
3131    E_Hwc_Window_Target *target_hwc_window;
3132    E_Hwc *hwc;
3133
3134    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3135    EINA_SAFETY_ON_NULL_RETURN_VAL(src_list, EINA_FALSE);
3136
3137    hwc = hwc_window->hwc;
3138    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
3139
3140    target_hwc_window = hwc->target_hwc_window;
3141    EINA_SAFETY_ON_NULL_RETURN_VAL(target_hwc_window, EINA_FALSE);
3142
3143    if (&hwc_window->presentation_callbacks == src_list)
3144      {
3145         if (eina_list_data_find(target_hwc_window->pending_presentation_cb_wins, hwc_window))
3146           {
3147              target_hwc_window->pending_presentation_cb_wins =
3148                eina_list_remove(target_hwc_window->pending_presentation_cb_wins, hwc_window);
3149
3150              e_hwc_window_unref(hwc_window);
3151           }
3152      }
3153
3154    e_hwc_presentation_callback_list_merge(&hwc_window->presentation_callbacks,
3155                                           src_list);
3156
3157    return EINA_TRUE;
3158 }
3159
3160 EINTERN Eina_Bool
3161 e_hwc_window_presentation_callback_call(E_Hwc_Window *hwc_window)
3162 {
3163    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
3164
3165    if (!eina_list_count(hwc_window->presentation_callbacks.callbacks))
3166      return EINA_TRUE;
3167
3168    e_hwc_presentation_callback_list_call(&hwc_window->presentation_callbacks);
3169
3170    return EINA_TRUE;
3171 }
3172
3173 static void
3174 _e_hwc_window_below_transparent_obj_map_apply(E_Hwc_Window *hwc_window)
3175 {
3176    E_Map *map = NULL, *new_map = NULL;
3177    int w, h;
3178    Eina_Bool enable;
3179
3180    EINA_SAFETY_ON_NULL_RETURN(hwc_window->below_transparent_obj);
3181
3182    evas_object_geometry_get(hwc_window->below_transparent_obj, NULL, NULL, &w, &h);
3183
3184    enable = e_client_transform_core_enable_get(hwc_window->ec);
3185    if (enable)
3186      map = e_comp_object_map_get(hwc_window->ec->frame);
3187
3188    if ((enable) && (map))
3189      {
3190         new_map = e_map_dup(map);
3191         if (!new_map)
3192           {
3193              EHWERR("fail to dup e_map", hwc_window->ec, hwc_window->hwc, hwc_window);
3194              e_map_free(map);
3195              return;
3196           }
3197      }
3198    else
3199      {
3200         new_map = e_map_new();
3201         if (!new_map)
3202           {
3203              EHWERR("fail to new e_map", hwc_window->ec, hwc_window->hwc, hwc_window);
3204              return;
3205           }
3206
3207         e_map_util_points_populate_from_object_full(new_map, hwc_window->ec->frame, 0);
3208         e_map_util_points_color_set(new_map, 255, 255, 255, 255);
3209      }
3210
3211    e_map_point_image_uv_set(new_map, 0, 0, 0);
3212    e_map_point_image_uv_set(new_map, 1, w, 0);
3213    e_map_point_image_uv_set(new_map, 2, w, h);
3214    e_map_point_image_uv_set(new_map, 3, 0, h);
3215
3216    e_comp_object_map_set(hwc_window->below_transparent_obj, new_map);
3217    e_comp_object_map_enable_set(hwc_window->below_transparent_obj, EINA_TRUE);
3218
3219    if (map) e_map_free(map);
3220
3221    e_map_free(new_map);
3222 }
3223
3224 static void
3225 _e_hwc_window_below_transparent_obj_cb_show(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3226 {
3227    E_Hwc_Window *hwc_window;
3228
3229    if (!(hwc_window = data)) return;
3230
3231    evas_object_show(hwc_window->below_transparent_obj);
3232 }
3233
3234 static void
3235 _e_hwc_window_below_transparent_obj_cb_hide(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3236 {
3237    E_Hwc_Window *hwc_window;
3238
3239    if (!(hwc_window = data)) return;
3240
3241    evas_object_hide(hwc_window->below_transparent_obj);
3242 }
3243
3244 static void
3245 _e_hwc_window_below_transparent_obj_cb_move(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3246 {
3247    E_Hwc_Window *hwc_window;
3248
3249    if (!(hwc_window = data)) return;
3250
3251    evas_object_move(hwc_window->below_transparent_obj, hwc_window->ec->x, hwc_window->ec->y);
3252
3253    _e_hwc_window_below_transparent_obj_map_apply(hwc_window);
3254 }
3255
3256 static void
3257 _e_hwc_window_below_transparent_obj_cb_resize(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3258 {
3259    E_Hwc_Window *hwc_window;
3260
3261    if (!(hwc_window = data)) return;
3262
3263    _e_hwc_window_below_transparent_obj_map_apply(hwc_window);
3264 }
3265
3266 static void
3267 _e_hwc_window_below_transparent_obj_cb_restack(void *data, Evas *evas EINA_UNUSED, Evas_Object *obj EINA_UNUSED, void *event EINA_UNUSED)
3268 {
3269    E_Hwc_Window *hwc_window;
3270
3271    if (!(hwc_window = data)) return;
3272
3273    evas_object_layer_set(hwc_window->below_transparent_obj, evas_object_layer_get(hwc_window->ec->frame));
3274    evas_object_stack_below(hwc_window->below_transparent_obj, hwc_window->ec->frame);
3275 }
3276
3277 EINTERN void
3278 e_hwc_window_below_transparent_obj_set(E_Hwc_Window *hwc_window, Eina_Bool set)
3279 {
3280    Evas_Object *below_transparent_obj;
3281
3282    EINA_SAFETY_ON_NULL_RETURN(hwc_window);
3283
3284    if (set)
3285      {
3286         EINA_SAFETY_ON_NULL_RETURN(hwc_window->ec);
3287
3288         if (hwc_window->below_transparent_obj) return;
3289
3290         below_transparent_obj = evas_object_rectangle_add(e_comp->evas);
3291         EINA_SAFETY_ON_NULL_RETURN(below_transparent_obj);
3292
3293         evas_object_pass_events_set(below_transparent_obj, EINA_TRUE);
3294
3295         evas_object_layer_set(below_transparent_obj, evas_object_layer_get(hwc_window->ec->frame));
3296         evas_object_stack_below(below_transparent_obj, hwc_window->ec->frame);
3297         evas_object_render_op_set(below_transparent_obj, EVAS_RENDER_COPY);
3298
3299         evas_object_color_set(below_transparent_obj, 0, 0, 0, 0);
3300         evas_object_move(below_transparent_obj, hwc_window->ec->x, hwc_window->ec->y);
3301         evas_object_resize(below_transparent_obj, 1, 1);
3302         evas_object_name_set(below_transparent_obj, "hwc_below_transparent_obj");
3303
3304         hwc_window->below_transparent_obj = below_transparent_obj;
3305
3306         _e_hwc_window_below_transparent_obj_map_apply(hwc_window);
3307
3308         if (evas_object_visible_get(hwc_window->ec->frame))
3309           evas_object_show(hwc_window->below_transparent_obj);
3310
3311         evas_object_event_callback_add(hwc_window->ec->frame, EVAS_CALLBACK_SHOW,
3312                                        _e_hwc_window_below_transparent_obj_cb_show,
3313                                        hwc_window);
3314         evas_object_event_callback_add(hwc_window->ec->frame, EVAS_CALLBACK_HIDE,
3315                                        _e_hwc_window_below_transparent_obj_cb_hide,
3316                                        hwc_window);
3317         evas_object_event_callback_add(hwc_window->ec->frame, EVAS_CALLBACK_MOVE,
3318                                        _e_hwc_window_below_transparent_obj_cb_move,
3319                                        hwc_window);
3320         evas_object_event_callback_add(hwc_window->ec->frame, EVAS_CALLBACK_RESIZE,
3321                                        _e_hwc_window_below_transparent_obj_cb_resize,
3322                                        hwc_window);
3323         evas_object_event_callback_add(hwc_window->ec->frame, EVAS_CALLBACK_RESTACK,
3324                                        _e_hwc_window_below_transparent_obj_cb_restack,
3325                                        hwc_window);
3326
3327         EHWINF("Set below_transparent_obj", hwc_window->ec, hwc_window->hwc, hwc_window);
3328      }
3329    else
3330      {
3331         if (!hwc_window->below_transparent_obj) return;
3332
3333         E_FREE_FUNC(hwc_window->below_transparent_obj, evas_object_del);
3334
3335         if (hwc_window->ec)
3336           {
3337              evas_object_event_callback_del_full(hwc_window->ec->frame, EVAS_CALLBACK_SHOW,
3338                                                  _e_hwc_window_below_transparent_obj_cb_show,
3339                                                  hwc_window);
3340              evas_object_event_callback_del_full(hwc_window->ec->frame, EVAS_CALLBACK_HIDE,
3341                                                  _e_hwc_window_below_transparent_obj_cb_hide,
3342                                                  hwc_window);
3343              evas_object_event_callback_del_full(hwc_window->ec->frame, EVAS_CALLBACK_MOVE,
3344                                                  _e_hwc_window_below_transparent_obj_cb_move,
3345                                                  hwc_window);
3346              evas_object_event_callback_del_full(hwc_window->ec->frame, EVAS_CALLBACK_RESIZE,
3347                                                  _e_hwc_window_below_transparent_obj_cb_resize,
3348                                                  hwc_window);
3349              evas_object_event_callback_del_full(hwc_window->ec->frame, EVAS_CALLBACK_RESTACK,
3350                                                  _e_hwc_window_below_transparent_obj_cb_restack,
3351                                                  hwc_window);
3352           }
3353
3354         EHWINF("Unset below_transparent_obj", hwc_window->ec, hwc_window->hwc, hwc_window);
3355      }
3356 }