Revert "e_hwc: do not prefer use gbm backend if gbm backend is drm and dri"
[platform/upstream/enlightenment.git] / src / bin / e_hwc.c
1 #include "e_hwc_window_intern.h"
2 #include "e_hwc_windows_intern.h"
3 #include "e_hwc_planes_intern.h"
4 #include "e_hwc_intern.h"
5 #include "e_utils_intern.h"
6 #include "e_comp_screen_intern.h"
7 #include "e_comp_intern.h"
8 #include "e_error_intern.h"
9 #include "e_hwc_window_queue_intern.h"
10
11 #include <Evas_GL.h>
12 #include <gbm.h>
13
14 #define EHERR(f, hwc, x...)                               \
15    do                                                     \
16      {                                                    \
17         ELOGFE("HWC","%2d|"f,                             \
18                NULL, (e_hwc_output_index_get(hwc)), ##x); \
19      }                                                    \
20    while (0)
21
22 #define EHINF(f, hwc, x...)                               \
23    do                                                     \
24      {                                                    \
25         ELOGF("HWC", "%2d|"f,                             \
26               NULL, (e_hwc_output_index_get(hwc)), ##x);  \
27      }                                                    \
28    while (0)
29
30 E_API int E_EVENT_HWC_ACTIVE = -1;
31 E_API int E_EVENT_HWC_DEACTIVE = -1;
32
33 static int E_EVENT_HWC_PROPERTY_CHANGED = -1;
34
35 static int _e_hwc_intercept_hooks_delete = 0;
36 static int _e_hwc_intercept_hooks_walking = 0;
37
38 static Eina_Inlist *_e_hwc_intercept_hooks[] =
39 {
40    [E_HWC_INTERCEPT_HOOK_PREPARE_PLANE] = NULL,
41    [E_HWC_INTERCEPT_HOOK_END_ALL_PLANE] = NULL,
42 };
43
44 static int _e_hwc_hooks_delete = 0;
45 static int _e_hwc_hooks_walking = 0;
46
47 static Eina_Inlist *_e_hwc_hooks[] =
48 {
49    [E_HWC_HOOK_NORENDER_SET] = NULL,
50 };
51
52 static void
53 _e_hwc_intercept_hooks_clean(void)
54 {
55    Eina_Inlist *l;
56    E_Hwc_Intercept_Hook *ch;
57    unsigned int x;
58
59    for (x = 0; x < E_HWC_INTERCEPT_HOOK_LAST; x++)
60      EINA_INLIST_FOREACH_SAFE(_e_hwc_intercept_hooks[x], l, ch)
61        {
62           if (!ch->delete_me) continue;
63           _e_hwc_intercept_hooks[x] = eina_inlist_remove(_e_hwc_intercept_hooks[x], EINA_INLIST_GET(ch));
64           free(ch);
65        }
66 }
67
68 EINTERN Eina_Bool
69 e_hwc_intercept_hook_call(E_Hwc_Intercept_Hook_Point hookpoint, E_Hwc *hwc)
70 {
71    E_Hwc_Intercept_Hook *ch;
72    Eina_Bool ret = EINA_TRUE;
73
74    _e_hwc_intercept_hooks_walking++;
75    EINA_INLIST_FOREACH(_e_hwc_intercept_hooks[hookpoint], ch)
76      {
77         if (ch->delete_me) continue;
78         if (!(ch->func(ch->data, hwc)))
79           {
80              ret = EINA_FALSE;
81              break;
82           }
83      }
84    _e_hwc_intercept_hooks_walking--;
85    if ((_e_hwc_intercept_hooks_walking == 0) && (_e_hwc_intercept_hooks_delete > 0))
86      _e_hwc_intercept_hooks_clean();
87
88    return ret;
89 }
90
91 E_API E_Hwc_Intercept_Hook *
92 e_hwc_intercept_hook_add(E_Hwc_Intercept_Hook_Point hookpoint, E_Hwc_Intercept_Hook_Cb func, const void *data)
93 {
94    E_Hwc_Intercept_Hook *ch;
95
96    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_HWC_INTERCEPT_HOOK_LAST, NULL);
97    ch = E_NEW(E_Hwc_Intercept_Hook, 1);
98    if (!ch) return NULL;
99    ch->hookpoint = hookpoint;
100    ch->func = func;
101    ch->data = (void*)data;
102    _e_hwc_intercept_hooks[hookpoint] = eina_inlist_append(_e_hwc_intercept_hooks[hookpoint], EINA_INLIST_GET(ch));
103    return ch;
104 }
105
106 E_API void
107 e_hwc_intercept_hook_del(E_Hwc_Intercept_Hook *ch)
108 {
109    ch->delete_me = 1;
110    if (_e_hwc_intercept_hooks_walking == 0)
111     {
112         _e_hwc_intercept_hooks[ch->hookpoint] = eina_inlist_remove(_e_hwc_intercept_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
113         free(ch);
114      }
115    else
116      _e_hwc_intercept_hooks_delete++;
117 }
118
119 static void
120 _e_hwc_hooks_clean(void)
121 {
122    Eina_Inlist *l;
123    E_Hwc_Hook *ch;
124    unsigned int x;
125
126    for (x = 0; x < E_HWC_HOOK_LAST; x++)
127      EINA_INLIST_FOREACH_SAFE(_e_hwc_hooks[x], l, ch)
128        {
129           if (!ch->delete_me) continue;
130           _e_hwc_hooks[x] = eina_inlist_remove(_e_hwc_hooks[x], EINA_INLIST_GET(ch));
131           free(ch);
132        }
133 }
134
135 static void
136 _e_hwc_hook_call(E_Hwc_Hook_Point hookpoint, E_Hwc *hwc)
137 {
138    E_Hwc_Hook *ch;
139
140    _e_hwc_hooks_walking++;
141    EINA_INLIST_FOREACH(_e_hwc_hooks[hookpoint], ch)
142      {
143         if (ch->delete_me) continue;
144         ch->func(ch->data, hwc);
145      }
146    _e_hwc_hooks_walking--;
147    if ((_e_hwc_hooks_walking == 0) && (_e_hwc_hooks_delete > 0))
148      _e_hwc_hooks_clean();
149 }
150
151 EINTERN E_Hwc_Hook *
152 e_hwc_hook_add(E_Hwc_Hook_Point hookpoint, E_Hwc_Hook_Cb func, const void *data)
153 {
154    E_Hwc_Hook *ch;
155
156    EINA_SAFETY_ON_TRUE_RETURN_VAL(hookpoint >= E_HWC_HOOK_LAST, NULL);
157    ch = E_NEW(E_Hwc_Hook, 1);
158    if (!ch) return NULL;
159    ch->hookpoint = hookpoint;
160    ch->func = func;
161    ch->data = (void*)data;
162    _e_hwc_hooks[hookpoint] = eina_inlist_append(_e_hwc_hooks[hookpoint], EINA_INLIST_GET(ch));
163    return ch;
164 }
165
166 EINTERN void
167 e_hwc_hook_del(E_Hwc_Hook *ch)
168 {
169    ch->delete_me = 1;
170    if (_e_hwc_hooks_walking == 0)
171     {
172         _e_hwc_hooks[ch->hookpoint] = eina_inlist_remove(_e_hwc_hooks[ch->hookpoint], EINA_INLIST_GET(ch));
173         free(ch);
174      }
175    else
176      _e_hwc_hooks_delete++;
177 }
178
179 static void *
180 _e_hwc_tbm_surface_queue_alloc(void *data, int w, int h)
181 {
182    E_Hwc *hwc = (E_Hwc *)data;
183    E_Output *output = hwc->output;
184    E_Comp_Screen *e_comp_screen = output->e_comp_screen;
185    tbm_surface_queue_h tqueue = NULL;
186    tdm_error error;
187    int queue_w, queue_h;
188
189    if ((output->tdm_hwc) && (!output->fake_config))
190      {
191         tqueue = tdm_hwc_get_client_target_buffer_queue(hwc->thwc, &error);
192         if (error != TDM_ERROR_NONE)
193          {
194             EHERR("fail to tdm_hwc_get_client_target_buffer_queue", hwc);
195             return (void *)NULL;
196          }
197      }
198    else
199      {
200         tqueue = tbm_surface_queue_create(3, w, h, TBM_FORMAT_ARGB8888, TBM_BO_SCANOUT);
201         if (!tqueue)
202           {
203              EHERR("fail to tbm_surface_queue_create", hwc);
204              return (void *)NULL;
205           }
206      }
207
208    queue_w = tbm_surface_queue_get_width(tqueue);
209    queue_h = tbm_surface_queue_get_height(tqueue);
210
211    if ((w != queue_w) || (h != queue_h))
212      tbm_surface_queue_reset(tqueue, w, h, tbm_surface_queue_get_format(tqueue));
213
214    hwc->target_buffer_queue = tqueue;
215    e_comp_screen->tqueue = tqueue;
216
217    EHINF("The tqueue(%p, %dx%d) is created.", hwc, tqueue, queue_w, queue_h);
218
219    return (void *)tqueue;
220 }
221
222 static void
223 _e_hwc_tbm_surface_queue_free(void *data, void *tqueue)
224 {
225    E_Hwc *hwc = (E_Hwc *)data;
226
227    tbm_surface_queue_destroy(tqueue);
228    hwc->target_buffer_queue = NULL;
229 }
230
231 static void *
232 _e_hwc_gbm_surface_alloc(void *data, int w, int h)
233 {
234    E_Hwc *hwc = (E_Hwc *)data;
235    E_Output *output = hwc->output;
236    struct gbm_device *gdevice;
237    struct gbm_surface *gsurface;
238
239    if (output->tdm_hwc)
240      {
241         EINA_SAFETY_ON_NULL_RETURN_VAL(e_comp, NULL);
242
243         gdevice = e_comp_screen_gbm_device_get(e_comp->e_comp_screen);
244         EINA_SAFETY_ON_NULL_RETURN_VAL(gdevice, NULL);
245
246         gsurface = gbm_surface_create(gdevice, w, h,
247                                       hwc->gbm_format,
248                                       GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
249         EINA_SAFETY_ON_NULL_RETURN_VAL(gsurface, NULL);
250      }
251    else
252      {
253         EHERR("only tdm hwc support gbm_surface", hwc);
254         return (void *) NULL;
255      }
256
257    hwc->gsurface = gsurface;
258    hwc->gsurface_width = w;
259    hwc->gsurface_height = h;
260    hwc->gsurface_format = hwc->gbm_format;
261
262    EHINF("The gbm_surface(%p, %dx%d) fmt(%c%c%c%c)is created.", hwc, gsurface, w, h, EHW_FOURCC_STR(hwc->gsurface_format));
263
264    return (void *)gsurface;
265 }
266
267 static void
268 _e_hwc_gbm_surface_free(void *data, void *gsurface)
269 {
270    E_Hwc *hwc = (E_Hwc *)data;
271
272    EHINF("The gbm_surface(%p) is destroyed.", NULL, gsurface);
273
274    gbm_surface_destroy(gsurface);
275    hwc->gsurface = NULL;
276 }
277
278 static Ecore_Evas *
279 _e_hwc_ecore_evas_tbm_alloc(E_Hwc *hwc, int src_w, int src_h)
280 {
281    Ecore_Evas *ee;
282
283    if (e_comp->avoid_afill)
284      {
285         ee = ecore_evas_tbm_allocfunc_new("gl_tbm_ES", src_w, src_h,
286                                           _e_hwc_tbm_surface_queue_alloc,
287                                           _e_hwc_tbm_surface_queue_free,
288                                           (void *)hwc);
289      }
290    else
291      {
292         ee = ecore_evas_tbm_allocfunc_new("gl_tbm", src_w, src_h,
293                                           _e_hwc_tbm_surface_queue_alloc,
294                                           _e_hwc_tbm_surface_queue_free,
295                                           (void *)hwc);
296      }
297
298    EHINF("ecore_evas engine:gl_tbm ee:%p avoid_afill:%d", hwc, ee, e_comp->avoid_afill);
299
300    return ee;
301 }
302
303 static Ecore_Evas *
304 _e_hwc_ecore_evas_gbm_alloc(E_Hwc *hwc, int src_w, int src_h)
305 {
306    Ecore_Evas *ee;
307    struct gbm_device *gdevice;
308    int gbm_formats[2] = {GBM_FORMAT_ABGR8888, GBM_FORMAT_ARGB8888};
309    int i, format_count;
310
311    gdevice = e_comp_screen_gbm_device_get(e_comp->e_comp_screen);
312    if (!gdevice) return NULL;
313
314    format_count = sizeof(gbm_formats) / sizeof(int);
315    for (i = 0; i < format_count; i++)
316      {
317         hwc->gbm_format = gbm_formats[i];
318
319         if (e_comp->avoid_afill)
320           {
321              ee = ecore_evas_tbm_native_allocfunc_new("gl_tbm_ES", gdevice, src_w, src_h,
322                                                       _e_hwc_gbm_surface_alloc,
323                                                       _e_hwc_gbm_surface_free,
324                                                       (void *)hwc);
325           }
326         else
327           {
328              ee = ecore_evas_tbm_native_allocfunc_new("gl_tbm", gdevice, src_w, src_h,
329                                                       _e_hwc_gbm_surface_alloc,
330                                                       _e_hwc_gbm_surface_free,
331                                                       (void *)hwc);
332           }
333
334         if (ee) break;
335      }
336
337    EHINF("ecore_evas engine:gl_tbm with gbm ee:%p avaoid_afill:%d", hwc, ee, e_comp->avoid_afill);
338
339    return ee;
340 }
341
342 EINTERN void
343 e_hwc_ecore_evas_deinit(void)
344 {
345    E_Output *primary_output = NULL;
346    E_Hwc *hwc = NULL;
347
348    primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
349    if (!primary_output) return;
350
351    hwc = primary_output->hwc;
352    if (!hwc) return;
353    if (!hwc->ee) return;
354
355    ecore_evas_free(hwc->ee);
356    hwc->ee =NULL;
357 }
358
359 static Eina_Bool
360 _e_hwc_prefer_gbm_check(void)
361 {
362    const char *backend_name;
363    struct gbm_device *gdevice;
364
365    if (e_comp->hwc_prefer_gbm)
366       return EINA_TRUE;
367
368    gdevice = e_comp_screen_gbm_device_get(e_comp->e_comp_screen);
369    if (!gdevice) return EINA_FALSE;
370
371    backend_name = gbm_device_get_backend_name(gdevice);
372    if (!backend_name) return EINA_FALSE;
373    if (!e_util_strcmp(backend_name, "gbm_tbm")) return EINA_FALSE;
374
375    return EINA_TRUE;
376 }
377
378 EINTERN Eina_Bool
379 e_hwc_ecore_evas_init(void)
380 {
381    E_Output *primary_output = NULL;
382    Ecore_Evas *ee = NULL;
383    int w = 0, h = 0, scr_w = 1, scr_h = 1;
384    E_Hwc *hwc;
385    int screen_rotation;
386    char buf[1024];
387
388    primary_output = e_comp_screen_primary_output_get(e_comp->e_comp_screen);
389    EINA_SAFETY_ON_NULL_RETURN_VAL(primary_output, EINA_FALSE);
390
391    hwc = primary_output->hwc;
392    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
393
394    EHINF("ecore evase engine init.", hwc);
395
396    // TODO: fix me. change the screen_rotation into output_rotation.
397    screen_rotation = primary_output->e_comp_screen->rotation;
398
399    /* set env for use tbm_surface_queue*/
400    setenv("USE_EVAS_SOFTWARE_TBM_ENGINE", "1", 1);
401    //setenv("USE_EVAS_GL_TBM_ENGINE", "1", 1);
402
403    /* set gl available if we have ecore_evas support */
404    if (ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_DRM) ||
405        ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_OPENGL_TBM))
406      e_comp_gl_set(EINA_TRUE);
407
408    e_comp_screen_size_get(e_comp->e_comp_screen, &scr_w, &scr_h);
409
410    EHINF("GL available:%d config engine:%d screen size:%dx%d", hwc,
411        e_comp_gl_get(), e_comp_config_get()->engine, scr_w, scr_h);
412
413    if ((e_comp_gl_get()) &&
414        (e_comp_config_get()->engine == E_COMP_ENGINE_GL))
415      {
416         e_main_ts_begin("\tEE_GL_TBM New");
417         if (_e_hwc_prefer_gbm_check())
418           {
419              ee = _e_hwc_ecore_evas_gbm_alloc(hwc, scr_w, scr_h);
420              if (!ee)
421                ee = _e_hwc_ecore_evas_tbm_alloc(hwc, scr_w, scr_h);
422           }
423         else
424           {
425              ee = _e_hwc_ecore_evas_tbm_alloc(hwc, scr_w, scr_h);
426              if (!ee)
427                ee = _e_hwc_ecore_evas_gbm_alloc(hwc, scr_w, scr_h);
428           }
429
430         snprintf(buf, sizeof(buf), "\tEE_GL_TBM New Done %p %dx%d", ee, scr_w, scr_h);
431         e_main_ts_end(buf);
432
433         if (!ee)
434           e_comp_gl_set(EINA_FALSE);
435      }
436
437    /* fallback to framebuffer drm (non-accel) */
438    if (!ee)
439      {
440         e_main_ts_begin("\tEE_DRM New");
441         ee = ecore_evas_tbm_allocfunc_new("software_tbm", scr_w, scr_h, _e_hwc_tbm_surface_queue_alloc, _e_hwc_tbm_surface_queue_free, (void *)hwc);
442         EHINF("ecore_evas engine:software_tbm fallback to software engine.", hwc);
443         snprintf(buf, sizeof(buf), "\tEE_DRM New Done %p %dx%d", ee, scr_w, scr_h);
444         e_main_ts_end(buf);
445      }
446
447    if (!ee)
448      {
449         e_error_message_show(_("Enlightenment cannot initialize outputs!\n"));
450         e_hwc_ecore_evas_deinit();
451         return EINA_FALSE;
452      }
453
454    hwc->ee = ee;
455    hwc->evas = ecore_evas_get(hwc->ee);
456
457    EHINF("ee(%p) with the tqueue(%p) is created.", hwc, ee, hwc->target_buffer_queue);
458
459    e_comp->ee = ee;
460    ecore_evas_data_set(e_comp->ee, "comp", e_comp);
461
462    if (screen_rotation)
463      {
464         /* SHOULD called with resize option after ecore_evas_resize */
465         ecore_evas_rotation_with_resize_set(e_comp->ee, screen_rotation);
466         ecore_evas_geometry_get(e_comp->ee, NULL, NULL, &w, &h);
467         snprintf(buf, sizeof(buf), "\tEE Rotate and Resize %d, %dx%d", screen_rotation, w, h);
468         e_main_ts(buf);
469      }
470
471    if (hwc->hwc_policy == E_HWC_POLICY_WINDOWS)
472      {
473         if (!e_hwc_windows_ecore_evas_set(hwc, ee))
474           {
475              ERR("fail to e_hwc_windows_ecore_evas_set");
476              e_hwc_ecore_evas_deinit();
477              return EINA_FALSE;
478           }
479      }
480    else
481      {
482         if (!e_hwc_planes_ecore_evas_set(hwc, ee))
483           {
484              ERR("fail to e_hwc_planes_ecore_evas_set");
485              e_hwc_ecore_evas_deinit();
486              return EINA_FALSE;
487           }
488      }
489
490    return EINA_TRUE;
491 }
492
493 EINTERN Eina_Bool
494 e_hwc_init(void)
495 {
496    E_EVENT_HWC_ACTIVE = ecore_event_type_new();
497    E_EVENT_HWC_DEACTIVE = ecore_event_type_new();
498    E_EVENT_HWC_PROPERTY_CHANGED = ecore_event_type_new();
499
500    return EINA_TRUE;
501 }
502
503 EINTERN void
504 e_hwc_deinit(void)
505 {
506 }
507
508 EINTERN E_Hwc *
509 e_hwc_new(E_Output *output, Eina_Bool primary_output)
510 {
511    E_Hwc *hwc = NULL;
512    tdm_hwc_capability hwc_caps = 0;
513    tdm_error error;
514
515    EINA_SAFETY_ON_NULL_RETURN_VAL(output, NULL);
516
517    hwc = E_NEW(E_Hwc, 1);
518    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
519    hwc->output = output;
520
521    hwc->commit_fence_fd = -1;
522
523    /*
524     * E20 has two hwc policy options.
525     * 1. One is the E_HWC_POLICY_PLANES.
526     *   - E20 decides the hwc policy with the E_Planes associated with the tdm_layers.
527     *   - E20 manages how to set the surface(buffer) of the ec to the E_Plane.
528     * 2. Another is the E_HWC_POLICY_WIDNOWS.
529     *   - The tdm-backend decides the hwc policy with the E_Hwc_Windows associated with the tdm_hwc_window.
530     *   - E20 asks to verify the composition types of the E_Hwc_Window of the ec.
531     */
532    if (!output->tdm_hwc)
533      {
534         hwc->hwc_policy = E_HWC_POLICY_PLANES;
535         EHINF("Use the HWC PLANES Policy.", hwc);
536      }
537    else
538      {
539         hwc->hwc_policy = E_HWC_POLICY_WINDOWS;
540         EHINF("Use the HWC WINDOWS Policy.", hwc);
541
542         hwc->thwc = tdm_output_get_hwc(output->toutput, &error);
543         if (!hwc->thwc)
544           {
545              EHERR("tdm_output_get_hwc failed", hwc);
546              goto fail;
547           }
548
549         error = tdm_hwc_get_capabilities(hwc->thwc, &hwc_caps);
550         if (error != TDM_ERROR_NONE)
551           {
552              EHERR("fail to tdm_hwc_get_capabilities", hwc);
553              return EINA_FALSE;
554           }
555
556         /* hwc video capabilities */
557         if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_STREAM)
558           hwc->tdm_hwc_video_stream = EINA_TRUE;
559         if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCALE)
560           hwc->tdm_hwc_video_scale = EINA_TRUE;
561         if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_TRANSFORM)
562           hwc->tdm_hwc_video_transform = EINA_TRUE;
563         if (hwc_caps & TDM_HWC_CAPABILITY_VIDEO_SCANOUT)
564           hwc->tdm_hwc_video_scanout = EINA_TRUE;
565         if (hwc_caps & TDM_HWC_CAPABILITY_FENCE)
566           hwc->tdm_hwc_fence = EINA_TRUE;
567      }
568
569    tdm_output_get_available_size(output->toutput,
570                                  &hwc->output_available.min_w,
571                                  &hwc->output_available.min_h,
572                                  &hwc->output_available.max_w,
573                                  &hwc->output_available.max_h,
574                                  NULL);
575
576    /* set the pirmary_output */
577    hwc->primary_output = primary_output;
578
579    if (e_hwc_policy_get(hwc) == E_HWC_POLICY_WINDOWS)
580      {
581         /* create the target_window to the hwc */
582         hwc->target_hwc_window = e_hwc_windows_target_window_new(hwc, EINA_FALSE);
583         if (!hwc->target_hwc_window)
584           {
585              EHERR("e_hwc_windows_target_window_new failed", hwc);
586              goto fail;
587           }
588
589         if (primary_output)
590           {
591              hwc->root_target_hwc_window = e_hwc_windows_target_window_new(hwc, EINA_TRUE);
592              if (!hwc->root_target_hwc_window)
593                {
594                   EHERR("e_hwc_windows_target_window_new failed", hwc);
595                   goto fail;
596                }
597           }
598      }
599
600    /* default active hwc */
601    ecore_event_add(E_EVENT_HWC_ACTIVE, NULL, NULL, NULL);
602
603    return hwc;
604
605 fail:
606    e_hwc_del(hwc);
607
608    return NULL;
609 }
610
611 EINTERN void
612 e_hwc_del(E_Hwc *hwc)
613 {
614    E_Hwc_Sync_Callback *sync_callback;
615    E_Hwc_Window *hwc_window;
616
617    if (!hwc) return;
618
619    if (e_hwc_policy_get(hwc) == E_HWC_POLICY_WINDOWS)
620      {
621         if (hwc->target_hwc_window)
622           {
623              e_hwc_windows_target_window_del(hwc->target_hwc_window);
624              hwc->target_hwc_window = NULL;
625           }
626
627         if (hwc->root_target_hwc_window)
628           {
629              e_hwc_windows_target_window_del(hwc->root_target_hwc_window);
630              hwc->root_target_hwc_window = NULL;
631           }
632      }
633
634    e_hwc_window_queue_buffer_reference(&hwc->pp_update.queue_buffer_ref, NULL);
635    e_comp_wl_buffer_reference(&hwc->pp_update.buffer_ref, NULL);
636
637    EINA_LIST_FREE(hwc->sync_callback_list, sync_callback)
638      sync_callback->hwc = NULL;
639
640    EINA_LIST_FREE(hwc->visible_windows, hwc_window)
641      e_hwc_window_unref(hwc_window);
642
643    if (hwc->commit_fence_fd >= 0)
644      close(hwc->commit_fence_fd);
645
646    E_FREE(hwc);
647 }
648
649 E_API E_Hwc_Mode
650 e_hwc_mode_get(E_Hwc *hwc)
651 {
652    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, E_HWC_MODE_NONE);
653
654    return hwc->hwc_mode;
655 }
656
657 E_API E_Hwc_Policy
658 e_hwc_policy_get(E_Hwc *hwc)
659 {
660    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, E_HWC_MODE_NONE);
661
662    return hwc->hwc_policy;
663 }
664
665 E_API void
666 e_hwc_deactive_set(E_Hwc *hwc, Eina_Bool set)
667 {
668    EINA_SAFETY_ON_NULL_RETURN(hwc);
669
670    if (hwc->hwc_deactive == set) return;
671
672    if (e_hwc_policy_get(hwc) == E_HWC_POLICY_PLANES)
673      e_hwc_planes_end(hwc, __FUNCTION__);
674
675    hwc->hwc_deactive = set;
676
677    if (set)
678      {
679         e_hwc_windows_restriction_set(hwc, E_HWC_WINS_RESTRICTION_DEACTIVE);
680         ecore_event_add(E_EVENT_HWC_DEACTIVE, NULL, NULL, NULL);
681      }
682    else
683      {
684         e_hwc_windows_restriction_unset(hwc, E_HWC_WINS_RESTRICTION_DEACTIVE);
685         ecore_event_add(E_EVENT_HWC_ACTIVE, NULL, NULL, NULL);
686      }
687
688    EHINF("e_hwc_deactive_set : %d", hwc, set);
689 }
690
691 E_API Eina_Bool
692 e_hwc_deactive_get(E_Hwc *hwc)
693 {
694    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
695
696    return hwc->hwc_deactive;
697 }
698
699 EINTERN Eina_Bool
700 e_hwc_client_is_above_hwc(E_Client *ec, E_Client *hwc_ec)
701 {
702    Evas_Object *o;
703    int layer, hwc_layer;
704
705    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
706    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_ec, EINA_FALSE);
707
708    if (ec == hwc_ec) return EINA_FALSE;
709    if (!evas_object_visible_get(ec->frame)) return EINA_FALSE;
710
711    layer = evas_object_layer_get(ec->frame);
712    hwc_layer = evas_object_layer_get(hwc_ec->frame);
713
714    /* compare layer */
715    if (hwc_layer > layer) return EINA_FALSE;
716    if (layer > hwc_layer) return EINA_TRUE;
717
718    o = evas_object_above_get(hwc_ec->frame);
719    if (evas_object_layer_get(o) == hwc_layer)
720      {
721         do {
722            if (o == ec->frame)
723              return EINA_TRUE;
724            o = evas_object_above_get(o);
725         } while (o && (evas_object_layer_get(o) == hwc_layer));
726      }
727    else
728      return EINA_TRUE;
729
730    return EINA_FALSE;
731 }
732
733 EINTERN int
734 e_hwc_output_index_get(E_Hwc *hwc)
735 {
736    if (!hwc) return -1;
737
738    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc->output, -1);
739
740    return hwc->output->index;
741 }
742
743 EINTERN tbm_surface_queue_h
744 e_hwc_tbm_surface_queue_get(E_Hwc *hwc)
745 {
746    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
747
748    if (e_hwc_policy_get(hwc) != E_HWC_POLICY_WINDOWS)
749    {
750       EHERR("fail to get target_buffer_queue. It is not E_HWC_POLICY_WINDOWS>", hwc);
751       return NULL;
752    }
753
754    return hwc->target_buffer_queue;
755 }
756
757 EINTERN void *
758 e_hwc_gbm_surface_get(E_Hwc *hwc, int *width, int *height, int *format)
759 {
760    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
761
762    if (e_hwc_policy_get(hwc) != E_HWC_POLICY_WINDOWS)
763      {
764         EHERR("fail to get target_buffer_queue. It is not E_HWC_POLICY_WINDOWS", hwc);
765         return NULL;
766      }
767
768    if (width) *width = hwc->gsurface_width;
769    if (height) *height = hwc->gsurface_height;
770    if (format) *format = hwc->gsurface_format;
771
772    return hwc->gsurface;
773 }
774
775 EINTERN void
776 e_hwc_norender_push(E_Hwc *hwc)
777 {
778    EINA_SAFETY_ON_FALSE_RETURN(hwc);
779
780    hwc->norender++;
781
782    if (hwc->norender == 1)
783      {
784         _e_hwc_hook_call(E_HWC_HOOK_NORENDER_SET, hwc);
785         EHINF("Norender enabled", hwc);
786      }
787 }
788
789 EINTERN void
790 e_hwc_norender_pop(E_Hwc *hwc)
791 {
792    EINA_SAFETY_ON_FALSE_RETURN(hwc);
793
794    if (hwc->norender <= 0) return;
795
796    hwc->norender--;
797
798    if (hwc->norender == 0)
799      EHINF("Norender disabled", hwc);
800 }
801
802 EINTERN int
803 e_hwc_norender_get(E_Hwc *hwc)
804 {
805    EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc, 0);
806
807    return hwc->norender;
808 }
809
810 static const char *
811 _e_hwc_prop_name_get_by_id(E_Hwc *hwc, unsigned int id)
812 {
813    const hwc_prop *props;
814    int i, count = 0;
815
816    if (!e_hwc_available_properties_get(hwc, &props, &count))
817      {
818         EHERR("e_hwc_available_properties_get failed.", hwc);
819         return NULL;
820      }
821
822    for (i = 0; i < count; i++)
823      {
824         if (props[i].id == id)
825           return props[i].name;
826      }
827
828    EHERR("No available property: id %d", hwc, id);
829
830    return NULL;
831 }
832
833 E_API Eina_Bool
834 e_hwc_available_properties_get(E_Hwc *hwc, const hwc_prop **props, int *count)
835 {
836    const tdm_prop *tprops;
837
838    EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
839    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
840
841    if (!e_hwc_windows_get_available_properties(hwc, &tprops, count))
842      {
843         EHERR("e_hwc_windows_get_available_properties failed", hwc);
844         return EINA_FALSE;
845      }
846
847    *props = (hwc_prop *)tprops;
848
849    return EINA_TRUE;
850 }
851
852 E_API Eina_Bool
853 e_hwc_property_get(E_Hwc *hwc, unsigned int id, hwc_value *value)
854 {
855    tdm_value tvalue;
856    tdm_error ret;
857
858    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
859    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
860
861    ret = tdm_hwc_get_property(hwc->thwc, id, &tvalue);
862    EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, EINA_FALSE);
863
864    memcpy(&value->ptr, &tvalue.ptr, sizeof(tdm_value));
865
866    EHINF("Get property id:%u value:%u", hwc, id, (unsigned int)value->u32);
867
868    return EINA_TRUE;
869 }
870
871 E_API Eina_Bool
872 e_hwc_property_set(E_Hwc *hwc, unsigned int id, hwc_value value)
873 {
874    const char *name;
875    tdm_value tvalue;
876    tdm_error ret;
877
878    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
879
880    name = _e_hwc_prop_name_get_by_id(hwc, id);
881    EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
882
883    memcpy(&tvalue.ptr, &value.ptr, sizeof(hwc_value));
884
885    ret = tdm_hwc_set_property(hwc->thwc, id, tvalue);
886    EINA_SAFETY_ON_TRUE_RETURN_VAL(ret != TDM_ERROR_NONE, EINA_FALSE);
887
888    hwc->property_changed = EINA_TRUE;
889
890    e_hwc_windows_changed_set(hwc, E_HWC_WINS_CHANGED_PROPERTY);
891
892    ecore_event_add(E_EVENT_HWC_PROPERTY_CHANGED, NULL, NULL, NULL);
893
894    EHINF("Set property id:%u value:%u", hwc, id, (unsigned int)value.u32);
895
896    return EINA_TRUE;
897 }
898
899 E_API Eina_Bool
900 e_client_hwc_available_properties_get(E_Client *ec, const hwc_prop **props, int *count)
901 {
902    E_Hwc *hwc;
903    E_Hwc_Window *hwc_window;
904    E_Hwc_Window_State state;
905    const tdm_prop *tprops;
906
907    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
908    EINA_SAFETY_ON_NULL_RETURN_VAL(count, EINA_FALSE);
909    hwc_window = ec->hwc_window;
910    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
911    hwc = hwc_window->hwc;
912    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
913
914    state = e_hwc_window_state_get(hwc_window);
915    if (state == E_HWC_WINDOW_STATE_VIDEO)
916      {
917         if (!e_hwc_windows_get_video_available_properties(hwc, &tprops, count))
918           {
919              EHERR("e_hwc_windows_get_video_available_properties failed", hwc);
920              return EINA_FALSE;
921           }
922      }
923    else
924      {
925         if (!e_hwc_windows_get_available_properties(hwc, &tprops, count))
926           {
927              EHERR("e_hwc_windows_get_available_properties failed", hwc);
928              return EINA_FALSE;
929           }
930      }
931
932    *props = (hwc_prop *)tprops;
933
934    return EINA_TRUE;
935 }
936
937 E_API Eina_Bool
938 e_client_hwc_property_get(E_Client *ec, unsigned int id, hwc_value *value)
939 {
940    E_Hwc_Window *hwc_window;
941    tdm_value tvalue;
942
943    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
944    EINA_SAFETY_ON_NULL_RETURN_VAL(value, EINA_FALSE);
945    hwc_window = ec->hwc_window;
946    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
947    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window->hwc, EINA_FALSE);
948
949    if (!e_hwc_window_get_property(hwc_window, id, &tvalue))
950      {
951         EHERR("e_hwc_window_get_property failed", hwc_window->hwc);
952         return EINA_FALSE;
953      }
954
955    memcpy(&value->ptr, &tvalue.ptr, sizeof(tdm_value));
956
957    EHINF("Get hwc_window:%p property id:%u value:%u",
958          hwc_window->hwc, hwc_window, id, (unsigned int)value->u32);
959
960    return EINA_TRUE;
961 }
962
963 const char *
964 _e_client_hwc_prop_name_get_by_id(E_Client *ec, unsigned int id)
965 {
966    const hwc_prop *props;
967    int i, count = 0;
968
969    if (!e_client_hwc_available_properties_get(ec, &props, &count))
970      {
971         EHERR("e_client_hwc_available_properties_get failed.", ec->hwc_window->hwc);
972         return EINA_FALSE;
973      }
974
975    for (i = 0; i < count; i++)
976      {
977         if (props[i].id == id)
978           return props[i].name;
979      }
980
981    EHERR("No available property: id %d", ec->hwc_window->hwc, id);
982
983    return NULL;
984 }
985
986 E_API Eina_Bool
987 e_client_hwc_property_set(E_Client *ec, unsigned int id, hwc_value value)
988 {
989    E_Hwc_Window *hwc_window;
990    const char *name;
991    tdm_value tvalue;
992
993    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
994    hwc_window = ec->hwc_window;
995    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
996
997    name = _e_client_hwc_prop_name_get_by_id(ec, id);
998    EINA_SAFETY_ON_NULL_RETURN_VAL(name, EINA_FALSE);
999
1000    memcpy(&tvalue.ptr, &value.ptr, sizeof(hwc_value));
1001
1002    if (!e_hwc_window_set_property(hwc_window, id, name, tvalue, EINA_TRUE))
1003      {
1004         EHERR("e_hwc_window_set_property failed", hwc_window->hwc);
1005         return EINA_FALSE;
1006      }
1007
1008    EHINF("Set hwc_window:%p property id:%u value:%u",
1009          hwc_window->hwc, hwc_window, id, (unsigned int)value.u32);
1010
1011    return EINA_TRUE;
1012 }
1013
1014 EINTERN Eina_Bool
1015 e_client_hwc_on_plane(E_Client *ec)
1016 {
1017    E_Output *output = NULL;
1018    E_Plane *plane = NULL;
1019    E_Client *plane_ec = NULL;
1020    E_Hwc_Window *hwc_window;
1021    E_Zone *zone;
1022    Eina_List *l = NULL;
1023    Eina_Bool ret = EINA_FALSE;
1024
1025    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1026    zone = e_comp_zone_find_by_ec(ec);
1027    EINA_SAFETY_ON_NULL_RETURN_VAL(zone, EINA_FALSE);
1028
1029    output = e_output_find(zone->output_id);
1030    EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1031
1032    if (e_hwc_policy_get(output->hwc) == E_HWC_POLICY_PLANES)
1033      {
1034         EINA_SAFETY_ON_NULL_RETURN_VAL(output, EINA_FALSE);
1035
1036         EINA_LIST_FOREACH(output->planes, l, plane)
1037           {
1038               plane_ec = e_plane_ec_get(plane);
1039               if (plane_ec == ec)
1040                 {
1041                    ret = EINA_TRUE;
1042                    break;
1043                 }
1044           }
1045      }
1046    else
1047      {
1048         hwc_window = ec->hwc_window;
1049         EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, EINA_FALSE);
1050
1051         ret = e_hwc_window_is_on_hw_overlay(hwc_window);
1052      }
1053
1054    return ret;
1055 }
1056
1057 E_API Eina_Bool
1058 e_client_hwc_visible_skip_set(E_Client *ec, Eina_Bool skip)
1059 {
1060    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, EINA_FALSE);
1061
1062    ec->hwc_visible_skip = skip;
1063
1064    if (ec->hwc_window)
1065      e_hwc_window_visible_skip_set(ec->hwc_window, skip);
1066
1067    return EINA_TRUE;
1068 }
1069
1070 E_API E_Hwc_Sync_Callback *
1071 e_hwc_sync_callback_add(E_Hwc *hwc, E_Hwc_Sync_Done_Cb cb, void *data)
1072 {
1073    E_Hwc_Sync_Callback *sync_callback;
1074
1075    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
1076    EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc->hwc_policy == E_HWC_POLICY_WINDOWS, NULL);
1077
1078    sync_callback = E_NEW(E_Hwc_Sync_Callback, 1);
1079    EINA_SAFETY_ON_NULL_RETURN_VAL(sync_callback, NULL);
1080
1081    sync_callback->hwc = hwc;
1082    sync_callback->cb = cb;
1083    sync_callback->data = data;
1084
1085    hwc->sync_callback_list = eina_list_append(hwc->sync_callback_list, sync_callback);
1086
1087    return sync_callback;
1088 }
1089
1090 E_API void
1091 e_hwc_sync_callback_del(E_Hwc_Sync_Callback *sync_callback)
1092 {
1093    EINA_SAFETY_ON_NULL_RETURN(sync_callback);
1094
1095    if (sync_callback->hwc)
1096      {
1097         sync_callback->hwc->sync_callback_list =
1098            eina_list_remove(sync_callback->hwc->sync_callback_list, sync_callback);
1099      }
1100
1101    E_FREE(sync_callback);
1102 }
1103
1104 EINTERN Eina_Bool
1105 e_hwc_sync_callback_call(E_Hwc_Sync_Callback *sync_callback)
1106 {
1107    EINA_SAFETY_ON_NULL_RETURN_VAL(sync_callback, EINA_FALSE);
1108
1109    if (sync_callback->done) return EINA_TRUE;
1110
1111    sync_callback->done = EINA_TRUE;
1112
1113    if (!sync_callback->cb) return EINA_TRUE;
1114
1115    /* it is possible callback is freed in callback */
1116    sync_callback->cb(sync_callback->data, sync_callback->hwc);
1117
1118    return EINA_TRUE;
1119 }
1120
1121 E_API E_Hwc_Presentation_Callback *
1122 e_client_hwc_presentation_callback_add(E_Client *ec, E_Hwc_Presentation_Done_Cb cb, void *data)
1123 {
1124    E_Hwc_Presentation_Callback *callback;
1125    E_Hwc *hwc;
1126    E_Hwc_Window *hwc_window;
1127
1128    EINA_SAFETY_ON_NULL_RETURN_VAL(ec, NULL);
1129    EINA_SAFETY_ON_NULL_RETURN_VAL(cb, NULL);
1130    hwc_window = ec->hwc_window;
1131    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc_window, NULL);
1132    hwc = hwc_window->hwc;
1133    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
1134    EINA_SAFETY_ON_FALSE_RETURN_VAL(hwc->hwc_policy == E_HWC_POLICY_WINDOWS, NULL);
1135
1136    callback = E_NEW(E_Hwc_Presentation_Callback, 1);
1137    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, NULL);
1138
1139    callback->hwc = hwc;
1140    callback->cb = cb;
1141    callback->data = data;
1142
1143    if (!e_hwc_window_presentation_callback_pending_set(hwc_window, callback))
1144      {
1145         ERR("fail to e_hwc_window_presentation_callback_set");
1146         free(callback);
1147         return NULL;
1148      }
1149
1150    EHINF("Add Presentation Callback:%p ec:%p hwc_window:%p",
1151          hwc,
1152          callback,
1153          ec,
1154          hwc_window);
1155
1156    return callback;
1157 }
1158
1159 E_API void
1160 e_hwc_presentation_callback_del(E_Hwc_Presentation_Callback *callback)
1161 {
1162    EINA_SAFETY_ON_NULL_RETURN(callback);
1163
1164    EHINF("Del Presentation Callback:%p", callback->hwc, callback);
1165
1166    if (callback->list)
1167      callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
1168
1169    free(callback);
1170 }
1171
1172 EINTERN void
1173 e_hwc_presentation_callback_list_init(E_Hwc_Presentation_Callback_List *list)
1174 {
1175    EINA_SAFETY_ON_NULL_RETURN(list);
1176 }
1177
1178 EINTERN void
1179 e_hwc_presentation_callback_list_finish(E_Hwc_Presentation_Callback_List *list)
1180 {
1181    E_Hwc_Presentation_Callback *callback = NULL;
1182    Eina_List *l, *ll;
1183
1184    if (!list) return;
1185
1186    /* remove list in resource_destroy callback */
1187    EINA_LIST_FOREACH_SAFE(list->callbacks, l, ll, callback)
1188      {
1189         callback->list = NULL;
1190         list->callbacks = eina_list_remove_list(list->callbacks, l);
1191         e_hwc_presentation_callback_call(callback);
1192      }
1193 }
1194
1195 EINTERN Eina_Bool
1196 e_hwc_presentation_callback_list_set(E_Hwc_Presentation_Callback_List *list,
1197                                      E_Hwc_Presentation_Callback *callback)
1198 {
1199    EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
1200    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
1201
1202    if (callback->list)
1203      callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
1204
1205    if (!eina_list_data_find(list->callbacks, callback))
1206      list->callbacks = eina_list_prepend(list->callbacks, callback);
1207
1208    callback->list = list;
1209
1210    return EINA_TRUE;
1211 }
1212
1213 EINTERN Eina_Bool
1214 e_hwc_presentation_callback_list_unset(E_Hwc_Presentation_Callback_List *list,
1215                                        E_Hwc_Presentation_Callback *callback)
1216 {
1217    EINA_SAFETY_ON_NULL_RETURN_VAL(list, EINA_FALSE);
1218    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
1219
1220    if (callback->list)
1221      callback->list->callbacks = eina_list_remove(callback->list->callbacks, callback);
1222
1223    callback->list = NULL;
1224
1225    return EINA_TRUE;
1226 }
1227
1228 EINTERN void
1229 e_hwc_presentation_callback_list_merge(E_Hwc_Presentation_Callback_List *inout,
1230                                         E_Hwc_Presentation_Callback_List *input)
1231 {
1232    E_Hwc_Presentation_Callback *callback = NULL;
1233    Eina_List *l, *ll;
1234
1235    EINA_SAFETY_ON_NULL_RETURN(inout);
1236    EINA_SAFETY_ON_NULL_RETURN(input);
1237
1238    /* remove list in feedback_set */
1239    EINA_LIST_FOREACH_SAFE(input->callbacks, l, ll, callback)
1240      e_hwc_presentation_callback_list_set(inout, callback);
1241 }
1242
1243 EINTERN Eina_Bool
1244 e_hwc_presentation_callback_call(E_Hwc_Presentation_Callback *callback)
1245 {
1246    EINA_SAFETY_ON_NULL_RETURN_VAL(callback, EINA_FALSE);
1247
1248    if (callback->done) return EINA_TRUE;
1249
1250    callback->done = EINA_TRUE;
1251
1252    if (!callback->cb) return EINA_TRUE;
1253
1254    EHINF("Call Presentation Callback:%p", callback->hwc, callback);
1255
1256    /* it is possible callback is freed in callback */
1257    callback->cb(callback->data, callback);
1258
1259    return EINA_TRUE;
1260 }
1261
1262 EINTERN void
1263 e_hwc_presentation_callback_list_call(E_Hwc_Presentation_Callback_List *list)
1264 {
1265    E_Hwc_Presentation_Callback *callback = NULL;
1266    Eina_List *l, *ll;
1267
1268    EINA_SAFETY_ON_NULL_RETURN(list);
1269
1270    /* remove list in resource_destroy callback */
1271    EINA_LIST_FOREACH_SAFE(list->callbacks, l, ll, callback)
1272      e_hwc_presentation_callback_call(callback);
1273 }
1274
1275 E_API E_Output *
1276 e_hwc_output_get(E_Hwc *hwc)
1277 {
1278    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, NULL);
1279
1280    return hwc->output;
1281 }
1282
1283 E_API E_Hwc_Policy
1284 e_hwc_hwc_policy_get(E_Hwc *hwc)
1285 {
1286    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, E_HWC_POLICY_NONE);
1287
1288    return hwc->hwc_policy;
1289 }
1290
1291 E_API void
1292 e_hwc_hwc_use_multi_plane_set(E_Hwc *hwc, Eina_Bool set)
1293 {
1294    EINA_SAFETY_ON_NULL_RETURN(hwc);
1295
1296    hwc->hwc_use_multi_plane = set;
1297 }
1298
1299 E_API Eina_Bool
1300 e_hwc_hwc_use_multi_plane_get(E_Hwc *hwc)
1301 {
1302    EINA_SAFETY_ON_NULL_RETURN_VAL(hwc, EINA_FALSE);
1303
1304    return hwc->hwc_use_multi_plane;
1305 }